|
29956
|
Barrel Roll Bullet by @ShinyMist | Stardance
|
ShinyMist
|
1
|
118.0
|
2120
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-24T07:55:16Z", "hours": 118.0, "multiplier": 17.91, "payout": 2120, "blessing": "neutral", "text": "Barrel Roll Bullet A recoil-based platformer where, instead of traditional jumping and movement, you shoot to propel yourself around each level. My game includes multiple abilities, unlockable gun skins and 50 levels. The biggest challenge I faced was developing an accurate and efficient collision system. Initially, I planned to use AABB collision, but because it relies on rectangular bounding boxes, I found that the gun barrel could appear to float when rotating or interacting with objects. I then experimented with mask collision to achieve pixel-perfect accuracy. However, using a large number of masks throughout a level caused noticeable drops in performance. I eventually settled on a middle ground using SAT (Separating Axis Theorem) polygon-based collision. This provided much more accurate collision detection for the rotating gun while being significantly more performant than mask collision, allowing me to maintain both responsive gameplay and consistent performance. I am proud of the persistence I have demonstrated throughout the project. During the early stages of development, I encountered significant gaps in my knowledge, particularly as I was new to object-oriented programming. At times, I struggled with seemingly simple tasks, such as correctly initialising a game window or positioning a rectangle where I intended it to be. Despite these difficulties, I continued to learn, troubleshoot and refine my approach rather than abandoning features when they became challenging.", "repo": "https://github.com/Oliver-Attoe/StarDanceProject_FLStudioGrind", "demo": "https://github.com/Oliver-Attoe/StarDanceProject_FLStudioGrind/releases/tag/v1.0.0"}]...
|
[{"post_id": 73026, "ts": "202 [{"post_id": 73026, "ts": "2026-09-24T07:21:08Z", "hours": 0.5231, "text": "Dev Log #39 . THE FINAL DEV LOG . I am finally ready to ship!!! . I did the following: Made a working read me Made a working exe file of my game Removed de-bugging features so game works as intended. Stopped music overlap from happening Removed all copyrighted music (may have mentioned this previously) I used pyinstaller tocreate my exe file. . Level buttons now only work if player max player level is less than or equal to the level you are selecting. . Stopped music overlap by puting stop music into every game state + in load room function . Its been a pleasure to take part in the stardance event. Lets have a look to see how far this project has come!!!"}, {"post_id": 71415, "ts": "2026-09-20T19:44:37Z", "hours": 2.6217, "text": "Dev Log #38 . DONE . I did the following: Added music that plays while in level Removed copyrighted music Finished all GUI Made code neat using ruff Will ship at some point soon. See you on ship day!!!!"}, {"post_id": 71257, "ts": "2026-09-20T15:13:48Z", "hours": 4.6078, "text": "Dev Log #37 . All code is 100% complete now, the only thing left to do is finish all of the UI and then I am ready to ship. . Today I: Fixed portals Added level skip button Displayed bonus objectives Made button rotation work when pressed also Made gun select display gun images Portal code issue was caused by object overlapping with tiles, cause tile collision resolution to push the player out of the tile, and at times out of the map. Fixed this by teleporting player slightly above the object (above being determined by orientation). . Level skip increases player level, restarts level and spawns player in next level. . Bonus objectives screen.blitted on win, text appears green when objective met, red when it hasn’t . Used updated rotated button rect rather then previous and changed screen.blit to use center of rect rather than topleft . For each button in gun group, i screen.blited that gun into the center of the select gun skin rect . Thats all, hope to ship by tonight."}, {"post_id": 69536, "ts": "2026-09-17T07:47:24Z", "hours": 5.2261, "text": "Dev Log #36 . I have done most of the updating of UI, having only a few assests left and one level left to edit. . In addition to this, I have also made it so that buttons now appear pressed when pressed, rather than disappearing. . My easter egg room also stops the music correctly on level complete. . The final objectives are as follows: Have gun select each have image of gun Waiver has displayed text Hint video made and linked correctly All button can only be pressed when on screen Finish misc Assets Add death, win, and coins/stars collected based on mission objectives complete Thats all, I think 20/09/2026 could still be the date for the books, but I’ve got to put the burners on to get this finsished to a level of polish I’m happy with."}, {"post_id": 66573, "ts": "2026-09-12T12:32:48Z", "hours": 1.6919, "text": "Dev Log #35 . Been a bit distracted from this project due to school starting but I’ve been able to get a few things done. . I have done the following: Finished dialogue texts Made it so that dialogue box only appears when there is text Given kill tiles rotatable counterparts Added muzzle flash Added ability pick up sounds Updated a few more assets My Git commits have started to get a bit sloppy as i do these little bits on during my free periods, but im getting back into the swing of things . The dialogue box will only appear if text != “” and will put the player in the start playing state, without requiring a mouse click like it did previously. . Adding sounds was pretty simple so I wil leave an example bellow if self.rect.colliderect(ability[\"rect\"]): if self.gravity_flip > 0: up_gravity_fx.play() else: down_gravity_fx.play() ability[\"collected\"] = True self.gravity_flip *= -1 That’s all, I think 20/09/2026 will be a date for the books as I’m confident I will be finished by then. ALSO, if anyone sees this before ship, could you let me know any ideas for what my 16x16 tile for regular tiles could look like? Many thanks if you respond"}, {"post_id": 64309, "ts": "2026-09-08T16:27:15Z", "hours": 5.7308, "text": "Dev Log #34. . Just cleaning some things up now, we are in the home stretch . I did the following: Updated assest Updated object display code fixed broken dialogue Most assets have a fresh new look created in photopea . Buttons can now be loaded at rotated orientations . Dialogue now does display and does not disapear on first level load. This is because the start playing state was being skipped, i fixed this by using a continue, which skipped the rest of the current loop iteration, preventing the start-state code from continuing to run after changing playing_state. . Thats all, most of my time when into design. See you next devlog"}, {"post_id": 57440, "ts": "2026-08-29T16:21:03Z", "hours": 9.3847, "text": "Dev Log #33 . As you can probably guess, I have done alot I have done the following: • Gave all levels the correct level variables • Made buttons work correctly when rotated • Made teleport bullets work as intended • Made gates and broken tiles allow bullets to pass through when collision is removed • Created an EXE file of my game for friends to use for playtesting • Made a stat tracker to use playtest information to improve my game • Corrected all file directories that had to be moved for PyInstaller to work properly • Fixed the Easter egg room so it now loads correctly • Added AI declaration comments That is a lots, so let me quick fire explain how i did them Painful repetition, change variables, restart level, change tiles, reset level, change ability position, reset. Repeat for level in levels (do this 50 times) . This was partially assisted by AI, but from what I understand the buttons’ Tiled rotation number is used to adjust the collision rectangle’s position so it matches the rotated button object in tiled. Collision check works as did previously. . Teleport bullets originally tp the player if a bullet fired priviously hit a way after pickup, despite no bullet being fired after pickup and also sometimes caused the player to shoot downwards through tiles. . I fixed the wrong bullet tp by using a self.variable rather than a global one as previously, allowing each bullet to know if they were teleport enabled, rather than all bullets being teleport enabled. . The tile collision isssue was fixed by by moving the player backwards along the bullet’s path until they are outside the tile, preventing the gun from passing through walls and being pulled down . This one will just explain itself (if tile in list, then ignore kill on contact): for tile in Tiles.tiles: if self.rect.colliderect(tile[\"rect\"]): tile_property = tile[\"property\"].get(\"type\") if tile_property in Tiles.open_gates: continue This used pyinstaller, not something i really code or anything so, I’ll just say i did it sucessfully . Stat tracker records bullet count, time and deaths/restarts that a level took on completion. Difficulty of a level can also be decided by a play tester by pressing any number button during a level. . This data is level specific, and on key press of /, will create a json file that holds all the data, which can then be sent for me for review of things like bullet max, time complete bonus time, ect. . Self explanatory, just changed things like “Image/buttn.png” to “Game/Image/button.png” . Restart all function was required in load room function as it contains map load, so the level map that was supposed to load is not displayed instead of the secret easter egg map. . 9.Should have declared AI usage earlier, but I have been checking my chat history and I have been able to determine what sections of my code are AI generated . That’s all, gotta try and keep my daily streak alive this time to score myself a free plush."}, {"post_id": 54686, "ts": "2026-08-25T19:01:58Z", "hours": 3.5433, "text": "Dev Log #32 . Made 50 levels today, that is all. . Every 3 levels, a new ability/feature is added. This allows the player to get used to the new thing added, making their later appearance managble as the player is now used to how they function. . I have not set the player and goal location co-ordinates for each level, or other variables like if mini stars are required. . That’s all for today."}, {"post_id": 54018, "ts": "2026-08-24T19:16:39Z", "hours": 2.2183, "text": "Dev Log #31 . I AM FINISHED!!! . Well, pretty much at least. . Today I: Completed the Waiver Made some more levels I made it so that the text box works with word wrap, enter key and backspace key. . I did this by splitting the text into words and lines, then checking each word’s width against the rect boundaries. . If the word exceeds the boundaries x, the texts’ x position is reset and the Y-coordinate is incremented, creating a new line. . The Enter key creates a new line by resetting x and incrementing y, while Backspace removes the last character from the text string, preventing it from being displayed. . The waiver now checks if all fields are filled and allows you to press a button that is connected to a hyperlink that will, in the future, take you to a video created my me showing how each level is complete. . Also made 12 levels today, each new feature is slowly implemented one at time. . That’s all for today."}, {"post_id": 53326, "ts": "2026-08-23T20:00:08Z", "hours": 2.7178, "text": "Dev Log #30 . The big 30!!! . Done quite a bit today, just last bit of polishing and then we move towards UI, music, level design, ect. . Today I: FINISHED THE DIALOGUE SYTEM Added a leave waiver button (was a softlock) Added a text box to waiver [WIP] Dialogue system works fully (minus sound but thats still a win in my books). Plays on level start and level completion and once dialogue is viewed by the player, it is not shown to them again. . Mouse can be clicked to remove dialogue from the screen, without triggering bullet fire. . Also fixed the issue of the text backround being displayed on re-entry and re-completion of the level, but fixed that easily with a variable, setting it to true or false if level had already been completed, then only displaying the text bg when it was true. . Waiver leave button pretty simple, basic pygame rect collidepoint detection. . Text box sets text_active to true on mouse click, mouse clicks anywhere else set it to false, meaning player can only type when they have clicked on it (when they want to). . I appened every event.unicode into a list on key press, meaning I had a list of the players key storkes, then screen.blitted each letter in the list. . Final touches are making all fields complete required to acess button that is a hyperlink to video of me completing stages with instuctions to help, and also backspace and enter and wordwrap working with the text_box. . Then I think I’m done for the most part on the coding side of things, and will move onto level creation. . The only thing I haven’t completed from my long list from a preious dev_log are: Level editor Upside down ability James bond level start Hint dialogue on multiple deaths Boss fight Not to say these aren’t going to be added but they are not simple things and will not really add to much to my game in all honesty. Given the deadline of end of this month I have given myself, I don’t know if I will have time to add these (except for the James bond level start thing as that is a UI thing that will require art, music ect so might work on that when not coding. . That’s all, thanks for reading (:"}, {"post_id": 52887, "ts": "2026-08-23T08:25:38Z", "hours": 2.2633, "text": "Dev Log #29 . I’m pretty close to finishing the code side of my game now, the rest of my efforts will soon be focous toward things like: Writing dialogue Making nicer looking UI Making tiles look good rather than coloured blocks Animations Music Today I did the following: Re made the dialogue system AGAIN Created a gun selection screen My dialogue system displays a word at a time and plays a short noise for each word shown, similarily to undertale voice blips. However, I think it sounds quite bad and I plan to replace it with a set dialogue sound that plays at the start, like animal crossing. . My dialogue system now plays on level start and level completion, and does not re-trigger on level repeat, using similar code used in my star tracking code. . Gun select code is similar to my level select code, using a different class but the same code, just changing the lock out code to only unlock once star count is >= button number - 1 * 6, so that each button is unlocked for each 6 stars earned, as well as having the default gun already unlocked. . That’s all for today, I hope to have a complete game by the end of the month so I can have this finished before the school year starts."}, {"post_id": 51905, "ts": "2026-08-21T20:16:23Z", "hours": 2.1786, "text": "Dev Log #28 . Didn’t do alot today, or for the 2 other days… . I finally made ghost bullets work correctly and have changed the dialogue sytem a bit . The ghost bullets working and not working previously was juts a matter of using variables inside the bullet class rather than global ones, making it work better for some reason, I had the assistance of a friend in fixing the issue, and safe to say it solved it . Dialogue sytem has only been changed slightly so not much point documenting the changes, spacing, timing of letters, ect. . Sorry for short devlog, I hope I have more tommorrow."}, {"post_id": 49659, "ts": "2026-08-18T15:26:51Z", "hours": 3.4011, "text": "Dev Log #27 . More things checked of the list today: . Today I did: Added gravity flip ability Added teleport bullets Added player mission objectives However, some other things i worked on today are still a work in progress, such as: Diologue system Ghost bullets (travel through walls) Gravity flip works similarily to how slow time works, settings the variable self.gravity_flip to -1 on contact, then multiplying graivty strenght by it, reversing the direction of gravity . This however made my realign function not work when on the ceiling, so i added to re-align that if gravity_flip was negative, to detect ceiling hit rather than grounded, allowing it to work why gravity was flipped. . Teleport bullets work by setting a can teleport function to True on contact, then when true, if bullet collidesrect with tile, self.rect of bullet is equal to self.rect of gun. the can tele[port function is then set to false, making the ability only work once as intended. . Player mission objects are as follows: Complete level Complete level in set ammount of time Complete level with less bullets than provided This uses lists in a way i have never used them before and looks like this total_stars = 0 level_stars = [[False, False, False] for _ in range(levels)] If player completes level, level_stars[Settings.player_level - 1][0] for current player level is set to True. . If player completes level quickly (complete_time < bonus_time), then …[1] is set to true . If player reaches has_won game state with a number of bullets lower than the bullet max, then then …[2] is set to True. . Total stars is incremented by one for each goal completed, and if level_stars[Settings.player_level - 1][1,2 or 3] is already set to true, then the increment is skipped, meaning you can only get 3 stars per level. . That’s all for now, hope to fix the issues I had today in tomorrows devlog!!"}, {"post_id": 49172, "ts": "2026-08-17T20:15:54Z", "hours": 2.1058, "text": "Dev Log #26 . Popped ULT today!!! . Today I added the following: Slow time ability Breakable surfaces Bullet pickup Fixed up dialogue system (Not fully complete) Slow time ability works by setting a time to a decimal then multplying the following by it: Velocity (Bullet + Player) Rotation speed Gravity strength Multiplying by a decimal reduces the numbers, emulating slowed time rather than reducing fps which is a bit of a cop-out . Breakable surfaces work similarly to the gate tiles, the tiles having a alpha value of 0 when bullet rect makes contact with tile of that class and adding that tile type to a list: broken_tiles. . All tiles in that list are then ignored by tile collision . Bullet pickup works by detecting rect collision between the player and the surface, when contact is made the players bullet count (representing bullets shot total) is reduced by one, increasing the number of shots available to the player by one. . Dialogue system now works with full words, voice blips are annoying but will fix late stage when adding polish. Will also make it that player has to click mouse to go to next dialogue screen to give them time to read the text. . That is 3 and a bit things of the list, very good progress, juggling summer work, this and most importantly my Minecraft duties has been an upward hill battle but I’m getting there. . See you next develop with more progress!!!"}, {"post_id": 48445, "ts": "2026-08-16T19:54:18Z", "hours": 0.6561, "text": "Dev Log #25 . My love for videojuegos has got the better of me. . Over theses 2 days all I have done is made some level maps and fixed the spawing positions of both win condition and the player based on the new maps. . But I have structure now, and rather than geting destracted, I have set myself some goals to complete hopefully by the end of the month, leaving me time to make the UI look nice. . I present to you. THE TOD0 LIST: . A - DIOLOGUE Fix dialogue system Add hint dialogue Add new level dialogue Add completed dialogue B - ABILITIES/TILES Bullet Pickup Ghost bullets Teleport bullets Time SLOW (not stop) Gravity flip ? Map flip ? Breakable tiles Level editor ? C - UI James bond level start animation Gun skin menu All menus with all required buttons D - Miscellaneous Mission objectives (Bad piggies esque) Determine gun skin unlock criteria A FINAL BOSS !?!?! I hope tomorrow if filled with WAY more advancements of the work kind rather than the Minecraft kind (;"}, {"post_id": 47115, "ts": "2026-08-14T19:25:06Z", "hours": 2.7211, "text": "Dev Log #24 . A progress full day today, but mabye not for the best?? . Today I done the following: Added a charcater diologue box Fixes re-align function so that it works when rotation direction is reversed Just doing little sidequests for now as I’m trying to hide from my enemy, level design. The things is I’m not very good at games, so i dont have the reaction time to create very punishing levels with little room for error. . So to combat this, I end up making really hard levels or super easy ones. . Additionally, I barley add any time to my total when creating levels as it uses a piece of software outside of visual studio. . My character text box is pretty much a recreation of the ones seen in undertale, even using the voice blip of toriel as a place holder. . This should allow me to add a small story that I will make sure to keep simple, like a mario esque plot. . The re-align function was fixed by using the variable rotation direction, then setting that to 1 or -1 depending on contact with reverse direction ability or not . Then multiplying rot_speed by that value reverse the direction that re-align moves. . I will have to knuckle down on level design tomorrow and make sure each level introduces the abilities and tiles one at a time, letting the player get used to them, allowing for levels that include a mix of multiple to be more approachable."}, {"post_id": 46505, "ts": "2026-08-13T19:34:14Z", "hours": 3.1664, "text": "Dev Log #23 . Very good day today, embracing the foddian likeness of my game, making sure that the player gets as angry as possible, just to make that feeling of victory feel so sweet. . Here’s what I did today: LOSER document created (must be filled in to reveal hints, which will be added later) Change rotation direction ability New map (Still a WIP) Document uses follow mouse function and draw line function. Starting the line at the mouses previous position and ending it at its new position. . This happens very fast, so the lines do not appear blocky and appear like real pencil drawing. . The change rotation ability uses the pbject layer like my previous time stop ability, and now that I understand how object layers work, i was easily able to make this ability by copying my clock abiltiy load and changing the result of contact. . The result being making rotation speed negative, reversing direction of rotation. . The new map uses a mix of many abilities and objects, but I have not added them in just yet. . I could quite easily I feel but I’ve reached my 3 hour brain capacity limit, because realisticly with the time spent making pngs, finding sounds, reading pygame documentation and waching tutorials, I’ve probably spent about 5. . But rewards are not for the weak or the lazy, and this little project of mine is helping me leaps and bounds for my future A-level comp sci journey. . See you next time, with some jucy new progress!!!!"}, {"post_id": 45899, "ts": "2026-08-12T17:26:00Z", "hours": 3.3278, "text": "Dev log #22 . Back to business!! . Today I added: Uncompleted level select lockout Separated tile load into own file Easter egg room added Level lockout works by calculating max_player_level, the furthest level a player can select based on if they have beat the previous levels. . This works buy using a function to check if current player_level is greater than max_player_level, if it is then max_player_level = player level. . Then for level select button with number greater than max_player_level, a red cross is screen.blited ontop,as well as not allowing mouse clicks of the rect from having any function. . Tile file separation helped me remove 150 lines from my main file, improving readability. . My easter egg has a 2% chance of happening and gives the player a custom gun appearance on discovery. . The code used to change the guns appearenece should let me, in future, make custom skins for the gun, skins that could be rewarded for levels complete, secondary level goals reached, ect… . I will not share how to reach my secret room, but I think it would be better for someone to stumble across it by accident. . Good day today, progress is picking up pace again, good job me!!! . Strange, it seems, there is a man here…."}, {"post_id": 45339, "ts": "2026-08-11T18:45:05Z", "hours": 2.1411, "text": "Dev Log #21 . Getting lazy now, saw hacktime was down and decided not to bother doing anything before 12, but I hope I will break this cycle. . Today I added working buttons that when pressed, remove gate blocking path. . Had to over hall all my tile loading and map loading and parts of my collision resolution to allow me to reduce the lag being caused in some levels and be able to remove collision selectively for tile types. . I learn how to use set today. I used a set to store the types of gates that have been opened because it prevents duplicates and allows me to quickly check whether a specific gate is open. . No animations for button presses yet as I want to leave that stuff for the end. . I’m feeling the time crunch now because I really want this to be finished before I get back to school and focus on my studies, but this still counts as practice so I’ll continue a little bit during school days. . I will do better tomorrow I promise, cause I’ve got this far, it would be a waste to stop now."}, {"post_id": 44821, "ts": "2026-08-10T20:55:15Z", "hours": 2.8053, "text": "Dev Log #20 . Sorry for the hiatus, not a lot done, but sure I will be soaring tomorrow. . Today I addded: Killable enemies New reset all function Killable enemies act as win conditions, similar to the mini stars, having to all be killed for the goal polygon to spawn. . The reset function made my code much more readable and allowed me to condense all of the restart events like lose velocity, set position here, screen.blit things again if needed. . I started working on 3 buttons that when pressed, open a gate but didn’t get to finishing it sadly. . I want each button to have different press conditions, one can be pressed by bullets only, one only on direct gun contact and the other working with either or. . In later stages, I will have to think how i will communicate this functionality to the player but I’m saving texturing and making the game look good for last. . Hope to have more progress tomorrow. Fingers crossed."}, {"post_id": 42861, "ts": "2026-08-07T20:19:50Z", "hours": 2.4408, "text": "Dev Log #19 . Getting lazy, need to lock in and get 3 hours tomorrow. . Today I added: Working portals Time stop ability Portals and time stop ability use object layers in tiles, a much easier solution compared to my use of polygons for complete goals, may change that but not sure. . Time stop ability is pretty simple, works like pause menu, but allows image rotation and enables follow mouse. . Portals work by on contact, moving player position centre to other portal centre. . The velocity changes with the exit direction using the following code: rotation_difference = entry_angle - exit_angle self.velocity.rotate_ip(rotation_difference) Overall, ok day, not sure what I’ll do tmr, but I’m sure theres something hiding on my checklist. . ALSO!!, Fix this horrible performance issue I had, see bellow for comparison"}, {"post_id": 42135, "ts": "2026-08-06T18:44:20Z", "hours": 2.5461, "text": "Dev Log #18 . Good day, but stopped early today beacuse, well, i’m afraid… . What I did today: Added mini_stars Added re-align option when grounded Added new map Mini stars are to be collected first, unlocking the finish goal. They are hard coded right now so cant be moved for new levels, but I can change that if need be. . Re-align was initially supposed to allow A to rotate the player one direction and D the other, but my game seemed to really not like decreasing the angle value when grounded. . So I’ve made it so rotation only happens one direction, but a full 360 range of motion is possible. . The new map that uses portals, but the portals are not actually functional yet so, thats a job for tomorrow . . Almost everything added from last devlogs check list, but decided against adding placeholder music during playing state as i think I would go insane from listening to it on loop, so that can wait till the end. . Hope to have a longer more prosperous dev log next time, see you then!!!"}, {"post_id": 41536, "ts": "2026-08-05T20:08:05Z", "hours": 3.6981, "text": "Dev Log #17 . Feel kinda stuck in-between, but once a pass my last hurdle, all of my efforts will be focused on new abilities, new tiles and art, but the basics are sooo close to being complete. . Today i did the following: Level stopwatch Level complete goal changed Edited map Complete goal had to be changed to make animation of win goal possible, like coin pick up in Mario. Uses polygon collision, freezes on contact currently but working on fix. . Level stopwatch works well, and works with pause menu by subtracting time passed in pause menu from counter total on continue button pressed. . Map needed editing as I feel my game is too hard and my muscle memory from 100’s of tries makes it feel easy, but really isn’t. . Tried making a new map that requires you to collect many little stars to reveal the goal but found it hard to find a map that works with wide range of movement. . This issue is caused by gun being useless most of the time on collision with floor as it is aimed the wrong way. . I plan to have the player be able to rotate the gun while its grounded using A or D, this re-ajusting stopping players getting stuck. That or a jump ability. . Next devlog hope to have: Mini stars working New map Rotate/jump when grounded Game in progress music See you next devlog, no 1 day hiatus next time (;"}, {"post_id": 40339, "ts": "2026-08-03T19:40:47Z", "hours": 2.6639, "text": "Dev Log #16 . Today was good. I was welmed. . I did the following today: Added working kill tile Fixed image lagging behind player polygon Switched over to match cases Kill tile works as intended, but doen’t ‘kill’ the player yet, it just freezes everything, plays a sound and propts you to restart. . Image lagging behind was a big issue, causing the kill tile to look as if it were killing without contact, but this was cause by the image lag behind. . I tried changing the order of functions in update() but that didn’t work, tried other stuff like changing how some functions work, in the end, it was because i called update after player_group.draw(). Silly me!! . Match case switch over was easy, just the indentation was at times a pain, but I’ve sorted it now, thank goodness! . Going to try and finish the loss screen that appears, adding a level select button and a return to start, but might not as its not strictly necessary, but does look nice. . Not sure what other stuff to add, maybe a new level? . Who knows, see you next Dev Log!!!!"}, {"post_id": 39640, "ts": "2026-08-02T19:23:20Z", "hours": 3.0406, "text": "#Dev Log 15 . Good day at the office. . Did the following today: Working level select Fixed Music Issue Fixed map loading issues (didn’t discover until today) Added tile classes to replace gid based system for tile specific collision My issues today were caused by my moving of code into separate files, but I’m getting there. I’m no longer using from ___ import * and I am instead using import ______. . The sound issue was caused by a variable in settings setting play music to False without my knowledge. . Map loading broke because my maps are only loaded once outside of the while loop, so I fixed that. . Tiles now have a class that can be checked, allowing for different interactions with tiles dependent on tile class. . Thinking about storing some of my variables into match statements for readability but I find using match cases in Settings.py to be really difficult so I will proceed with caution and immense fear!!! . Not sure what tomorrow holds, thinking about making the kill and win tiles do something rather than print win or killed, but might be held up by this switch from many elifs to match cases. . Staying determined, see you next dev log. . PS, a little hint to my little easter egg 📂︎🖮︎"}, {"post_id": 39080, "ts": "2026-08-01T19:29:51Z", "hours": 4.105, "text": "#Dev Log 14 . Ying ang Yang session today: . I did the following: 2 new maps - one I’m keeping a secret for the complete game >;] Level select rect load (not working YET) Kill tile (detection only) Separating code into files outside of main Music Broke…. Level select menu was a perfect mix of challenge and enjoyability. . I loaded the squares in this even patter by creating a rect at (360, 260), then after the first rectangle is created, add 120 to the x value, until x >= 960. . Then I added 120 to y to create a new line and set x back to 360. . The kill tile collision was done the same way as the win tile collision, using tile ID’s. . The only issue I’ve come across is the music suddenyl not working after moving it into its own seperate file, despite it working like an hour before. . I’ve left this issue for tomorrow as I’ve already got a lot of hours under my belt today. . Also the new level is not possible despite all my effort so will have to change that also. . Good progress today, I’ve made a lit of all I want to achieve in Barrel Roll Bullet before the dedline and one by one, I’m checking that list of. . See you next devlog. Maybe then I’ll reveal the space in-between 💣︎♋︎■︎📬︎□︎♑︎♑︎"}, {"post_id": 38447, "ts": "2026-07-31T20:17:36Z", "hours": 2.0106, "text": "Dev Log #13.Unlucky for some, but not for me! . Collision resolution finally working!!!! . Here’s how it works: . SAT algorithm returns the axis with the smallest overlap (this is the shortest distance to separate the player and the tile). . Correct normal line direction so that it points from the tile to the player. . Move player across MTV (Minimum Translation Vector), pushing player out of the tile. Note: MTV is calculated by choosing the smallest overlap in the direction that moves the two shapes apart. . Remove velocity that is parallel to the collision surface, allowing the object to glide across it without getting stuck. . That’s the jist of it. There are some other things I didn’t include, like how only polygons are made for tiles touching the player’s polygon/rect, but I discussed this in a past dev log. . In all honesty, I don’t fully understand the maths behind it, but I was still able to make my own SAT collision system, so I obviously know enough. . Also added some smaller things like a bullet limit and a restart caused by holding the R button down. . This is good progress and should allow me to add more easily things like level select, new Tiled maps, new tile variants that cause different effects, etc. . Next dev log is going to be packed with stuff!!!!.See you then (;"}, {"post_id": 37832, "ts": "2026-07-30T19:46:46Z", "hours": 2.4217, "text": "#Dev Log 12 . Good honest session today. . Changed my collision resolution as it seemed to be causing me alot of trouble and hurting preformance. . Now using polygon collision detection instead of mask collision as it greatly improves preformance and simplicty of colllision resolution. . Although that is still not perfect. . I had it working quite well to a point but once I tried to prevent wall riding through on ground variables set to True or False, everyhting seemed to go wibledy wobeldy from there. . My collision detection works as follow: Dictionary of tiles is made, each tile with a rect and id (needed to make certain tile types do different things). . From that list, add the tiles with rectangles that colide with the player into a new list . 3.With this list, I then draw a mask on the tile, setting the co-ordinates to the corners of the rect . Last step, use self.polygon_collision() to check for collision . This worked without a hitch, but my collision resolution sytem is not so flawless. . This has been a 3ish day long ordeal, but I want to get it solved now so that once I’ve got the basics done I can divert my attention to more fun things like gun abilities, kill tiles, moving platforms, ect. . Progress is not necessarily slow, just stuck on one convoluted thing. I hope I get things sorted soon, this is starting to be a real de-motervator. . But I got that frisk undertale in me so I’ll stay DETERMINED!!!"}, {"post_id": 37179, "ts": "2026-07-29T18:07:52Z", "hours": 3.7003, "text": "Dev Log #11 . Not Good. Very NOT Good. . What I achieved today Victory tile added Aiming reticle completely destroyed Fixed aiming reticle Mask detection not working as intended Gun no longer stopping rotation on collision complete loss of sanity OK, fun. How did this all happen? . My aiming reticle misangling issue was caused by setting initial rotation angle to 15. I did this to increse rotation speed. . The issue being this caused my gun image to also be rotated 15 degrees, causing the barrel not to point to my mouse. . I solved the issue by making initial rotation angle to 0, only += it to = 15 once first shot had been fired. . The next issue I have yet to solve is collision resolution. . It had been an underlying issue for some time, and i still don’t yet know how to fix it. But in my attempt to fix it, I then broke my stop_rotation function, meaning rotation now continues despite collision. . Hope to fix these issues by next devlog, then also give my recoil a bit of calibrating as each bullet seems to be weaker than the last, i think this is caused by my collision resolution setting velocity to 0. . Next devlog will hopefully be more fruitful!"}, {"post_id": 36456, "ts": "2026-07-28T16:14:07Z", "hours": 3.5108, "text": "Dev log #10 . DOUBLE DIGITS!! . What I did today: Added a working pause menu Fixed start screen size Spruced up mask collisions An issue im having with my new and improved collision sytem is that when i reduce player velocity on collision, as well as rotation speed, my player comes to a hault. . In real life, as im sure many of you know, a gun isnt likely to ballance on the barrel verticly, its handle will fall due to being heavier. . I do not yet know how to combat this issue, but I have brain stormed some ideas. . I was going to try and find a center of mass, but that wouldn’t work because that would cause my barrel to float at times due to being disproportionally lighter compared to the gun grip, meaning when gravity acted on it, it would be lob sided. . My other idea was to break the gun into 3 rectangles, barrel, handel and inbetween, then give these rectangles set weights. But i was unable to implement that. . I’m going to try some other solutions, but i think this is going to be some of my toughest challenges yet! . Still undesided on the goals for next devlog, we will see what my brain decided that faithfull day."}, {"post_id": 35966, "ts": "2026-07-27T19:09:25Z", "hours": 3.4547, "text": "Dev Log #9 . Not the best keyboard clacking session, but not the worst. Looking at you Dev Log #4 >:[ . Today I added pixel perfect collision. . First I got the players mask and a list of the rectangle tiles touching my player rectangle. I then listed these rectangles and was able to detect collision based on if they made contact with the players mask. . The next step was collision resolution. . After a detected collision, the location of collision is then increase the y co-ordinate of the player mask, effectivly keeping the player above the ground. This is how collision resolution works for all the other directions, just with varying positions. . With this I then attempted to add a feature that stopped rotation as a surface was hit, to prevent a constanly spinning gun that sits on the floor. . This is still a WIP, but I have been able to make the gun stop all movement once on contact on a wall, but this is unrealistic as in real life if an object makes contact with a wall it does not loose all its momentum. . I will try to combat this isse by adding a bounce effect that gradually reduces momentum on wall contact, rather than causing it to loose all of it. . Next devlog I hope to have a working wall bounce system and maybe a finish goal that, when entered, plays a victory noise and victory screen. . Holding out hope for the future!!"}, {"post_id": 35259, "ts": "2026-07-26T15:42:00Z", "hours": 2.6272, "text": "Dev Log #8 . I new it was too good to be true, progress has slowed yet again. ): . Today I added: ‘Working’ collisions While my collisions ‘work’, they only work when my player rectangle is unchanged. . The issue being when my gun rotates, its rectangle changes size. . This change of size is interpreted as a movement by my collision sytem, therefore once I come in contact with a tile, the bottom of the rectangle slowly becomes bigger and smaller. . this caused it to move to the tops of different tiles, eventually causing it to be flung out of the game window at rapid speed. . I plan to combat this issue with either of these methods: . OPTION A: Pixel perfect collision done through player masks. . This option is harder and can effect preformance if not implemented properly, but with give a smooth and finished collision effect . OPTION B: Set hitbox collision . This option creates a set region on the player, only that region (probably a rectangle shape to make collision detection easy) being able to collide with tiles. . This option will likely be easier, but will look less pollished as the gun barrel would not fall due to gravity, it would stay above the ground while the grip sits on the ground. . My goals for next dev-log are unclear, but for now I hope to have a working collision system at least!!!"}, {"post_id": 34808, "ts": "2026-07-25T20:07:27Z", "hours": 2.8481, "text": "Dev Log #7 . Another prosperous coding session today! . I have added the following features: Correct bullet orientation Sound effects Tiled surface (no collisions) I also had to change the screen size as its height and length needed to be divisible by 16 in order for my tiles to be used easily. . I added the pytmx python library to allow me to use Tiled, a software that makes level creation very simple and quickly repeatable. . It should significantly increase my workflow speed when I get far enough in development to actually be making levels. . I also did some fine tuning on the strength of recoil, making it stronger but controllable. . Additionally, I increased the speed at which the gun rotates in air to make aiming more difficult but still manageable. . Overall, 7/10 work day today. . By next devlog I hope to have some of the following complete: Working collision Finish goal that takes you to the next level Possible moving colidable tile Bullet limit and UI to show this I’m back in business now, regained most of the knowledge I lost from my 1 week hiatus. Wishing future me luck for the next devlog! . And all you others out there as well. STAY DETERMINED!!!!!"}, {"post_id": 34255, "ts": "2026-07-24T19:58:07Z", "hours": 3.2694, "text": "Dev Log #6 . I have made some absolute serious progress!! . I have added: . Working recoil In-air gun rotation Aiming phase and playing phase (turning aiming guide on and off) Dotted aiming guide This has by far been my best coding session as of late and had little to no complications… . Well there was one… Where my entire recoil system was built on mouse position, a mouse which only controls the direction of the bullet once and never again per level. . So that caused me some grief. But I was able to calculate recoil based on the bullet’s movement rather than the mouse’s position. . A bullet which would spawn and move forward from the barrel despite orientation, solving my problem and making the rest of the other features added much simpler to implement. . In the next few dev logs I hope to have added the following: . Make bullet orientation match barrel orientation Add a start menu soundtrack Bullet trail Sound effects (e.g. gunshot, start button pressed) Complete level (with collisions) I hope progress continues at the rate it is, because if so, I will be drowning in stardust."}, {"post_id": 33415, "ts": "2026-07-23T10:41:34Z", "hours": 1.5733, "text": "Dev Log #5 . I have redeemed myself 10 fold. I have finally added recoil to my game!!!! . This moment shows real progress. I have been trying to implement recoil for a while now, and I have finally done it. . I did this by using the velocity I calculated to determine what direction and what speed bullets are shot at from the gun: def __init__(self, barrel_pos, m_pos): super().__init__() self.image = pygame.image.load(\"Images/BULLET.png\").convert_alpha() self.rect = self.image.get_rect(center=barrel_pos) direction = pygame.Vector2( m_pos[0] - barrel_pos[0], m_pos[1] - barrel_pos[1] ) if direction.length() > 0: direction = direction.normalize() self.velocity = direction * 10 Passing the velocity into my player group and subtracting it from the player’s centre, effectively creating movement opposite to the direction of the bullets, aka recoil!!! def recoil(self, velocity): self.recoiled = velocity self.rect.x -= (self.recoiled.x * 10) self.rect.y -= (self.recoiled.y * 10) I also made it so that bullets despawn once off-screen, optimising performance. . Finally, I re-ordered my code, making debugging and overall readability much easier. . While my recoil is not fully complete, this is a large step in the right direction. . I hope by the next devlog I have a fully working recoil system and possibly a working level. Who knows! . Aim for the stars and you’ll at least reach the moon."}, {"post_id": 33031, "ts": "2026-07-22T16:18:00Z", "hours": 5.3169, "text": "Dev Log Number 4 . With the amount of time logged, you would think a lot has been achieved. But no… . After an almost 2 week long holiday induced hiatus, it seemed I had lost my confidence with pygame, and at some points, felt like i had lost my brain entirely. . My attempt to add shootable bullets should have been a simple task, yet it seemed to be impossible. And its not like I could have packed up shop and tried something else, a shootable bullet is esential for a game where the only playable charcater is, well, A GUN! . The first challenge was getting the bullet to spawn from the correct location. Initially, the bullets appeared from the centre of the gun rather than the barrel. Obviously that was not the intent. . I eventually solved the issue (casued by my own ignorance) and passed the barrel position calculated previously into my bullet class rather than re-calculating this (why would i do this, what on earth was I thinking 😩) . With that issue conquered, i then had to do the maths required to shoot a bullet from the barrel to the position of the mouse. Easy enough. NOT. . To cut a long story short, I used the code attatched to finally make my gun work. . My shootable bullets are far from perfect, they sometimes don’t shoot at all even when the mouse is pressed, their orientation does not match the direction the gun is facing and they are far too small. . I plan to fix this by: killing bullets as they go offscreen, adding some sort of rotation to the bullets and for the bullets not being shot when intended, i have no real plan on how I’m going to fix that. . I hope I come back to you in the next dev log with some actually real progress, because this is a sad excuse. . But with determination and grit and endless scrolling of the pygame documentation, I am sure progress will come as fast as a speeding train [or some sort of blue mammal with quills (^_~)]"}, {"post_id": 24165, "ts": "2026-07-07T15:40:34Z", "hours": 2.0261, "text": "Dev log #3 . Today I got a bit sidetracked and decided to move all of my code within a sprite class to reduce clutter. As a newbie, this was my greatest challenge (besides my arch enemy recoil physics). . This process was tedious and caused my entire code to break completely on multiple occasions. But the risk and complication was worth the reward. I reduced my codes line count by 15. . Due to the length of this process, very little was added. However, I did manage to add a aiming reticle for your first initial shot of the gun. . As seen in the images below, this feature came with its own plethora of annoyances. Annoyances such as multiplying rapidly and staying fixed on the gun trigger rather than the barrel. . I also created a new gun sprite that now faced the mouse correctly. . In the next dev log, I hope I come bearing more features. . I plan to add: .Basic bullet firing .Dotted aiming line instead of solid .Player start game (in which gravity will be applied) .NOT recoil, sadly that will have to wait . Went back to my roots today and used my beginner tutorial to help me learn how to apply the sprite class, video linked here: https://youtu.be/AY9MnQ4x3zk?si=9UtUnmyWYpsHZ6d5 . While the sprite class has acted as a roadblock to speed of development, I believe that by the next devlog, my progress will be sure to amaze (I say with confidence 🤞)"}, {"post_id": 23525, "ts": "2026-07-06T15:26:32Z", "hours": 2.0483, "text": "Dev Log #2 – Start and Turn . Now with the basics ingrained in my head, my game is beginning to take shape. While I wasn’t able to add the recoil mechanics I had hoped for, I was able to: .Create a functioning start screen. .Make my player sprite follow the mouse direction. . Today I used a different tutorial to assist me, linked here: https://youtu.be/WnIycS9Gf_c?si=UhNQQ8ekJLdPhRZO . While these are small achievements, they will help build a much greater finished product. Thanks to implementing these new features, I now understand the importance of game states and how to apply them, as well as how to track mouse movement and mouse input. . The reason I implemented sprite rotation based on mouse direction was to allow the player to aim their initial shot and determine their trajectory. . Later, the player will have to use well-timed shots to control their direction rather than relying on this simpler aiming system, making my game’s movement feel more unique and rewarding fast reaction times. . By the next dev log, I hope to create a new gun sprite that follows the mouse correctly, make a shootable bullet, and finally implement the recoil effect when the gun is fired, although this still seems to be my biggest hurdle. . Progress is picking up pace. Every new feature is another lesson learned, helping build the foundations of what I hope will become my magnum opus. See you in the next dev log. ;)"}, {"post_id": 22879, "ts": "2026-07-05T14:44:05Z", "hours": 2.0386, "text": "Dev Log #1 – Grasping the Basics of Pygame . Since I’m new to Pygame, my first goal has been learning the fundamentals and applying them to build the foundations of my game. . So far I’ve implemented: . .Basic gravity .Collision detection with the floor .Upward player movement using mouse input .Loading and displaying sprites and backgrounds . Building these simple features helped me understand how the game loop works, how collision is detected using rectangles, and how offsetting the player’s y-coordinate can be used to create gravity. . At the moment, the player is represented with a placeholder sprite, as my focus is on the code behind my game (and art has never been my strong suit). . I’ve been using the following tutorial, a learning resource that has helped me greatly: . https://youtu.be/AY9MnQ4x3zk?si=x9KrrOI12N1CwT29 . Now that I have an understanding of the basics, I’m going to start moving towards creating the mechanics required for the actual game. . My goal before the next dev log is to have a basic title screen completed and, if possible, implement the recoil mechanic for my player. . Progress is slow at the moment, but every feature I build teaches me something new. Hopefully, the next update will be bigger and come together more quickly (as long as all goes well 🤞)."}]...
|
Title: Barrel Roll Bullet by @ShinyMist | Stardanc Title: Barrel Roll Bullet by @ShinyMist | Stardance
Devlogs:
Dev Log #1 – Grasping the Basics of Pygame . Since I’m new to Pygame, my first goal has been learning the fundamentals and applying them to build the foundations of my game. . So far I’ve implemented: . .Basic gravity .Collision detection with the floor .Upward player movement using mouse input .Loading and displaying sprites and backgrounds . Building these simple features helped me understand how the game loop works, how collision is detected using rectangles, and how offsetting the player’s y-coordinate can be used to create gravity. . At the moment, the player is represented with a placeholder sprite, as my focus is on the code behind my game (and art has never been my strong suit). . I’ve been using the following tutorial, a learning resource that has helped me greatly: . https://youtu.be/AY9MnQ4x3zk?si=x9KrrOI12N1CwT29 . Now that I have an understanding of the basics, I’m going to start moving towards creating the mechanics required for the actual game. . My goal before the next dev log is to have a basic title screen completed and, if possible, implement the recoil mechanic for my player. . Progress is slow at the moment, but every feature I build teaches me something new. Hopefully, the next update will be bigger and come together more quickly (as long as all goes well 🤞).
Dev Log #2 – Start and Turn . Now with the basics ingrained in my head, my game is beginning to take shape. While I wasn’t able to add the recoil mechanics I had hoped for, I was able to: .Create a functioning start screen. .Make my player sprite follow the mouse direction. . Today I used a different tutorial to assist me, linked here: https://youtu.be/WnIycS9Gf_c?si=UhNQQ8ekJLdPhRZO . While these are small achievements, they will help build a much greater finished product. Thanks to implementing these new features, I now understand the importance of game states and how to apply them, as well as how to track mouse movement and mouse input. . The reason I implemented sprite rotation based on mouse direction was to allow the player to aim their initial shot and determine their trajectory. . Later, the player will have to use well-timed shots to control their direction rather than relying on this simpler aiming system, making my game’s movement feel more unique and rewarding fast reaction times. . By the next dev log, I hope to create a new gun sprite that follows the mouse correctly, make a shootable bullet, and finally implement the recoil effect when the gun is fired, although this still seems to be my biggest hurdle. . Progress is picking up pace. Every new feature is another lesson learned, helping build the foundations of what I hope will become my magnum opus. See you in the next dev log. ;)
Dev log #3 . Today I got a bit sidetracked and decided to move all of my code within a sprite class to reduce clutter. As a newbie, this was my greatest challenge (besides my arch enemy recoil physics). . This process was tedious and caused my entire code to break completely on multiple occasions. But the risk and complication was worth the reward. I reduced my codes line count by 15. . Due to the length of this process, very little was added. However, I did manage to add a aiming reticle for your first initial shot of the gun. . As seen in the images below, this feature came with its own plethora of annoyances. Annoyances such as multiplying rapidly and staying fixed on the gun trigger rather than the barrel. . I also created a new gun sprite that now faced the mouse correctly. . In the next dev log, I hope I come bearing more features. . I plan to add: .Basic bullet firing .Dotted aiming line instead of solid .Player start game (in which gravity will be applied) .NOT recoil, sadly that will have to wait . Went back to my roots today and used my beginner tutorial to help me learn how to apply the sprite class, video linked here: https://youtu.be/AY9MnQ4x3zk?si=9UtUnmyWYpsHZ6d5 . While the sprite class has acted as a roadblock to speed of development, I believe that by the next devlog, my progress will be sure to amaze (I say with confidence 🤞)
Dev Log Number 4 . With the amount of time logged, you would think a lot has been achieved. But no… . After an almost 2 week long holiday induced hiatus, it seemed I had lost my confidence with pygame, and at some points, felt like i had lost my brain entirely. . My attempt to add shootable bullets should have been a simple task, yet it seemed to be impossible. And its not like I could have packed up shop and tried something else, a shootable bullet is esential for a game where the only playable charcater is, well, A GUN! . The first challenge was getting the bullet to spawn from the correct location. Initially, the bullets appeared from the centre of the gun rather than the barrel. Obviously that was not the intent. . I eventually solved the issue (casued by my own ignorance) and passed the barrel position calculated previously into my bullet class rather than re-calculating this (why would i do this, what on earth was I thinking 😩) . With that issue conquered, i then had to do the maths required to shoot a bullet from the barrel to the position of the mouse. Easy enough. NOT. . To cut a long story short, I used the code attatched to finally make my gun work. . My shootable bullets are far from perfect, they sometimes don’t shoot at all even when the mouse is pressed, their orientation does not match the direction the gun is facing and they are far too small. . I plan to fix this by: killing bullets as they go offscreen, adding some sort of rotation to the bullets and for the bullets not being shot when intended, i have no real plan on how I’m going to fix that. . I hope I come back to you in the next dev log with some actually real progress, because this is a sad excuse. . But with determination and grit and endless scrolling of the pygame documentation, I am sure progress will come as fast as a speeding train [or some sort of blue mammal with quills (^_~)]
Dev Log #5 . I have redeemed myself 10 fold. I have finally added recoil to my game!!!! . This moment shows real progress. I have been trying to implement recoil for a while now, and I have finally done it. . I did this by using the velocity I calculated to determine what direction and what speed bullets are shot at from the gun: def __init__(self, barrel_pos, m_pos): super().__init__() self.image = pygame.image.load("Images/BULLET.png").convert_alpha() self.rect = self.image.get_rect(center=barrel_pos) direction = pygame.Vector2( m_pos[0] - barrel_pos[0], m_pos[1] - barrel_pos[1] ) if direction.length() > 0: direction = direction.normalize() self.velocity = direction * 10 Passing the velocity into my player group and subtracting it from the player’s centre, effectively creating movement opposite to the direction of the bullets, aka recoil!!! def recoil(self, velocity): self.recoiled = velocity self.rect.x -= (self.recoiled.x * 10) self.rect.y -= (self.recoiled.y * 10) I also made it so that bullets despawn once off-screen, optimising performance. . Finally, I re-ordered my code, making debugging and overall readability much easier. . While my recoil is not fully complete, this is a large step in the right direction. . I hope by the next devlog I have a fully working recoil system and possibly a working level. Who knows! . Aim for the stars and you’ll at least reach the moon.
Dev Log #6 . I have made some absolute serious progress!! . I have added: . Working recoil In-air gun rotation Aiming phase and playing phase (turning aiming guide on and off) Dotted aiming guide This has by far been my best coding session as of late and had little to no complications… . Well there was one… Where my entire recoil system was built on mouse position, a mouse which only controls the direction of the bullet once and never again per level. . So that caused me some grief. But I was able to calculate recoil based on the bullet’s movement rather than the mouse’s position. . A bullet which would spawn and move forward from the barrel despite orientation, solving my problem and making the rest of the other features added much simpler to implement. . In the next few dev logs I hope to have added the following: . Make bullet orientation match barrel orientation Add a start menu soundtrack Bullet trail Sound effects (e.g. gunshot, start button pressed) Complete level (with collisions) I hope progress continues at the rate it is, because if so, I will be drowning in stardust.
Dev Log #7 . Another prosperous coding session today! . I have added the following features: Correct bullet orientation Sound effects Tiled surface (no collisions) I also had to change the screen size as its height and length needed to be divisible by 16 in order for my tiles to be used easily. . I added the pytmx python library to allow me to use Tiled, a software that makes level creation very simple and quickly repeatable. . It should significantly increase my workflow speed when I get far enough in development to actually be making levels. . I also did some fine tuning on the strength of recoil, making it stronger but controllable. . Additionally, I increased the speed at which the gun rotates in air to make aiming more difficult but still manageable. . Overall, 7/10 work day today. . By next devlog I hope to have some of the following complete: Working collision Finish goal that takes you to the next level Possible moving colidable tile Bullet limit and UI to show this I’m back in business now, regained most of the knowledge I lost from my 1 week hiatus. Wishing future me luck for the next devlog! . And all you others out there as well. STAY DETERMINED!!!!!
Dev Log #8 . I new it was too good to be true, progress has slowed yet again. ): . Today I added: ‘Working’ collisions While my collisions ‘work’, they only work when my player rectangle is unchanged. . The issue being when my gun rotates, its rectangle changes size. . This change of size is interpreted as a movement by my collision sytem, therefore once I come in contact with a tile, the bottom of the rectangle slowly becomes bigger and smaller. . this caused it to move to the tops of different tiles, eventually causing it to be flung out of the game window at rapid speed. . I plan to combat this issue with either of these methods: . OPTION A: Pixel perfect collision done through player masks. . This option is harder and can effect preformance if not implemented properly, but with give a smooth and finished collision effect . OPTION B: Set hitbox collision . This option creates a set region on the player, only that region (probably a rectangle shape to make collision detection easy) being able to collide with tiles. . This option will likely be easier, but will look less pollished as the gun barrel would not fall due to gravity, it would stay above the ground while the grip sits on the ground. . My goals for next dev-log are unclear, but for now I hope to have a working collision system at least!!!
Dev Log #9 . Not the best keyboard clacking session, but not the worst. Looking at you Dev Log #4 >:[ . Today I added pixel perfect collision. . First I got the players mask and a list of the rectangle tiles touching my player rectangle. I then listed these rectangles and was able to detect collision based on if they made contact with the players mask. . The next step was collision resolution. . After a detected collision, the location of collision is then increase the y co-ordinate of the player mask, effectivly keeping the player above the ground. This is how collision resolution works for all the other directions, just with varying positions. . With this I then attempted to add a feature that stopped rotation as a surface was hit, to prevent a constanly spinning gun that sits on the floor. . This is still a WIP, but I have been able to make the gun stop all movement once on contact on a wall, but this is unrealistic as in real life if an object makes contact with a wall it does not loose all its momentum. . I will try to combat this isse by adding a bounce effect that gradually reduces momentum on wall contact, rather than causing it to loose all of it. . Next devlog I hope to have a working wall bounce system and maybe a finish goal that, when entered, plays a victory noise and victory screen. . Holding out hope for the future!!
Dev log #10 . DOUBLE DIGITS!! . What I did today: Added a working pause menu Fixed start screen size Spruced up mask collisions An issue im having with my new and improved collision sytem is that when i reduce player velocity on collision, as well as rotation speed, my player comes to a hault. . In real life, as im sure many of you know, a gun isnt likely to ballance on the barrel verticly, its handle will fall due to being heavier. . I do not yet know how to combat this issue, but I have brain stormed some ideas. . I was going to try and find a center of mass, but that wouldn’t work because that would cause my barrel to float at times due to being disproportionally lighter compared to the gun grip, meaning when gravity acted on it, it would be lob sided. . My other idea was to break the gun into 3 rectangles, barrel, handel and inbetween, then give these rectangles set weights. But i was unable to implement that. . I’m going to try some other solutions, but i think this is going to be some of my toughest challenges yet! . Still undesided on the goals for next devlog, we will see what my brain decided that faithfull day.
Dev Log #11 . Not Good. Very NOT Good. . What I achieved today Victory tile added Aiming reticle completely destroyed Fixed aiming reticle Mask detection not working as intended Gun no longer stopping rotation on collision complete loss of sanity OK, fun. How did this all happen? . My aiming reticle misangling issue was caused by setting initial rotation angle to 15. I did this to increse rotation speed. . The issue being this caused my gun image to also be rotated 15 degrees, causing the barrel not to point to my mouse. . I solved the issue by making initial rotation angle to 0, only += it to = 15 once first shot had been fired. . The next issue I have yet to solve is collision resolution. . It had been an underlying issue for some time, and i still don’t yet know how to fix it. But in my attempt to fix it, I then broke my stop_rotation function, meaning rotation now continues despite collision. . Hope to fix these issues by next devlog, then also give my recoil a bit of calibrating as each bullet seems to be weaker than the last, i think this is caused by my collision resolution setting velocity to 0. . Next devlog will hopefully be more fruitful!
#Dev Log 12 . Good honest session today. . Changed my collision resolution as it seemed to be causing me alot of trouble and hurting preformance. . Now using polygon collision detection instead of mask collision as it greatly improves preformance and simplicty of colllision resolution. . Although that is still not perfect. . I had it working quite well to a point but once I tried to prevent wall riding through on ground variables set to True or False, everyhting seemed to go wibledy wobeldy from there. . My collision detection works as follow: Dictionary of tiles is made, each tile with a rect and id (needed to make certain tile types do different things). . From that list, add the tiles with rectangles that colide with the player into a new list . 3.With this list, I then draw a mask on the tile, setting the co-ordinates to the corners of the rect . Last step, use self.polygon_collision() to check for collision . This worked without a hitch, but my collision resolution sytem is not so flawless. . This has been a 3ish day long ordeal, but I want to get it solved now so that once I’ve got the basics done I can divert my attention to more fun things like gun abilities, kill tiles, moving platforms, ect. . Progress is not necessarily slow, just stuck on one convoluted thing. I hope I get things sorted soon, this is starting to be a real de-motervator. . But I got that frisk undertale in me so I’ll stay DETERMINED!!!
Dev Log #13.Unlucky for some, but not for me! . Collision resolution finally working!!!! . Here’s how it works: . SAT algorithm returns the axis with the smallest overlap (this is the shortest distance to separate the player and the tile). . Correct normal line direction so that it points from the tile to the player. . Move player across MTV (Minimum Translation Vector), pushing player out of the tile. Note: MTV is calculated by choosing the smallest overlap in the direction that moves the two shapes apart. . Remove velocity that is parallel to the collision surface, allowing the object to glide across it without getting stuck. . That’s the jist of it. There are some other things I didn’t include, like how only polygons are made for tiles touching the player’s polygon/rect, but I discussed this in a past dev log. . In all honesty, I don’t fully understand the maths behind it, but I was still able to make my own SAT collision system, so I obviously know enough. . Also added some smaller things like a bullet limit and a restart caused by holding the R button down. . This is good progress and should allow me to add more easily things like level select, new Tiled maps, new tile variants that cause different effects, etc. . Next dev log is going to be packed with stuff!!!!.See you then (;
#Dev Log 14 . Ying ang Yang session today: . I did the following: 2 new maps - one I’m keeping a secret for the complete game >;] Level select rect load (not working YET) Kill tile (detection only) Separating code into files outside of main Music Broke…. Level select menu was a perfect mix of challenge and enjoyability. . I loaded the squares in this even patter by creating a rect at (360, 260), then after the first rectangle is created, add 120 to the x value, until x >= 960. . Then I added 120 to y to create a new line and set x back to 360. . The kill tile collision was done the same way as the win tile collision, using tile ID’s. . The only issue I’ve come across is the music suddenyl not working after moving it into its own seperate file, despite it working like an hour before. . I’ve left this issue for tomorrow as I’ve already got a lot of hours under my belt today. . Also the new level is not possible despite all my effort so will have to change that also. . Good progress today, I’ve made a lit of all I want to achieve in Barrel Roll Bullet before the dedline and one by one, I’m checking that list of. . See you next devlog. Maybe then I’ll reveal the space in-between 💣︎♋︎■︎📬︎□︎♑︎♑︎
#Dev Log 15 . Good day at the office. . Did the following today: Working level select Fixed Music Issue Fixed map loading issues (didn’t discover until today) Added tile classes to replace gid based system for tile specific collision My issues today were caused by my moving of code into separate files, but I’m getting there. I’m no longer using from ___ import * and I am instead using import ______. . The sound issue was caused by a variable in settings setting play music to False without my knowledge. . Map loading broke because my maps are only loaded once outside of the while loop, so I fixed that. . Tiles now have a class that can be checked, allowing for different interactions with tiles dependent on tile class. . Thinking about storing some of my variables into match statements for readability but I find using match cases in Settings.py to be really difficult so I will proceed with caution and immense fear!!! . Not sure what tomorrow holds, thinking about making the kill and win tiles do something rather than print win or killed, but might be held up by this switch from many elifs to match cases. . Staying determined, see you next dev log. . PS, a little hint to my little easter egg 📂︎🖮︎
Dev Log #16 . Today was good. I was welmed. . I did the following today: Added working kill tile Fixed image lagging behind player polygon Switched over to match cases Kill tile works as intended, but doen’t ‘kill’ the player yet, it just freezes everything, plays a sound and propts you to restart. . Image lagging behind was a big issue, causing the kill tile to look as if it were killing without contact, but this was cause by the image lag behind. . I tried changing the order of functions in update() but that didn’t work, tried other stuff like changing how some functions work, in the end, it was because i called update after player_group.draw(). Silly me!! . Match case switch over was easy, just the indentation was at times a pain, but I’ve sorted it now, thank goodness! . Going to try and finish the loss screen that appears, adding a level select button and a return to start, but might not as its not strictly necessary, but does look nice. . Not sure what other stuff to add, maybe a new level? . Who knows, see you next Dev Log!!!!
Dev Log #17 . Feel kinda stuck in-between, but once a pass my last hurdle, all of my efforts will be focused on new abilities, new tiles and art, but the basics are sooo close to being complete. . Today i did the following: Level stopwatch Level complete goal changed Edited map Complete goal had to be changed to make animation of win goal possible, like coin pick up in Mario. Uses polygon collision, freezes on contact currently but working on fix. . Level stopwatch works well, and works with pause menu by subtracting time passed in pause menu from counter total on continue button pressed. . Map needed editing as I feel my game is too hard and my muscle memory from 100’s of tries makes it feel easy, but really isn’t. . Tried making a new map that requires you to collect many little stars to reveal the goal but found it hard to find a map that works with wide range of movement. . This issue is caused by gun being useless most of the time on collision with floor as it is aimed the wrong way. . I plan to have the player be able to rotate the gun while its grounded using A or D, this re-ajusting stopping players getting stuck. That or a jump ability. . Next devlog hope to have: Mini stars working New map Rotate/jump when grounded Game in progress music See you next devlog, no 1 day hiatus next time (;
Dev Log #18 . Good day, but stopped early today beacuse, well, i’m afraid… . What I did today: Added mini_stars Added re-align option when grounded Added new map Mini stars are to be collected first, unlocking the finish goal. They are hard coded right now so cant be moved for new levels, but I can change that if need be. . Re-align was initially supposed to allow A to rotate the player one direction and D the other, but my game seemed to really not like decreasing the angle value when grounded. . So I’ve made it so rotation only happens one direction, but a full 360 range of motion is possible. . The new map that uses portals, but the portals are not actually functional yet so, thats a job for tomorrow . . Almost everything added from last devlogs check list, but decided against adding placeholder music during playing state as i think I would go insane from listening to it on loop, so that can wait till the end. . Hope to have a longer more prosperous dev log next time, see you then!!!
Dev Log #19 . Getting lazy, need to lock in and get 3 hours tomorrow. . Today I added: Working portals Time stop ability Portals and time stop ability use object layers in tiles, a much easier solution compared to my use of polygons for complete goals, may change that but not sure. . Time stop ability is pretty simple, works like pause menu, but allows image rotation and enables follow mouse. . Portals work by on contact, moving player position centre to other portal centre. . The velocity changes with the exit direction using the following code: rotation_difference = entry_angle - exit_angle self.velocity.rotate_ip(rotation_difference) Overall, ok day, not sure what I’ll do tmr, but I’m sure theres something hiding on my checklist. . ALSO!!, Fix this horrible performance issue I had, see bellow for comparison
Dev Log #20 . Sorry for the hiatus, not a lot done, but sure I will be soaring tomorrow. . Today I addded: Killable enemies New reset all function Killable enemies act as win conditions, similar to the mini stars, having to all be killed for the goal polygon to spawn. . The reset function made my code much more readable and allowed me to condense all of the restart events like lose velocity, set position here, screen.blit things again if needed. . I started working on 3 buttons that when pressed, open a gate but didn’t get to finishing it sadly. . I want each button to have different press conditions, one can be pressed by bullets only, one only on direct gun contact and the other working with either or. . In later stages, I will have to think how i will communicate this functionality to the player but I’m saving texturing and making the game look good for last. . Hope to have more progress tomorrow. Fingers crossed.
Dev Log #21 . Getting lazy now, saw hacktime was down and decided not to bother doing anything before 12, but I hope I will break this cycle. . Today I added working buttons that when pressed, remove gate blocking path. . Had to over hall all my tile loading and map loading and parts of my collision resolution to allow me to reduce the lag being caused in some levels and be able to remove collision selectively for tile types. . I learn how to use set today. I used a set to store the types of gates that have been opened because it prevents duplicates and allows me to quickly check whether a specific gate is open. . No animations for button presses yet as I want to leave that stuff for the end. . I’m feeling the time crunch now because I really want this to be finished before I get back to school and focus on my studies, but this still counts as practice so I’ll continue a little bit during school days. . I will do better tomorrow I promise, cause I’ve got this far, it would be a waste to stop now.
Dev log #22 . Back to business!! . Today I added: Uncompleted level select lockout Separated tile load into own file Easter egg room added Level lockout works by calculating max_player_level, the furthest level a player can select based on if they have beat the previous levels. . This works buy using a function to check if current player_level is greater than max_player_level, if it is then max_player_level = player level. . Then for level select button with number greater than max_player_level, a red cross is screen.blited ontop,as well as not allowing mouse clicks of the rect from having any function. . Tile file separation helped me remove 150 lines from my main file, improving readability. . My easter egg has a 2% chance of happening and gives the player a custom gun appearance on discovery. . The code used to change the guns appearenece should let me, in future, make custom skins for the gun, skins that could be rewarded for levels complete, secondary level goals reached, ect… . I will not share how to reach my secret room, but I think it would be better for someone to stumble across it by accident. . Good day today, progress is picking up pace again, good job me!!! . Strange, it seems, there is a man here….
Dev Log #23 . Very good day today, embracing the foddian likeness of my game, making sure that the player gets as angry as possible, just to make that feeling of victory feel so sweet. . Here’s what I did today: LOSER document created (must be filled in to reveal hints, which will be added later) Change rotation direction ability New map (Still a WIP) Document uses follow mouse function and draw line function. Starting the line at the mouses previous position and ending it at its new position. . This happens very fast, so the lines do not appear blocky and appear like real pencil drawing. . The change rotation ability uses the pbject layer like my previous time stop ability, and now that I understand how object layers work, i was easily able to make this ability by copying my clock abiltiy load and changing the result of contact. . The result being making rotation speed negative, reversing direction of rotation. . The new map uses a mix of many abilities and objects, but I have not added them in just yet. . I could quite easily I feel but I’ve reached my 3 hour brain capacity limit, because realisticly with the time spent making pngs, finding sounds, reading pygame documentation and waching tutorials, I’ve probably spent about 5. . But rewards are not for the weak or the lazy, and this little project of mine is helping me leaps and bounds for my future A-level comp sci journey. . See you next time, with some jucy new progress!!!!
Dev Log #24 . A progress full day today, but mabye not for the best?? . Today I done the following: Added a charcater diologue box Fixes re-align function so that it works when rotation direction is reversed Just doing little sidequests for now as I’m trying to hide from my enemy, level design. The things is I’m not very good at games, so i dont have the reaction time to create very punishing levels with little room for error. . So to combat this, I end up making really hard levels or super easy ones. . Additionally, I barley add any time to my total when creating levels as it uses a piece of software outside of visual studio. . My character text box is pretty much a recreation of the ones seen in undertale, even using the voice blip of toriel as a place holder. . This should allow me to add a small story that I will make sure to keep simple, like a mario esque plot. . The re-align function was fixed by using the variable rotation direction, then setting that to 1 or -1 depending on contact with reverse direction ability or not . Then multiplying rot_speed by that value reverse the direction that re-align moves. . I will have to knuckle down on level design tomorrow and make sure each level introduces the abilities and tiles one at a time, letting the player get used to them, allowing for levels that include a mix of multiple to be more approachable.
Dev Log #25 . My love for videojuegos has got the better of me. . Over theses 2 days all I have done is made some level maps and fixed the spawing positions of both win condition and the player based on the new maps. . But I have structure now, and rather than geting destracted, I have set myself some goals to complete hopefully by the end of the month, leaving me time to make the UI look nice. . I present to you. THE TOD0 LIST: . A - DIOLOGUE Fix dialogue system Add hint dialogue Add new level dialogue Add completed dialogue B - ABILITIES/TILES Bullet Pickup Ghost bullets Teleport bullets Time SLOW (not stop) Gravity flip ? Map flip ? Breakable tiles Level editor ? C - UI James bond level start animation Gun skin menu All menus with all required buttons D - Miscellaneous Mission objectives (Bad piggies esque) Determine gun skin unlock criteria A FINAL BOSS !?!?! I hope tomorrow if filled with WAY more advancements of the work kind rather than the Minecraft kind (;
Dev Log #26 . Popped ULT today!!! . Today I added the following: Slow time ability Breakable surfaces Bullet pickup Fixed up dialogue system (Not fully complete) Slow time ability works by setting a time to a decimal then multplying the following by it: Velocity (Bullet + Player) Rotation speed Gravity strength Multiplying by a decimal reduces the numbers, emulating slowed time rather than reducing fps which is a bit of a cop-out . Breakable surfaces work similarly to the gate tiles, the tiles having a alpha value of 0 when bullet rect makes contact with tile of that class and adding that tile type to a list: broken_tiles. . All tiles in that list are then ignored by tile collision . Bullet pickup works by detecting rect collision between the player and the surface, when contact is made the players bullet count (representing bullets shot total) is reduced by one, increasing the number of shots available to the player by one. . Dialogue system now works with full words, voice blips are annoying but will fix late stage when adding polish. Will also make it that player has to click mouse to go to next dialogue screen to give them time to read the text. . That is 3 and a bit things of the list, very good progress, juggling summer work, this and most importantly my Minecraft duties has been an upward hill battle but I’m getting there. . See you next develop with more progress!!!
Dev Log #27 . More things checked of the list today: . Today I did: Added gravity flip ability Added teleport bullets Added player mission objectives However, some other things i worked on today are still a work in progress, such as: Diologue system Ghost bullets (travel through walls) Gravity flip works similarily to how slow time works, settings the variable self.gravity_flip to -1 on contact, then multiplying graivty strenght by it, reversing the direction of gravity . This however made my realign function not work when on the ceiling, so i added to re-align that if gravity_flip was negative, to detect ceiling hit rather than grounded, allowing it to work why gravity was flipped. . Teleport bullets work by setting a can teleport function to True on contact, then when true, if bullet collidesrect with tile, self.rect of bullet is equal to self.rect of gun. the can tele[port function is then set to false, making the ability only work once as intended. . Player mission objects are as follows: Complete level Complete level in set ammount of time Complete level with less bullets than provided This uses lists in a way i have never used them before and looks like this total_stars = 0 level_stars = [[False, False, False] for _ in range(levels)] If player completes level, level_stars[Settings.player_level - 1][0] for current player level is set to True. . If player completes level quickly (complete_time < bonus_time), then …[1] is set to true . If player reaches has_won game state with a number of bullets lower than the bullet max, then then …[2] is set to True. . Total stars is incremented by one for each goal completed, and if level_stars[Settings.player_level - 1][1,2 or 3] is already set to true, then the increment is skipped, meaning you can only get 3 stars per level. . That’s all for now, hope to fix the issues I had today in tomorrows devlog!!
Dev Log #28 . Didn’t do alot today, or for the 2 other days… . I finally made ghost bullets work correctly and have changed the dialogue sytem a bit . The ghost bullets working and not working previously was juts a matter of using variables inside the bullet class rather than global ones, making it work better for some reason, I had the assistance of a friend in fixing the issue, and safe to say it solved it . Dialogue sytem has only been changed slightly so not much point documenting the changes, spacing, timing of letters, ect. . Sorry for short devlog, I hope I have more tommorrow.
Dev Log #29 . I’m pretty close to finishing the code side of my game now, the rest of my efforts will soon be focous toward things like: Writing dialogue Making nicer looking UI Making tiles look good rather than coloured blocks Animations Music Today I did the following: Re made the dialogue system AGAIN Created a gun selection screen My dialogue system displays a word at a time and plays a short noise for each word shown, similarily to undertale voice blips. However, I think it sounds quite bad and I plan to replace it with a set dialogue sound that plays at the start, like animal crossing. . My dialogue system now plays on level start and level completion, and does not re-trigger on level repeat, using similar code used in my star tracking code. . Gun select code is similar to my level select code, using a different class but the same code, just changing the lock out code to only unlock once star count is >= button number - 1 * 6, so that each button is unlocked for each 6 stars earned, as well as having the default gun already unlocked. . That’s all for today, I hope to have a complete game by the end of the month so I can have this finished before the school year starts.
Dev Log #30 . The big 30!!! . Done quite a bit today, just last bit of polishing and then we move towards UI, music, level design, ect. . Today I: FINISHED THE DIALOGUE SYTEM Added a leave waiver button (was a softlock) Added a text box to waiver [WIP] Dialogue system works fully (minus sound but thats still a win in my books). Plays on level start and level completion and once dialogue is viewed by the player, it is not shown to them again. . Mouse can be clicked to remove dialogue from the screen, without triggering bullet fire. . Also fixed the issue of the text backround being displayed on re-entry and re-completion of the level, but fixed that easily with a variable, setting it to true or false if level had already been completed, then only displaying the text bg when it was true. . Waiver leave button pretty simple, basic pygame rect collidepoint detection. . Text box sets text_active to true on mouse click, mouse clicks anywhere else set it to false, meaning player can only type when they have clicked on it (when they want to). . I appened every event.unicode into a list on key press, meaning I had a list of the players key storkes, then screen.blitted each letter in the list. . Final touches are making all fields complete required to acess button that is a hyperlink to video of me completing stages with instuctions to help, and also backspace and enter and wordwrap working with the text_box. . Then I think I’m done for the most part on the coding side of things, and will move onto level creation. . The only thing I haven’t completed from my long list from a preious dev_log are: Level editor Upside down ability James bond level start Hint dialogue on multiple deaths Boss fight Not to say these aren’t going to be added but they are not simple things and will not really add to much to my game in all honesty. Given the deadline of end of this month I have given myself, I don’t know if I will have time to add these (except for the James bond level start thing as that is a UI thing that will require art, music ect so might work on that when not coding. . That’s all, thanks for reading (:
Dev Log #31 . I AM FINISHED!!! . Well, pretty much at least. . Today I: Completed the Waiver Made some more levels I made it so that the text box works with word wrap, enter key and backspace key. . I did this by splitting the text into words and lines, then checking each word’s width against the rect boundaries. . If the word exceeds the boundaries x, the texts’ x position is reset and the Y-coordinate is incremented, creating a new line. . The Enter key creates a new line by resetting x and incrementing y, while Backspace removes the last character from the text string, preventing it from being displayed. . The waiver now checks if all fields are filled and allows you to press a button that is connected to a hyperlink that will, in the future, take you to a video created my me showing how each level is complete. . Also made 12 levels today, each new feature is slowly implemented one at time. . That’s all for today.
Dev Log #32 . Made 50 levels today, that is all. . Every 3 levels, a new ability/feature is added. This allows the player to get used to the new thing added, making their later appearance managble as the player is now used to how they function. . I have not set the player and goal location co-ordinates for each level, or other variables like if mini stars are required. . That’s all for today.
Dev Log #33 . As you can probably guess, I have done alot I have done the following: • Gave all levels the correct level variables • Made buttons work correctly when rotated • Made teleport bullets work as intended • Made gates and broken tiles allow bullets to pass through when collision is removed • Created an EXE file of my game for friends to use for playtesting • Made a stat tracker to use playtest information to improve my game • Corrected all file directories that had to be moved for PyInstaller to work properly • Fixed the Easter egg room so it now loads correctly • Added AI declaration comments That is a lots, so let me quick fire explain how i did them Painful repetition, change variables, restart level, change tiles, reset level, change ability position, reset. Repeat for level in levels (do this 50 times) . This was partially assisted by AI, but from what I understand the buttons’ Tiled rotation number is used to adjust the collision rectangle’s position so it matches the rotated button object in tiled. Collision check works as did previously. . Teleport bullets originally tp the player if a bullet fired priviously hit a way after pickup, despite no bullet being fired after pickup and also sometimes caused the player to shoot downwards through tiles. . I fixed the wrong bullet tp by using a self.variable rather than a global one as previously, allowing each bullet to know if they were teleport enabled, rather than all bullets being teleport enabled. . The tile collision isssue was fixed by by moving the player backwards along the bullet’s path until they are outside the tile, preventing the gun from passing through walls and being pulled down . This one will just explain itself (if tile in list, then ignore kill on contact): for tile in Tiles.tiles: if self.rect.colliderect(tile["rect"]): tile_property = tile["property"].get("type") if tile_property in Tiles.open_gates: continue This used pyinstaller, not something i really code or anything so, I’ll just say i did it sucessfully . Stat tracker records bullet count, time and deaths/restarts that a level took on completion. Difficulty of a level can also be decided by a play tester by pressing any number button during a level. . This data is level specific, and on key press of /, will create a json file that holds all the data, which can then be sent for me for review of things like bullet max, time complete bonus time, ect. . Self explanatory, just changed things like “Image/buttn.png” to “Game/Image/button.png” . Restart all function was required in load room function as it contains map load, so the level map that was supposed to load is not displayed instead of the secret easter egg map. . 9.Should have declared AI usage earlier, but I have been checking my chat history and I have been able to determine what sections of my code are AI generated . That’s all, gotta try and keep my daily streak alive this time to score myself a free plush.
Dev Log #34. . Just cleaning some things up now, we are in the home stretch . I did the following: Updated assest Updated object display code fixed broken dialogue Most assets have a fresh new look created in photopea . Buttons can now be loaded at rotated orientations . Dialogue now does display and does not disapear on first level load. This is because the start playing state was being skipped, i fixed this by using a continue, which skipped the rest of the current loop iteration, preventing the start-state code from continuing to run after changing playing_state. . Thats all, most of my time when into design. See you next devlog
Dev Log #35 . Been a bit distracted from this project due to school starting but I’ve been able to get a few things done. . I have done the following: Finished dialogue texts Made it so that dialogue box only appears when there is text Given kill tiles rotatable counterparts Added muzzle flash Added ability pick up sounds Updated a few more assets My Git commits have started to get a bit sloppy as i do these little bits on during my free periods, but im getting back into the swing of things . The dialogue box will only appear if text != “” and will put the player in the start playing state, without requiring a mouse click like it did previously. . Adding sounds was pretty simple so I wil leave an example bellow if self.rect.colliderect(ability["rect"]): if self.gravity_flip > 0: up_gravity_fx.play() else: down_gravity_fx.play() ability["collected"] = True self.gravity_flip *= -1 That’s all, I think 20/09/2026 will be a date for the books as I’m confident I will be finished by then. ALSO, if anyone sees this before ship, could you let me know any ideas for what my 16x16 tile for regular tiles could look like? Many thanks if you respond
Dev Log #36 . I have done most of the updating of UI, having only a few assests left and one level left to edit. . In addition to this, I have also made it so that buttons now appear pressed when pressed, rather than disappearing. . My easter egg room also stops the music correctly on level complete. . The final objectives are as follows: Have gun select each have image of gun Waiver has displayed text Hint video made and linked correctly All button can only be pressed when on screen Finish misc Assets Add death, win, and coins/stars collected based on mission objectives complete Thats all, I think 20/09/2026 could still be the date for the books, but I’ve got to put the burners on to get this finsished to a level of polish I’m happy with.
Dev Log #37 . All code is 100% complete now, the only thing left to do is finish all of the UI and then I am ready to ship. . Today I: Fixed portals Added level skip button Displayed bonus objectives Made button rotation work when pressed also Made gun select display gun images Portal code issue was caused by object overlapping with tiles, cause tile collision resolution to push the player out of the tile, and at times out of the map. Fixed this by teleporting player slightly above the object (above being determined by orientation). . Level skip increases player level, restarts level and spawns player in next level. . Bonus objectives screen.blitted on win, text appears green when objective met, red when it hasn’t . Used updated rotated button rect rather then previous and changed screen.blit to use center of rect rather than topleft . For each button in gun group, i screen.blited that gun into the center of the select gun skin rect . Thats all, hope to ship by tonight.
Dev Log #38 . DONE . I did the following: Added music that plays while in level Removed copyrighted music Finished all GUI Made code neat using ruff Will ship at some point soon. See you on ship day!!!!
Dev Log #39 . THE FINAL DEV LOG . I am finally ready to ship!!! . I did the following: Made a working read me Made a working exe file of my game Removed de-bugging features so game works as intended. Stopped music overlap from happening Removed all copyrighted music (may have mentioned this previously) I used pyinstaller tocreate my exe file. . Level buttons now only work if player max player level is less than or equal to the level you are selecting. . Stopped music overlap by puting stop music into every game state + in load room function . Its been a pleasure to take part in the stardance event. Lets have a look to see how far this project has come!!!
Ships:
Barrel Roll Bullet A recoil-based platformer where, instead of traditional jumping and movement, you shoot to propel yourself around each level. My game includes multiple abilities, unlockable gun skins and 50 levels. The biggest challenge I faced was developing an accurate and efficient collision system. Initially, I planned to use AABB collision, but because it relies on rectangular bounding boxes, I found that the gun barrel could appear to float when rotating or interacting with objects. I then experimented with mask collision to achieve pixel-perfect accuracy. However, using a large number of masks throughout a level caused noticeable drops in performance. I eventually settled on a middle ground using SAT (Separating Axis Theorem) polygon-based collision. This provided much more accurate collision detection for the rotating gun while being significantly more performant than mask collision, allowing me to maintain both responsive gameplay and consistent performance. I am proud of the persistence I have demonstrated throughout the project. During the early stages of development, I encountered significant gaps in my knowledge, particularly as I was new to object-oriented programming. At times, I struggled with seemingly simple tasks, such as correctly initialising a game window or positioning a rectangle where I intended it to be. Despite these difficulties, I continued to learn, troubleshoot and refine my approach rather than abandoning features when they became challenging....
|
1792853549.024615
|
1792939949.024615
|
|
9756
|
tinystudio by @ratmuds | Stardance
|
ratmuds
|
1
|
109.8
|
2123
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-14T02:08:29Z", "hours": 108.0, "multiplier": 19.71, "payout": 2123, "blessing": "neutral", "text": "I made a game engine that I tried to make the UI look nice and feel accessible. I wanted to design it around what I liked about other game engines like Roblox Studio and Godot, and try and make it as easy as possible to make prototypes of games quickly. The decision to not let any 3D imports was intentional to keep the engine style of more retro, as you can see by the rendering style. Instead, you can fuse and subtract shapes together with CSG. The flow editor state machines fully work, and was inspired by Playmaker. The scripting system is a little bit janky sometimes but it somewhat works. The scripting system has a basic scheduler and profiler similar to Roblox’s Luau scheduler but without the complexity of CPU budget. The engine uses a custom ECS that uses Svelte Runes to provide reactivity to the engine sidebars and editor. There is also a basic UI system, and physics. There are three demo projects to try out too.", "repo": "https://github.com/ratmuds/tinystudio", "demo": "https://tinystudio.ratmud.studio/"}]...
|
[{"post_id": 69622, "ts": "202 [{"post_id": 69622, "ts": "2026-09-17T13:08:36Z", "hours": 1.7972, "text": "Redid UI styling to feel more blocky I rewrote the UI to look less bubbly I guess, now it looks more like lego and stuff and more space for work instead of tons of padding"}, {"post_id": 67806, "ts": "2026-09-14T01:58:45Z", "hours": 5.0589, "text": "Finalized Project I added a projects manager and generally just cleaned up the repository. Then created three basic demos, like a basic moon landing game, a very basic parkour game, and a physics sandbox. And finished the README"}, {"post_id": 48210, "ts": "2026-08-16T14:44:47Z", "hours": 4.7264, "text": "Scope Leaking Bug Fixed, Mouse Input, Scripting Improvements, ECS & Events Scripting Improvements and Fixes, Cameras There was an issue where I used a single variable to hold the last used scope before and forgot to change it to support multiple scripts. That is fixed now and scopes aren’t mixed weirdly anymore. There is now mouse functions and events Events can be called like part.physics:on(\"touched\") instead of part:on(\"Physics.touched\") for clarity Cameras are added, game wide function to change active camera, and camera system that updates the camera things bidirectionally supporting multiple camera types."}, {"post_id": 46256, "ts": "2026-08-13T11:31:38Z", "hours": 5.1194, "text": "Script Scheduling Engine Revamp The entire scripting engine has been redone. It was a lot of cascading changes again, with now each “Scope” having it’s own scheduler. A “scope” is a single logic component that gets attached to entities. How it works now The scheduler handles the Lua engine stuff. It wraps the main script around into a coroutine automatically now, and extracts the coroutine into a thread. It then creates a scheduler job object, pending into the queue. The scheduler then gets stepped, and initializes the jobs into the main queue and steps them. By stepping them, it resumes the coroutine until the script either ends or manually pauses the coroutine itself (usually done with a predefined “wait” function). I think this is very similar to how Roblox handles it’s script scheduler, although Roblox’s is of course much more complicated. Handling the events and callbacks was much more difficult though. Each of those ALSO need it’s own thread to run to access coroutine related functions and to access data (otherwise very weird errors will happen, like calling code over a boundary or something). This all gets added as a scheduler job, and that allows us to record telemetry data. Eventually, threads can be assigned a “budget”, where they can be stalled if they consume more than the allotted time or even do things like infinite loop detection, etc. There was just generally tedious work that was annoying."}, {"post_id": 45759, "ts": "2026-08-12T13:35:44Z", "hours": 5.3428, "text": "Added CSG Operations I added CSG operations, using the Manifold library. It makes it a bit simpler, making watertight meshes and giving back the geometry for me to make a custom mesh in ThreeJS. The reason it took so long was because I had to add cascading changes to a lot of the data structures to support this custom geometry. I also added a little loading thing at the bottom right for CSG operations. As of right now Union and Subtract are supported. Materials are not preserved as of right now, due to the simplistic way I’m handling materials but when I finish building out the materials system I basically just need to get the triangle references out of Manifold and relink them to the correct materials."}, {"post_id": 40725, "ts": "2026-08-04T13:16:47Z", "hours": 5.4036, "text": "Engine Events System & Starting Significant Scheduler Engine Revamp So I made the events system. It works by a class on the JavaScript (engine) layer, and is attached to all entities. There are a couple of functions: on: fires on event once: fires on event only once off: clears event callback clear: clears all callbacks Other entities are allowed to access another entitys events, being able to listen or even emit. A game architecture could work like having “manager” entities at the top level of the game which hold different events. For example, an “InventoryManager” entity could have an event for when an item is picked up, it itself can listen to it, as well as any other things that may find it useful. I’ve also cleaned up the code, and now there is a “game” reference. Eventually, it will have access to more things but as of right now you can access an “inputManager” which holds functions and events for user inputs. It works by attaching a metatable to it and exposing global hidden functions to call to my JavaScript engine code. But a huge problem showed up, the way I was running scripts. Before I thought just a simple coroutine running with a timeout for delays was just fine, but I was super wrong. If a callback from an event is fired and the function wants to do something, like call an external function or wait, it completely breaks. Why? I didn’t know and it took me a lot of time to find out. It’s because the callbacks aren’t a coroutine too. This is when I realized why something like Roblox has a full blown scheduler. So I’ve been planning and starting on the scheduler engine. It has to handle a lot of stuff, including managing when scripts run, including WHEN they want to run (next frame, in 3 seconds, etc) and track if they are causing issues by keeping track of their budget. Everything will need to be in a coroutine coordinated by the scheduler. Including callbacks from events too. It’s going to be pretty complicated I think, requiring a rewrite of the entire scripting system. I also just encountered a lot of bugs. And I fixed the errors from Wasmoon including the entire JS stacktrace for no reason too."}, {"post_id": 39522, "ts": "2026-08-02T15:10:03Z", "hours": 4.0047, "text": "Scripting System Affecting the Game Scripts now can change parts. There are getEntityById and getEntityByName functions now, and a bunch of metatables and stuff to get it working. Now you can query for an entity, and then modify it’s component data with metatables. For example to access or set the position of a part, you can do part.transform.position . The transform finds the transform component and position finds the data entry of position inside the component. This is all done on runtime, with component queries happening dynamically so no manual programming for new components is required. This may affect performance a little bit though. There is a custom Vector3 object now too. Error messages are also now a little less vague but still pretty confusing. I don’t know how to solve that."}, {"post_id": 38632, "ts": "2026-08-01T04:02:22Z", "hours": 6.7036, "text": "Logic & Scripting Prototype Working this was so difficult basically a TON of things needed to be changed for this to work. i had to rework the entire scripting system. i had to also think about how the system is going to work the system i landed on, basically is you can create nodes in the state machine editor, and attach scripts on those states. instead of scripts, im calling the whole package of state machine + scripts a “Logic”. i havent reflected the name everywhere else yet though, and that is probably going to take a really long time as its a major architectural shift that i didn’t plan for beforehand. i made custom nodes in the editor as you can see, a start, end and the script node. there is now a nice dropdown to select the script (a searchbar will be added later) and you can create new scripts. i fixed the code editor to actually load/save code properly. i had to redo how it saved data, so i could communicate the scripts, nodes, connections, etc all to the ScriptingSystem, which starts off at the “Start” node and steps the state once, going into the first node. This part of the code is an absolute MESS. i had a ton of bugs to fix, including state and Svelte firing state over and over again for some reason, Lua issues, dealing with coroutines, dealing with external functions which would change the state and exit the code, etc To add the script, there is now a “Add component” button which you can select the script and select the logic. The state machine handles direct to end, looping nodes, multiple handles, infinite loops going into other nodes, etc. At the end of the video, you can see that i created two states and the second state had two outputs, and the path is a 50/50 random decided by the Lua code to loop back into the first state or exit. Overall, this was really tiring and I’m glad it’s done. The amount of time thinking and debugging isn’t included in the time tracked so yeah :("}, {"post_id": 36862, "ts": "2026-07-29T06:06:34Z", "hours": 2.8403, "text": "Scripting System I added Svelte Flow and the Monaco editor Basically, I think that the system will work mainly off of state machines. Each state will have an attached script. The scripts can decide when to change states. For example, the scripting for a bee in a game could have states for wandering, eating, etc and the scripts handle only it’s own state which could make the code a little cleaner. I also tried making the script editor to look really good. I spent a bunch of time trying to add LSPs and intellisense/autocomplete and syntax and formatting but honestly I give up for now."}, {"post_id": 36780, "ts": "2026-07-29T01:39:01Z", "hours": 3.6069, "text": "Fixed Constraints Getting constraints working was super annoying. Basically, there is a problem where the engine is built around models, and you can spawn in multiple models. When models are spawned in, the parts inside are cloned including their IDs to not lose reference, but this comes with the huge issue as in the backend, the engine actually flattens this structure for more efficient processing of entities, meaning that there will be multiple entities sharing IDs, which is really bad. But creating new IDs is also a huge problem because when we reference it, the ID is not final and changes all the time on load. So instead it does <model_id>:<entity_id>, for targeting. The constraint creator lets you select two points (snapping will be added in the future) and it creates a constraint. This is later processed by the PhysicsSystem detecting the ConstraintComponent. Later there will be debug viewer for constraints. Anyway it was just a lot of annoying work."}, {"post_id": 36178, "ts": "2026-07-28T03:01:00Z", "hours": 1.4972, "text": "Opening Tabs Working There is now a flow for opening and creating tabs, now new tabs can be created and new models in the same way. Opening a tab that is already open just switches to it."}, {"post_id": 35581, "ts": "2026-07-27T03:36:46Z", "hours": 5.8286, "text": "Runtime working This took so long There was just so many things that just weren’t working well together. Especially the data loading code. I initially just made the code use and modify the gameData directly, meaning that if I stop and play again the game would not reset and would probably completely break. But cloning is so difficult. Since the gameData is pretty complicated with nested classes and data, simply JSON.stringify and parse, and even structuredClone didn’t work. I had to use a function to manually copy a lot of things which was really annoying. Another thing that was weird was that parts would only have physics if it was dictated by the parent model, which wasn’t what I wanted. Now there is a function to flatten models, since I want them to kind of just be fancy folders at the end of the day anyway. There was just generally a lot of rework to get everything working, with systems and components working now with a setup phase, and a general frame tick function for systems to process. I also had to add dirty flags to all ComponentDataEntries so other components actually notice changes by OTHER components which was so annoying :(("}, {"post_id": 32943, "ts": "2026-07-22T12:52:14Z", "hours": 3.2719, "text": "Model Thumbnails, Better Highlighting, Reactivity, Sidebar, etc The models now have a place to store a thumbnail, and on save, it autogenerates a new thumbnail. It creates a new ThreeJS scene in the background and adds all the entities to it. For now it only cares about the Transform component, so that’s why all the parts don’t have the correct colors. The face highlighting also is fixed to use ThreeJS’s Line2 so an adjustable line thickness can be used. The face edge highlights are now thicker and a lot easier to see. Reactivity is now fixed, so dragging an object in the editor updates the UI, and the other way around. In the video, you can also see the “–” when multiple objects were selected. It means they have unique values, but they can still be all updated. The system works by storing all seen components in a JS map, and then only filtering for components that appear in ALL of the selected parts. I might change that functionality later but it works for now. I also added the sidebar to the model workspace. I also did work on the ECS system and just engine code in general."}, {"post_id": 32397, "ts": "2026-07-21T15:37:04Z", "hours": 3.5475, "text": "Fixed ECS Data Storage and UI Displays ECS Data I got the UI to display the data for the ECS components. I had some weird bugs, also I messed up earlier on the code to store the data entries for the components (stores things like data type and stuff) and then now it displays on the sidebar. For now I temporarily disabled the code to handle multiple different objects that could have differing component values or different components altogether, because it was causing a bunch of problems cuz the code is not great :("}, {"post_id": 31028, "ts": "2026-07-19T02:40:47Z", "hours": 4.5597, "text": "Started Data and ECS Code I started working on the ECS system, and now the parts spawned are “entities” and they have “components” like a mesh, a transform, and a physics component. The components are queried and cached by the game engine and passed to the “systems” that actually do work with the component data of the entity. I also dealt with a stupid tab bug :((( And generally other engine code."}, {"post_id": 15172, "ts": "2026-06-24T17:28:53Z", "hours": 3.5117, "text": "Worked on Model tab and Working on Refactoring Backend & Renderer Component There’s now a model tab, also I made some more animations and things to make the app more fun to use. I’m also in the process of rebuilding the data types and completely redoing the reusable Renderer component since it was an absolute disaster before."}, {"post_id": 14600, "ts": "2026-06-23T19:23:32Z", "hours": 6.5047, "text": "Completely Revamped UI and Working On Refactoring Entire Engine I really tried making the UI look a lot nicer than the generic UI it was before, and I think it looks pretty nice. I might need to simplify some stuff, but I spent a long time trying to make the UI more welcoming and easy to use and for the UI to seem more playful in a way I guess, than the more mono font boring gray it was last time. I also have started on completely refactoring the engine. The previous data stores and data types were too limiting and I made some bad decisions early on so starting from scratch is kind of necessary"}, {"post_id": 11366, "ts": "2026-06-18T16:29:57Z", "hours": 1.5181, "text": "Added constraints, which took a while because the way I store objects just isn’t sustainable I’m going to redo the entire architechure of this app, mostly the backend because it’s just such a mess. I’ve been piling on features and the technical debt and poor early decisions are catching up to me and it’s making development slower so I’m going to start refactoring a lot of stuff. This should mean everything will be less buggy and make it faster for me to develop new features Now that I know how the app will be I can make smarter decisions"}, {"post_id": 10184, "ts": "2026-06-16T20:00:27Z", "hours": 4.2217, "text": "Reworked script system for better and easier scripting and added some basic part modification functions Basically, before you would need to type something like find(“stud”):setVelocity({10, 10, 10}) or something like that, but with metatables Metatables are kind of weird, but they basically let me return a special object from the find() function, and modify that object to override functions and add new ones. For example, you can override the metatable of custom Vector3 objects to handle addition, so you can do v1 + v2 instead of addVectors(v1, v2) and it’s a lot cleaner and straightforward. This means injecting a bunch of Lua code to set these metatables, and exposing global functions from JS to handle the metatable calls. I also added some event handling (very basic for now) but you can see in the video the part moving from me using WASD You can also see a ton of errors, and I’m trying to fix those right now. I really don’t know why they are here"}, {"post_id": 8431, "ts": "2026-06-14T00:48:37Z", "hours": 3.4253, "text": "Part sidebar shows parent/child relationships now (also had to change backend) I also got save data to serialize, but loading seems to break the other components that rely on the state I also added the cool little part add thing. I changed the font of the app too and stuff. I tried different search things but this one from shadcn-svelte seemed to work the best. I also picked the Lyra theme from shadcn-svelte"}, {"post_id": 8181, "ts": "2026-06-13T17:01:57Z", "hours": 6.7944, "text": "It’s been a while, I kind of forgot to log in the middle I reimplemented parts of the backend to support play testing and handling the state of the current game, keeping track of parts and bodies and scripts Added physics engine (Rapier), requiring keeping track of colliders and physics bodies. Right now only convex meshes for performance meaning concave colliders might be a little broken for now so I plan to add something like VHACD or a more modern alternative to split up complicated meshes into smaller convex and simplified colliders. Added Wasmoon (Lua interpreter) and CodeMirror 6 (code editor component) and some old language parser for Lua to be supported properly, this was also a challenge because Wasmoon just wants to run all the code in one go, so instead there has to be a coroutine setup where the code returns back out temporarily (with a custom wait function that utilized the coroutine function) where then my code ticks every frame to tick the code (while loop) again and also adds the delay if applicable The renderer also needed a few tweaks to get this to work properly Also something kind of weird was I couldn’t get the playTest state to update and propagate throughout the application (thats why the top bar button doesn’t work for now) and honestly I have no idea why and I spent a lot of time debugging it"}, {"post_id": 7159, "ts": "2026-06-11T23:12:48Z", "hours": 0.8367, "text": "Can now apply textures to objects with a new Texture Studio tab :) It’s still really buggy and doesn’t work on CSG objects. It also ignores the coplanar face detection I have right now for simplicity so it only works on ThreeJS primitive face groups as of right now."}, {"post_id": 6571, "ts": "2026-06-11T01:16:28Z", "hours": 2.0747, "text": "I added the framework of a UV atlas editor, and also the painting studio for the texture editor I’m working on the texture system. I’m still working on UVs. It’s honestly really complicated, I have no idea so far how to make it intuitive for users. Auto unwrapping it would not give easy to use results because most assets in this engine are going to be simple. Showing all the vertices on a single atlas also would be very overwhelming. I’m trying to figure something out. It could be determined on a face by face basis, but some faces could be super super weird due to imported meshes or weird CSG operations, which would lead to a mess of a UV unwrap I’m also going to make an editor to assemble the texture atlases by stitching together the individual smaller textures."}, {"post_id": 5862, "ts": "2026-06-09T20:15:37Z", "hours": 2.4597, "text": "Finally got the world studio to work properly, it was because I didn’t assign an ID to the spawned objects And I added the premade things in the scene also be added to the store"}, {"post_id": 5285, "ts": "2026-06-09T00:22:45Z", "hours": 1.6897, "text": "I finally got model saving to sort of work. This required revamping the backend stores to support multiple tabs, and updating the sidebar to actually use the correct tab state data."}, {"post_id": 5199, "ts": "2026-06-08T21:54:17Z", "hours": 0.5725, "text": "Moved 3D rendering code to be shared between both studios via creating a component that applies the shading and stuff and exposing the scene for the individual studios to add objects And added an isolation mode that allows the user to focus a single object or group of objects (whatever the user is selecting) and pressing i to toggle. Useful for like creating constraints and stuff more easily"}, {"post_id": 4853, "ts": "2026-06-08T11:54:31Z", "hours": 0.6908, "text": "Transform controls (now can switch to rotate and scale) And basic undo/redo system that basically just takes the ThreeJS properties and saves it and reapplies it back on undo And delete"}, {"post_id": 4609, "ts": "2026-06-07T23:55:10Z", "hours": 1.5267, "text": "Face selection (took so long) and with face selection I added constraint creation system that just creates a constraint in the center of the faces selected I had to add another face renderer, and then also refactor the stores and how I stored data to get this to work and to keep track of faces selected and stuff which took a long time"}, {"post_id": 4556, "ts": "2026-06-07T22:02:26Z", "hours": 1.1836, "text": "The CSG works really well now. Union operations now maintain materials by keeping track of the mesh IDs and then reassigning the materials afterwards manually. Also some clean up and general improvement"}, {"post_id": 4504, "ts": "2026-06-07T20:51:13Z", "hours": 0.3275, "text": "I’ve fixed the face selection code to check the dot product of the faces to make sure they are actually coplanar. I also added some cleanup functions to perform after the CSG operations to clean up geometry to make it more usable"}, {"post_id": 4494, "ts": "2026-06-07T20:31:36Z", "hours": 1.1086, "text": "Face detection and highlighting working This was pretty complicated because 3D objects are made up of triangles, but the user probably does NOT want to select triangles, but the faces themselves. So basically, I got the face the raycast hit, and then looped through all the triangles of the mesh they are hovering and got the vertex indices and got their positions and turned that into a normal and compared it with the other faces and decided if the normals were close enough"}, {"post_id": 4361, "ts": "2026-06-07T17:35:23Z", "hours": 1.2006, "text": "Added retro shader that quantizes the colors to look more like a limited color space Fixed CSG errors and fixed gizmo disappearing over and over again Added another render pass and raycast to add outline to hovered objects"}, {"post_id": 4305, "ts": "2026-06-07T15:51:36Z", "hours": 0.5503, "text": "I switched the CSG library to Manifold3D and it’s better but the meshes are a bit weird. Hopefully I’ll figure it out later. Also for some reason selection of these meshes and their transform gizmos are really difficult and buggy so I have to fix that. Also I know that there are errors I’m going to fix that now"}, {"post_id": 4280, "ts": "2026-06-07T15:18:31Z", "hours": 1.0586, "text": "CSG is being very annoying. I’m using three-bvh-csg but it’s not really what I need I think. There’s some subtraction artifacts, and most importantly, materials are not preserved I think I’m going to switch to a different library because this one isn’t really working great for me but it is pretty nice and simple"}, {"post_id": 4244, "ts": "2026-06-07T14:14:51Z", "hours": 0.9067, "text": "Added multi part select. Trying to debug why CSG operations not working I honestly don’t know what’s wrong because I followed the example code from the library but it’s not working :("}, {"post_id": 4189, "ts": "2026-06-07T12:39:07Z", "hours": 0.9372, "text": "The sidebars are now synced, but I still need to make them sync correctly to the current tab. Right now they sync exclusively to the model studio. The raycasting & selection of parts work now and I fixed the tabs to not unload and reload on each tab switch which caused data sync issues and lag and instead all tabs stay loaded."}, {"post_id": 4157, "ts": "2026-06-07T11:23:44Z", "hours": 0.7944, "text": "I made the part selected have an outline and made the gizmo work, but currently I can’t select other parts for some reason and I’ve just been debugging that"}, {"post_id": 3649, "ts": "2026-06-06T17:48:15Z", "hours": 1.8894, "text": "I started work on the “World Studio” and “Model Studio” of this game engine/fantasy console. The model studio is where you create the models that you drag into the world studio. I’ve added a gizmo and a way to place the parts and also made a more stylized rendering thing to make it feel more retro in a way."}, {"post_id": 3482, "ts": "2026-06-06T13:13:24Z", "hours": 0.41, "text": "I started the project and installed SvelteKit and added ThreeJS"}]...
|
Title: tinystudio by @ratmuds | Stardance
Devlogs Title: tinystudio by @ratmuds | Stardance
Devlogs:
I started the project and installed SvelteKit and added ThreeJS
I started work on the “World Studio” and “Model Studio” of this game engine/fantasy console. The model studio is where you create the models that you drag into the world studio. I’ve added a gizmo and a way to place the parts and also made a more stylized rendering thing to make it feel more retro in a way.
I made the part selected have an outline and made the gizmo work, but currently I can’t select other parts for some reason and I’ve just been debugging that
The sidebars are now synced, but I still need to make them sync correctly to the current tab. Right now they sync exclusively to the model studio. The raycasting & selection of parts work now and I fixed the tabs to not unload and reload on each tab switch which caused data sync issues and lag and instead all tabs stay loaded.
Added multi part select. Trying to debug why CSG operations not working I honestly don’t know what’s wrong because I followed the example code from the library but it’s not working :(
CSG is being very annoying. I’m using three-bvh-csg but it’s not really what I need I think. There’s some subtraction artifacts, and most importantly, materials are not preserved I think I’m going to switch to a different library because this one isn’t really working great for me but it is pretty nice and simple
I switched the CSG library to Manifold3D and it’s better but the meshes are a bit weird. Hopefully I’ll figure it out later. Also for some reason selection of these meshes and their transform gizmos are really difficult and buggy so I have to fix that. Also I know that there are errors I’m going to fix that now
Added retro shader that quantizes the colors to look more like a limited color space Fixed CSG errors and fixed gizmo disappearing over and over again Added another render pass and raycast to add outline to hovered objects
Face detection and highlighting working This was pretty complicated because 3D objects are made up of triangles, but the user probably does NOT want to select triangles, but the faces themselves. So basically, I got the face the raycast hit, and then looped through all the triangles of the mesh they are hovering and got the vertex indices and got their positions and turned that into a normal and compared it with the other faces and decided if the normals were close enough
I’ve fixed the face selection code to check the dot product of the faces to make sure they are actually coplanar. I also added some cleanup functions to perform after the CSG operations to clean up geometry to make it more usable
The CSG works really well now. Union operations now maintain materials by keeping track of the mesh IDs and then reassigning the materials afterwards manually. Also some clean up and general improvement
Face selection (took so long) and with face selection I added constraint creation system that just creates a constraint in the center of the faces selected I had to add another face renderer, and then also refactor the stores and how I stored data to get this to work and to keep track of faces selected and stuff which took a long time
Transform controls (now can switch to rotate and scale) And basic undo/redo system that basically just takes the ThreeJS properties and saves it and reapplies it back on undo And delete
Moved 3D rendering code to be shared between both studios via creating a component that applies the shading and stuff and exposing the scene for the individual studios to add objects And added an isolation mode that allows the user to focus a single object or group of objects (whatever the user is selecting) and pressing i to toggle. Useful for like creating constraints and stuff more easily
I finally got model saving to sort of work. This required revamping the backend stores to support multiple tabs, and updating the sidebar to actually use the correct tab state data.
Finally got the world studio to work properly, it was because I didn’t assign an ID to the spawned objects And I added the premade things in the scene also be added to the store
I added the framework of a UV atlas editor, and also the painting studio for the texture editor I’m working on the texture system. I’m still working on UVs. It’s honestly really complicated, I have no idea so far how to make it intuitive for users. Auto unwrapping it would not give easy to use results because most assets in this engine are going to be simple. Showing all the vertices on a single atlas also would be very overwhelming. I’m trying to figure something out. It could be determined on a face by face basis, but some faces could be super super weird due to imported meshes or weird CSG operations, which would lead to a mess of a UV unwrap I’m also going to make an editor to assemble the texture atlases by stitching together the individual smaller textures.
Can now apply textures to objects with a new Texture Studio tab :) It’s still really buggy and doesn’t work on CSG objects. It also ignores the coplanar face detection I have right now for simplicity so it only works on ThreeJS primitive face groups as of right now.
It’s been a while, I kind of forgot to log in the middle I reimplemented parts of the backend to support play testing and handling the state of the current game, keeping track of parts and bodies and scripts Added physics engine (Rapier), requiring keeping track of colliders and physics bodies. Right now only convex meshes for performance meaning concave colliders might be a little broken for now so I plan to add something like VHACD or a more modern alternative to split up complicated meshes into smaller convex and simplified colliders. Added Wasmoon (Lua interpreter) and CodeMirror 6 (code editor component) and some old language parser for Lua to be supported properly, this was also a challenge because Wasmoon just wants to run all the code in one go, so instead there has to be a coroutine setup where the code returns back out temporarily (with a custom wait function that utilized the coroutine function) where then my code ticks every frame to tick the code (while loop) again and also adds the delay if applicable The renderer also needed a few tweaks to get this to work properly Also something kind of weird was I couldn’t get the playTest state to update and propagate throughout the application (thats why the top bar button doesn’t work for now) and honestly I have no idea why and I spent a lot of time debugging it
Part sidebar shows parent/child relationships now (also had to change backend) I also got save data to serialize, but loading seems to break the other components that rely on the state I also added the cool little part add thing. I changed the font of the app too and stuff. I tried different search things but this one from shadcn-svelte seemed to work the best. I also picked the Lyra theme from shadcn-svelte
Reworked script system for better and easier scripting and added some basic part modification functions Basically, before you would need to type something like find(“stud”):setVelocity({10, 10, 10}) or something like that, but with metatables Metatables are kind of weird, but they basically let me return a special object from the find() function, and modify that object to override functions and add new ones. For example, you can override the metatable of custom Vector3 objects to handle addition, so you can do v1 + v2 instead of addVectors(v1, v2) and it’s a lot cleaner and straightforward. This means injecting a bunch of Lua code to set these metatables, and exposing global functions from JS to handle the metatable calls. I also added some event handling (very basic for now) but you can see in the video the part moving from me using WASD You can also see a ton of errors, and I’m trying to fix those right now. I really don’t know why they are here
Added constraints, which took a while because the way I store objects just isn’t sustainable I’m going to redo the entire architechure of this app, mostly the backend because it’s just such a mess. I’ve been piling on features and the technical debt and poor early decisions are catching up to me and it’s making development slower so I’m going to start refactoring a lot of stuff. This should mean everything will be less buggy and make it faster for me to develop new features Now that I know how the app will be I can make smarter decisions
Completely Revamped UI and Working On Refactoring Entire Engine I really tried making the UI look a lot nicer than the generic UI it was before, and I think it looks pretty nice. I might need to simplify some stuff, but I spent a long time trying to make the UI more welcoming and easy to use and for the UI to seem more playful in a way I guess, than the more mono font boring gray it was last time. I also have started on completely refactoring the engine. The previous data stores and data types were too limiting and I made some bad decisions early on so starting from scratch is kind of necessary
Worked on Model tab and Working on Refactoring Backend & Renderer Component There’s now a model tab, also I made some more animations and things to make the app more fun to use. I’m also in the process of rebuilding the data types and completely redoing the reusable Renderer component since it was an absolute disaster before.
Started Data and ECS Code I started working on the ECS system, and now the parts spawned are “entities” and they have “components” like a mesh, a transform, and a physics component. The components are queried and cached by the game engine and passed to the “systems” that actually do work with the component data of the entity. I also dealt with a stupid tab bug :((( And generally other engine code.
Fixed ECS Data Storage and UI Displays ECS Data I got the UI to display the data for the ECS components. I had some weird bugs, also I messed up earlier on the code to store the data entries for the components (stores things like data type and stuff) and then now it displays on the sidebar. For now I temporarily disabled the code to handle multiple different objects that could have differing component values or different components altogether, because it was causing a bunch of problems cuz the code is not great :(
Model Thumbnails, Better Highlighting, Reactivity, Sidebar, etc The models now have a place to store a thumbnail, and on save, it autogenerates a new thumbnail. It creates a new ThreeJS scene in the background and adds all the entities to it. For now it only cares about the Transform component, so that’s why all the parts don’t have the correct colors. The face highlighting also is fixed to use ThreeJS’s Line2 so an adjustable line thickness can be used. The face edge highlights are now thicker and a lot easier to see. Reactivity is now fixed, so dragging an object in the editor updates the UI, and the other way around. In the video, you can also see the “–” when multiple objects were selected. It means they have unique values, but they can still be all updated. The system works by storing all seen components in a JS map, and then only filtering for components that appear in ALL of the selected parts. I might change that functionality later but it works for now. I also added the sidebar to the model workspace. I also did work on the ECS system and just engine code in general.
Runtime working This took so long There was just so many things that just weren’t working well together. Especially the data loading code. I initially just made the code use and modify the gameData directly, meaning that if I stop and play again the game would not reset and would probably completely break. But cloning is so difficult. Since the gameData is pretty complicated with nested classes and data, simply JSON.stringify and parse, and even structuredClone didn’t work. I had to use a function to manually copy a lot of things which was really annoying. Another thing that was weird was that parts would only have physics if it was dictated by the parent model, which wasn’t what I wanted. Now there is a function to flatten models, since I want them to kind of just be fancy folders at the end of the day anyway. There was just generally a lot of rework to get everything working, with systems and components working now with a setup phase, and a general frame tick function for systems to process. I also had to add dirty flags to all ComponentDataEntries so other components actually notice changes by OTHER components which was so annoying :((
Opening Tabs Working There is now a flow for opening and creating tabs, now new tabs can be created and new models in the same way. Opening a tab that is already open just switches to it.
Fixed Constraints Getting constraints working was super annoying. Basically, there is a problem where the engine is built around models, and you can spawn in multiple models. When models are spawned in, the parts inside are cloned including their IDs to not lose reference, but this comes with the huge issue as in the backend, the engine actually flattens this structure for more efficient processing of entities, meaning that there will be multiple entities sharing IDs, which is really bad. But creating new IDs is also a huge problem because when we reference it, the ID is not final and changes all the time on load. So instead it does <model_id>:<entity_id>, for targeting. The constraint creator lets you select two points (snapping will be added in the future) and it creates a constraint. This is later processed by the PhysicsSystem detecting the ConstraintComponent. Later there will be debug viewer for constraints. Anyway it was just a lot of annoying work.
Scripting System I added Svelte Flow and the Monaco editor Basically, I think that the system will work mainly off of state machines. Each state will have an attached script. The scripts can decide when to change states. For example, the scripting for a bee in a game could have states for wandering, eating, etc and the scripts handle only it’s own state which could make the code a little cleaner. I also tried making the script editor to look really good. I spent a bunch of time trying to add LSPs and intellisense/autocomplete and syntax and formatting but honestly I give up for now.
Logic & Scripting Prototype Working this was so difficult basically a TON of things needed to be changed for this to work. i had to rework the entire scripting system. i had to also think about how the system is going to work the system i landed on, basically is you can create nodes in the state machine editor, and attach scripts on those states. instead of scripts, im calling the whole package of state machine + scripts a “Logic”. i havent reflected the name everywhere else yet though, and that is probably going to take a really long time as its a major architectural shift that i didn’t plan for beforehand. i made custom nodes in the editor as you can see, a start, end and the script node. there is now a nice dropdown to select the script (a searchbar will be added later) and you can create new scripts. i fixed the code editor to actually load/save code properly. i had to redo how it saved data, so i could communicate the scripts, nodes, connections, etc all to the ScriptingSystem, which starts off at the “Start” node and steps the state once, going into the first node. This part of the code is an absolute MESS. i had a ton of bugs to fix, including state and Svelte firing state over and over again for some reason, Lua issues, dealing with coroutines, dealing with external functions which would change the state and exit the code, etc To add the script, there is now a “Add component” button which you can select the script and select the logic. The state machine handles direct to end, looping nodes, multiple handles, infinite loops going into other nodes, etc. At the end of the video, you can see that i created two states and the second state had two outputs, and the path is a 50/50 random decided by the Lua code to loop back into the first state or exit. Overall, this was really tiring and I’m glad it’s done. The amount of time thinking and debugging isn’t included in the time tracked so yeah :(
Scripting System Affecting the Game Scripts now can change parts. There are getEntityById and getEntityByName functions now, and a bunch of metatables and stuff to get it working. Now you can query for an entity, and then modify it’s component data with metatables. For example to access or set the position of a part, you can do part.transform.position . The transform finds the transform component and position finds the data entry of position inside the component. This is all done on runtime, with component queries happening dynamically so no manual programming for new components is required. This may affect performance a little bit though. There is a custom Vector3 object now too. Error messages are also now a little less vague but still pretty confusing. I don’t know how to solve that.
Engine Events System & Starting Significant Scheduler Engine Revamp So I made the events system. It works by a class on the JavaScript (engine) layer, and is attached to all entities. There are a couple of functions: on: fires on event once: fires on event only once off: clears event callback clear: clears all callbacks Other entities are allowed to access another entitys events, being able to listen or even emit. A game architecture could work like having “manager” entities at the top level of the game which hold different events. For example, an “InventoryManager” entity could have an event for when an item is picked up, it itself can listen to it, as well as any other things that may find it useful. I’ve also cleaned up the code, and now there is a “game” reference. Eventually, it will have access to more things but as of right now you can access an “inputManager” which holds functions and events for user inputs. It works by attaching a metatable to it and exposing global hidden functions to call to my JavaScript engine code. But a huge problem showed up, the way I was running scripts. Before I thought just a simple coroutine running with a timeout for delays was just fine, but I was super wrong. If a callback from an event is fired and the function wants to do something, like call an external function or wait, it completely breaks. Why? I didn’t know and it took me a lot of time to find out. It’s because the callbacks aren’t a coroutine too. This is when I realized why something like Roblox has a full blown scheduler. So I’ve been planning and starting on the scheduler engine. It has to handle a lot of stuff, including managing when scripts run, including WHEN they want to run (next frame, in 3 seconds, etc) and track if they are causing issues by keeping track of their budget. Everything will need to be in a coroutine coordinated by the scheduler. Including callbacks from events too. It’s going to be pretty complicated I think, requiring a rewrite of the entire scripting system. I also just encountered a lot of bugs. And I fixed the errors from Wasmoon including the entire JS stacktrace for no reason too.
Added CSG Operations I added CSG operations, using the Manifold library. It makes it a bit simpler, making watertight meshes and giving back the geometry for me to make a custom mesh in ThreeJS. The reason it took so long was because I had to add cascading changes to a lot of the data structures to support this custom geometry. I also added a little loading thing at the bottom right for CSG operations. As of right now Union and Subtract are supported. Materials are not preserved as of right now, due to the simplistic way I’m handling materials but when I finish building out the materials system I basically just need to get the triangle references out of Manifold and relink them to the correct materials.
Script Scheduling Engine Revamp The entire scripting engine has been redone. It was a lot of cascading changes again, with now each “Scope” having it’s own scheduler. A “scope” is a single logic component that gets attached to entities. How it works now The scheduler handles the Lua engine stuff. It wraps the main script around into a coroutine automatically now, and extracts the coroutine into a thread. It then creates a scheduler job object, pending into the queue. The scheduler then gets stepped, and initializes the jobs into the main queue and steps them. By stepping them, it resumes the coroutine until the script either ends or manually pauses the coroutine itself (usually done with a predefined “wait” function). I think this is very similar to how Roblox handles it’s script scheduler, although Roblox’s is of course much more complicated. Handling the events and callbacks was much more difficult though. Each of those ALSO need it’s own thread to run to access coroutine related functions and to access data (otherwise very weird errors will happen, like calling code over a boundary or something). This all gets added as a scheduler job, and that allows us to record telemetry data. Eventually, threads can be assigned a “budget”, where they can be stalled if they consume more than the allotted time or even do things like infinite loop detection, etc. There was just generally tedious work that was annoying.
Scope Leaking Bug Fixed, Mouse Input, Scripting Improvements, ECS & Events Scripting Improvements and Fixes, Cameras There was an issue where I used a single variable to hold the last used scope before and forgot to change it to support multiple scripts. That is fixed now and scopes aren’t mixed weirdly anymore. There is now mouse functions and events Events can be called like part.physics:on("touched") instead of part:on("Physics.touched") for clarity Cameras are added, game wide function to change active camera, and camera system that updates the camera things bidirectionally supporting multiple camera types.
Finalized Project I added a projects manager and generally just cleaned up the repository. Then created three basic demos, like a basic moon landing game, a very basic parkour game, and a physics sandbox. And finished the README
Redid UI styling to feel more blocky I rewrote the UI to look less bubbly I guess, now it looks more like lego and stuff and more space for work instead of tons of padding
Ships:
I made a game engine that I tried to make the UI look nice and feel accessible. I wanted to design it around what I liked about other game engines like Roblox Studio and Godot, and try and make it as easy as possible to make prototypes of games quickly. The decision to not let any 3D imports was intentional to keep the engine style of more retro, as you can see by the rendering style. Instead, you can fuse and subtract shapes together with CSG. The flow editor state machines fully work, and was inspired by Playmaker. The scripting system is a little bit janky sometimes but it somewhat works. The scripting system has a basic scheduler and profiler similar to Roblox’s Luau scheduler but without the complexity of CPU budget. The engine uses a custom ECS that uses Svelte Runes to provide reactivity to the engine sidebars and editor. There is also a basic UI system, and physics. There are three demo projects to try out too....
|
1792853853.8560073
|
1792940253.8560073
|
|
8111
|
Poorup.io by @jeremy | Stardance
|
jeremy
|
3
|
179.0
|
2137
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-06T17:48:41Z", "hours": 135.0, "multiplier": 18.44, "payout": 1778, "blessing": "neutral", "text": "Poorup — Biggest Update to date I’ve given the project a major overhaul, from its visual identity and everything else. This is geninuly one of the best projects i have created and iam proud to announce it I first started Poorup 3 and 1/2 months ago as a project to get introcude into webdesing and since then i have created 4 more website and revesiting it really shows my growth. Of course Ai was used by even then I could really feel my growth What was challening i decide to stay on CSS, html, and js instead of transferring it into another language for a simple reason i wanted to test how far i can push these 3 languages( i was just to lazy to learn a new language) How I used AI AI WAS USED IN THIS PROJECT for debugging and coding no UI or art generation. AI was a substantial coding and debugging tool, especially for backend work, bot logic, and tricky multiplayer edge cases. I used CodeScene to identify code-health hotspots. I wrote many page-specific backend features myself, then used GPT/Codex to help debug or split some larger hotspot files into smaller modules. Ai was also used to fix bugs in the Ipad Ui I created Poorup’s frontend UI and its SVG and art assets myself. AI helped in coding but never touched art. I didn’t compose the soundtrack. I selected open-source and other openly licensed tracks; their sources and license details are in the audio credits . I also rewrote the Git history to make the repository cleaner, so the current commit log isn’t a complete record of the project’s development. Also after around the 6th or 7th devlog i turned ai traccking of as to not fraud myself hours So if needed deplete hours. What’s new in this patch UI Full ui rework of everything nothing was left out every single Ui elemt was redone by scratch, with upto 6 themse each with their own custom soundtrack and background, this was the largest wish people had wished for when they reviewed my game and iam so proud of the UI. Boards and multiplayer New 40 and Metro-52 boards, with custom visual themes. Public rooms and private rooms with shareable codes; people can join as guests. Configurable rules, including double rent, vacation cash, even building, and randomized turn order. A deeper economy system Bank loans, player-to-player loans, equity deals, and hybrid contracts, with collateral and default consequences. Sponsored purchases: one player can fund another player’s property purchase in exchange for an agreed share. Negotiating now youre able to negotiate all offers you get instead of accepting or declining on the spot you can also keep them on hold An optional stock market for all the quant bros(gamblers) casino so now youre able to gamble Social I also added a full social systems with achievements, friends inviting people to lobbys seeing match history and more, also added the option to create your own 16x16 user icon Events one of the biggest features I decided to add global events which appear under certain conditions like to many houses standing which should reference the 2008 housing crises i also added stock market crash and alot more. Also global events can also combine to create seacil ones Parlor patrol this was supposed to be a cool minigame while waiting for your friends but it doesnt work and i cant fix the bug for the life of me so you can test it out but it doesnt work correclty all svg assets for it exist", "repo": "https://github.com/jeremy341/Poorup/", "demo": "https://poorup.jeremy-d.hackclub.app/"}, {"ship_num": 2, "ts": "2026-08-11T21:30:56Z", "hours": 7.0, "multiplier": 15.34, "payout": 115, "blessing": "neutral", "text": "Project Update I didnt even notice but all the changes i did i the last patches never got shipped so this one is about the last to changes which were adding modals, creating new UI and removing AI code check it out https://poorup.jeremy-d.hackclub.app/", "repo": "https://github.com/jeremy341/Poorup/", "demo": "https://poorup.jeremy-d.hackclub.app/"}, {"ship_num": 3, "ts": "2026-06-17T14:42:48Z", "hours": 17.0, "multiplier": 14.39, "payout": 244, "blessing": "neutral", "text": "Poorup Poorup is a real-time multiplayer board game inspired by Richup(Monopoly), playable entirely in the browser What did I make? A full multiplayer board game running on a Node.js server with Socket.IO for real-time communication. The client is pure HTML, CSS, and JavaScript, no frameworks which is stupid if I look back on it . Features include: Room-based lobbies with a shareable room code Full Monopoly-style rules: buying, renting, building houses and hotels, mortgaging, and trading Live auctions with a countdown timer when a property is declined Configurable game rules per room (double rent, vacation cash, even build, auction, mortgage, randomized turn order, no rent in jail) Reconnect support — if you disconnect mid-turn, you can rejoin and resume In-game chat Automatic room cleanup when everyone leaves What was challenging? Shared states across multiple clients. Every player action, rolling dice, buying a property, placing a bid, has to be read server-side, broadcast to everyone, and reflected correctly on each client without race conditions or desync. Getting that right, especially during edge cases, took a lot of work. Edge cases in disconnects. A player disconnecting mid-auction is a different problem than disconnecting on their turn, which is different from the host disconnecting entirely. Each case needed its own handling: timers need to be cleared, pending actions need to be resolved, and remaining players need to stay in a valid game state. and i need alot of time and a bit of AI to fix that for me. Building a complete game UI with vanilla CSS. No component library, no utility framework — every modal, toggle, property card, and animation is hand-written. Honestly needed a lot of AI help here. Probally should have used a libary if I look back at it but it was fun to do it in plain CSS also for anyone wondering why the favicon is the one from vite i never deleted it and i wasnt in the mode to redesign a new one and tried to use the board map but that didnt work for some reason. What am I proud of? The architecture. The game logic lives entirely in gameLogic.js and has no knowledge of sockets or HTTP. The server in server.js wires events to logic calls and broadcasts the results. That separation made the codebase much easier to debug than it would have been otherwise but i needed AI to implement the idea i had the idea but wasnt quite able to do it. How to test it git clone https://github.com/jeremy341/Poorup.git cd Poorup npm install npm start Then open http://localhost:8080 in two separate tabs or browser windows.", "repo": "https://github.com/jeremy341/Poorup/", "demo": "https://poorup.jeremy-d.hackclub.app/"}]...
|
[{"post_id": 81740, "ts": "202 [{"post_id": 81740, "ts": "2026-10-22T09:55:56Z", "hours": 9.6928, "text": "Rework #1 Now you could be asking yourself? What have i done in the last 8 days to not post? Well Iam nearly finished with the full rework off all UI, Bug fixing and introducing new features, Chart Engine So i redid the whole system for charts and decided to build my own, because though i had one which worked it looked horrendous and really didnt fit poorup, you can see the new chart engine in the screenshot Game history I redid the whole entire game history system, because to be honest it was heavily vibed including its Ui and while cheking it, it looked like trash so I sat myself down and worked tiresly to fully redo it, and I even implemented the new chart system into it, Modals, Modals, Modals So I REDID NEARLY EVERY SINGLE MODAL IN THE GAME to provide a better User experience this took hella long and while doing it i noticed i had hackatime tracking off, because i had been working on some personal projects, hence the reason I only posted now because I lost so many hours, #Next Features Well to be honest there really arent anymore features i can add, the only thing left is fixing bugs and preparing it for the release and advertising it on reddit"}, {"post_id": 79607, "ts": "2026-10-14T18:07:25Z", "hours": 10.3072, "text": "Devlog after ship So after getting hella positive feedback regarding poorup which i highly appreciate my aim is to now make it have an even better user experience and etc. why? cause from the feedback i got, there are 3 areas I need to tackle, UI, game logic which is to complex and the User experience including rules and etc, Full redesign of the ingame lobby So after getting feedback that the board was to smallwhich was kinda expected and that the whole game is just clutered which i also assumed would happen cause all the features dont fit into the game i have done the following. I have redesigned the full ingame lobby with a new layout further inspired by richup(didnt want to do this but they have the most optimial layout) I have also redone the whole entire admin window cause to be honest it was horrondous and hard to use, and also just some small changes all around full redesign of modals so after doing the lobby i have now decided to fully redo a lot of the modal to have a better layout and etc so they are way more user friendly and acttually easy to understand, this also included cutting alot of features from certain modals because they just made them to complex and hard to use Cards and airpots this was something i was orrignally planning to release in the last ship but i just decided to ship it with this one i have finnaly added the option to buy new bank cards which you can use to get benefits like cashback of 10% on purchsees like rent payment suprise cards and other stuff, and I also added the option to use airpots to fly from one point to another and allow players to set the prices, Bots After reflecting a bit on my ai usage for the bots i decided to fully plug the whole programm into a repo which visualises it to see if it checks out with my mental map and I noticed so much slop which I would have never noticed before, this includes the whole Bot logic which i have probally never looked at cause i knew i wouldnt be able to code them. Though i probally should have cause this is the biggest slop i have ever seen and It introduced so many bugs which the ai couldnt find Next steps Right now all these changes are locally and not on github which are around +17000 lines of code and my aim is to further clean this up and fully push it with a new domain which is alredy online but will be kept hidden. here are soem before and afters, the more clutterd ones are the befores and the simplifyed ones after"}, {"post_id": 75006, "ts": "2026-09-28T20:36:43Z", "hours": 10.8294, "text": "Poorup Redesign - Devlog #11 (FUCK MY LIFE) I am geniunly so tired of this project and my life in general i was so busy in the last few days cause of school and after shool clubs. This phase was mainly about recoding the Bot engine by hand, and updating the stock market modal inside the game also added New Ui for theme chooser and music and also added more sound tracks. I also redid statistics tabs in profile by hand and added better match history tracking Bot engine To be honest to Bot engine was so much AI stuff that i genuinly didnt understand what it was build on and how that is why I decided to take some time to read and research all the papers its build on and how it works. I then rewrote large parts of it to improve it and also found mutipile bugs in the logic of how it works and how it assigns values New account and preferences tab I fully redid some parts of the accounts and prefences tab to now allow for easier choosing of themes and also worked on the music engine so the music loops and youre able to choose different music depending on the theme. #Statsics tab I redid the whole tab as I found it quite stacked with 12 boxes for statsics and decicd to now add internal tabs to make it look cleaner this was a quick 30 minute changes as I didnt change logic but just frontend Next Steps Hopefully shipping adding HCAI and testing the AI bots and further UI refinement on tablet UI and 1440px desktop cause these are 2 of the most weirdest sizes https://poorup.jeremy-d.hackclub.app/ also if anybody wants to check it our but it is nowhere near finished so dont expect anything"}, {"post_id": 73301, "ts": "2026-09-24T20:06:52Z", "hours": 28.7353, "text": "Poorup Redesign - Devlog #10 Iam aware this phase is 30 hours this is just cause i used hella AI and didnt want to count it towards my payout. this phase mainly about finishing touches running mutipile tests suits playing some games and finishing some things also fixing Ui and redoing the Ui of the Music First of all I added music for each of the 6 theme with a secondary theme which you can select under account and preferences I also made it easier to spot the different themes as they were hella hidden to be honest. Deactivation of palor patrol Though i didnt want to this I needed to deactivate palor patrol as it was simply impossible to use I checked m code in detail used and really did everything but I couldnt find the bug which makes it unplayablle so as long as I cant manage to fix it I have to deacitvate it. Next Phase pushing everything on nest setting up a piepleine so nest automatticaly pulls everything I push onto main in my repo and finnaly realsing it with thhe bots for players to use."}, {"post_id": 70576, "ts": "2026-09-19T11:55:06Z", "hours": 11.6328, "text": "Poorup Redesign - Devlog #9 this phase was mainly about adding some missing things fully balancing everything also used the new model jev from typesafe as it was a perfect fit for the task. Admin Dashboard I now added a section in the admin Dashboard fully centered around the Bots which allows for dropping in any provider and choosing the model and see the request if theyre failing or not and etc this took quite a while as I coded this myself again as I wanted to practice a bit though I still needed Ai help as Iam so trash at js Removing TOS pages As i mentioned in the last devlog i have now decided to remove the TOS pages as they were jst not good looking and not complete and not needed. Music system I decided to remove the music player and rather make it so 1 music track is there for each theme and my next step ix expanding the profile page to allow choosing another music track as 12 are available in total but only 6 are used rn. I also decided that I am going to move the Theme chooser somewhere else as people get no indicator rn to find it New Idea for the Future Also I had a great Idea which i can incoperate into this but after the next ship. Its training a custom ml model on all the matches played by people and then incoperating it in the game. Because essentialy it would be a custom AI/Bot that is able to play monopoly as good as possible new features I also added the option to download all the data cause i noticed its saved on the server and maybe smb wants to download it will then be in a json. I also added the option to add an recovery email, because my plan is to allow people to sign up without email but they still need an option to recover data if needed I also added the option to rovoke all otehr session tokens then the onnes youre logged into rn, so essentially log out of all other devices and server sessions Next steps Cleaning up Ai code and reading through it all, 1 or 2 adjustments in Ui for example the global event banner needs to be relocated or the graphs for match history need to remade. Also the ranking page needs a little redesing. The next one will be the LAST ONE cause i cant deal with stardance anymore all my projects are getting rejected for dumb reasons, so this will be the last devlog and if it does not get accepted iam relocating somewhere else."}, {"post_id": 68664, "ts": "2026-09-15T14:29:22Z", "hours": 15.3047, "text": "Poorup Redesign - Devlog #8 this phase mainly about consolidating the backend and adding a New admin only dashboard which will allow to analyze things easier for balane patches and etc in the future. This Phase was written only by hand hence the long time, normally I would use AI to speed up the process but I wanted to get some practice in. Also added legal and TOS pages Backend I found mutipile bugs such as simple Game bugs to not so simple leackage problems and other stuff which took quite some time to fix by hand and this really shows how I will probally pause using AI for coding after this project for a while Admin Dashboard I created this Dashboard so I would be allowed to pracitally analyze everything from how certain things affect the game and for example analyze them to see if they need fixes, balances or even remove them entirly. I also added things like seeing a rough strucutre of where my player base is from. If anybody is abusing the game somehow or bot traffic. Tos Pages These took quite long and were quite the hassle but I did it. though i am debating jus tdeleting them as I couldnt fill them out entirley as certain information is needed which would then make them 100% fool proof I forgot I also updated the Snow Theme and added music for each theme with a small music player in the bottom left though I just noticed I placed the icons wrong should be a quick 2 line fix Next Steps do the last fixes finnaly test the AI bots as they are fully setup but not setup do some balancing and realese it The next post should really be the last. Hopefully."}, {"post_id": 66650, "ts": "2026-09-12T14:36:54Z", "hours": 16.8883, "text": "Poorup Redesign - Devlog #7 This phase was mainly about doing a full audit over the game, fixing bugs which were still hidden inside the server and UI, and making the whole project easier to trust before the next merge. Finalising Bots, adding, themes adding new suprise features and more. Themes I decided to create 5 more themes which will fully change the look of the game, for the 5 i decided on 5 directions first of light mode, and then the 4 seasons so summer,autumm, winter, and spring. These took quite some time to create but I think they came out quite decent though they still need cleaning up Ranking Seasons I have now added ranking seasons which are 1 month each if you manage to rank on the leaderbaord at the end of the season you get a special cosmetic(newly added system) and a special Title Cosmetics I added a full cosmetics system and the ranking system so you can now get cosmetics from 2 places, either by getting them at the end of the season form the leaderboard or by getting them from achievements Card Upgrade I also now added the features to upgrade your bank account, if you pay enough money you can upgrade your card for 1000$ this gives you a card with 5% cashback which is the Spaarkasse karte(german Bank) and the nex level is the amex black card wich give you 10$ cashback and amex points which you can use for flying. Gambling UI I also decided to now give the gambling UI an animation it now has the same kind of case opening animation as CS2 so the roulette which goes form right to left. Plane station card Also made it so that you can now use the airplanes to skip things so you can fly to another station but of course you will have to pay alot and you have to pay a landing fee. If a player owns an Airpot he can decide the flying fee himeslf and the landing fee which means he could extort people if he is smart enough Quick Table I did some changes to Quick Table as it used to create a new public room every time. It now checks the live public room directory first, joins the most suitable open table, retries if somebody fills it during the join, and only creates a new Standard-40 room when no table can be joined. Private room codes are never exposed and the server still makes the final decision. Favicon I also designed a quick little favicon which is Just a P with a box around it but it looks quite good Music Candidates I am now searching for new Music for each theme so music changes with the theme Next Steps Cleaning up the UI one final time trying everything out and finally realsing the Beta and promoting it on reddit."}, {"post_id": 63820, "ts": "2026-09-07T19:51:24Z", "hours": 5.0128, "text": "Poorup Redesign - Devlog #6 This phase was mainly about adding more depth to the player interactions, improving the bot system, and making the rankings feel more alive. Deal Negotiation I redesigned the deal flow so trades, loans, equity, and hybrid deals all work in the same way. When you receive a deal, a modal appears with accept and negotiate. If you close it, the deal does not get declined and stays inside the Finance rail. Both players can now see the same deal collapsed in Finance. The receiver can negotiate, while the sender can adjust or cancel the deal. You can open a full read-only view, change the parameters, and send the new version back. The server also checks old deal IDs so an outdated modal cannot change a newer deal. Sponsored Purchases I also added sponsored purchases. If a player cannot afford a property, they can ask the table for help. Other players can reserve contributions, and once the full amount is available, the buyer accepts and is forced to buy that exact property. The money is automatically returned if the request is canceled, the property changes owner, or a player disconnects. It is not a loan and does not create equity. Bots I continued improving the AI and no-AI bots. The bots now receive more context about the board, current obligations, loans, events, opponents, future rent risk, expected cash flow, and their own previous decisions.AI bots can now also counter trades, negotiate player contracts, choose debt rescue actions, and make auction decisions. If the AI provider runs out of credits or fails, the no api key AI takes over Rankings I added recent trend indicators to the ranking rows, so you can see if a player is moving up, down, or staying flat. I also added a seasonal ranking scope based on the current calendar season. Rules Fixes I also fixed the Double GO setting so landing exactly on GO now pays the boosted amount, while simply passing GO still pays the normal amount.TestingI expanded the tests and ran long bot campaigns with auctions, loans, casino, market, global events, sponsorships, and negotiations. The latest regression suite passes and the longer 2,500-game campaign had zero stalled games. Next Steps The next major step is making the bots simulate several complete future turns and improving long-term negotiation behavior. After that I want to add deeper browser testing and seasonal ranking rewards. Also to lazy to do screenshots of new UI so you will get everything in the next devpost"}, {"post_id": 63109, "ts": "2026-09-06T18:42:52Z", "hours": 11.5353, "text": "Poorup Redesign - Devlog #5 This phase was mainly about fixing all bugs still exisitng, refactoring further with codescene and letting AI run over my code, also fixed some small missing features and simple bugs myself. Choosing Icon I noticed a bug in which because of logic I made before setting up custom icons the programm mapped custom icons people created onto persets and blocked them so for example your icon had red in it, the game decided to map it onto the red preset in the backend blocking it but showing yours in game, this came because I never rewrote this section after introducing custom icons. Ownership icon Before this change owenship on board was only shown with a simple like quadrat in the top right corner of the tile in the color you picked this is also something left over from the old preset logic. I decided to make it so It shows a smaller version of the face of the player which makes it look a lot cleaner. Missing Buttons This was mainly because I let AI write to much of my code, the finical trading tab which is centered around equity and everything missed a dropdown to choose who you send the trade to and even the button to send the trade which was a dumb oversight on my end. I also added a simple backend system for the dropdown inside that modal to only show the propertys a person owns. Bots I also continued working on the bot system though this was mainly watching tutorials and brainstorming further Next Steps Fix last bugs, fully add bot system and make sure UI looks good to release the first beta test hopefully the next post will be the last"}, {"post_id": 62110, "ts": "2026-09-05T11:15:14Z", "hours": 13.0397, "text": "Poorup Redesign - Devlog #4 This phase was mainly about setting up codescene doing a full restructuing with the help of AI and fixing bugs and adding missing features. I also added a simple, gambling and stock market system. Bots I first started with setting up the initial idea of bots so to the UI and a bit of the backend logic for bots and how they will interact with the game iam nowhere finished and I havent tried it out yet. Codescene After checking out the github studentpack again after a while I saw codescene, which is a code reviewer similar to coderabbit. I struggled a bit with the Setup but after running an analysisi I noticed how abysmall my codebase really is and how its missing structure, archtiectuer and etc, for example sepearting certain getures from game logic.js and creating their own thread for it. I also setup a full pr pipieline which I can use with my AI agents which aim will be fixing my architecture, and finding bugs before i push them. bugs I ran Qwen 3.8 flash on my pr pipileine with codescene and let it work indepnedlty to full restructer my codebase so the results are better and I have better architectural design I also let it fix any bugs it found. Bugs I found While trying out the game i found mutipile BUGS one of them affecting my secret minigame palor patrol. For some reason I was losing hearts for no appearent reason. The reason behind it was that even though UI was hidden the helicopters were still flying through. For some reason the heart bug still exists afterwards and even the AI isnt able to find out what it is so Iam completating making architecture changes to it. #Gambling I added a smile gambling system where you can bet money on a roulete on red, black, and green I didnt add any animation for it as I found it unecessary and I also made sure iam legally clear to make sth like this Stock market I created a simple stock market tab and backend which allows people to buy indexes of a property and made sure to connect it with global events so global events can affect the stock market but that is nowhere near usable. Next Steps Iam going to let my AI continue improving my codebase with codescene and continue the Stock market and afterwards add the bots."}, {"post_id": 60301, "ts": "2026-09-02T16:03:55Z", "hours": 10.9608, "text": "Poorup Redesign – Devlog #3 This phase was about expanding the social side of Poorup, adding more depth to the game, and planning future systems that make every round feel more alive. Social, Rankings, Achievements I added a complete friend system. Players can search for unique usernames, send and accept friend requests, remove or block players, report users, invite friends to rooms, and view public profiles without leaving the lobby. Profiles now include statistics such as wins, win rate, games played, average money, bankruptcies, achievements, and match history. I also added global rankings for wins, win rate, games played, achievements, and other statistics. Rankings and Social are now independent tabs instead of modals, with wider layouts that use the available screen space more effectively. Achievements now have custom pixel-art and SVG icons, rarity levels from Common to Mythical, filters, dates, categories, and clickable detail modals. Mythical achievements are extremely rare and can trigger a server-wide announcement for every player. Easter Egg I added the hidden Parlor Patrol minigame. Pressing CTRL + P on the home screen opens a secret mode where you shoot down police helicopters, planes, and drones. It includes custom explosions, animations, sounds, score tracking, and a secret achievement. Global Events Global Events are rare events that affect every player instead of only the person who landed on a tile. They can be triggered by round conditions or Surprise cards and can last several rounds. Ideas include: Housing Bubble Pop Credit Freeze Inflation Spiral Bank Run Interest Rate Shock Airport Strike Energy Crisis Tax Scandal City Election Rent Control Tourism Boom Supply Chain Breakdown Events can combine with each other, create unexpected situations, and unlock secret achievements. I also want a global-event setting that is simply on or off, while event strength and duration scale with the round length. Rules Page I added a complete Rules tab designed like a pixel-art game manual. It explains the board, movement, properties, loans, cards, achievements, global events, social features, and settings. It uses an internal book-style scroll so the main application does not become a long scrolling page. Future Systems I am also planning a casino system using virtual money, with red, black, and green bets where the odds are not equal. Another planned feature is a fictional stock market connected to properties, countries, airports, utilities, and global events. Events could crash markets, increase rent values, affect airports, or create temporary investment opportunities. I also want to add unethical and outrages bank loans with high interest, strict repayment rules, and serious consequences. Music/sound icons I also added simple music and sound icons for the buttons instead of having the music on/off text Next Steps The next phase will be making these systems work together while keeping the game balanced, and also adding AI bots which utilise AI like deepseek v4 and so on so they able to actually judge the situation and think of possible ways for them to win. The aim is to use hcai to power them. I will also add normal BOTS as a fallback if my usage runs out"}, {"post_id": 58798, "ts": "2026-08-31T11:42:39Z", "hours": 9.8108, "text": "Poorup Redesign – Devlog #2 This phase was about continuing the complete redesign of the website, deciding on a UI theme, and implementing a new feature that I had wanted from the start but was not advanced enough to create before. New UI I am very proud to announce a complete redesign of the application. I decided to fully embrace a pixelated theme, and I personally think it looks great. It is genuinely one of the best UI systems I have ever designed. New Feature I decided to expand the trading system. You can now give out loans in exchange for premiums, equity, money, and more. This allows you to create fully customizable loans, such as: I give you $200 for 30% permanent equity in this spot. This means that you have to pay 30% less rent when you land on it and gain 30% of all rent paid on that plot. This is a system I have never seen in a Monopoly game, and I wanted to implement it from the start when I first had the idea for Poorup. New Feature #2 I have also decided to take the advice I was given and implement a room system. This allows players to join and create rooms, as well as make them public or private. I also added a quick-table feature that matches you with other people who have pressed the button, allowing you to play a quick round with random players. New Feature #3 I have created a complete profile system. You can now create a profile, view your statistics, win percentage, average money, and more. You are also able to create custom 32×32 icons to use while playing the game. New Feature #4 I also decided to add sounds and an open-source soundtrack I found called Pondering the Cosmos . which i think fits my new theme perfectly but maybe iam going to change it Next Step AI Bots The next Step will be adding bots but normal bots are boring they are just glofired search engines why i want to be a bit creative. I will use hackclub ai provider and give the bot a brain by combinging them with an AI like deepseek v4 flash this means the bot will be able to check how is he performing what are the most logical steps sell buy properties and trade and if wanted even chat with the user to make a deal would anybody like that?"}, {"post_id": 57234, "ts": "2026-08-29T10:31:03Z", "hours": 1.5744, "text": "Poorup Redesign So after my last ship i read through all the reviews and have decided to continue this project even though i really didnt plan for that. So there were 3 addition people wanted. A new UI, being able to join random people, better Animations and a Dev mode to test in solo player possibly with mods. What did i do? So i first started with thinking of a new design route so i asked chatgpt for some references of a good design. I decided on making the Whole Ui pixellated similar to the Arcade style and fully redesingen the SVG witth and now iam going to go over it and adjust it to fit ours. Of course this took like around 6 hours but I use figma on desktop and the browser tracking of hackatime doesnt seem to work how do you like the new svg? Next Steps Next Steps i redesignen the Full Ui to fit this pexelated style and making sure it looks good"}, {"post_id": 14594, "ts": "2026-06-23T19:20:12Z", "hours": 5.6261, "text": "Project Update: Bug Fixes Overview This phase was all about polishing the user experience, squashing gameplay bugs, and adding new repository documentation. After getting feedback I decided to change The whole UI Dynamic Theming & UI Improvements One of the major frontend improvements in this sprint was fixing the player icon chooser button functionality in the web interface. Fully redesignen the Front-End and more. I first of all started with replacing my .root with some new colors which are greenish. I also added some simple fade in/out animations to all Popups. Another bug was that it couldn’t quite fit in a screen of the size 1980 x 1080. I fixed that by making it possible to scroll down so everything you need for the game is shown on your screen. The way i tested it is by local hosting it and then pressin F12 in the browser and then you could adjust the size of the Window which was pretty neat. Also fixed a lot more of UI bugs such as weird buttons and more but this was the important stuff. Squashing Gameplay Bugs I knocked out two major bugs in this update: Trading System Fix: There was a bug where it wasnt possible for people to only request something without giving anything or make only money transactions so I fixed this. Special Property Popups: I resolved a rendering issue with the popups for special properties, specifically the Airports and Companies (Utilities). Now, when a player interacts with these tiles, the modal correctly pulls the specific data object and displays the unique rent calculations and purchase prices. Documentation Revamp I updated the README.md to ensure the decumentation was on point for anyone cloning the repo. I refactored and renamed SHOWCASE.md to Instructions.md . This provides a much clearer, step-by-step guide on how the game operates and how to get the local server running instead of just showcasing the Repo more. Conclusion The feedback was essential and really showed me how sloppy I worked it should now work perfectly even though i couldnt test it for 4 people"}, {"post_id": 11340, "ts": "2026-06-18T15:32:39Z", "hours": 1.8406, "text": "Update: UI/UX Fixes, Auction System Fixes, and Property Manager Integration FInal This update focused on providing a better user experience and just making it less buggy Key Changes 1. UI/UX Improvements Refactored layout components to improve visual consistency. Updated navigation paths so it makes more sense for the User and is just more logical Adjusted CSS rules to improve the game across different screen sizes. 2. Auction System Fixes Addressed synchronization issues with the auction state. Fixed logical errors in bid processing and countdown timers. 3. Property Manager Integration Fixed the Property Manager feature, allowing users to track and organize their properties. Integrated the property database schema with the existing auction mechanisms. Created user views for listing and editing properties. So just new UI 4. General Bug Fixes & Stability Cleaned up left over parts of old system"}, {"post_id": 10630, "ts": "2026-06-17T14:13:23Z", "hours": 2.5769, "text": "Poorup — Production Ready Over the past few days I’ve been doing a full production-readiness pass on Poorup . Here’s what I worked on: Bug fixes — Fixed auction edge cases where a disconnecting player would leave a ghost bid, locking the game Memory leak prevention — Added a garbage collector on the server to clean up empty rooms after 10 minutes UI polish — Fixed text cut-off in buttons and settings toggles, improved layout consistency across screen sizes Layout centering — The game board is now properly centered vertically and horizontally in the viewport Accessibility — Added focus-visible styles for keyboard navigation New setting — Exposed the “Double rent” toggle in the UI (the rule already existed in the engine) Code quality — Added JSDoc comments to core server classes, removed dead code The game is now polished and stable. Im shipping it"}, {"post_id": 8803, "ts": "2026-06-14T16:57:35Z", "hours": 0.465, "text": "Overview Today I worked on the front end an am basically finished with the easy stuff Iam now going to add the player icon and etc Front End I designed my front end and i think i can say that I am pretty good at basic JS/HTML/CSS and this project teached me alot Iam probally going to wrap it up in the next 2 post and focus on smth else. Monopoly repo After resarching a bit i found another open source monopoly game and my plan is now to copy some backend logic from it but i need to adjust it because his game is made to be playable localy and mine online so it will take same adjustment #Backend I added a Room system with the help of mutipile videos in which a random room code is generated and the server saves the generated room code making it possible for another use to insert it. The code will be if the round was ended."}, {"post_id": 8249, "ts": "2026-06-13T18:30:59Z", "hours": 2.8419, "text": "Overview Over the last few days, I’ve been triying to refactor my project, but i realised something I killed it i refactored it so often that i lost sight of the real goal and will proablly start from scratch restarting it from 0 i designed and svg file but just couldnt implement the right way. Cleaning the SVG My biggest headache was the game board. I designed a beautiful, detailed map in Figma, but exporting it as an SVG just made things difficult i tried making i clickable but i didnt know how to and i found no totorials regarding this so i will probally just create a board using html and css or maybe look for solution using ai Current System Status At the moment i have decided to refractor to vue by advice of some friends and ai because it makes the backend easier but i will proablly change back, because iam realising Iam making the project more complex than it has to be also. Conclusion I just wasted time trying to learn new stuff an refractoring and trying to not use ai. I would like for some adivice which ai I should use and if I should stick with vue or stay with or change back to default also this made me reflect on what kind of perfectionist iam an I will probally wrap up this project in the next few days because I realised front end is not for me I will continue learning it but will soon work on either python or C project after. I will just add the missing features with Ai"}, {"post_id": 6430, "ts": "2026-06-10T20:16:01Z", "hours": 0.6117, "text": "#Overview So today i didnt really code just refactored again and went back to css and decided to design all design elements in figma. It was pretty easy and II am now qustoning why i didnt do that instead also i only copied these 2. I will make my own streets afterwards and i also decided to redesign the website because it realy just a copy and i dont want to be sued but the board will probally look the same just different countries and maybe prices need to look for balancing and how it is normally in monopoly. But this probally going to take 2 to 3 days cause i really dont got any time in the next few days."}, {"post_id": 5789, "ts": "2026-06-09T18:22:00Z", "hours": 0.7531, "text": "Project Update: The Great Refactor & React Integration 📋 Overview Damn this looks trash just a small update and i jsut noticed tailwind actaully looks like trash are there any alternatives because i didnt expect it to look this bad in comparison to before and yes i do know its looks aigenrerated but i did myslef also tailwind is pretty easy if you get the hang of it just looks trash maybe going to watch some tuts cause i cant upload the final product like this."}, {"post_id": 5743, "ts": "2026-06-09T17:20:02Z", "hours": 1.3414, "text": "Overview This phase was a major point for the project. After successfully implementing the lobby chat and the 11x11 Monopoly board using Vanilla JS and CSS Grid, I realized that managing the game states (turns, money, properties, transactions) in Vanilla JS was going to lead to unmanageable spaghetti code and was way to hard. To keep the project clean and professional, I decided to perform a complete “hard reset” and refactor the entire frontend into a modern React Single Page Application (SPA) utilizing Tailwind CSS v4 [1.1.1, 1.1.8]. I always though about using it but found it weird and dififult for a beginer The Great Redesign Instead of keeping duplicate file structures or nesting my React app in a subfolder, I decided to do a complete wipe of the repository and initialize Vite directly at the root of my Poorup folder [1.1.1]. My backend directory ( server/ ) with the working Socket.io logic stays at the root level, sitting side-by-side with my brand-new React source directory ( src/ ).Because i didnt want to rewrite that all Tailwind v4 & Vite Setup (React Redesign - Lab 1) I verified that the setup is 100% correct by creating a basic functional component in src/App.jsx and rendering a test heading styled in large, bold, violet text using Tailwind v4 utility classes [1.1.8]. It compiled instantly and loaded perfectly in the browser. Next Steps Now that the modern React + Tailwind ecosystem is up and running at the root, I am starting Lab Challenge 2 (React Redesign) . I’ll be creating a dedicated <LandingScreen /> component, managing the nickname input using React useState hooks, and connecting Socket.io to React to emit player connection data back to the server [1.1.1, 1.2.6]. You know lab challenges for this i will watch some more videos leanr more js and learn react if possible Conclusion Deciding to start over from a blank folder was tough, but it was absolutely necessary. The codebase feels incredibly clean and changing to React will save me massive amounts of time as I start building out the actual Monopoly gameplay. But i now learned alot in the time i decided to atleast built the lobby and board in vanilla js,css and html. Also anybody knows an ki which is good in front end because i just realised iam trash in front end and ki is too"}, {"post_id": 5131, "ts": "2026-06-08T20:23:58Z", "hours": 1.7286, "text": "Overview This phase was important even though it was short. I transitioned from basic static mockups to building a fully functional, real-time multiplayer lobby system. I resolved tricky logical bugs and fought port conflicts, I also expanded my knowledge on js and am probally going to need to take a break to really learn all of js and will soon watch a 22 hour tut. Fixing the SPA Screen Switch (Lab 9) I started by tackling the dynamic transition from the login screen ( #landing-screen ) to the lobby screen ( #lobby-screen ). Space in HTML ID: I accidentally wrote id=\"landing screen\" (with a space) in my HTML, which broke my JavaScript’s querySelector because IDs cannot have spaces. Once I replaced the space with a dash ( id=\"landing-screen\" ) Now it works perfectly fine. Port Conflicts Right after getting the transitions working, my local server crashed on Port 3000. My terminal crashed and restored its history, leaving a Node process running in the background and locking the port i still dont know why it does that just looked on reddit and youtube. To easily bypass this without fighting Windows process managers, I updated my server.js and local client connection to run on Port 3005 . It started up instantly. Designing the 3-Column Lobby (Lab 10) With the screen switching working, I redesigned the lobby HTML to match the responsive 3-column layout of Richup.io [1]. I used Flexbox ( flex: 1 and flex: 2 for the center) to align: Left Column: A placeholder invite link input and a scrollable chat area [1]. Center Column: The player greeting, token color picker, and “Join Game” button [1]. Right Column: Game settings (dropdowns for starting cash) [1]. Structuring this required a bit of tweaking but not to hard. Interactive Color Picker & Socket Events (Lab 11) Next, I tackled the token selection grid [1]. I styled four distinct color circles (Red, Blue, Green, Yellow) in CSS and set up a .selected class that applies a thick white border and a glowing shadow. In client.js , I wrote a forEach loop that listens for clicks on each circle, removes the .selected class from all others, adds it to the active circle, and stores the selection in a global variable. On the server side, I set up a 'join-room' socket listener. Now, when a player selects a color and clicks “Join Game”, the client emits the color choice, and the backend successfully receives and logs it in the terminal [1]. Server-Side Multiplayer Sync (Lab 12) The most exciting part and hard part today was implementing real-time state synchronization. I declared a global activePlayers dictionary on the server to keep track of active sessions. When a user logs in, they are registered in the dictionary. When they choose a color and click “Join Game”, their color is updated, and the server broadcasts the entire updated list to all active clients via io.emit(\"update-players\") [1]. On the client side, I wrote a listener that clears out the #player-list and dynamically rebuilds it, coloring each player’s username text to match their selected token color. I also handled the 'disconnect' socket event to delete players from the dictionary when they close it. You can see the messaged in the terminal and yes it is antigravity but i dont use the ai and have only used it to refractor my notes, so i dont even have tokens anymore cause of the amount of notes i had. So i also decided i probally need to expand my file directory and iam thinking of using tailwind css or just using css and making custom icons using favicons and etc by using figma also i got approved for the Student github :)."}, {"post_id": 4397, "ts": "2026-06-07T18:32:25Z", "hours": 3.6853, "text": "Overview Today was massive for Poorup. I officially made the first steps into the website, creating the backend for the hompage and creating the CSS.. Transitioning From HTML to CSS I officially finished the basic HTML path on freeCodeCamp! It feels great to have the basic foundation down. I am still missing a lot of depth in semantic HTML and more advanced stuff, but I have enough of experienc to now build on it. I just need to learn some more js and CSS. I then watched some video regarding CSS and worked on it. I realised that CSS is really simple but involes alot of googling to find certain functions . I did one rooky mistake which was having the css file not in the right folder so it wasnt loading correctly and i was quite suprised Backend & Real-Time Socket.io Integration This is where the real engineering started today. Since Poorup is a real-time multiplayer board game, I can’t just use standard HTTP requests where the browser has to reload every time a player moves. I needed a permanent, open connection between the browser and the server. I set up a Node.js server with Express in server/server.js to serve my static folder. Then, I integrated Socket.io: Express Server: Serving the public folder on http://localhost:3000 . Socket.io Setup: Wrapped the Express app in an HTTP server and configured the connection listeners. Client-Side JS: Wrote client.js to capture input data and handle form events. The Struggle: I ran into a bug where clicking “Play” triggered the server connection even when the username field was completely empty, which bypassed my HTML required attribute. After digging into my event listeners, I realized I was listening to the click event on the button instead of the submit event on the form . Since the browser’s native validation only checks fields during a form submission, the click listener was bypassing it. Switching my listener to form.addEventListener(\"submit\") fixed the empty-name validation instantly. When I run node server/server.js now and type a name in the browser, the server terminal immediately logs the connection and prints the player’s name in real-time. Next Steps & Screen Switching Now that the backend is running and successfully communicating with the client, my next step is handling the UI transitions. Since we don’t want a full page reload (which would kill the WebSocket connection), I am working on setting up a Single Page Application (SPA) structure ,aksed ki what to do next by usign my earlier stated Lab approach in which i dont get code but how to do stuff and have to implement it. I am currently working on Lab Challenge 9 , where I will be wrapping the login screen in a #landing-screen div and the lobby in a #lobby-screen div. I’ll use JS to dynamically swap the .hidden class as soon as the server acknowledges that a player has successfully joined. Conclusion Overall, this phase was a huge step up from just writing static tags. I’m taking active notes on everything which you will later find in a second repo so you can build it your own with all the Lab challenges. I find it to be quite rewarding but now i have to lock in for school cause i got a vocabulary test in 2 days. I will probally upload a demo soon an do some major changes to color, theme, name and etc for copyright reasons"}, {"post_id": 3686, "ts": "2026-06-06T18:51:12Z", "hours": 2.2747, "text": "Stardance Progress Log: Poorup Development Current Progress Learning Path: Almost completed the Basic HTML section on freeCodeCamp. Note-taking: Iam taking personal notes on semantic HTML, document structures, tags, and form elements. My Learning Methodology (AI as a Mentor) To make sure I actually understand every line of code I write, I am using a strict, self-guided approach to learning: First of all i have strictly said to the ai to never write code for me and never give me the answer and just show me how i could achieve it. Also the ai acts strictly as a mentor. It analyzes my goals and designs custom “Lab Challenges” formatted exactly like freeCodeCamp exercises (with Objectives, User Stories, and Test suites). Because i found this to be quite efective. Also i decided to install the live preview extenstion to see my code in person and debug it easiear. What I’ve Built So Far Landing Page Structure: Created a solid textual game menu and lobby framework in public/index.html using headings ( h1 , h2 ), paragraphs, an unordered list for features, and an ordered list for instructions. Interactive Elements: Added call-to-action buttons for joining and creating lobbies. Next Steps Currently working on Lab Challenge 2 given by the ai: The Player Registration Form to practice form validation, input types (text, radio, checkbox), and connecting labels with inputs via attributes. Once HTML basics are solid, I will start exploring basic CSS styling."}, {"post_id": 2926, "ts": "2026-06-05T20:35:05Z", "hours": 0.7811, "text": "I have now started with creating the Github and also learning some HTML with free Code Camp. I also decided to take some notes in a md file reading through the guides"}]...
|
Title: Poorup.io by @jeremy | Stardance
Devlogs:
Title: Poorup.io by @jeremy | Stardance
Devlogs:
I have now started with creating the Github and also learning some HTML with free Code Camp. I also decided to take some notes in a md file reading through the guides
Stardance Progress Log: Poorup Development Current Progress Learning Path: Almost completed the Basic HTML section on freeCodeCamp. Note-taking: Iam taking personal notes on semantic HTML, document structures, tags, and form elements. My Learning Methodology (AI as a Mentor) To make sure I actually understand every line of code I write, I am using a strict, self-guided approach to learning: First of all i have strictly said to the ai to never write code for me and never give me the answer and just show me how i could achieve it. Also the ai acts strictly as a mentor. It analyzes my goals and designs custom “Lab Challenges” formatted exactly like freeCodeCamp exercises (with Objectives, User Stories, and Test suites). Because i found this to be quite efective. Also i decided to install the live preview extenstion to see my code in person and debug it easiear. What I’ve Built So Far Landing Page Structure: Created a solid textual game menu and lobby framework in public/index.html using headings ( h1 , h2 ), paragraphs, an unordered list for features, and an ordered list for instructions. Interactive Elements: Added call-to-action buttons for joining and creating lobbies. Next Steps Currently working on Lab Challenge 2 given by the ai: The Player Registration Form to practice form validation, input types (text, radio, checkbox), and connecting labels with inputs via attributes. Once HTML basics are solid, I will start exploring basic CSS styling.
Overview Today was massive for Poorup. I officially made the first steps into the website, creating the backend for the hompage and creating the CSS.. Transitioning From HTML to CSS I officially finished the basic HTML path on freeCodeCamp! It feels great to have the basic foundation down. I am still missing a lot of depth in semantic HTML and more advanced stuff, but I have enough of experienc to now build on it. I just need to learn some more js and CSS. I then watched some video regarding CSS and worked on it. I realised that CSS is really simple but involes alot of googling to find certain functions . I did one rooky mistake which was having the css file not in the right folder so it wasnt loading correctly and i was quite suprised Backend & Real-Time Socket.io Integration This is where the real engineering started today. Since Poorup is a real-time multiplayer board game, I can’t just use standard HTTP requests where the browser has to reload every time a player moves. I needed a permanent, open connection between the browser and the server. I set up a Node.js server with Express in server/server.js to serve my static folder. Then, I integrated Socket.io: Express Server: Serving the public folder on http://localhost:3000 . Socket.io Setup: Wrapped the Express app in an HTTP server and configured the connection listeners. Client-Side JS: Wrote client.js to capture input data and handle form events. The Struggle: I ran into a bug where clicking “Play” triggered the server connection even when the username field was completely empty, which bypassed my HTML required attribute. After digging into my event listeners, I realized I was listening to the click event on the button instead of the submit event on the form . Since the browser’s native validation only checks fields during a form submission, the click listener was bypassing it. Switching my listener to form.addEventListener("submit") fixed the empty-name validation instantly. When I run node server/server.js now and type a name in the browser, the server terminal immediately logs the connection and prints the player’s name in real-time. Next Steps & Screen Switching Now that the backend is running and successfully communicating with the client, my next step is handling the UI transitions. Since we don’t want a full page reload (which would kill the WebSocket connection), I am working on setting up a Single Page Application (SPA) structure ,aksed ki what to do next by usign my earlier stated Lab approach in which i dont get code but how to do stuff and have to implement it. I am currently working on Lab Challenge 9 , where I will be wrapping the login screen in a #landing-screen div and the lobby in a #lobby-screen div. I’ll use JS to dynamically swap the .hidden class as soon as the server acknowledges that a player has successfully joined. Conclusion Overall, this phase was a huge step up from just writing static tags. I’m taking active notes on everything which you will later find in a second repo so you can build it your own with all the Lab challenges. I find it to be quite rewarding but now i have to lock in for school cause i got a vocabulary test in 2 days. I will probally upload a demo soon an do some major changes to color, theme, name and etc for copyright reasons
Overview This phase was important even though it was short. I transitioned from basic static mockups to building a fully functional, real-time multiplayer lobby system. I resolved tricky logical bugs and fought port conflicts, I also expanded my knowledge on js and am probally going to need to take a break to really learn all of js and will soon watch a 22 hour tut. Fixing the SPA Screen Switch (Lab 9) I started by tackling the dynamic transition from the login screen ( #landing-screen ) to the lobby screen ( #lobby-screen ). Space in HTML ID: I accidentally wrote id="landing screen" (with a space) in my HTML, which broke my JavaScript’s querySelector because IDs cannot have spaces. Once I replaced the space with a dash ( id="landing-screen" ) Now it works perfectly fine. Port Conflicts Right after getting the transitions working, my local server crashed on Port 3000. My terminal crashed and restored its history, leaving a Node process running in the background and locking the port i still dont know why it does that just looked on reddit and youtube. To easily bypass this without fighting Windows process managers, I updated my server.js and local client connection to run on Port 3005 . It started up instantly. Designing the 3-Column Lobby (Lab 10) With the screen switching working, I redesigned the lobby HTML to match the responsive 3-column layout of Richup.io [1]. I used Flexbox ( flex: 1 and flex: 2 for the center) to align: Left Column: A placeholder invite link input and a scrollable chat area [1]. Center Column: The player greeting, token color picker, and “Join Game” button [1]. Right Column: Game settings (dropdowns for starting cash) [1]. Structuring this required a bit of tweaking but not to hard. Interactive Color Picker & Socket Events (Lab 11) Next, I tackled the token selection grid [1]. I styled four distinct color circles (Red, Blue, Green, Yellow) in CSS and set up a .selected class that applies a thick white border and a glowing shadow. In client.js , I wrote a forEach loop that listens for clicks on each circle, removes the .selected class from all others, adds it to the active circle, and stores the selection in a global variable. On the server side, I set up a 'join-room' socket listener. Now, when a player selects a color and clicks “Join Game”, the client emits the color choice, and the backend successfully receives and logs it in the terminal [1]. Server-Side Multiplayer Sync (Lab 12) The most exciting part and hard part today was implementing real-time state synchronization. I declared a global activePlayers dictionary on the server to keep track of active sessions. When a user logs in, they are registered in the dictionary. When they choose a color and click “Join Game”, their color is updated, and the server broadcasts the entire updated list to all active clients via io.emit("update-players") [1]. On the client side, I wrote a listener that clears out the #player-list and dynamically rebuilds it, coloring each player’s username text to match their selected token color. I also handled the 'disconnect' socket event to delete players from the dictionary when they close it. You can see the messaged in the terminal and yes it is antigravity but i dont use the ai and have only used it to refractor my notes, so i dont even have tokens anymore cause of the amount of notes i had. So i also decided i probally need to expand my file directory and iam thinking of using tailwind css or just using css and making custom icons using favicons and etc by using figma also i got approved for the Student github :).
Overview This phase was a major point for the project. After successfully implementing the lobby chat and the 11x11 Monopoly board using Vanilla JS and CSS Grid, I realized that managing the game states (turns, money, properties, transactions) in Vanilla JS was going to lead to unmanageable spaghetti code and was way to hard. To keep the project clean and professional, I decided to perform a complete “hard reset” and refactor the entire frontend into a modern React Single Page Application (SPA) utilizing Tailwind CSS v4 [1.1.1, 1.1.8]. I always though about using it but found it weird and dififult for a beginer The Great Redesign Instead of keeping duplicate file structures or nesting my React app in a subfolder, I decided to do a complete wipe of the repository and initialize Vite directly at the root of my Poorup folder [1.1.1]. My backend directory ( server/ ) with the working Socket.io logic stays at the root level, sitting side-by-side with my brand-new React source directory ( src/ ).Because i didnt want to rewrite that all Tailwind v4 & Vite Setup (React Redesign - Lab 1) I verified that the setup is 100% correct by creating a basic functional component in src/App.jsx and rendering a test heading styled in large, bold, violet text using Tailwind v4 utility classes [1.1.8]. It compiled instantly and loaded perfectly in the browser. Next Steps Now that the modern React + Tailwind ecosystem is up and running at the root, I am starting Lab Challenge 2 (React Redesign) . I’ll be creating a dedicated <LandingScreen /> component, managing the nickname input using React useState hooks, and connecting Socket.io to React to emit player connection data back to the server [1.1.1, 1.2.6]. You know lab challenges for this i will watch some more videos leanr more js and learn react if possible Conclusion Deciding to start over from a blank folder was tough, but it was absolutely necessary. The codebase feels incredibly clean and changing to React will save me massive amounts of time as I start building out the actual Monopoly gameplay. But i now learned alot in the time i decided to atleast built the lobby and board in vanilla js,css and html. Also anybody knows an ki which is good in front end because i just realised iam trash in front end and ki is too
Project Update: The Great Refactor & React Integration 📋 Overview Damn this looks trash just a small update and i jsut noticed tailwind actaully looks like trash are there any alternatives because i didnt expect it to look this bad in comparison to before and yes i do know its looks aigenrerated but i did myslef also tailwind is pretty easy if you get the hang of it just looks trash maybe going to watch some tuts cause i cant upload the final product like this.
#Overview So today i didnt really code just refactored again and went back to css and decided to design all design elements in figma. It was pretty easy and II am now qustoning why i didnt do that instead also i only copied these 2. I will make my own streets afterwards and i also decided to redesign the website because it realy just a copy and i dont want to be sued but the board will probally look the same just different countries and maybe prices need to look for balancing and how it is normally in monopoly. But this probally going to take 2 to 3 days cause i really dont got any time in the next few days.
Overview Over the last few days, I’ve been triying to refactor my project, but i realised something I killed it i refactored it so often that i lost sight of the real goal and will proablly start from scratch restarting it from 0 i designed and svg file but just couldnt implement the right way. Cleaning the SVG My biggest headache was the game board. I designed a beautiful, detailed map in Figma, but exporting it as an SVG just made things difficult i tried making i clickable but i didnt know how to and i found no totorials regarding this so i will probally just create a board using html and css or maybe look for solution using ai Current System Status At the moment i have decided to refractor to vue by advice of some friends and ai because it makes the backend easier but i will proablly change back, because iam realising Iam making the project more complex than it has to be also. Conclusion I just wasted time trying to learn new stuff an refractoring and trying to not use ai. I would like for some adivice which ai I should use and if I should stick with vue or stay with or change back to default also this made me reflect on what kind of perfectionist iam an I will probally wrap up this project in the next few days because I realised front end is not for me I will continue learning it but will soon work on either python or C project after. I will just add the missing features with Ai
Overview Today I worked on the front end an am basically finished with the easy stuff Iam now going to add the player icon and etc Front End I designed my front end and i think i can say that I am pretty good at basic JS/HTML/CSS and this project teached me alot Iam probally going to wrap it up in the next 2 post and focus on smth else. Monopoly repo After resarching a bit i found another open source monopoly game and my plan is now to copy some backend logic from it but i need to adjust it because his game is made to be playable localy and mine online so it will take same adjustment #Backend I added a Room system with the help of mutipile videos in which a random room code is generated and the server saves the generated room code making it possible for another use to insert it. The code will be if the round was ended.
Poorup — Production Ready Over the past few days I’ve been doing a full production-readiness pass on Poorup . Here’s what I worked on: Bug fixes — Fixed auction edge cases where a disconnecting player would leave a ghost bid, locking the game Memory leak prevention — Added a garbage collector on the server to clean up empty rooms after 10 minutes UI polish — Fixed text cut-off in buttons and settings toggles, improved layout consistency across screen sizes Layout centering — The game board is now properly centered vertically and horizontally in the viewport Accessibility — Added focus-visible styles for keyboard navigation New setting — Exposed the “Double rent” toggle in the UI (the rule already existed in the engine) Code quality — Added JSDoc comments to core server classes, removed dead code The game is now polished and stable. Im shipping it
Update: UI/UX Fixes, Auction System Fixes, and Property Manager Integration FInal This update focused on providing a better user experience and just making it less buggy Key Changes 1. UI/UX Improvements Refactored layout components to improve visual consistency. Updated navigation paths so it makes more sense for the User and is just more logical Adjusted CSS rules to improve the game across different screen sizes. 2. Auction System Fixes Addressed synchronization issues with the auction state. Fixed logical errors in bid processing and countdown timers. 3. Property Manager Integration Fixed the Property Manager feature, allowing users to track and organize their properties. Integrated the property database schema with the existing auction mechanisms. Created user views for listing and editing properties. So just new UI 4. General Bug Fixes & Stability Cleaned up left over parts of old system
Project Update: Bug Fixes Overview This phase was all about polishing the user experience, squashing gameplay bugs, and adding new repository documentation. After getting feedback I decided to change The whole UI Dynamic Theming & UI Improvements One of the major frontend improvements in this sprint was fixing the player icon chooser button functionality in the web interface. Fully redesignen the Front-End and more. I first of all started with replacing my .root with some new colors which are greenish. I also added some simple fade in/out animations to all Popups. Another bug was that it couldn’t quite fit in a screen of the size 1980 x 1080. I fixed that by making it possible to scroll down so everything you need for the game is shown on your screen. The way i tested it is by local hosting it and then pressin F12 in the browser and then you could adjust the size of the Window which was pretty neat. Also fixed a lot more of UI bugs such as weird buttons and more but this was the important stuff. Squashing Gameplay Bugs I knocked out two major bugs in this update: Trading System Fix: There was a bug where it wasnt possible for people to only request something without giving anything or make only money transactions so I fixed this. Special Property Popups: I resolved a rendering issue with the popups for special properties, specifically the Airports and Companies (Utilities). Now, when a player interacts with these tiles, the modal correctly pulls the specific data object and displays the unique rent calculations and purchase prices. Documentation Revamp I updated the README.md to ensure the decumentation was on point for anyone cloning the repo. I refactored and renamed SHOWCASE.md to Instructions.md . This provides a much clearer, step-by-step guide on how the game operates and how to get the local server running instead of just showcasing the Repo more. Conclusion The feedback was essential and really showed me how sloppy I worked it should now work perfectly even though i couldnt test it for 4 people
Poorup Redesign So after my last ship i read through all the reviews and have decided to continue this project even though i really didnt plan for that. So there were 3 addition people wanted. A new UI, being able to join random people, better Animations and a Dev mode to test in solo player possibly with mods. What did i do? So i first started with thinking of a new design route so i asked chatgpt for some references of a good design. I decided on making the Whole Ui pixellated similar to the Arcade style and fully redesingen the SVG witth and now iam going to go over it and adjust it to fit ours. Of course this took like around 6 hours but I use figma on desktop and the browser tracking of hackatime doesnt seem to work how do you like the new svg? Next Steps Next Steps i redesignen the Full Ui to fit this pexelated style and making sure it looks good
Poorup Redesign – Devlog #2 This phase was about continuing the complete redesign of the website, deciding on a UI theme, and implementing a new feature that I had wanted from the start but was not advanced enough to create before. New UI I am very proud to announce a complete redesign of the application. I decided to fully embrace a pixelated theme, and I personally think it looks great. It is genuinely one of the best UI systems I have ever designed. New Feature I decided to expand the trading system. You can now give out loans in exchange for premiums, equity, money, and more. This allows you to create fully customizable loans, such as: I give you $200 for 30% permanent equity in this spot. This means that you have to pay 30% less rent when you land on it and gain 30% of all rent paid on that plot. This is a system I have never seen in a Monopoly game, and I wanted to implement it from the start when I first had the idea for Poorup. New Feature #2 I have also decided to take the advice I was given and implement a room system. This allows players to join and create rooms, as well as make them public or private. I also added a quick-table feature that matches you with other people who have pressed the button, allowing you to play a quick round with random players. New Feature #3 I have created a complete profile system. You can now create a profile, view your statistics, win percentage, average money, and more. You are also able to create custom 32×32 icons to use while playing the game. New Feature #4 I also decided to add sounds and an open-source soundtrack I found called Pondering the Cosmos . which i think fits my new theme perfectly but maybe iam going to change it Next Step AI Bots The next Step will be adding bots but normal bots are boring they are just glofired search engines why i want to be a bit creative. I will use hackclub ai provider and give the bot a brain by combinging them with an AI like deepseek v4 flash this means the bot will be able to check how is he performing what are the most logical steps sell buy properties and trade and if wanted even chat with the user to make a deal would anybody like that?
Poorup Redesign – Devlog #3 This phase was about expanding the social side of Poorup, adding more depth to the game, and planning future systems that make every round feel more alive. Social, Rankings, Achievements I added a complete friend system. Players can search for unique usernames, send and accept friend requests, remove or block players, report users, invite friends to rooms, and view public profiles without leaving the lobby. Profiles now include statistics such as wins, win rate, games played, average money, bankruptcies, achievements, and match history. I also added global rankings for wins, win rate, games played, achievements, and other statistics. Rankings and Social are now independent tabs instead of modals, with wider layouts that use the available screen space more effectively. Achievements now have custom pixel-art and SVG icons, rarity levels from Common to Mythical, filters, dates, categories, and clickable detail modals. Mythical achievements are extremely rare and can trigger a server-wide announcement for every player. Easter Egg I added the hidden Parlor Patrol minigame. Pressing CTRL + P on the home screen opens a secret mode where you shoot down police helicopters, planes, and drones. It includes custom explosions, animations, sounds, score tracking, and a secret achievement. Global Events Global Events are rare events that affect every player instead of only the person who landed on a tile. They can be triggered by round conditions or Surprise cards and can last several rounds. Ideas include: Housing Bubble Pop Credit Freeze Inflation Spiral Bank Run Interest Rate Shock Airport Strike Energy Crisis Tax Scandal City Election Rent Control Tourism Boom Supply Chain Breakdown Events can combine with each other, create unexpected situations, and unlock secret achievements. I also want a global-event setting that is simply on or off, while event strength and duration scale with the round length. Rules Page I added a complete Rules tab designed like a pixel-art game manual. It explains the board, movement, properties, loans, cards, achievements, global events, social features, and settings. It uses an internal book-style scroll so the main application does not become a long scrolling page. Future Systems I am also planning a casino system using virtual money, with red, black, and green bets where the odds are not equal. Another planned feature is a fictional stock market connected to properties, countries, airports, utilities, and global events. Events could crash markets, increase rent values, affect airports, or create temporary investment opportunities. I also want to add unethical and outrages bank loans with high interest, strict repayment rules, and serious consequences. Music/sound icons I also added simple music and sound icons for the buttons instead of having the music on/off text Next Steps The next phase will be making these systems work together while keeping the game balanced, and also adding AI bots which utilise AI like deepseek v4 and so on so they able to actually judge the situation and think of possible ways for them to win. The aim is to use hcai to power them. I will also add normal BOTS as a fallback if my usage runs out
Poorup Redesign - Devlog #4 This phase was mainly about setting up codescene doing a full restructuing with the help of AI and fixing bugs and adding missing features. I also added a simple, gambling and stock market system. Bots I first started with setting up the initial idea of bots so to the UI and a bit of the backend logic for bots and how they will interact with the game iam nowhere finished and I havent tried it out yet. Codescene After checking out the github studentpack again after a while I saw codescene, which is a code reviewer similar to coderabbit. I struggled a bit with the Setup but after running an analysisi I noticed how abysmall my codebase really is and how its missing structure, archtiectuer and etc, for example sepearting certain getures from game logic.js and creating their own thread for it. I also setup a full pr pipieline which I can use with my AI agents which aim will be fixing my architecture, and finding bugs before i push them. bugs I ran Qwen 3.8 flash on my pr pipileine with codescene and let it work indepnedlty to full restructer my codebase so the results are better and I have better architectural design I also let it fix any bugs it found. Bugs I found While trying out the game i found mutipile BUGS one of them affecting my secret minigame palor patrol. For some reason I was losing hearts for no appearent reason. The reason behind it was that even though UI was hidden the helicopters were still flying through. For some reason the heart bug still exists afterwards and even the AI isnt able to find out what it is so Iam completating making architecture changes to it. #Gambling I added a smile gambling system where you can bet money on a roulete on red, black, and green I didnt add any animation for it as I found it unecessary and I also made sure iam legally clear to make sth like this Stock market I created a simple stock market tab and backend which allows people to buy indexes of a property and made sure to connect it with global events so global events can affect the stock market but that is nowhere near usable. Next Steps Iam going to let my AI continue improving my codebase with codescene and continue the Stock market and afterwards add the bots.
Poorup Redesign - Devlog #5 This phase was mainly about fixing all bugs still exisitng, refactoring further with codescene and letting AI run over my code, also fixed some small missing features and simple bugs myself. Choosing Icon I noticed a bug in which because of logic I made before setting up custom icons the programm mapped custom icons people created onto persets and blocked them so for example your icon had red in it, the game decided to map it onto the red preset in the backend blocking it but showing yours in game, this came because I never rewrote this section after introducing custom icons. Ownership icon Before this change owenship on board was only shown with a simple like quadrat in the top right corner of the tile in the color you picked this is also something left over from the old preset logic. I decided to make it so It shows a smaller version of the face of the player which makes it look a lot cleaner. Missing Buttons This was mainly because I let AI write to much of my code, the finical trading tab which is centered around equity and everything missed a dropdown to choose who you send the trade to and even the button to send the trade which was a dumb oversight on my end. I also added a simple backend system for the dropdown inside that modal to only show the propertys a person owns. Bots I also continued working on the bot system though this was mainly watching tutorials and brainstorming further Next Steps Fix last bugs, fully add bot system and make sure UI looks good to release the first beta test hopefully the next post will be the last
Poorup Redesign - Devlog #6 This phase was mainly about adding more depth to the player interactions, improving the bot system, and making the rankings feel more alive. Deal Negotiation I redesigned the deal flow so trades, loans, equity, and hybrid deals all work in the same way. When you receive a deal, a modal appears with accept and negotiate. If you close it, the deal does not get declined and stays inside the Finance rail. Both players can now see the same deal collapsed in Finance. The receiver can negotiate, while the sender can adjust or cancel the deal. You can open a full read-only view, change the parameters, and send the new version back. The server also checks old deal IDs so an outdated modal cannot change a newer deal. Sponsored Purchases I also added sponsored purchases. If a player cannot afford a property, they can ask the table for help. Other players can reserve contributions, and once the full amount is available, the buyer accepts and is forced to buy that exact property. The money is automatically returned if the request is canceled, the property changes owner, or a player disconnects. It is not a loan and does not create equity. Bots I continued improving the AI and no-AI bots. The bots now receive more context about the board, current obligations, loans, events, opponents, future rent risk, expected cash flow, and their own previous decisions.AI bots can now also counter trades, negotiate player contracts, choose debt rescue actions, and make auction decisions. If the AI provider runs out of credits or fails, the no api key AI takes over Rankings I added recent trend indicators to the ranking rows, so you can see if a player is moving up, down, or staying flat. I also added a seasonal ranking scope based on the current calendar season. Rules Fixes I also fixed the Double GO setting so landing exactly on GO now pays the boosted amount, while simply passing GO still pays the normal amount.TestingI expanded the tests and ran long bot campaigns with auctions, loans, casino, market, global events, sponsorships, and negotiations. The latest regression suite passes and the longer 2,500-game campaign had zero stalled games. Next Steps The next major step is making the bots simulate several complete future turns and improving long-term negotiation behavior. After that I want to add deeper browser testing and seasonal ranking rewards. Also to lazy to do screenshots of new UI so you will get everything in the next devpost
Poorup Redesign - Devlog #7 This phase was mainly about doing a full audit over the game, fixing bugs which were still hidden inside the server and UI, and making the whole project easier to trust before the next merge. Finalising Bots, adding, themes adding new suprise features and more. Themes I decided to create 5 more themes which will fully change the look of the game, for the 5 i decided on 5 directions first of light mode, and then the 4 seasons so summer,autumm, winter, and spring. These took quite some time to create but I think they came out quite decent though they still need cleaning up Ranking Seasons I have now added ranking seasons which are 1 month each if you manage to rank on the leaderbaord at the end of the season you get a special cosmetic(newly added system) and a special Title Cosmetics I added a full cosmetics system and the ranking system so you can now get cosmetics from 2 places, either by getting them at the end of the season form the leaderboard or by getting them from achievements Card Upgrade I also now added the features to upgrade your bank account, if you pay enough money you can upgrade your card for 1000$ this gives you a card with 5% cashback which is the Spaarkasse karte(german Bank) and the nex level is the amex black card wich give you 10$ cashback and amex points which you can use for flying. Gambling UI I also decided to now give the gambling UI an animation it now has the same kind of case opening animation as CS2 so the roulette which goes form right to left. Plane station card Also made it so that you can now use the airplanes to skip things so you can fly to another station but of course you will have to pay alot and you have to pay a landing fee. If a player owns an Airpot he can decide the flying fee himeslf and the landing fee which means he could extort people if he is smart enough Quick Table I did some changes to Quick Table as it used to create a new public room every time. It now checks the live public room directory first, joins the most suitable open table, retries if somebody fills it during the join, and only creates a new Standard-40 room when no table can be joined. Private room codes are never exposed and the server still makes the final decision. Favicon I also designed a quick little favicon which is Just a P with a box around it but it looks quite good Music Candidates I am now searching for new Music for each theme so music changes with the theme Next Steps Cleaning up the UI one final time trying everything out and finally realsing the Beta and promoting it on reddit.
Poorup Redesign - Devlog #8 this phase mainly about consolidating the backend and adding a New admin only dashboard which will allow to analyze things easier for balane patches and etc in the future. This Phase was written only by hand hence the long time, normally I would use AI to speed up the process but I wanted to get some practice in. Also added legal and TOS pages Backend I found mutipile bugs such as simple Game bugs to not so simple leackage problems and other stuff which took quite some time to fix by hand and this really shows how I will probally pause using AI for coding after this project for a while Admin Dashboard I created this Dashboard so I would be allowed to pracitally analyze everything from how certain things affect the game and for example analyze them to see if they need fixes, balances or even remove them entirly. I also added things like seeing a rough strucutre of where my player base is from. If anybody is abusing the game somehow or bot traffic. Tos Pages These took quite long and were quite the hassle but I did it. though i am debating jus tdeleting them as I couldnt fill them out entirley as certain information is needed which would then make them 100% fool proof I forgot I also updated the Snow Theme and added music for each theme with a small music player in the bottom left though I just noticed I placed the icons wrong should be a quick 2 line fix Next Steps do the last fixes finnaly test the AI bots as they are fully setup but not setup do some balancing and realese it The next post should really be the last. Hopefully.
Poorup Redesign - Devlog #9 this phase was mainly about adding some missing things fully balancing everything also used the new model jev from typesafe as it was a perfect fit for the task. Admin Dashboard I now added a section in the admin Dashboard fully centered around the Bots which allows for dropping in any provider and choosing the model and see the request if theyre failing or not and etc this took quite a while as I coded this myself again as I wanted to practice a bit though I still needed Ai help as Iam so trash at js Removing TOS pages As i mentioned in the last devlog i have now decided to remove the TOS pages as they were jst not good looking and not complete and not needed. Music system I decided to remove the music player and rather make it so 1 music track is there for each theme and my next step ix expanding the profile page to allow choosing another music track as 12 are available in total but only 6 are used rn. I also decided that I am going to move the Theme chooser somewhere else as people get no indicator rn to find it New Idea for the Future Also I had a great Idea which i can incoperate into this but after the next ship. Its training a custom ml model on all the matches played by people and then incoperating it in the game. Because essentialy it would be a custom AI/Bot that is able to play monopoly as good as possible new features I also added the option to download all the data cause i noticed its saved on the server and maybe smb wants to download it will then be in a json. I also added the option to add an recovery email, because my plan is to allow people to sign up without email but they still need an option to recover data if needed I also added the option to rovoke all otehr session tokens then the onnes youre logged into rn, so essentially log out of all other devices and server sessions Next steps Cleaning up Ai code and reading through it all, 1 or 2 adjustments in Ui for example the global event banner needs to be relocated or the graphs for match history need to remade. Also the ranking page needs a little redesing. The next one will be the LAST ONE cause i cant deal with stardance anymore all my projects are getting rejected for dumb reasons, so this will be the last devlog and if it does not get accepted iam relocating somewhere else.
Poorup Redesign - Devlog #10 Iam aware this phase is 30 hours this is just cause i used hella AI and didnt want to count it towards my payout. this phase mainly about finishing touches running mutipile tests suits playing some games and finishing some things also fixing Ui and redoing the Ui of the Music First of all I added music for each of the 6 theme with a secondary theme which you can select under account and preferences I also made it easier to spot the different themes as they were hella hidden to be honest. Deactivation of palor patrol Though i didnt want to this I needed to deactivate palor patrol as it was simply impossible to use I checked m code in detail used and really did everything but I couldnt find the bug which makes it unplayablle so as long as I cant manage to fix it I have to deacitvate it. Next Phase pushing everything on nest setting up a piepleine so nest automatticaly pulls everything I push onto main in my repo and finnaly realsing it with thhe bots for players to use.
Poorup Redesign - Devlog #11 (FUCK MY LIFE) I am geniunly so tired of this project and my life in general i was so busy in the last few days cause of school and after shool clubs. This phase was mainly about recoding the Bot engine by hand, and updating the stock market modal inside the game also added New Ui for theme chooser and music and also added more sound tracks. I also redid statistics tabs in profile by hand and added better match history tracking Bot engine To be honest to Bot engine was so much AI stuff that i genuinly didnt understand what it was build on and how that is why I decided to take some time to read and research all the papers its build on and how it works. I then rewrote large parts of it to improve it and also found mutipile bugs in the logic of how it works and how it assigns values New account and preferences tab I fully redid some parts of the accounts and prefences tab to now allow for easier choosing of themes and also worked on the music engine so the music loops and youre able to choose different music depending on the theme. #Statsics tab I redid the whole tab as I found it quite stacked with 12 boxes for statsics and decicd to now add internal tabs to make it look cleaner this was a quick 30 minute changes as I didnt change logic but just frontend Next Steps Hopefully shipping adding HCAI and testing the AI bots and further UI refinement on tablet UI and 1440px desktop cause these are 2 of the most weirdest sizes https://poorup.jeremy-d.hackclub.app/ also if anybody wants to check it our but it is nowhere near finished so dont expect anything
Devlog after ship So after getting hella positive feedback regarding poorup which i highly appreciate my aim is to now make it have an even better user experience and etc. why? cause from the feedback i got, there are 3 areas I need to tackle, UI, game logic which is to complex and the User experience including rules and etc, Full redesign of the ingame lobby So after getting feedback that the board was to smallwhich was kinda expected and that the whole game is just clutered which i also assumed would happen cause all the features dont fit into the game i have done the following. I have redesigned the full ingame lobby with a new layout further inspired by richup(didnt want to do this but they have the most optimial layout) I have also redone the whole entire admin window cause to be honest it was horrondous and hard to use, and also just some small changes all around full redesign of modals so after doing the lobby i have now decided to fully redo a lot of the modal to have a better layout and etc so they are way more user friendly and acttually easy to understand, this also included cutting alot of features from certain modals because they just made them to complex and hard to use Cards and airpots this was something i was orrignally planning to release in the last ship but i just decided to ship it with this one i have finnaly added the option to buy new bank cards which you can use to get benefits like cashback of 10% on purchsees like rent payment suprise cards and other stuff, and I also added the option to use airpots to fly from one point to another and allow players to set the prices, Bots After reflecting a bit on my ai usage for the bots i decided to fully plug the whole programm into a repo which visualises it to see if it checks out with my mental map and I noticed so much slop which I would have never noticed before, this includes the whole Bot logic which i have probally never looked at cause i knew i wouldnt be able to code them. Though i probally should have cause this is the biggest slop i have ever seen and It introduced so many bugs which the ai couldnt find Next steps Right now all these changes are locally and not on github which are around +17000 lines of code and my aim is to further clean this up and fully push it with a new domain which is alredy online but will be kept hidden. here are soem before and afters, the more clutterd ones are the befores and the simplifyed ones after
Rework #1 Now you could be asking yourself? What have i done in the last 8 days to not post? Well Iam nearly finished with the full rework off all UI, Bug fixing and introducing new features, Chart Engine So i redid the whole system for charts and decided to build my own, because though i had one which worked it looked horrendous and really didnt fit poorup, you can see the new chart engine in the screenshot Game history I redid the whole entire game history system, because to be honest it was heavily vibed including its Ui and while cheking it, it looked like trash so I sat myself down and worked tiresly to fully redo it, and I even implemented the new chart system into it, Modals, Modals, Modals So I REDID NEARLY EVERY SINGLE MODAL IN THE GAME to provide a better User experience this took hella long and while doing it i noticed i had hackatime tracking off, because i had been working on some personal projects, hence the reason I only posted now because I lost so many hours, #Next Features Well to be honest there really arent anymore features i can add, the only thing left is fixing bugs and preparing it for the release and advertising it on reddit
Ships:
Poorup Poorup is a real-time multiplayer board game inspired by Richup(Monopoly), playable entirely in the browser What did I make? A full multiplayer board game running on a Node.js server with Socket.IO for real-time communication. The client is pure HTML, CSS, and JavaScript, no frameworks which is stupid if I look back on it . Features include: Room-based lobbies with a shareable room code Full Monopoly-style rules: buying, renting, building houses and hotels, mortgaging, and trading Live auctions with a countdown timer when a property is declined Configurable game rules per room (double rent, vacation cash, even build, auction, mortgage, randomized turn order, no rent in jail) Reconnect support — if you disconnect mid-turn, you can rejoin and resume In-game chat Automatic room cleanup when everyone leaves What was challenging? Shared states across multiple clients. Every player action, rolling dice, buying a property, placing a bid, has to be read server-side, broadcast to everyone, and reflected correctly on each client without race conditions or desync. Getting that right, especially during edge cases, took a lot of work. Edge cases in disconnects. A player disconnecting mid-auction is a different problem than disconnecting on their turn, which is different from the host disconnecting entirely. Each case needed its own handling: timers need to be cleared, pending actions need to be resolved, and remaining players need to stay in a valid game state. and i need alot of time and a bit of AI to fix that for me. Building a complete game UI with vanilla CSS. No component library, no utility framework — every modal, toggle, property card, and animation is hand-written. Honestly needed a lot of AI help here. Probally should have used a libary if I look back at it but it was fun to do it in plain CSS also for anyone wondering why the favicon is the one from vite i never deleted it and i wasnt in the mode to redesign a new one and tried to use the board map but that didnt work for some reason. What am I proud of? The architecture. The game logic lives entirely in gameLogic.js and has no knowledge of sockets or HTTP. The server in server.js wires events to logic calls and broadcasts the results. That separation made the codebase much easier to debug than it would have been otherwise but i needed AI to implement the idea i had the idea but wasnt quite able to do it. How to test it git clone https://github.com/jeremy341/Poorup.git cd Poorup npm install npm start Then open http://localhost:8080 in two separate tabs or browser windows.
Project Update I didnt even notice but all the changes i did i the last patches never got shipped so this one is about the last to changes which were adding modals, creating new UI and removing AI code check it out https://poorup.jeremy-d.hackclub.app/
Poorup — Biggest Update to date I’ve given the project a major overhaul, from its visual identity and everything else. This is geninuly one of the best projects i have created and iam proud to announce it I first started Poorup 3 and 1/2 months ago as a project to get introcude into webdesing and since then i have created 4 more website and revesiting it really shows my growth. Of course Ai was used by even then I could really feel my growth What was challening i decide to stay on CSS, html, and js instead of transferring it into another language for a simple reason i wanted to test how far i can push these 3 languages( i was just to lazy to learn a new language) How I used AI AI WAS USED IN THIS PROJECT for debugging and coding no UI or art generation. AI was a substantial coding and debugging tool, especially for backend work, bot logic, and tricky multiplayer edge cases. I used CodeScene to identify code-health hotspots. I wrote many page-specific backend features myself, then used GPT/Codex to help debug or split some larger hotspot files into smaller modules. Ai was also used to fix bugs in the Ipad Ui I created Poorup’s frontend UI and its SVG and art assets myself. AI helped in coding but never touched art. I didn’t compose the soundtrack. I selected open-source and other openly licensed tracks; their sources and license details are in the audio credits . I also rewrote the Git history to make the repository cleaner, so the current commit log isn’t a complete record of the project’s development. Also after around the 6th or 7th devlog i turned ai traccking of as to not fraud myself hours So if needed deplete hours. What’s new in this patch UI Full ui rework of everything nothing was left out every single Ui elemt was redone by scratch, with upto 6 themse each with their own custom soundtrack and background, this was the largest wish people had wished for when they reviewed my game and iam so proud of the UI. Boards and multiplayer New 40 and Metro-52 boards, with custom visual themes. Public rooms and private rooms with shareable codes; people can join as guests. Configurable rules, including double rent, vacation cash, even building, and randomized turn order. A deeper economy system Bank loans, player-to-player loans, equity deals, and hybrid contracts, with collateral and default consequences. Sponsored purchases: one player can fund another player’s property purchase in exchange for an agreed share. Negotiating now youre able to negotiate all offers you get instead of accepting or declining on the spot you can also keep them on hold An optional stock market for all the quant bros(gamblers) casino so now youre able to gamble Social I also added a full social systems with achievements, friends inviting people to lobbys seeing match history and more, also added the option to create your own 16x16 user icon Events one of the biggest features I decided to add global events which appear under certain conditions like to many houses standing which should reference the 2008 housing crises i also added stock market crash and alot more. Also global events can also combine to create seacil ones Parlor patrol this was supposed to be a cool minigame while waiting for your friends but it doesnt work and i cant fix the bug for the life of me so you can test it out but it doesnt work correclty all svg assets for it exist...
|
1792849780.3860598
|
1792936180.3860598
|
|
21382
|
Hadronize by @ethmarks | Stardance
|
ethmarks
|
1
|
118.0
|
2150
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-26T05:16:19Z", "hours": 118.0, "multiplier": 19.09, "payout": 2150, "blessing": "neutral", "text": "Hadronize: a quark-themed set collection game. It has a web UI with a custom SvelteKit virtual layout engine, a polyglot CLI that runs across Node, Deno, Bun, and the browser console, a QuickJS bot sandbox, a comprehensive test suite, and more. I’m really proud of Hadronize and hope that you enjoy it.", "repo": "https://github.com/ethmarks/hadronize", "demo": "https://ethmarks.github.io/hadronize/"}]...
|
[{"post_id": 35009, "ts": "202 [{"post_id": 35009, "ts": "2026-07-26T05:04:06Z", "hours": 0.4372, "text": "Shipping I did a few miscellaneous things like make the remote script endpoint production-ready, fix some typos across the project, and create a favicon in Inkscape. After I write this devlog, I’m going to press the big “Ship your project!” button. If you’re a reviewer reading this: I hope you enjoy Hadronize. It’s one of my biggest projects ever, and I’m really proud of how it’s turned out."}, {"post_id": 32762, "ts": "2026-07-22T03:54:56Z", "hours": 5.1389, "text": "Revised Readme (again) Still working on the README. I think that Hadronize is more or less ready to ship now, but there’s probably still a bit more polishing I can do. In my other Stardance projects, I’ve gotten really positive feedback on my READMEs, so apparently my writing style and README format of choice is a winning combination. I’ve been referencing my past READMEs and the Stardance README guide a lot while writing this one. The bulk of what I added was the How it Works section, which explains some of the technical details and design choices that I made. It’s a dense topic so it’s obviously a long section. At first it was just a wall of text, even when I tried to break it up with lists and subheadings. So I spent about half an hour taking screenshots and editing them in GIMP until I had decorative images that I was satisfied with for each subsection. I think that drop shadows on transparent backgrounds look really cool in README images, so I used GIMP’s drop shadow filter to add them to my screenshots (in addition to cropping, rounding corners, et cetera). I kept fiddling with the drop shadow settings and I didn’t want to go back and redo the images that I’d already done, so the shadows are kind of inconsistent, which really irks me but I don’t think is very noticeable. I also added a Running Locally section and fixed a few typos throughout the README. Lastly, I did a bit of work on the home page. I added a big screenshot below the intro paragraph, thanks to feedback from the awesome @Luksus , whose project you should totally check out ."}, {"post_id": 31601, "ts": "2026-07-20T04:06:53Z", "hours": 2.7375, "text": "Revised README I worked on updating and basically completely rewriting the README to something more polished. I still need to add more sections and revise what I have, but I think that it’s alright. I’m trying to strike a balance between not having enough content and being a wall of text. It’s also surprisingly difficult to come up with bullet points for the features list. After I finish up the README, I’m going to redesign the home page a bit. After that, I think I might be ready to ship."}, {"post_id": 31058, "ts": "2026-07-19T04:31:59Z", "hours": 6.4664, "text": "How to play page I wrote a page that explains how to play, assuming zero knowledge. I think that this’ll be helpful for onboarding, because this way they learn the rules at the same time as they learn how to use the UI, rather than reading the abstract and theoretical rules and then trial-and-erroring their way through the UI. The actual writing part took a few hours, and most of it was revision and trying to find better ways to phrase things. It’s nearly 1000 words, meaning I could turn it in for an essay assignment and not fail the word count, which is funny. But what also took a lot of time was making the visual aid. I had to record myself performing the same action in the UI many times to get a perfect take, and then I had to craft an ffmpeg command to crop and trim it because I refuse to use graphical video editors. Also my recording software kept stuffing H.264 video data in a webm container, which made ffmpeg freak out because that file is technically corrupted. I also had to figure out how to screen record on my phone to get a tap indicator, which I’d never done before. You can read the page here: https://ethmarks.github.io/hadronize/how"}, {"post_id": 30534, "ts": "2026-07-18T05:53:11Z", "hours": 3.6139, "text": "Discontinuing the ranking arena I’ve decided to stop working on the driver ranking arena. I already have an MVP that works well enough to kinda sorta determine which drivers are good and which are bad, but it’s not robust and it just sums up rankings rather than implementing an actual Elo algorithm . The reason I’m not going to continue working on it is that it seems like a lot of work, and I don’t think that it’ll provide any value. Like, at all. The root of the problem is that Hadronize just isn’t a strategic-enough game. There’s certainly some strategy, of course, and probabilistic modeling, but luck plays just as much of a factor. The cleverest Hadronize driver can still routinely lose to the dumbest one just due to slightly bad luck. So it doesn’t really make sense to build tooling for strategic bots if the strategy is not a very big aspect of the game. Thinking back, I’m not really sure why I decided to start working on the driver arena in the first place. It just seemed like the right thing to do at the time even though I now realize that it would be kind of useless. Anyways, I also created two new drivers. The first is called Kingslayer, and it just tries to steal from the player who’s currently winning. It’s not very good at actually winning, but it does make things more challenging for the other players. The second is called Gentleman (aka charm ). It’s obsessed with trying to collect charm quarks, because its a charming gentleman. I made it as a joke because I thought it was funny, but to my complete surprise it turns out to be a pretty good strategy? Not charm quarks in particular, but trying to collect a specific flavor of quark at all costs turns out to be surprisingly effective. It consistently wins more often than EVan, the driver that I specifically built to be a good strategy and that actually does probabilistic expected value calculations. I think that next I’ll start working on the README and documentation, because I haven’t updated the README in like 3 weeks and it’s extremely outdated."}, {"post_id": 29906, "ts": "2026-07-17T02:31:07Z", "hours": 1.8094, "text": "Benchmark Before I started working on the bot ranking arena, I did a quick sidequest to figure out how many games per second I could simulate. So I wrote this script to execute a bunch of games sequentially, then print the elapsed time and calculate the games per second rate. I ran the benchmark in Node 24.15.0 on my 4.40 GHz Intel i5-12450H using Bogo drivers: Simulated 82157 turns across 1000 games Took 109048ms (109.048s). Speed is 9.170273640965446 games per second So that was surprising. I was expecting a speed in the low thousands, but instead it was less than 10. I had a suspicion what was causing the slowdowns. To make sure, I swapped out the Bogo driver (which uses QuickJS) with a non-QuickJS driver that I made for testing, and reran the same benchmark: Simulated 53854 turns across 1000 games. Took 130ms (0.13s). Speed is 7692.307692307692 games per second (the turn count is smaller because the drivers used a different strategy which made games end faster) So, obviously, the slowdown is caused entirely by QuickJS. Which makes sense. Every time a QuickJS driver is invoked, it spins up a brand new QuickJS VM, configures it, executes the actual code, extracts the return value from the VM, disposes of the VM to avoid memory leaks, and then finally returns the value. Non-QuickJS drivers can just execute the code directly, and the code can be optimized very well by the JIT compiler that Node uses. So the solution seems simple, right? Just don’t use QuickJS for the drivers. Whatever the advantages of using QuickJS are, surely they aren’t worth an 839x decrease in performance. Well, unfortunately that’s not an option. More specifically, dynamically running strings of JS (like the driver code that users write at runtime) as native code is not possible, so I have to use a JS VM. And QuickJS is by far the best embeddable JS VM that I know of. So I just have to accept the slowness. This means that I’ll have to be clever about the bot arena, though. I can’t just brute-force a ranking with thousands of games if I can only run 10 games per second. btw, if you’d like to see how your PC does on my benchmark, just run these commands: git clone https://github.com/ethmarks/hadronize.git cd hadronize pnpm install pnpm bench --count 1000 --driver prng If your time is faster than mine, leave a comment to gloat."}, {"post_id": 29828, "ts": "2026-07-16T23:29:46Z", "hours": 6.7503, "text": "Bot editor I integrated the QuickJS driver code that I made last devlog into the rest of the site. Things I did: I made the QuickJS VM override the default Math.random function and replace it with a mulberry32 prng seeded by stringifying the game state and hashing it through djbs2 . So now drivers can still use Math.random without making the rng predictable or sacrificing perfect determinism. I gave the drivers names and descriptions. The prng driver is named “Bogo” (after Bogosort ) and the expected value driver is named “EVan” (because it’s a normal name that starts with the abbreviation of “ E xpected V alue”). I moved the code for the existing drivers into a centralized array, rather than in multiple different files that had to be imported individually. I’m calling this array the “stock drivers”. I added a bot editor page. You can check it out at https://ethmarks.github.io/hadronize/bots . I used contenteditable and Svelte’s bind:textContent to let users edit the title, ID, and description. I used Prism code editor as the embedded IDE for editing the actual driver code. I made the play page fetch the list of drivers from localstorage on page load, defaulting to the stock drivers. I also made the bot editor automatically sync the drivers to localstorage . I added a new driver strategy: tit for tat . As expected, it plays pretty terribly because that strategy just isn’t very good in Hadronize. I mostly made it so that users looking at the stock drivers can learn how to reference the timeline from the state. I think that next I’ll work on a driver ranking system so that when I make more drivers, I’ll know whether they’re better or worse than the others. I might research how chess ranking systems work and copy concepts from those."}, {"post_id": 29163, "ts": "2026-07-15T21:36:28Z", "hours": 1.3381, "text": "QuickJS drivers I can now store driver strategy code as strings, execute the strings as JS code using QuickJS , read the quickjs output, and use it as driver output. This might not sound like much of a difference, but it completely changes how I can run drivers. Before, all driver strategies had to be present in the actual source code. Now, they just have to be strings. Because we can manipulate strings at runtime, this means that we can create new drivers while the site is running without modifying the source code. In other words: this lays the groundwork for letting you create and play against your own drivers without making a PR to the repo. To make sure that my implementation works, I converted the expected value driver to use quickjs. I enclosed all of the actual logic in backticks, making it a giant string, and then passed the string through my quickjs driver factory function. I ran the expected value driver test suite, and it failed immediately because I forgot to remove the type annotations (quickjs can only execute plain JS, not TS). But once I fixed that, all 19 tests passed, and it seems to work perfectly from my playtests. I eventually plan on adding a page that uses Prism code editor to let users edit driver strategies and save them to localStorage. But first I’m going to add more features to the quickjs runtime. For example, I want to have it swap all Math.random() calls with a deterministic psuedorandom generator, so that way developers can use randomness without making it non-deterministic."}, {"post_id": 28712, "ts": "2026-07-15T04:13:36Z", "hours": 1.0886, "text": "New quark style I made new quark graphics, like I promised last devlog. I’m not really sure if it fits the aesthetic I’m going for, but it’s something , and I tried to make it extensible so that I can experiment with more styles later. I also added a dropdown menu in the setup flow so that you can select which style you want to use, though I might remove that in the future if I decide on one style to be the definitive one. The new style is just patterns masked onto the same flat color circles as before. Each flavor has a different pattern: up: vertical lines down: horizontal lines charm: checkerboard strange: square grid with irregular shading top: light dot grid bottom: dark rhombus grid hadron: solid (unchanged) I don’t know if this makes the quarks look nicer or not, but it definitely makes them more accessible. If the abbreviation text isn’t visible for whatever reason (e.g. because the chamber is in count layout mode), quark flavors used to be distinguished solely by color. But the new patterns make them distinguishable without color, which is important for colorblind accessibility."}, {"post_id": 28687, "ts": "2026-07-15T02:53:52Z", "hours": 2.3578, "text": "Minor graphics improvements This is a smaller devlog. Stuff I did since last devlog: Fixed the winning animation to work with the new layout planner Added transitions to the quark text. Whenever a quark changes its display text (e.g. from a ‘?’ to a flavor abbreviation like ‘s’), rather than instantly snapping to the new text, it’ll do a quick crossfade. Changing the font used for the quark text from the default to a font called Degheest that I think looks nice. Merging the layout refactor into prod because I’ve decided that it seems stable enough. Next, I’m going to work on improving the quark graphics. I’m trying to go for an aesthetic that looks like it’s from a physics textbook (hence the dot grid backdrop I’ve had for a while), so it’s already pretty close, but imo it looks a bit too plain right now. I don’t have a precise vision for exactly what I want the quarks to look like, so I’ll need to figure that out."}, {"post_id": 28484, "ts": "2026-07-14T19:10:09Z", "hours": 0.4922, "text": "Touchscreen support Idk why I was worried that this would be difficult. Less than 20 lines of code later, Hadronize now automatically detects whether you’re using a fine pointer (e.g. a mouse) or a coarse pointer (e.g. a touchscreen), and changes its behavior accordingly. So now you can select chambers on touchscreen just by tapping on them. You don’t have to drag the superposed quark, you just tap. I recorded a video showcasing this in action using Firefox’s mobile device simulator (aka RDM). As you can see, when I disable touch simulation, the chambers respond to hovering and I have to drag the quark around. But when I enable touch, the chambers don’t react at all until I click one, and then the superposed quark gets added to that chamber like normal. I’ve also tested this on an actual phone and it works perfectly, but it’s more difficult to record on there which is why I used Firefox’s simulator for the video."}, {"post_id": 28121, "ts": "2026-07-14T06:24:57Z", "hours": 8.2808, "text": "Layout optimization algorithm It took an entire day, but I did it. Hadronize will now automatically adjust 5 different layout variables in order of priority to make everything fit on screen. I think that the algorithm is probably the most complicated part of this entire project. I’m going to try to explain it really simply in this devlog, but if you want to see how it actually works, I wrote a bunch of comments that explain the priority pipeline in this file . So basically, every time a new layout update is triggered, the layout manager calculates a brand new layout plan from scratch. Once it’s finished calculating, it applies the layout plan onto the actual layout variables that are used to move the quarks on the screen. If I modified the layout variables directly, the rapid-fire modifications while calculating would trigger a bajillion reactive updates from Svelte which would slow the page down. Anyways, the way that the layout plan is calculated is that it starts by assuming ideal conditions: there is more than enough room for everything to fit comfortably. So it does the calculations using the preferred ideal variables, it modifies the plan, and then it actually checks to see if anything is overlapping. If there is any overlap, it tries to resolve it using the least-disruptive adjustment it can make. If that doesn’t work, it tries the next least-disruptive adjustment. And so on. Also, each time it moves up the chain of disruptiveness, it tries to use the ideal variables for all of the less-disruptive adjustments. If that makes sense. Here are the adjustments that it can make, in ascending order of disruptiveness: Increasing the radius of the ring of quarks of a single chamber Adjusting the radius of the ring of chambers around the center of the screen Switching chambers to use count mode, which is when it only displays the number of quarks of each flavor rather than displaying each quark individually. Switching the global layout from ring mode to grid mode. This is the thing that I built last devlog. Decreasing the size of all quarks I’m pleased to report that when I tested it on my phone, everything worked perfectly. I still haven’t implemented mobile input yet, but I started a 6-player game of all bots, and the layout planner managed to keep all of the quarks visible all of the time, even when a single chamber had more than 20 quarks. Never once did I see two chambers overlap with each other or go partially offscreen, which used to happen 100% of the time on small mobile screens. It just changed layout modes and decreased the quark size whenever it started to run out of room. Anyways, I’m not going to merge the new layout planner just yet because I’m not 100% sure how stable it is, but I’ll do that soon. Next up is mobile input."}, {"post_id": 27452, "ts": "2026-07-13T01:01:10Z", "hours": 1.7111, "text": "So the first step to mobile support is making the all of the quarks in all of the chambers actually fit on a phone screen. Right now they just overlap a bunch and you can’t tell which quarks belong to who. I have some ideas for an algorithm that can automatically adjust layout variables until everything fits, but first I need to give the algorithm things that it can adjust. The crux of the problem is that there’s simply no way to fit 6 chambers in a circular ring around the center of the screen on mobile. There’s just not enough screen space. So I made a new layout that places chambers in a grid instead of a ring. It works on desktop in addition to mobile. I don’t think it looks quite as nice, but it’s much more space efficient. I attached some side-by-side comparison screenshots. As you can see, the quarks still don’t quite fit on mobile even with the grid layout, but it’s much closer. Next step is either writing the automatic layout algorithm, or making input work on mobile."}, {"post_id": 27350, "ts": "2026-07-12T20:49:30Z", "hours": 3.1975, "text": "Sound effects! I added sound effects to the game UI. A unique sound plays for each of these: Starting a game Dragging a quark over a chamber Dropping a quark onto a chamber A quark hadronizing A quark tunneling Winning a game Closing a game I sourced them all from https://freesound.org/ , and I left attribution for each one in sounds.svelte.ts . I also modified a few in Audacity to trim them or apply simple effects. I’m not sure that I’m 100% satisfied with the sounds. I sourced almost all of the effects from different freesound sounds because I couldn’t find a sound pack that I liked, so the sounds don’t quite match tonally. Some of them are generic UI sounds while others are clearly scifi-ey. I may change some of the sounds later if I find more cohesive ones. I’d never done audio in HTML/JS before, so this was new for me. I originally just used the Audio() constructor because that was the most obvious way to play, but when I realized the many issues with it (though it did work!), I rewrote my code to use AudioContext . I also made a multi-step preloading and decoding pipeline that fetches all sound effects on page load, but doesn’t decode them until the user presses a button because otherwise JS throws a warning in the console and suspends the audio context. I think that the sound effects make Hadronize feel a lot more polished and nicer to play. Next up on my list is mobile support. I’m not looking forward to it. (Make sure to turn on sound for the video below)"}, {"post_id": 27016, "ts": "2026-07-12T04:52:57Z", "hours": 1.6675, "text": "Mouse handler refactor https://github.com/ethmarks/hadronize/commit/3a5adcb I started working on writing audio code and looking through sound effect libraries, but when I tried to hook my WIP sound-playing function into the mouse handler, I realized what an awful mess my mouse handler code was. So I spent over an hour refactoring it. While I was at it, I optimized it a tiny bit and fixed the hover thrashing bug that had been bugging me for nearly 2 weeks now."}, {"post_id": 26956, "ts": "2026-07-12T01:34:57Z", "hours": 2.6592, "text": "Style improvements and new pages So, funny story about the site styles. When I first made the CLI page 3 weeks ago (has it really been that long?! wow), I added holiday.css to make it look nice as a stopgap measure until I made the real styles. However, as the old saying goes, there’s nothing more permanent than a temporary solution. I’ve decided to just embrace using holiday.css for the entire site because it looks much nicer than anything I could make. The styles in the actual game component are entirely my own, of course, but the homepage, rule page, and rewritten CLI page all use holiday.css. “what rule page and rewritten CLI page?”, you ask? That’s the other thing that I did this devlog. I created a dedicated page on the site for the rules, and I rewrote the CLI page to only contain instructions on how to use the CLI rather than a playable browser CLI. Don’t worry, you can still play Hadronize via the browser console. The main UI has had that functionality since the beginning. I just didn’t see a reason to maintain two different game UIs, especially because the main UI can do everything that the playable CLI page could (and much more). I think that next I’ll start polishing the game UI. It’s long overdue. I’ll add sound effects, add mobile support, and maybe (don’t hold me to this) improve the graphics."}, {"post_id": 26635, "ts": "2026-07-11T15:55:24Z", "hours": 8.3731, "text": "UI Setup Flow diff from last devlog to this one I added a setup flow to the main UI page, and did a lot of refactoring. I also removed support for setting up the game via browser console. I didn’t make this choice lightly because it was a fun feature, but the tradeoffs were just too much and I decided that it wasn’t worth it, especially because the console setup is much clunkier than just using the HTML form, so I doubt anyone would even use it. But anyways, the main focus of this devlog is the setup flow on the main UI page (aka the play page). I also added some pretty sleek animations when activating and deactivating the game overlay."}, {"post_id": 20570, "ts": "2026-07-02T05:53:52Z", "hours": 3.7103, "text": "UI Refactor diff from last devlog to this one I refactored the Hadronize UI code. Rather than one giant 570-line file that handled the quark positioning, state tracking, mouse movement, and game loop, I split the code into four different files, each dedicated to one specific thing, with an average line count of ~154 (191, 184, 111, and 132, respectively). This makes the codebase way more maintainable and easy to work in. I also deduplicated most of the main game loop code. Before, I had just copied the entire content of the executeTurn() function, pasted it into the UI code, and customized it until the logic code correctly interfaced with the UI. Maintaining two separate functions that do basically the same thing is bad practice, so today I came up with an alternative solution: adding a bunch of “hooks” as optional parameters, which are just functions that the executeTurn() function runs at specific stages. In a CLI game, the hooks are never provided to the function, so they’re never run and nothing changes. But the UI code does provide hooks, to do things like trigger re-renders. This way, the same code can be reused for two different use cases (CLI and UI). Next Steps There’s still more refactoring to do, but I don’t think that I’ll do any more major restructuring."}, {"post_id": 19746, "ts": "2026-07-01T04:11:24Z", "hours": 14.7989, "text": "Huge UI Progress diff from last devlog to this one I’ve been working a lot on the Hadronize UI. Last devlog, all that it could do was render all of the quarks into a big overlapping heap and you could drag around one specific quark. Now, you can play a full game in the UI from start to finish, and it’s reasonably polished. How to play the UI prototype Visit https://ethmarks.github.io/hadronize/play . Make sure that you’ve read the game rules in the README . I haven’t implemented a setup flow in the main UI yet, so right now it’s pre-configured with two human players named Arthur and Ford, one bot player named Marvin, and seed 42. On each human player’s turn (their name will be highlighted in yellow), click and drag the superposed quark to the chamber of the player who you want to observe it. The superposed quark will collapse, get added to the chamber you selected, possibly react with existing quarks, and then play will proceed to the next player. Continue this until someone wins. It will probably be Marvin. Refresh the page to play again. Playtest I also conducted the first playtest with a few friends. Nothing broke during the playtest and they all liked it and gave positive feedback, which was really encouraging. We all got absolutely crushed by the expected value driver I built last devlog. Next Steps It sounds hyperbolic to say that this UI is the messiest code I’ve ever written, but I legitimately can’t think of any other contenders. Of the 800+ lines of code in the UI, about 570 of them are in one massive Game.svelte component. This component handles state tracking, mouse movement, the main game loop, and most of the geometry to position the quarks. The very next thing that I need to do is massively refactor the UI code. After that, I have a few ideas: A setup flow that lets the user choose the seed to use and configure the players. Sound effects, UI indicators (e.g. “you formed a baryon!”), and other game juice. Proper mobile support. Right now it kind of works on mobile, but the layout gets really cramped. I’ve been working a lot on the Hadronize UI. Last devlog, all that it could do was render all of the quarks into a big overlapping heap and you could drag around one specific quark. Now, you can play a full game in the UI from start to finish, and it’s reasonably polished."}, {"post_id": 17689, "ts": "2026-06-28T16:19:54Z", "hours": 3.3139, "text": "Drivers Each player in Hadronize is controlled by a Driver, which is basically just a function that takes the current game state as an input and outputs a player. I implemented drivers on like day #2, but I don’t think I’ve talked about them in a devlog yet. The first driver I made is the dogpile driver. It’s logic is extremely simple: it just selects the player who goes first. It doesn’t even reference the game state at all. If every player is a dogpile driver, this means that everyone just dogpiles onto the first player and ends up stealing basically all of its quarks before it can use them. This is obviously a terrible strategy because it’s not even capable of trying to score, but it was very simple to implement and I use it as a placeholder. The second driver I made is the rng driver. It just makes random decisions. However, because I insist on everything being deterministic, it can’t just use Math.random . Instead, it stringifies the game state, converts that string into a 32-bit integer via a djb2 hash, then uses that integer to seed a mulberry32 pseudorandom number generator, then uses the output of the mulberry to make its player selection. The newest driver that I just finished developing is the expected value driver. It does actual strategic calculations to determine what the expected value of choosing each player would be based on the information it has available, then selects the player that maximizes that value. Next Steps I’ve started building the UI, but I’ve still been procrastinating on actually working on it in earnest. I should probably do that."}, {"post_id": 15374, "ts": "2026-06-25T00:16:45Z", "hours": 5.18, "text": "Tests and CLI Args You can now add arguments to the Hadronize CLI in the terminal, which lets you avoid having to use the setup flow. Here’s an example. pnpm run cli --seed 12345 --player Alice:human --player Bob:bot It also works if you run the CLI as a remote script. deno run -A http://ethmarks.github.io/hadronize/cli.ts -s 8 -p a:bot -p b:bot -p c:bot This was pretty easy to implement. I just used Node’s parseArgs utility for the main arg parsing and wrote a bunch of validation logic that converts the raw arguments (which are always strings) into the data types that my code uses. Tests Over the past couple days, I’ve made a little test suite for the game logic using Vitest. I’ve written 19 individual tests, but some of them repeat multiple times with different game seeds and whatnot to ensure that it works with a variety of inputs, so Vitest actually runs 101 tests in total. All of the tests pass, and I didn’t discover any bugs, which either means that I managed to get all the game logic correct on the first try, or that there’s something wrong with my tests. Next Steps I think that I’ve probably spent too much time on the CLI. I don’t think that it was time wasted, but I probably ought to get started on the main game UI."}, {"post_id": 14724, "ts": "2026-06-23T22:42:34Z", "hours": 6.3972, "text": "CLI Remote Script You can now run Hadronize CLI in a terminal without cloning the repo. If you run the command below, Deno will automatically fetch all the dependencies. deno run -A http://ethmarks.github.io/hadronize/cli.ts Node doesn’t support remote scripts because it lacks Deno’s awesomeness, but because of the Deno binary on npm , you can run Deno (and therefore Hadronize) through any of the other package managers! npx deno run -A http://ethmarks.github.io/hadronize/cli.ts pnpm dlx deno run -A http://ethmarks.github.io/hadronize/cli.ts bunx deno run -A http://ethmarks.github.io/hadronize/cli.ts For example, in the attached screenshot, I SSH-ed into one of my home servers that hadn’t cloned the Hadronize repo nor installed Deno, and tried to run Hadronize as a remote script via pnpm . After resolving dependencies for a few seconds, it ran flawlessly. How it works I first encountered Deno remote scripts in Lume’s init command , and my implementation is heavily inspired by it. Basically, all that the cli.ts file does is fetch the CLI code from JSDelivr, which fetches it directly from the GitHub repo. From there, Deno is smart enough to resolve all of the CLI code’s dependencies and run it. Compatibility Before today’s changes, running Hadronize via Deno worked perfectly fine. deno task cli behaved identically to pnpm run cli . However, that’s because Deno has an automatic Node compatibility layer , not because Deno can actually run the code natively. That compatibility layer doesn’t really work with remote scripts (because Deno can’t find the package.json ), so when I first tried to run the remote script while developing it, it crashed and burned immediately. This was because, without the compatibility layer, Deno and Node handle things fundamentally differently. There were several differences, some of which I expected and some of which I didn’t, but the easiest one to understand is NPM imports. NPM imports My CLI code relies on the picocolors library for getting ANSI escape codes. When I was first writing the code, I added the picocolors package via NPM and imported it in the normal Node way: import pc from \" picocolors \" ; The problem is that Deno can’t parse bare imports like that. Deno expects this format, which Node cannot parse: import pc from \" npm:picocolors \" ; I tried configuring an import map in deno.json , but it didn’t work. I considered just hardcoding the ANSI escape sequences, but I decided that I would need to figure out how to polyglottally import NPM packages in both Node and Deno at some point, so I might as well figure it out now. My solution was to create a deps/picocolors.ts file to proxy the picocolors import by dynamically importing it based on whether it’s being run in Deno or not: const { default : pc } = \" Deno \" in globalThis ? await import ( \" npm:picocolors \" ) : await import ( \" picocolors \" ); export default pc ; NPM imports were only one of the issues that sprung up. Frustratingly, the only way to test whether or not a solution worked was to commit, push to main, and test on production. The whole Deno compatibility saga required 12 commits in total. Next Steps I’m still working on writing unit tests for the game logic. I already have a few tests, but they’re definitely not comprehensive. I’ll write a devlog about the tests once I’m finished with them."}, {"post_id": 13920, "ts": "2026-06-22T20:31:39Z", "hours": 5.8247, "text": "Setup Flow diff from last devlog to this one Since my last devlog, I added a flow that lets users set up each game before starting it. The setup includes specifying the seed, player count, the names of each player, and whether each player should be a human or a bot. I made it work in three different formats, each of which had to be implemented individually: The terminal : at its core, this format is just a normal TUI. It prints input prompts, awaits the user’s input using the abstracted NbrInputFunc I mentioned last time, and repeats this until the user provides an input that passes the validation function. Pretty standard stuff. The browser console : I used the same trick that I described last time to allow users to enter their input via the browser console. It creates a custom window property that resumes execution, then halts execution with a Promise<void> until the window property is called. Unfortunately, it wasn’t possible to use the anonymous getter trick that I used last time. If I did that, I would have to create custom window properties for every possible 32-bit number to allow user to enter the seed, and create custom properties for every possible string to allow users to enter player names. That obviously wasn’t possible, so instead I just created a window.r function that takes any input type. The “r” stands for “respond”. To set the seed to 42, you type r(42) into the console, which is a reasonably clean UX, I think, though not as clean as just typing 42 like you can in the terminal. The webpage : this uses HTML <input> s and SvelteKit’s reactivity. The trickiest part was navigating the fact that the value of one of the inputs (player count) controls the structure of some of the other inputs (player configs). At first I tried writing code to dynamically construct a variable-length Array, but that was a nightmare of complexity. Then I tried making all 6 possible player configs visible all the time and just adding the “Disabled” type, but that made the UI look ugly and was also kind of complicated to implement. The solution I settled on was to internally use an Array with a fixed length, automatically hide the player config UI elements with an index less than the player count value, and slice the player config Array before passing it into the main game function. I think that this solution is the best of both worlds while also being fairly simple to implement. Next Steps I know that I’ve been saying this for the past 4 days, but I need to write some internal docs for my game logic code and write tests. I haven’t noticed any bugs during my playtests while building the CLI, but I’d like the peace of mind to be fairly confident that I’ve implemented my game rules correctly."}, {"post_id": 12947, "ts": "2026-06-21T05:52:51Z", "hours": 10.3317, "text": "Browser CLI Since my last devlog, I implemented a CLI for Hadronize that works across Node, Deno, Bun, and browsers. You can try it out by visiting https://ethmarks.github.io/hadronize/cli or running the following commands (you only have to run one of the Node/Deno/Bun commands): # Clone the repo git clone https://github.com/ethmarks/hadronize.git cd hadronize # Run with Node (via npm or pnpm) npm install npm run cli # Run with Deno deno task cli # Run with Bun bun install bun run cli Link to the diff between last devlog and this one Abstraction In case you’re not familiar with the JS ecosystem, a cross-runtime CLI like this is not normal. My CLI uses styled text, but the different runtimes have different ways of logging styled text. Node, Deno, and Bun all use ANSI escape characters, but browsers use %c placeholders (Deno also supports %c because Deno is awesome, but none of the others do). Node uses the readline API to get user input, but Deno and Bun both use prompt() , and browsers don’t even have a way to get user input without clever tricks (as you’ll see later). My solution to the styled text problem was to create a custom micro-library which I call styledLog.ts (or sl for short) which invents an easy-to-use syntax for rich-text logging called slChunk , then automatically detects if it’s running in a browser and renders slChunks with either ANSI escapes or %c placeholders accordingly. Cross-runtime user input My solution to the user input problem was a little less elegant, but in my opinion it’s much cleverer. Node, Deno, and Bun were the low-hanging fruit. All I had to do was create an abstracted NbrInputFunc() function that automatically detects which runtime is running the code, then switches out the method it internally uses to fetch input accordingly. Easy. But implementing a CLI in the browser was a lot more tricky. I could have just used the window.prompt() method , but that opens a disruptive pop-up window that looks terrible. Instead, my code dynamically adds custom properties to the window object, then halts the script execution via a Promise<void> . Each custom property is named after a player name and has an anonymous getter function. When you type a player’s name (e.g. alice ) in the console, it automatically evaluates window.alice , which triggers the getter. The getter sets the userInput variable then resolves the frozen Promise to resume execution. I hope that made sense. It’s a really hacky solution, but it does work, and it provides an elegant input syntax that resembles that of terminal CLIs. My first idea (which is still used as the fallback) was to just define a window.turn() function, so you would enter your input with turn(\"alice\") . The current solution is much more elegant, in my opinion, because the user doesn’t need to type parenthesis or quotes. Here’s a link to the code if you want to check it out for yourself. Beginnings of the UI I also started working on the UI the tiniest bit. Not anything that’ll make it into the final version, mind you, but I added a page that demos the Hadronize CLI. It seemed wrong to make the demo page blank and not include instructions, so I wrote some. It seemed wrong to use unstyled bare HTML, so I added holidaycss . Next Steps I think that there’s still some work I need to do in the game logic and CLI before I start working on the UI. The CLI demo currently doesn’t have any way to customize the game settings (e.g. how many players there are and what deterministic seed to use), so I’ll probably work on that next. Thanks for reading!"}, {"post_id": 11813, "ts": "2026-06-19T07:15:15Z", "hours": 6.4697, "text": "Core Game Logic Today I implemented most of the core game logic in TypeScript. My code is pretty messy, probably has some bugs, and definitely has some idiosyncrasies that I should add docs for, but it does work correctly. Mostly. Here are a few highlights from today: Determinism The rules specify that quarks are created on-the-fly at the start of each turn, and that it’s impossible to predict what flavor a superposition will collapse into. Nondeterministic code makes me uncomfortable, so I decided to cheat a bit behind the scenes to make the whole thing pseudorandom and fully deterministic. In the game constructor, every quark that will ever be used during the game is pre-generated based on values from a mulberry32 function, then the collapsed flavor is predetermined ahead of time. Those two things: the list of future quarks that will be “created” on subsequent turns, and the flavor that each superposition will collapse into, are secret information that the players aren’t allowed to know, which means I have to be careful to sanitize the game state before it’s given to players. I hate references So, one of the first things that I did was create the Quark class. It has a few methods, but mainly it’s just a DTO for a flavor and a superposition. So my original plan was involved doing normal OOP and having each quark be owned by a Player class or the Game class itself. But once I actually started coding it, I remembered that I hate having to remember what’s stored as a value and what’s stored as a reference in JS. This is especially annoying when moving quarks between containers. So instead, I decided to just store an array of every extant quark, including not only a flavor and superposition but also an index. When a player class “owns” a quark, it really just owns that quark’s index number which corresponds to a quark in the game class’s SSoT. Crucially, the index number is a simple integer that doesn’t have any of JS’s object reference silliness. Timeline I decided that the game class should save every past state that it’s been in for some reason. I might use it in the UI to let users scroll back in time to see how the game played out, or maybe use it to make neat statistics at the end of the game, or something like that. It might also be useful for bots (more on that in a future devlog). But anyways, actually implementing the timeline was extremely frustrating, mainly due to Typescript. The final implementation that I settled on is pretty clean, but it was not my first thought, and I went through maybe a dozen different iterations over the course of an hour. Next Steps I’m probably going to spent a bit more time in the game logic before starting work on the UI. As I mentioned, I need to write docs for the idiosyncrasies of my code because otherwise I’ll forget how it works and that’s how bugs happen. Speaking of bugs, I’m sure that there are a few in my code, so I’ll probably write some tests to try to find them. Thanks for reading!"}, {"post_id": 11089, "ts": "2026-06-18T04:06:18Z", "hours": 3.65, "text": "Hadronize This is my first devlog for this project. It’s a multiplayer strategy game that you can play in your browser. https://github.com/ethmarks/hadronize Basically the only things that I’ve done so far are write the rules in the README and brainstorm a bunch. The rules are pretty important, so I’ll write them in this devlog. Because there’s a 4000-character limit to Stardance devlogs, I’m going to try to keep the rules shorter and less thorough than I did in the README. Rules Hadronize is a 2-6 player game which will probably take about ~10 minutes per game. The goal is to be the first player to hadronize 10 or more quarks. Quarks are basically the cards. There are 6 different flavors of quark: up, down, strange, charm, bottom, and top. By the way, I’m not making that part up . Quarks start out as Superposed Quarks, which are quarks in a state of superposition between three different flavors. Once the superposition collapses (more on that later), it chooses one of the three flavors in its superposition and becomes a normal quark with a single flavor. Each player starts with four collapsed quarks with randomly-chosen flavors in their respective cloud chamber . On each turn, a new superposed quark appears. The players know that the quark will be one of the three flavors in its superposition, but they don’t know which one. The player whose turn it is (aka the active player) will choose any player (including themselves) to be the observing player. The observing player observes the superposed quark, which collapses it and adds it to their cloud chamber. If the observing player has none of that flavor (e.g. the new quark collapsed into charm and the player only has down quarks), then nothing else happens and the turn ends. But if the observing player does have at least one quark of the same flavor, something does happen. If the active player chose themselves to be the observing player, the new quark reacts with all existing quarks of the same flavor, and they all hadronize together. If the active player chose a different player to be the observing player, the new quark reacts with all existing quarks of the same flavor, and they all quantum tunnel from the observing player’s chamber into the active player’s chamber. In other words, the active player steals some of the observing player’s quarks. If my explanation is unclear, check out the README because I probably explained it better there. If the README is unclear too, feel free to let me know by commenting on this devlog or opening an issue or whatever. Mantis If the rules sound familiar, it’s because I mostly just stole them from the card game Mantis by Exploding Kittens. My original idea was to just create a digital version of Mantis, but I was concerned about running into copyright trouble if I called it “Mantis” and used the same terminology and whatnot. Game mechanics can’t be copyrighted, but names and terminology absolutely can. I considered just making my game about abstract colors, but then I suddenly realized that making it about quarks would fit really well, so I did that instead. I did make a few changes to the core mechanics (e.g. using 6 flavors instead of 7 colors, and combining “scoring” and “stealing” into “observing”), but it’s still basically just a reskin of Mantis. Next Steps The next thing I’m going to work on is actually implementing the rules in TypeScript. After that I’ll probably work on the UI. P.S. I also spent like an hour making a terrible-looking banner for Hadronize to use as the Stardance project image."}]...
|
Title: Hadronize by @ethmarks | Stardance
Devlogs Title: Hadronize by @ethmarks | Stardance
Devlogs:
Hadronize This is my first devlog for this project. It’s a multiplayer strategy game that you can play in your browser. https://github.com/ethmarks/hadronize Basically the only things that I’ve done so far are write the rules in the README and brainstorm a bunch. The rules are pretty important, so I’ll write them in this devlog. Because there’s a 4000-character limit to Stardance devlogs, I’m going to try to keep the rules shorter and less thorough than I did in the README. Rules Hadronize is a 2-6 player game which will probably take about ~10 minutes per game. The goal is to be the first player to hadronize 10 or more quarks. Quarks are basically the cards. There are 6 different flavors of quark: up, down, strange, charm, bottom, and top. By the way, I’m not making that part up . Quarks start out as Superposed Quarks, which are quarks in a state of superposition between three different flavors. Once the superposition collapses (more on that later), it chooses one of the three flavors in its superposition and becomes a normal quark with a single flavor. Each player starts with four collapsed quarks with randomly-chosen flavors in their respective cloud chamber . On each turn, a new superposed quark appears. The players know that the quark will be one of the three flavors in its superposition, but they don’t know which one. The player whose turn it is (aka the active player) will choose any player (including themselves) to be the observing player. The observing player observes the superposed quark, which collapses it and adds it to their cloud chamber. If the observing player has none of that flavor (e.g. the new quark collapsed into charm and the player only has down quarks), then nothing else happens and the turn ends. But if the observing player does have at least one quark of the same flavor, something does happen. If the active player chose themselves to be the observing player, the new quark reacts with all existing quarks of the same flavor, and they all hadronize together. If the active player chose a different player to be the observing player, the new quark reacts with all existing quarks of the same flavor, and they all quantum tunnel from the observing player’s chamber into the active player’s chamber. In other words, the active player steals some of the observing player’s quarks. If my explanation is unclear, check out the README because I probably explained it better there. If the README is unclear too, feel free to let me know by commenting on this devlog or opening an issue or whatever. Mantis If the rules sound familiar, it’s because I mostly just stole them from the card game Mantis by Exploding Kittens. My original idea was to just create a digital version of Mantis, but I was concerned about running into copyright trouble if I called it “Mantis” and used the same terminology and whatnot. Game mechanics can’t be copyrighted, but names and terminology absolutely can. I considered just making my game about abstract colors, but then I suddenly realized that making it about quarks would fit really well, so I did that instead. I did make a few changes to the core mechanics (e.g. using 6 flavors instead of 7 colors, and combining “scoring” and “stealing” into “observing”), but it’s still basically just a reskin of Mantis. Next Steps The next thing I’m going to work on is actually implementing the rules in TypeScript. After that I’ll probably work on the UI. P.S. I also spent like an hour making a terrible-looking banner for Hadronize to use as the Stardance project image.
Core Game Logic Today I implemented most of the core game logic in TypeScript. My code is pretty messy, probably has some bugs, and definitely has some idiosyncrasies that I should add docs for, but it does work correctly. Mostly. Here are a few highlights from today: Determinism The rules specify that quarks are created on-the-fly at the start of each turn, and that it’s impossible to predict what flavor a superposition will collapse into. Nondeterministic code makes me uncomfortable, so I decided to cheat a bit behind the scenes to make the whole thing pseudorandom and fully deterministic. In the game constructor, every quark that will ever be used during the game is pre-generated based on values from a mulberry32 function, then the collapsed flavor is predetermined ahead of time. Those two things: the list of future quarks that will be “created” on subsequent turns, and the flavor that each superposition will collapse into, are secret information that the players aren’t allowed to know, which means I have to be careful to sanitize the game state before it’s given to players. I hate references So, one of the first things that I did was create the Quark class. It has a few methods, but mainly it’s just a DTO for a flavor and a superposition. So my original plan was involved doing normal OOP and having each quark be owned by a Player class or the Game class itself. But once I actually started coding it, I remembered that I hate having to remember what’s stored as a value and what’s stored as a reference in JS. This is especially annoying when moving quarks between containers. So instead, I decided to just store an array of every extant quark, including not only a flavor and superposition but also an index. When a player class “owns” a quark, it really just owns that quark’s index number which corresponds to a quark in the game class’s SSoT. Crucially, the index number is a simple integer that doesn’t have any of JS’s object reference silliness. Timeline I decided that the game class should save every past state that it’s been in for some reason. I might use it in the UI to let users scroll back in time to see how the game played out, or maybe use it to make neat statistics at the end of the game, or something like that. It might also be useful for bots (more on that in a future devlog). But anyways, actually implementing the timeline was extremely frustrating, mainly due to Typescript. The final implementation that I settled on is pretty clean, but it was not my first thought, and I went through maybe a dozen different iterations over the course of an hour. Next Steps I’m probably going to spent a bit more time in the game logic before starting work on the UI. As I mentioned, I need to write docs for the idiosyncrasies of my code because otherwise I’ll forget how it works and that’s how bugs happen. Speaking of bugs, I’m sure that there are a few in my code, so I’ll probably write some tests to try to find them. Thanks for reading!
Browser CLI Since my last devlog, I implemented a CLI for Hadronize that works across Node, Deno, Bun, and browsers. You can try it out by visiting https://ethmarks.github.io/hadronize/cli or running the following commands (you only have to run one of the Node/Deno/Bun commands): # Clone the repo git clone https://github.com/ethmarks/hadronize.git cd hadronize # Run with Node (via npm or pnpm) npm install npm run cli # Run with Deno deno task cli # Run with Bun bun install bun run cli Link to the diff between last devlog and this one Abstraction In case you’re not familiar with the JS ecosystem, a cross-runtime CLI like this is not normal. My CLI uses styled text, but the different runtimes have different ways of logging styled text. Node, Deno, and Bun all use ANSI escape characters, but browsers use %c placeholders (Deno also supports %c because Deno is awesome, but none of the others do). Node uses the readline API to get user input, but Deno and Bun both use prompt() , and browsers don’t even have a way to get user input without clever tricks (as you’ll see later). My solution to the styled text problem was to create a custom micro-library which I call styledLog.ts (or sl for short) which invents an easy-to-use syntax for rich-text logging called slChunk , then automatically detects if it’s running in a browser and renders slChunks with either ANSI escapes or %c placeholders accordingly. Cross-runtime user input My solution to the user input problem was a little less elegant, but in my opinion it’s much cleverer. Node, Deno, and Bun were the low-hanging fruit. All I had to do was create an abstracted NbrInputFunc() function that automatically detects which runtime is running the code, then switches out the method it internally uses to fetch input accordingly. Easy. But implementing a CLI in the browser was a lot more tricky. I could have just used the window.prompt() method , but that opens a disruptive pop-up window that looks terrible. Instead, my code dynamically adds custom properties to the window object, then halts the script execution via a Promise<void> . Each custom property is named after a player name and has an anonymous getter function. When you type a player’s name (e.g. alice ) in the console, it automatically evaluates window.alice , which triggers the getter. The getter sets the userInput variable then resolves the frozen Promise to resume execution. I hope that made sense. It’s a really hacky solution, but it does work, and it provides an elegant input syntax that resembles that of terminal CLIs. My first idea (which is still used as the fallback) was to just define a window.turn() function, so you would enter your input with turn("alice") . The current solution is much more elegant, in my opinion, because the user doesn’t need to type parenthesis or quotes. Here’s a link to the code if you want to check it out for yourself. Beginnings of the UI I also started working on the UI the tiniest bit. Not anything that’ll make it into the final version, mind you, but I added a page that demos the Hadronize CLI. It seemed wrong to make the demo page blank and not include instructions, so I wrote some. It seemed wrong to use unstyled bare HTML, so I added holidaycss . Next Steps I think that there’s still some work I need to do in the game logic and CLI before I start working on the UI. The CLI demo currently doesn’t have any way to customize the game settings (e.g. how many players there are and what deterministic seed to use), so I’ll probably work on that next. Thanks for reading!
Setup Flow diff from last devlog to this one Since my last devlog, I added a flow that lets users set up each game before starting it. The setup includes specifying the seed, player count, the names of each player, and whether each player should be a human or a bot. I made it work in three different formats, each of which had to be implemented individually: The terminal : at its core, this format is just a normal TUI. It prints input prompts, awaits the user’s input using the abstracted NbrInputFunc I mentioned last time, and repeats this until the user provides an input that passes the validation function. Pretty standard stuff. The browser console : I used the same trick that I described last time to allow users to enter their input via the browser console. It creates a custom window property that resumes execution, then halts execution with a Promise<void> until the window property is called. Unfortunately, it wasn’t possible to use the anonymous getter trick that I used last time. If I did that, I would have to create custom window properties for every possible 32-bit number to allow user to enter the seed, and create custom properties for every possible string to allow users to enter player names. That obviously wasn’t possible, so instead I just created a window.r function that takes any input type. The “r” stands for “respond”. To set the seed to 42, you type r(42) into the console, which is a reasonably clean UX, I think, though not as clean as just typing 42 like you can in the terminal. The webpage : this uses HTML <input> s and SvelteKit’s reactivity. The trickiest part was navigating the fact that the value of one of the inputs (player count) controls the structure of some of the other inputs (player configs). At first I tried writing code to dynamically construct a variable-length Array, but that was a nightmare of complexity. Then I tried making all 6 possible player configs visible all the time and just adding the “Disabled” type, but that made the UI look ugly and was also kind of complicated to implement. The solution I settled on was to internally use an Array with a fixed length, automatically hide the player config UI elements with an index less than the player count value, and slice the player config Array before passing it into the main game function. I think that this solution is the best of both worlds while also being fairly simple to implement. Next Steps I know that I’ve been saying this for the past 4 days, but I need to write some internal docs for my game logic code and write tests. I haven’t noticed any bugs during my playtests while building the CLI, but I’d like the peace of mind to be fairly confident that I’ve implemented my game rules correctly.
CLI Remote Script You can now run Hadronize CLI in a terminal without cloning the repo. If you run the command below, Deno will automatically fetch all the dependencies. deno run -A http://ethmarks.github.io/hadronize/cli.ts Node doesn’t support remote scripts because it lacks Deno’s awesomeness, but because of the Deno binary on npm , you can run Deno (and therefore Hadronize) through any of the other package managers! npx deno run -A http://ethmarks.github.io/hadronize/cli.ts pnpm dlx deno run -A http://ethmarks.github.io/hadronize/cli.ts bunx deno run -A http://ethmarks.github.io/hadronize/cli.ts For example, in the attached screenshot, I SSH-ed into one of my home servers that hadn’t cloned the Hadronize repo nor installed Deno, and tried to run Hadronize as a remote script via pnpm . After resolving dependencies for a few seconds, it ran flawlessly. How it works I first encountered Deno remote scripts in Lume’s init command , and my implementation is heavily inspired by it. Basically, all that the cli.ts file does is fetch the CLI code from JSDelivr, which fetches it directly from the GitHub repo. From there, Deno is smart enough to resolve all of the CLI code’s dependencies and run it. Compatibility Before today’s changes, running Hadronize via Deno worked perfectly fine. deno task cli behaved identically to pnpm run cli . However, that’s because Deno has an automatic Node compatibility layer , not because Deno can actually run the code natively. That compatibility layer doesn’t really work with remote scripts (because Deno can’t find the package.json ), so when I first tried to run the remote script while developing it, it crashed and burned immediately. This was because, without the compatibility layer, Deno and Node handle things fundamentally differently. There were several differences, some of which I expected and some of which I didn’t, but the easiest one to understand is NPM imports. NPM imports My CLI code relies on the picocolors library for getting ANSI escape codes. When I was first writing the code, I added the picocolors package via NPM and imported it in the normal Node way: import pc from " picocolors " ; The problem is that Deno can’t parse bare imports like that. Deno expects this format, which Node cannot parse: import pc from " npm:picocolors " ; I tried configuring an import map in deno.json , but it didn’t work. I considered just hardcoding the ANSI escape sequences, but I decided that I would need to figure out how to polyglottally import NPM packages in both Node and Deno at some point, so I might as well figure it out now. My solution was to create a deps/picocolors.ts file to proxy the picocolors import by dynamically importing it based on whether it’s being run in Deno or not: const { default : pc } = " Deno " in globalThis ? await import ( " npm:picocolors " ) : await import ( " picocolors " ); export default pc ; NPM imports were only one of the issues that sprung up. Frustratingly, the only way to test whether or not a solution worked was to commit, push to main, and test on production. The whole Deno compatibility saga required 12 commits in total. Next Steps I’m still working on writing unit tests for the game logic. I already have a few tests, but they’re definitely not comprehensive. I’ll write a devlog about the tests once I’m finished with them.
Tests and CLI Args You can now add arguments to the Hadronize CLI in the terminal, which lets you avoid having to use the setup flow. Here’s an example. pnpm run cli --seed 12345 --player Alice:human --player Bob:bot It also works if you run the CLI as a remote script. deno run -A http://ethmarks.github.io/hadronize/cli.ts -s 8 -p a:bot -p b:bot -p c:bot This was pretty easy to implement. I just used Node’s parseArgs utility for the main arg parsing and wrote a bunch of validation logic that converts the raw arguments (which are always strings) into the data types that my code uses. Tests Over the past couple days, I’ve made a little test suite for the game logic using Vitest. I’ve written 19 individual tests, but some of them repeat multiple times with different game seeds and whatnot to ensure that it works with a variety of inputs, so Vitest actually runs 101 tests in total. All of the tests pass, and I didn’t discover any bugs, which either means that I managed to get all the game logic correct on the first try, or that there’s something wrong with my tests. Next Steps I think that I’ve probably spent too much time on the CLI. I don’t think that it was time wasted, but I probably ought to get started on the main game UI.
Drivers Each player in Hadronize is controlled by a Driver, which is basically just a function that takes the current game state as an input and outputs a player. I implemented drivers on like day #2, but I don’t think I’ve talked about them in a devlog yet. The first driver I made is the dogpile driver. It’s logic is extremely simple: it just selects the player who goes first. It doesn’t even reference the game state at all. If every player is a dogpile driver, this means that everyone just dogpiles onto the first player and ends up stealing basically all of its quarks before it can use them. This is obviously a terrible strategy because it’s not even capable of trying to score, but it was very simple to implement and I use it as a placeholder. The second driver I made is the rng driver. It just makes random decisions. However, because I insist on everything being deterministic, it can’t just use Math.random . Instead, it stringifies the game state, converts that string into a 32-bit integer via a djb2 hash, then uses that integer to seed a mulberry32 pseudorandom number generator, then uses the output of the mulberry to make its player selection. The newest driver that I just finished developing is the expected value driver. It does actual strategic calculations to determine what the expected value of choosing each player would be based on the information it has available, then selects the player that maximizes that value. Next Steps I’ve started building the UI, but I’ve still been procrastinating on actually working on it in earnest. I should probably do that.
Huge UI Progress diff from last devlog to this one I’ve been working a lot on the Hadronize UI. Last devlog, all that it could do was render all of the quarks into a big overlapping heap and you could drag around one specific quark. Now, you can play a full game in the UI from start to finish, and it’s reasonably polished. How to play the UI prototype Visit https://ethmarks.github.io/hadronize/play . Make sure that you’ve read the game rules in the README . I haven’t implemented a setup flow in the main UI yet, so right now it’s pre-configured with two human players named Arthur and Ford, one bot player named Marvin, and seed 42. On each human player’s turn (their name will be highlighted in yellow), click and drag the superposed quark to the chamber of the player who you want to observe it. The superposed quark will collapse, get added to the chamber you selected, possibly react with existing quarks, and then play will proceed to the next player. Continue this until someone wins. It will probably be Marvin. Refresh the page to play again. Playtest I also conducted the first playtest with a few friends. Nothing broke during the playtest and they all liked it and gave positive feedback, which was really encouraging. We all got absolutely crushed by the expected value driver I built last devlog. Next Steps It sounds hyperbolic to say that this UI is the messiest code I’ve ever written, but I legitimately can’t think of any other contenders. Of the 800+ lines of code in the UI, about 570 of them are in one massive Game.svelte component. This component handles state tracking, mouse movement, the main game loop, and most of the geometry to position the quarks. The very next thing that I need to do is massively refactor the UI code. After that, I have a few ideas: A setup flow that lets the user choose the seed to use and configure the players. Sound effects, UI indicators (e.g. “you formed a baryon!”), and other game juice. Proper mobile support. Right now it kind of works on mobile, but the layout gets really cramped. I’ve been working a lot on the Hadronize UI. Last devlog, all that it could do was render all of the quarks into a big overlapping heap and you could drag around one specific quark. Now, you can play a full game in the UI from start to finish, and it’s reasonably polished.
UI Refactor diff from last devlog to this one I refactored the Hadronize UI code. Rather than one giant 570-line file that handled the quark positioning, state tracking, mouse movement, and game loop, I split the code into four different files, each dedicated to one specific thing, with an average line count of ~154 (191, 184, 111, and 132, respectively). This makes the codebase way more maintainable and easy to work in. I also deduplicated most of the main game loop code. Before, I had just copied the entire content of the executeTurn() function, pasted it into the UI code, and customized it until the logic code correctly interfaced with the UI. Maintaining two separate functions that do basically the same thing is bad practice, so today I came up with an alternative solution: adding a bunch of “hooks” as optional parameters, which are just functions that the executeTurn() function runs at specific stages. In a CLI game, the hooks are never provided to the function, so they’re never run and nothing changes. But the UI code does provide hooks, to do things like trigger re-renders. This way, the same code can be reused for two different use cases (CLI and UI). Next Steps There’s still more refactoring to do, but I don’t think that I’ll do any more major restructuring.
UI Setup Flow diff from last devlog to this one I added a setup flow to the main UI page, and did a lot of refactoring. I also removed support for setting up the game via browser console. I didn’t make this choice lightly because it was a fun feature, but the tradeoffs were just too much and I decided that it wasn’t worth it, especially because the console setup is much clunkier than just using the HTML form, so I doubt anyone would even use it. But anyways, the main focus of this devlog is the setup flow on the main UI page (aka the play page). I also added some pretty sleek animations when activating and deactivating the game overlay.
Style improvements and new pages So, funny story about the site styles. When I first made the CLI page 3 weeks ago (has it really been that long?! wow), I added holiday.css to make it look nice as a stopgap measure until I made the real styles. However, as the old saying goes, there’s nothing more permanent than a temporary solution. I’ve decided to just embrace using holiday.css for the entire site because it looks much nicer than anything I could make. The styles in the actual game component are entirely my own, of course, but the homepage, rule page, and rewritten CLI page all use holiday.css. “what rule page and rewritten CLI page?”, you ask? That’s the other thing that I did this devlog. I created a dedicated page on the site for the rules, and I rewrote the CLI page to only contain instructions on how to use the CLI rather than a playable browser CLI. Don’t worry, you can still play Hadronize via the browser console. The main UI has had that functionality since the beginning. I just didn’t see a reason to maintain two different game UIs, especially because the main UI can do everything that the playable CLI page could (and much more). I think that next I’ll start polishing the game UI. It’s long overdue. I’ll add sound effects, add mobile support, and maybe (don’t hold me to this) improve the graphics.
Mouse handler refactor https://github.com/ethmarks/hadronize/commit/3a5adcb I started working on writing audio code and looking through sound effect libraries, but when I tried to hook my WIP sound-playing function into the mouse handler, I realized what an awful mess my mouse handler code was. So I spent over an hour refactoring it. While I was at it, I optimized it a tiny bit and fixed the hover thrashing bug that had been bugging me for nearly 2 weeks now.
Sound effects! I added sound effects to the game UI. A unique sound plays for each of these: Starting a game Dragging a quark over a chamber Dropping a quark onto a chamber A quark hadronizing A quark tunneling Winning a game Closing a game I sourced them all from https://freesound.org/ , and I left attribution for each one in sounds.svelte.ts . I also modified a few in Audacity to trim them or apply simple effects. I’m not sure that I’m 100% satisfied with the sounds. I sourced almost all of the effects from different freesound sounds because I couldn’t find a sound pack that I liked, so the sounds don’t quite match tonally. Some of them are generic UI sounds while others are clearly scifi-ey. I may change some of the sounds later if I find more cohesive ones. I’d never done audio in HTML/JS before, so this was new for me. I originally just used the Audio() constructor because that was the most obvious way to play, but when I realized the many issues with it (though it did work!), I rewrote my code to use AudioContext . I also made a multi-step preloading and decoding pipeline that fetches all sound effects on page load, but doesn’t decode them until the user presses a button because otherwise JS throws a warning in the console and suspends the audio context. I think that the sound effects make Hadronize feel a lot more polished and nicer to play. Next up on my list is mobile support. I’m not looking forward to it. (Make sure to turn on sound for the video below)
So the first step to mobile support is making the all of the quarks in all of the chambers actually fit on a phone screen. Right now they just overlap a bunch and you can’t tell which quarks belong to who. I have some ideas for an algorithm that can automatically adjust layout variables until everything fits, but first I need to give the algorithm things that it can adjust. The crux of the problem is that there’s simply no way to fit 6 chambers in a circular ring around the center of the screen on mobile. There’s just not enough screen space. So I made a new layout that places chambers in a grid instead of a ring. It works on desktop in addition to mobile. I don’t think it looks quite as nice, but it’s much more space efficient. I attached some side-by-side comparison screenshots. As you can see, the quarks still don’t quite fit on mobile even with the grid layout, but it’s much closer. Next step is either writing the automatic layout algorithm, or making input work on mobile.
Layout optimization algorithm It took an entire day, but I did it. Hadronize will now automatically adjust 5 different layout variables in order of priority to make everything fit on screen. I think that the algorithm is probably the most complicated part of this entire project. I’m going to try to explain it really simply in this devlog, but if you want to see how it actually works, I wrote a bunch of comments that explain the priority pipeline in this file . So basically, every time a new layout update is triggered, the layout manager calculates a brand new layout plan from scratch. Once it’s finished calculating, it applies the layout plan onto the actual layout variables that are used to move the quarks on the screen. If I modified the layout variables directly, the rapid-fire modifications while calculating would trigger a bajillion reactive updates from Svelte which would slow the page down. Anyways, the way that the layout plan is calculated is that it starts by assuming ideal conditions: there is more than enough room for everything to fit comfortably. So it does the calculations using the preferred ideal variables, it modifies the plan, and then it actually checks to see if anything is overlapping. If there is any overlap, it tries to resolve it using the least-disruptive adjustment it can make. If that doesn’t work, it tries the next least-disruptive adjustment. And so on. Also, each time it moves up the chain of disruptiveness, it tries to use the ideal variables for all of the less-disruptive adjustments. If that makes sense. Here are the adjustments that it can make, in ascending order of disruptiveness: Increasing the radius of the ring of quarks of a single chamber Adjusting the radius of the ring of chambers around the center of the screen Switching chambers to use count mode, which is when it only displays the number of quarks of each flavor rather than displaying each quark individually. Switching the global layout from ring mode to grid mode. This is the thing that I built last devlog. Decreasing the size of all quarks I’m pleased to report that when I tested it on my phone, everything worked perfectly. I still haven’t implemented mobile input yet, but I started a 6-player game of all bots, and the layout planner managed to keep all of the quarks visible all of the time, even when a single chamber had more than 20 quarks. Never once did I see two chambers overlap with each other or go partially offscreen, which used to happen 100% of the time on small mobile screens. It just changed layout modes and decreased the quark size whenever it started to run out of room. Anyways, I’m not going to merge the new layout planner just yet because I’m not 100% sure how stable it is, but I’ll do that soon. Next up is mobile input.
Touchscreen support Idk why I was worried that this would be difficult. Less than 20 lines of code later, Hadronize now automatically detects whether you’re using a fine pointer (e.g. a mouse) or a coarse pointer (e.g. a touchscreen), and changes its behavior accordingly. So now you can select chambers on touchscreen just by tapping on them. You don’t have to drag the superposed quark, you just tap. I recorded a video showcasing this in action using Firefox’s mobile device simulator (aka RDM). As you can see, when I disable touch simulation, the chambers respond to hovering and I have to drag the quark around. But when I enable touch, the chambers don’t react at all until I click one, and then the superposed quark gets added to that chamber like normal. I’ve also tested this on an actual phone and it works perfectly, but it’s more difficult to record on there which is why I used Firefox’s simulator for the video.
Minor graphics improvements This is a smaller devlog. Stuff I did since last devlog: Fixed the winning animation to work with the new layout planner Added transitions to the quark text. Whenever a quark changes its display text (e.g. from a ‘?’ to a flavor abbreviation like ‘s’), rather than instantly snapping to the new text, it’ll do a quick crossfade. Changing the font used for the quark text from the default to a font called Degheest that I think looks nice. Merging the layout refactor into prod because I’ve decided that it seems stable enough. Next, I’m going to work on improving the quark graphics. I’m trying to go for an aesthetic that looks like it’s from a physics textbook (hence the dot grid backdrop I’ve had for a while), so it’s already pretty close, but imo it looks a bit too plain right now. I don’t have a precise vision for exactly what I want the quarks to look like, so I’ll need to figure that out.
New quark style I made new quark graphics, like I promised last devlog. I’m not really sure if it fits the aesthetic I’m going for, but it’s something , and I tried to make it extensible so that I can experiment with more styles later. I also added a dropdown menu in the setup flow so that you can select which style you want to use, though I might remove that in the future if I decide on one style to be the definitive one. The new style is just patterns masked onto the same flat color circles as before. Each flavor has a different pattern: up: vertical lines down: horizontal lines charm: checkerboard strange: square grid with irregular shading top: light dot grid bottom: dark rhombus grid hadron: solid (unchanged) I don’t know if this makes the quarks look nicer or not, but it definitely makes them more accessible. If the abbreviation text isn’t visible for whatever reason (e.g. because the chamber is in count layout mode), quark flavors used to be distinguished solely by color. But the new patterns make them distinguishable without color, which is important for colorblind accessibility.
QuickJS drivers I can now store driver strategy code as strings, execute the strings as JS code using QuickJS , read the quickjs output, and use it as driver output. This might not sound like much of a difference, but it completely changes how I can run drivers. Before, all driver strategies had to be present in the actual source code. Now, they just have to be strings. Because we can manipulate strings at runtime, this means that we can create new drivers while the site is running without modifying the source code. In other words: this lays the groundwork for letting you create and play against your own drivers without making a PR to the repo. To make sure that my implementation works, I converted the expected value driver to use quickjs. I enclosed all of the actual logic in backticks, making it a giant string, and then passed the string through my quickjs driver factory function. I ran the expected value driver test suite, and it failed immediately because I forgot to remove the type annotations (quickjs can only execute plain JS, not TS). But once I fixed that, all 19 tests passed, and it seems to work perfectly from my playtests. I eventually plan on adding a page that uses Prism code editor to let users edit driver strategies and save them to localStorage. But first I’m going to add more features to the quickjs runtime. For example, I want to have it swap all Math.random() calls with a deterministic psuedorandom generator, so that way developers can use randomness without making it non-deterministic.
Bot editor I integrated the QuickJS driver code that I made last devlog into the rest of the site. Things I did: I made the QuickJS VM override the default Math.random function and replace it with a mulberry32 prng seeded by stringifying the game state and hashing it through djbs2 . So now drivers can still use Math.random without making the rng predictable or sacrificing perfect determinism. I gave the drivers names and descriptions. The prng driver is named “Bogo” (after Bogosort ) and the expected value driver is named “EVan” (because it’s a normal name that starts with the abbreviation of “ E xpected V alue”). I moved the code for the existing drivers into a centralized array, rather than in multiple different files that had to be imported individually. I’m calling this array the “stock drivers”. I added a bot editor page. You can check it out at https://ethmarks.github.io/hadronize/bots . I used contenteditable and Svelte’s bind:textContent to let users edit the title, ID, and description. I used Prism code editor as the embedded IDE for editing the actual driver code. I made the play page fetch the list of drivers from localstorage on page load, defaulting to the stock drivers. I also made the bot editor automatically sync the drivers to localstorage . I added a new driver strategy: tit for tat . As expected, it plays pretty terribly because that strategy just isn’t very good in Hadronize. I mostly made it so that users looking at the stock drivers can learn how to reference the timeline from the state. I think that next I’ll work on a driver ranking system so that when I make more drivers, I’ll know whether they’re better or worse than the others. I might research how chess ranking systems work and copy concepts from those.
Benchmark Before I started working on the bot ranking arena, I did a quick sidequest to figure out how many games per second I could simulate. So I wrote this script to execute a bunch of games sequentially, then print the elapsed time and calculate the games per second rate. I ran the benchmark in Node 24.15.0 on my 4.40 GHz Intel i5-12450H using Bogo drivers: Simulated 82157 turns across 1000 games Took 109048ms (109.048s). Speed is 9.170273640965446 games per second So that was surprising. I was expecting a speed in the low thousands, but instead it was less than 10. I had a suspicion what was causing the slowdowns. To make sure, I swapped out the Bogo driver (which uses QuickJS) with a non-QuickJS driver that I made for testing, and reran the same benchmark: Simulated 53854 turns across 1000 games. Took 130ms (0.13s). Speed is 7692.307692307692 games per second (the turn count is smaller because the drivers used a different strategy which made games end faster) So, obviously, the slowdown is caused entirely by QuickJS. Which makes sense. Every time a QuickJS driver is invoked, it spins up a brand new QuickJS VM, configures it, executes the actual code, extracts the return value from the VM, disposes of the VM to avoid memory leaks, and then finally returns the value. Non-QuickJS drivers can just execute the code directly, and the code can be optimized very well by the JIT compiler that Node uses. So the solution seems simple, right? Just don’t use QuickJS for the drivers. Whatever the advantages of using QuickJS are, surely they aren’t worth an 839x decrease in performance. Well, unfortunately that’s not an option. More specifically, dynamically running strings of JS (like the driver code that users write at runtime) as native code is not possible, so I have to use a JS VM. And QuickJS is by far the best embeddable JS VM that I know of. So I just have to accept the slowness. This means that I’ll have to be clever about the bot arena, though. I can’t just brute-force a ranking with thousands of games if I can only run 10 games per second. btw, if you’d like to see how your PC does on my benchmark, just run these commands: git clone https://github.com/ethmarks/hadronize.git cd hadronize pnpm install pnpm bench --count 1000 --driver prng If your time is faster than mine, leave a comment to gloat.
Discontinuing the ranking arena I’ve decided to stop working on the driver ranking arena. I already have an MVP that works well enough to kinda sorta determine which drivers are good and which are bad, but it’s not robust and it just sums up rankings rather than implementing an actual Elo algorithm . The reason I’m not going to continue working on it is that it seems like a lot of work, and I don’t think that it’ll provide any value. Like, at all. The root of the problem is that Hadronize just isn’t a strategic-enough game. There’s certainly some strategy, of course, and probabilistic modeling, but luck plays just as much of a factor. The cleverest Hadronize driver can still routinely lose to the dumbest one just due to slightly bad luck. So it doesn’t really make sense to build tooling for strategic bots if the strategy is not a very big aspect of the game. Thinking back, I’m not really sure why I decided to start working on the driver arena in the first place. It just seemed like the right thing to do at the time even though I now realize that it would be kind of useless. Anyways, I also created two new drivers. The first is called Kingslayer, and it just tries to steal from the player who’s currently winning. It’s not very good at actually winning, but it does make things more challenging for the other players. The second is called Gentleman (aka charm ). It’s obsessed with trying to collect charm quarks, because its a charming gentleman. I made it as a joke because I thought it was funny, but to my complete surprise it turns out to be a pretty good strategy? Not charm quarks in particular, but trying to collect a specific flavor of quark at all costs turns out to be surprisingly effective. It consistently wins more often than EVan, the driver that I specifically built to be a good strategy and that actually does probabilistic expected value calculations. I think that next I’ll start working on the README and documentation, because I haven’t updated the README in like 3 weeks and it’s extremely outdated.
How to play page I wrote a page that explains how to play, assuming zero knowledge. I think that this’ll be helpful for onboarding, because this way they learn the rules at the same time as they learn how to use the UI, rather than reading the abstract and theoretical rules and then trial-and-erroring their way through the UI. The actual writing part took a few hours, and most of it was revision and trying to find better ways to phrase things. It’s nearly 1000 words, meaning I could turn it in for an essay assignment and not fail the word count, which is funny. But what also took a lot of time was making the visual aid. I had to record myself performing the same action in the UI many times to get a perfect take, and then I had to craft an ffmpeg command to crop and trim it because I refuse to use graphical video editors. Also my recording software kept stuffing H.264 video data in a webm container, which made ffmpeg freak out because that file is technically corrupted. I also had to figure out how to screen record on my phone to get a tap indicator, which I’d never done before. You can read the page here: https://ethmarks.github.io/hadronize/how
Revised README I worked on updating and basically completely rewriting the README to something more polished. I still need to add more sections and revise what I have, but I think that it’s alright. I’m trying to strike a balance between not having enough content and being a wall of text. It’s also surprisingly difficult to come up with bullet points for the features list. After I finish up the README, I’m going to redesign the home page a bit. After that, I think I might be ready to ship.
Revised Readme (again) Still working on the README. I think that Hadronize is more or less ready to ship now, but there’s probably still a bit more polishing I can do. In my other Stardance projects, I’ve gotten really positive feedback on my READMEs, so apparently my writing style and README format of choice is a winning combination. I’ve been referencing my past READMEs and the Stardance README guide a lot while writing this one. The bulk of what I added was the How it Works section, which explains some of the technical details and design choices that I made. It’s a dense topic so it’s obviously a long section. At first it was just a wall of text, even when I tried to break it up with lists and subheadings. So I spent about half an hour taking screenshots and editing them in GIMP until I had decorative images that I was satisfied with for each subsection. I think that drop shadows on transparent backgrounds look really cool in README images, so I used GIMP’s drop shadow filter to add them to my screenshots (in addition to cropping, rounding corners, et cetera). I kept fiddling with the drop shadow settings and I didn’t want to go back and redo the images that I’d already done, so the shadows are kind of inconsistent, which really irks me but I don’t think is very noticeable. I also added a Running Locally section and fixed a few typos throughout the README. Lastly, I did a bit of work on the home page. I added a big screenshot below the intro paragraph, thanks to feedback from the awesome @Luksus , whose project you should totally check out .
Shipping I did a few miscellaneous things like make the remote script endpoint production-ready, fix some typos across the project, and create a favicon in Inkscape. After I write this devlog, I’m going to press the big “Ship your project!” button. If you’re a reviewer reading this: I hope you enjoy Hadronize. It’s one of my biggest projects ever, and I’m really proud of how it’s turned out.
Ships:
Hadronize: a quark-themed set collection game. It has a web UI with a custom SvelteKit virtual layout engine, a polyglot CLI that runs across Node, Deno, Bun, and the browser console, a QuickJS bot sandbox, a comprehensive test suite, and more. I’m really proud of Hadronize and hope that you enjoy it....
|
1792821406.139325
|
1792907806.139325
|
|
32533
|
Kobayashi OS by @Riko | Stardance
|
Riko
|
2
|
151.0
|
2155
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-06T13:18:06Z", "hours": 108.0, "multiplier": 19.95, "payout": 2155, "blessing": "neutral", "text": "What did you make? Kobayashi OS — a web OS themed around Miss Kobayashi’s Dragon Maid . I wanted to make one of the most feature-rich and polished web OS experiences possible, something that actually feels like you’re using a PC. And yeah, this is Kobayashi’s PC, so don’t be surprised if you find something interesting related to her. The main thing I focused on was making everything feel connected, just like a real OS. Apps don’t just exist separately — Camera connects to Gallery and Files, downloads go into Files, Kanvas can save things to Files, widgets remember where you put them, and Kobayashi-chan can actually interact with the system. Basically, it’s not just a collection of apps. It’s one big little OS. What was challenging? Interconnecting all the apps and keeping everything persistent was definitely a challenge. I wanted things to behave like an actual OS instead of just being separate demos. Making the Kobayashi-chan AI work was one of the toughest hurdles. Getting tool calling, memory, emotions, and system interaction to work together took a lot of trial and error. Designing and building the widget system was another tough one. Making widgets draggable, positionable, persistent, and actually useful took quite a bit of work. Honestly, getting all the small details and polish right took way more time than I expected. What am I proud of? First — Kobayashi-chan AI. This is probably my favorite part of the whole project. She has tool calling, memory, emotions, and can actually interact with the OS. I genuinely didn’t expect I would be able to make something like this. It’s basically a little Jarvis, but Kobayashi-chan. The piano. I spent way more time on this than I probably should have. Not building it — playing it. It’s such a stupidly fun little feature that I keep losing track of time playing on it. The overall polish. I’ve been working on this for so long that I’ve honestly lost count of all the little things I added. I designed the UI in Figma, made a lot of the icons myself, kept redesigning things, learned a ridiculous amount along the way, and kept adding small details until it finally started feeling like a real OS. I’m genuinely proud of how it turned out. There are a lot of things packed into this project, and I think the best way to understand the amount of work that went into it is to actually explore it yourself. What should you know before testing? The project: https://kobayashi.cawai.site/ Please explore the widgets. This is one of the parts I spent a lot of time on. Please try the piano. Seriously. On the first load, some images may take 1–2 seconds to appear. Give it a moment. Wallpaper customization, live wallpapers, and icon customization may also take a little time on the first load. There are a LOT of games: Thor, Spider-Man, Minecraft, etc. If you open one and see a black screen, don’t panic. Some of them just take a little while to load. Come on, we’re talking about Minecraft here. Give it some time. And obviously, click around. Open things. Break things. Try stuff. A lot of the fun is finding the little details hidden around the OS. That’s Kobayashi OS. I started with the idea of making a web OS, but somewhere along the way it turned into this huge little world with its own apps, games, music, memories, AI, and way too many tiny details. Hope you have fun exploring it.", "repo": "https://github.com/anshumitasahu/Kobayashi--OS", "demo": "https://kobayashi.cawai.site/"}, {"ship_num": 2, "ts": "2026-08-01T08:57:08Z", "hours": 43.0, "multiplier": null, "payout": 0, "blessing": "neutral", "text": "Kobayashi OS v1.0 is finally live! Kobayashi OS is a lightweight, anime-inspired Web Operating System built to bring a desktop-like experience to the browser. This first release focuses on a smooth window management system, allowing multiple instances of the same application, along with wallpaper, icon, and brightness customization. It uses React, TypeScript, Bun, Tailwind CSS, Zustand, and Local Storage to provide a persistent experience. The custom logo and launch banner were also designed specifically for this release. Some applications currently contain placeholder alerts and are still under development, with more features and apps planned for future updates. Highlights Anime-inspired light theme Interactive multi-window desktop Multiple instances of the same app Wallpaper, icon & brightness customization Zustand + Local Storage More apps and features coming soon", "repo": "https://github.com/anshumitasahu/Kobayashi--OS", "demo": "https://kobayashi.cawai.site/"}]...
|
[{"post_id": 62884, "ts": "202 [{"post_id": 62884, "ts": "2026-09-06T12:36:45Z", "hours": 1.8994, "text": "Polished the UI of the widgets, improved wallpaper customization, refined the app UX, resized the apps, added a bunch of new features, and made countless small tweaks across the OS. A lot has gone into this project, and I really hope it becomes the star project considering how much time I’ve poured into it. 🥹 Still more to come!"}, {"post_id": 62379, "ts": "2026-09-05T18:24:34Z", "hours": 1.5711, "text": "Kobayashi-chan is here! Chat, open apps, change settings. She remembers, reacts, and doesn’t mind a little flirting. :) Major changes!! A summary of everything I’ve done over the past 5 days. Lots of design work too—especially Figma stuff. StarDance doesn’t log my Figma hours though… too bad."}, {"post_id": 62033, "ts": "2026-09-05T07:58:56Z", "hours": 10.0164, "text": "Damnn!! Been a while haven’t posted anything bout my Work!!!!!! added a piano added a lots of Fun games improved the architecture and UI/UX improved the response of the Kobai added Terminal and Code editor.. added a proper and nice widget system changed the whole UI of my apps_ and more features are coming soon!!!!!"}, {"post_id": 58672, "ts": "2026-08-31T05:42:22Z", "hours": 9.2753, "text": "Added a lots of appppss!!! embeded few games, hackclub and typingtest.com … and Yeah added my own built apps (Json Lab , DevScope, and MoneyTrail)"}, {"post_id": 55183, "ts": "2026-08-26T18:06:02Z", "hours": 3.21, "text": "Another day on Kobayashi OS. Damn, I really turned the AI Assistant into what I actually wanted it to be. And yeah, now the Shorts app isn’t just some mere app with a icon sitting there — it actually has Shorts embedded hehe. And yeah… there’s a Kanvas app now too lol."}, {"post_id": 54549, "ts": "2026-08-25T16:00:46Z", "hours": 9.8811, "text": "Damn !! Been a while !! Yup was working on the assistant.. yeah which actually works!!! changed the architecture of ai chatbot and yeah its much better now !! and Yeah some more tweaks ongoing"}, {"post_id": 52981, "ts": "2026-08-23T11:05:21Z", "hours": 1.2497, "text": "Making the UI of music player nicer .."}, {"post_id": 52917, "ts": "2026-08-23T09:19:23Z", "hours": 3.9803, "text": "BIG ALERT IN KOBAYASHI OS I SUCCESSFULLY BUILT AN AI ASSISTANT FOR MY WEB OS! 🎉 It can actually understand commands and interact with the OS — opening apps, handling actions, and more.Another huge step for Kobayashi OS. I’m learning a LOT about AI while building this, and it’s honestly crazy seeing everything come together."}, {"post_id": 52189, "ts": "2026-08-22T08:54:28Z", "hours": 5.2606, "text": "Worked on the adding more apps.. with functionality and zero css hehe but yeah add it later currently working on a ai chat box on my project apps"}, {"post_id": 51173, "ts": "2026-08-20T17:52:30Z", "hours": 3.4503, "text": "Today was more focused on research and architecture than coding, but I still made some solid progress. I perfected the widgets, made the right-click menu fully functional, and built a basic music player that’s already working. I’ll be focusing on the CSS and visual polish for the music player tomorrow. Overall, another productive day on Kobayashi OS."}, {"post_id": 50444, "ts": "2026-08-19T16:37:20Z", "hours": 3.5219, "text": "Spent some more time working on the Widgets section 👀 Made the widgets draggable and closable only when the widgets menu the widgets top bar is being displayed.Also fixed up some CSS issues, added a right-click context menu, and added an Open option. So far, only one widget is actually openable; the rest will come later 😅 That’s enough UI work for today though — my shoulders and back are officially protesting. 💀 More to come!"}, {"post_id": 50174, "ts": "2026-08-19T09:00:29Z", "hours": 1.9064, "text": "Update Made a few solid improvements to the widget experience: Widget positions are now stored globally and persisted in local storage, so the app restores exactly where you left it after a refresh. Tweaked the visuals for a cleaner, more polished look. Added resizable widgets for a more flexible, customizable layout. Small changes, but they make the overall experience feel much smoother. More to come!"}, {"post_id": 49755, "ts": "2026-08-18T17:54:09Z", "hours": 3.4989, "text": "A little update on the Widgets section It’s already looking pretty cool , but I’m not quite done with it yet. There are still a few tweaks and some changes I want to make to how the widget system works under the hood. The goal is to make the whole experience feel cleaner, more flexible, and easier to build on as I keep adding more widgets. For now, though… I’m pretty happy with how it’s coming together. 🚀More tweaks incoming."}, {"post_id": 49478, "ts": "2026-08-18T10:44:19Z", "hours": 5.8236, "text": "Yahooooooo! Made some awesome progress! Added the Widgets feature Added a toggle function to open/close the Widgets list Added a Calendar widget Added a Clock widget Added toggle functionality for opening and closing widgets So happy to see it all coming together! 😄 🔥One step at a time, and the project is getting better and better! ✨ 💪"}, {"post_id": 48289, "ts": "2026-08-16T16:27:18Z", "hours": 3.5703, "text": "Camera Improvements Fixed a few bugs and made some nice improvements to the camera flow. Now, the last captured photo is shown directly in the camera. Tap it, and the gallery opens with the image displayed at full width and height. From there, you can swipe through the rest of your photos. Still have a few things I want to tweak in this flow, but the experience is already feeling much smoother. Next up: widgets !!"}, {"post_id": 47551, "ts": "2026-08-15T15:04:05Z", "hours": 7.6117, "text": "Been a while! Added a working camera + gallery and implemented IndexedDB for storing captured photos.Honestly, the camera logic and IndexedDB were the biggest challenges since I knew nothing about them before this. Learned from internet resources, experimented, broke things, fixed them… and finally cracked it."}, {"post_id": 44158, "ts": "2026-08-09T18:47:51Z", "hours": 3.5058, "text": "I worked on improving the app bar behavior in Kobayashi OS. I added the Menu app icon to the apps bar whenever it’s opened, and also implemented position shifting for existing apps so they adjust automatically when a new app appears. Small interaction improvements, but they make the desktop feel more dynamic and consistent."}, {"post_id": 43954, "ts": "2026-08-09T12:32:36Z", "hours": 4.1286, "text": "Gallery is successfully made! Glad it turned out well. The main challenge was the UI 🙄, but yeah, it now has Next/Previous and Back functionality. The selected image expands to the full width and height—just like we see in a proper gallery, without appearing in some corner or another section. Overall, pretty happy with how it turned out!"}, {"post_id": 43099, "ts": "2026-08-08T05:43:08Z", "hours": 7.2944, "text": "It’s been a while since my last update, but I’m happy to say Kobayashi OS is getting closer to the finish line! 🚀 Update: Added a toggle to open/close the Menu app Improved the Settings & overall UI Added app resizing App bar now hides when the screen is maximized Added a background for active page in settings Changed the About us Section More apps and features coming soon!🔥"}, {"post_id": 41836, "ts": "2026-08-06T09:25:46Z", "hours": 1.5522, "text": "Worked on the menu app UI. It’s not fully functional yet, but I’ve added some basic functionality. I think it’s looking pretty good so far. This isn’t the final version, but the overall design will probably stay pretty close to this."}, {"post_id": 41800, "ts": "2026-08-06T07:15:41Z", "hours": 4.815, "text": "Worked on the icon styling and UI, and implemented the app menu with close functionality. What ended up taking most of my time was a tiny bug—I was referencing a value as a string in one place while providing it as an object in another. It took me hours to spot the mismatch. Funny how the smallest errors can consume the most time."}, {"post_id": 40844, "ts": "2026-08-04T17:03:57Z", "hours": 3.7994, "text": "I’ve been working on the app’s UI in the maximized state. Initially, the main challenges were around the overall workflow and approach. After experimenting with a few different directions, everything clicked and I landed on this design. Next, I’ll be refining the icon styles further."}, {"post_id": 40140, "ts": "2026-08-03T15:22:36Z", "hours": 4.1178, "text": "I updated the minimize/maximize buttons so restored windows remember their previous position via the global store. Minimized apps now show a dot indicator at the bottom instead of the top. I also fixed a topbar bug where its z-index and absolute positioning caused maximized windows to get stuck underneath. My main hurdle right now is UI scaling: the window container maximizes fine, but the internal components don’t resize with it. I’m weighing a few fixes to see which approach works best."}, {"post_id": 39349, "ts": "2026-08-02T08:39:42Z", "hours": 0.9731, "text": "Just fixed the README"}, {"post_id": 38957, "ts": "2026-08-01T16:01:53Z", "hours": 2.0964, "text": "Implemented minimize and restore with functionality and the maximize feat will be implemented in the 2nd version.."}, {"post_id": 38729, "ts": "2026-08-01T08:51:37Z", "hours": 1.1942, "text": "Fixed the README and got it ready for the first official launch. The main issue was that the images and screenshots weren’t displaying correctly. Since it was a GitHub README, every small change required a commit and push just to verify whether the images loaded properly, which made the process slower than expected. Despite that, the final README turned out well and is now ready for launch."}, {"post_id": 38361, "ts": "2026-07-31T18:19:40Z", "hours": 3.6125, "text": "Added a notes app and added loading and welcome page .. Creating the logo was a bit hard :< More feats and apps are coming!!"}, {"post_id": 38107, "ts": "2026-07-31T10:07:15Z", "hours": 3.5414, "text": "Worked on the icons bar and added a new feature to the Settings app — you can now switch icon styles. Also saved wallpaper, brightness, and icon styles to localStorage . Biggest challenges were digging through a massive icon file, organising them, and getting the UI right. At one point the icons just wouldn’t change… turns out I forgot to call the function. 😅 Moving on to more features and apps."}, {"post_id": 37465, "ts": "2026-07-30T07:17:09Z", "hours": 1.4686, "text": "Updated the app icons — they look so much better now. The old ones felt a bit off. Funny disaster though: right after the change, nothing would open. Threw in some console.log()s … and the system crashed. Turns out the old icon was still being called in the main code, which made every window try to open. 😂"}, {"post_id": 37085, "ts": "2026-07-29T15:46:45Z", "hours": 2.3036, "text": "Very small visible change this time. Added functionality to the settings sidebar . Yeah thinking bout the architecture!! I did added different colors to my app background then removed it due to change in the architecture. Working on something which looks like a small change 🥲 but needs a solid time and architecture 🫠 😮💨."}, {"post_id": 36496, "ts": "2026-07-28T17:20:36Z", "hours": 2.3367, "text": "Nothing!! Just refactored the UI of the Settings app. Added a side bar with the search bar. The main headache was the Architecture !! Damn!! My head hurts !! Still moving on. I will update the full functionality of settings app next time !! (That’s my goal) . But yeah will add the other features later as the OS grows."}, {"post_id": 36275, "ts": "2026-07-28T08:28:19Z", "hours": 1.7669, "text": "Just dropped a fresh update for my web OS, Kobayashi OS ! It can now fully customize the desktop’s wallpaper with solid colors and gradients , all powered by a global store so everything stays smooth and in sync. And Yo!! not gonna lie, building this took me on a absolute emotional roller coaster. I hit bug after bug, spent ages searching for answers, only to discover the culprits were… simple typos and missed JavaScript punctuation!! Classic! But hey, every bug fixed is a lesson learned. I’m on a roll , so expect more updates super soon! Next up on the build list: making the Settings app feel like a real-deal OS and dropping some brand-new apps."}, {"post_id": 35678, "ts": "2026-07-27T08:43:11Z", "hours": 2.6417, "text": "I recently refactored our z-index management from local storage to a global system. Naturally, it brought a wave of visual bugs along with it—fix one, and four more pop up!After a solid debugging session with console.log(), everything is stable and working as expected. Next up: building out the Settings app to make it fully functional."}, {"post_id": 34138, "ts": "2026-07-24T17:18:12Z", "hours": 1.5758, "text": "Cleaned up the codebase, fixed a minor bug, and finally built a manual wallpaper changer. Decided to use global state for it and… wow. It actually clicked. I was stuck for a minute overthinking how the workflow should look, but once I just started typing, it made total sense. State management isn’t nearly as painful as I used to think. Naturally, it didn’t work on the first try—the wallpaper wasn’t updating at all. Turns out I forgot a set of parentheses and had a stupid typo. Classic. Fixed that, and now it’s smooth sailing."}, {"post_id": 33969, "ts": "2026-07-24T10:18:51Z", "hours": 2.7989, "text": "I started moving my app state from local state to a global store using Zustand. Right now, the open/close state of applications is managed globally, and next I’ll move the window dragging logic there as well. The dragging system already works locally, so this is mostly a refactor to make the OS easier to scale.I also added a Settings app, although it doesn’t do anything yet. I decided to focus on getting the core OS functionality solid before adding more features and applications. Once that’s done, I’ll add things like manually changeable wallpapers and expand the Settings app. As someone who’s still new to state management, I had no idea how to use a global store when I started. So before writing code, I spent time learning Zustand, understanding how global state works, and planning the architecture instead of jumping straight into implementation.There were plenty of moments where I got stuck. I had a few headaches trying to wrap my head around the concepts, but I kept going until it finally clicked. No big visual changes, but I think I crossed a small milestone—one that’s going to make everything I build next much cleaner and easier to manage."}, {"post_id": 31816, "ts": "2026-07-20T14:35:36Z", "hours": 1.2033, "text": "Fixed a sneaky LocalStorage bug today! 🛠️ I initially put JSON.stringify directly inside useState , which completely crashed the app and prevented it from opening. Rewrote the logic by moving JSON.stringify into a useEffect hook with tasks as a dependency. That got it working, but refreshing the page triggered a new bug: local storage was getting overwritten with an empty array. I logged the data flow at every stage and caught the issue: useEffect was running on initial mount before state was restored. Added a simple length check (tasks.length > 0) before stringifying, and everything works perfectly now! Always check your mount cycles! 🚀"}, {"post_id": 31692, "ts": "2026-07-20T09:40:11Z", "hours": 6.9306, "text": "It’s been a while since my last update, so here is what I’ve been building and refining lately: UI Refactoring: Invested a significant amount of time redesigning and polishing the UI (still a work in progress, but looking much better!). Window Management: Added support for opening, minimizing, and closing windows. Calculator App: Cleaned up the codebase and added new functionality. Task Tracking: Added a strike-through feature for completed items in To-Dos App. Next up: Implementing localStorage so task completions and window states persist across sessions."}, {"post_id": 27792, "ts": "2026-07-13T17:37:49Z", "hours": 1.6667, "text": "Focus was the window manager. Completed Implemented dynamic z-index so the active window is always brought to the front. Added window minimization.Implemented restore functionality from the Apps Bar. Preserved window state while minimized instead of closing the application. Challenge: Initially, minimizing a window removed it from the UI, but there was no way to bring it back because clicking the app icon simply ignored already opened apps. Solution: Instead of treating minimized windows as closed, I introduced a minimized state for each window. The Apps Bar now checks whether an app is already open, minimized, or closed, and performs the appropriate action—open, restore, or bring it to the front. This keeps the component mounted and preserves its state while hidden. The desktop now supports opening, closing, dragging, minimizing, restoring, and proper window stacking. With these core interactions in place, the next milestone is maximize/restore, followed by window resizing and a global state refactor with Zustand."}, {"post_id": 27668, "ts": "2026-07-13T13:16:12Z", "hours": 2.5236, "text": "Continued building the window management system for Kobayashi OS. Implemented draggable application windows from scratch using React mouse events (mousedown, mousemove, mouseup) with proper drag offsets for smooth movement. Refactored the layout to introduce a dedicated desktop area, keeping windows constrained within the workspace instead of the entire page. Spent most of the session debugging positioning logic, DOM measurements, and boundary constraints. The draggable window system is now functional and forms the foundation for upcoming features like minimize, maximize, focus (z-index), and Zustand-powered window state management."}, {"post_id": 27273, "ts": "2026-07-12T18:23:14Z", "hours": 1.3567, "text": "Continued refining the Kobayashi OS interface.Finalized the built-in app icons and continued shaping the application dock and overall desktop structure to make the OS feel more like a complete desktop environment.Built the first built-in application—a basic calculator—with support for standard arithmetic operations. This marks the beginning of adding functional utilities to the OS.The focus remains on establishing a solid foundation before expanding into more advanced applications and features."}, {"post_id": 27129, "ts": "2026-07-12T12:31:10Z", "hours": 1.3028, "text": "Continued working on the Kobayashi OS layout. The overall design is still evolving, and I’m experimenting with different arrangements before settling on a final structure. I added icons for the built-in applications and started shaping how the interface should feel. No application logic yet—right now the focus is on finding the right layout before building the functionality."}, {"post_id": 27073, "ts": "2026-07-12T09:23:01Z", "hours": 1.6333, "text": "DevDock is no longer just a collection of developer tools—it’s being redesigned into Kobayashi OS , a browser-based operating system built for developers . This update focuses on restructuring the application’s architecture, replacing the original layout with an OS-inspired interface, and laying the groundwork for applications, tools, and a desktop-like workflow. The goal is to create a cohesive environment where developer utilities feel like native applications rather than separate web pages.The transition is still in progress, but the foundation for Kobayashi OS is now replacing the original DevDock vision."}, {"post_id": 25205, "ts": "2026-07-09T09:44:08Z", "hours": 3.5269, "text": "DevLog 1 — DevDock After wrapping up DevScope, I wanted to build something that solves a problem. Introducing DevDock — a workspace that brings essential developer tools together in one place, reducing context switching and making common development tasks faster and more convenient.I’ve already finished the initial landing page. It took far more CSS work than I’m used to, but I’m happy with where it stands for now. Of course, nothing is ever truly finished—I’ll keep refining it if future feedback or better ideas come up.This is only the beginning. The real work starts now as I begin building the tools that will make DevDock genuinely useful."}]...
|
Title: Kobayashi OS by @Riko | Stardance
Devlogs: Title: Kobayashi OS by @Riko | Stardance
Devlogs:
DevLog 1 — DevDock After wrapping up DevScope, I wanted to build something that solves a problem. Introducing DevDock — a workspace that brings essential developer tools together in one place, reducing context switching and making common development tasks faster and more convenient.I’ve already finished the initial landing page. It took far more CSS work than I’m used to, but I’m happy with where it stands for now. Of course, nothing is ever truly finished—I’ll keep refining it if future feedback or better ideas come up.This is only the beginning. The real work starts now as I begin building the tools that will make DevDock genuinely useful.
DevDock is no longer just a collection of developer tools—it’s being redesigned into Kobayashi OS , a browser-based operating system built for developers . This update focuses on restructuring the application’s architecture, replacing the original layout with an OS-inspired interface, and laying the groundwork for applications, tools, and a desktop-like workflow. The goal is to create a cohesive environment where developer utilities feel like native applications rather than separate web pages.The transition is still in progress, but the foundation for Kobayashi OS is now replacing the original DevDock vision.
Continued working on the Kobayashi OS layout. The overall design is still evolving, and I’m experimenting with different arrangements before settling on a final structure. I added icons for the built-in applications and started shaping how the interface should feel. No application logic yet—right now the focus is on finding the right layout before building the functionality.
Continued refining the Kobayashi OS interface.Finalized the built-in app icons and continued shaping the application dock and overall desktop structure to make the OS feel more like a complete desktop environment.Built the first built-in application—a basic calculator—with support for standard arithmetic operations. This marks the beginning of adding functional utilities to the OS.The focus remains on establishing a solid foundation before expanding into more advanced applications and features.
Continued building the window management system for Kobayashi OS. Implemented draggable application windows from scratch using React mouse events (mousedown, mousemove, mouseup) with proper drag offsets for smooth movement. Refactored the layout to introduce a dedicated desktop area, keeping windows constrained within the workspace instead of the entire page. Spent most of the session debugging positioning logic, DOM measurements, and boundary constraints. The draggable window system is now functional and forms the foundation for upcoming features like minimize, maximize, focus (z-index), and Zustand-powered window state management.
Focus was the window manager. Completed Implemented dynamic z-index so the active window is always brought to the front. Added window minimization.Implemented restore functionality from the Apps Bar. Preserved window state while minimized instead of closing the application. Challenge: Initially, minimizing a window removed it from the UI, but there was no way to bring it back because clicking the app icon simply ignored already opened apps. Solution: Instead of treating minimized windows as closed, I introduced a minimized state for each window. The Apps Bar now checks whether an app is already open, minimized, or closed, and performs the appropriate action—open, restore, or bring it to the front. This keeps the component mounted and preserves its state while hidden. The desktop now supports opening, closing, dragging, minimizing, restoring, and proper window stacking. With these core interactions in place, the next milestone is maximize/restore, followed by window resizing and a global state refactor with Zustand.
It’s been a while since my last update, so here is what I’ve been building and refining lately: UI Refactoring: Invested a significant amount of time redesigning and polishing the UI (still a work in progress, but looking much better!). Window Management: Added support for opening, minimizing, and closing windows. Calculator App: Cleaned up the codebase and added new functionality. Task Tracking: Added a strike-through feature for completed items in To-Dos App. Next up: Implementing localStorage so task completions and window states persist across sessions.
Fixed a sneaky LocalStorage bug today! 🛠️ I initially put JSON.stringify directly inside useState , which completely crashed the app and prevented it from opening. Rewrote the logic by moving JSON.stringify into a useEffect hook with tasks as a dependency. That got it working, but refreshing the page triggered a new bug: local storage was getting overwritten with an empty array. I logged the data flow at every stage and caught the issue: useEffect was running on initial mount before state was restored. Added a simple length check (tasks.length > 0) before stringifying, and everything works perfectly now! Always check your mount cycles! 🚀
I started moving my app state from local state to a global store using Zustand. Right now, the open/close state of applications is managed globally, and next I’ll move the window dragging logic there as well. The dragging system already works locally, so this is mostly a refactor to make the OS easier to scale.I also added a Settings app, although it doesn’t do anything yet. I decided to focus on getting the core OS functionality solid before adding more features and applications. Once that’s done, I’ll add things like manually changeable wallpapers and expand the Settings app. As someone who’s still new to state management, I had no idea how to use a global store when I started. So before writing code, I spent time learning Zustand, understanding how global state works, and planning the architecture instead of jumping straight into implementation.There were plenty of moments where I got stuck. I had a few headaches trying to wrap my head around the concepts, but I kept going until it finally clicked. No big visual changes, but I think I crossed a small milestone—one that’s going to make everything I build next much cleaner and easier to manage.
Cleaned up the codebase, fixed a minor bug, and finally built a manual wallpaper changer. Decided to use global state for it and… wow. It actually clicked. I was stuck for a minute overthinking how the workflow should look, but once I just started typing, it made total sense. State management isn’t nearly as painful as I used to think. Naturally, it didn’t work on the first try—the wallpaper wasn’t updating at all. Turns out I forgot a set of parentheses and had a stupid typo. Classic. Fixed that, and now it’s smooth sailing.
I recently refactored our z-index management from local storage to a global system. Naturally, it brought a wave of visual bugs along with it—fix one, and four more pop up!After a solid debugging session with console.log(), everything is stable and working as expected. Next up: building out the Settings app to make it fully functional.
Just dropped a fresh update for my web OS, Kobayashi OS ! It can now fully customize the desktop’s wallpaper with solid colors and gradients , all powered by a global store so everything stays smooth and in sync. And Yo!! not gonna lie, building this took me on a absolute emotional roller coaster. I hit bug after bug, spent ages searching for answers, only to discover the culprits were… simple typos and missed JavaScript punctuation!! Classic! But hey, every bug fixed is a lesson learned. I’m on a roll , so expect more updates super soon! Next up on the build list: making the Settings app feel like a real-deal OS and dropping some brand-new apps.
Nothing!! Just refactored the UI of the Settings app. Added a side bar with the search bar. The main headache was the Architecture !! Damn!! My head hurts !! Still moving on. I will update the full functionality of settings app next time !! (That’s my goal) . But yeah will add the other features later as the OS grows.
Very small visible change this time. Added functionality to the settings sidebar . Yeah thinking bout the architecture!! I did added different colors to my app background then removed it due to change in the architecture. Working on something which looks like a small change 🥲 but needs a solid time and architecture 🫠 😮💨.
Updated the app icons — they look so much better now. The old ones felt a bit off. Funny disaster though: right after the change, nothing would open. Threw in some console.log()s … and the system crashed. Turns out the old icon was still being called in the main code, which made every window try to open. 😂
Worked on the icons bar and added a new feature to the Settings app — you can now switch icon styles. Also saved wallpaper, brightness, and icon styles to localStorage . Biggest challenges were digging through a massive icon file, organising them, and getting the UI right. At one point the icons just wouldn’t change… turns out I forgot to call the function. 😅 Moving on to more features and apps.
Added a notes app and added loading and welcome page .. Creating the logo was a bit hard :< More feats and apps are coming!!
Fixed the README and got it ready for the first official launch. The main issue was that the images and screenshots weren’t displaying correctly. Since it was a GitHub README, every small change required a commit and push just to verify whether the images loaded properly, which made the process slower than expected. Despite that, the final README turned out well and is now ready for launch.
Implemented minimize and restore with functionality and the maximize feat will be implemented in the 2nd version..
Just fixed the README
I updated the minimize/maximize buttons so restored windows remember their previous position via the global store. Minimized apps now show a dot indicator at the bottom instead of the top. I also fixed a topbar bug where its z-index and absolute positioning caused maximized windows to get stuck underneath. My main hurdle right now is UI scaling: the window container maximizes fine, but the internal components don’t resize with it. I’m weighing a few fixes to see which approach works best.
I’ve been working on the app’s UI in the maximized state. Initially, the main challenges were around the overall workflow and approach. After experimenting with a few different directions, everything clicked and I landed on this design. Next, I’ll be refining the icon styles further.
Worked on the icon styling and UI, and implemented the app menu with close functionality. What ended up taking most of my time was a tiny bug—I was referencing a value as a string in one place while providing it as an object in another. It took me hours to spot the mismatch. Funny how the smallest errors can consume the most time.
Worked on the menu app UI. It’s not fully functional yet, but I’ve added some basic functionality. I think it’s looking pretty good so far. This isn’t the final version, but the overall design will probably stay pretty close to this.
It’s been a while since my last update, but I’m happy to say Kobayashi OS is getting closer to the finish line! 🚀 Update: Added a toggle to open/close the Menu app Improved the Settings & overall UI Added app resizing App bar now hides when the screen is maximized Added a background for active page in settings Changed the About us Section More apps and features coming soon!🔥
Gallery is successfully made! Glad it turned out well. The main challenge was the UI 🙄, but yeah, it now has Next/Previous and Back functionality. The selected image expands to the full width and height—just like we see in a proper gallery, without appearing in some corner or another section. Overall, pretty happy with how it turned out!
I worked on improving the app bar behavior in Kobayashi OS. I added the Menu app icon to the apps bar whenever it’s opened, and also implemented position shifting for existing apps so they adjust automatically when a new app appears. Small interaction improvements, but they make the desktop feel more dynamic and consistent.
Been a while! Added a working camera + gallery and implemented IndexedDB for storing captured photos.Honestly, the camera logic and IndexedDB were the biggest challenges since I knew nothing about them before this. Learned from internet resources, experimented, broke things, fixed them… and finally cracked it.
Camera Improvements Fixed a few bugs and made some nice improvements to the camera flow. Now, the last captured photo is shown directly in the camera. Tap it, and the gallery opens with the image displayed at full width and height. From there, you can swipe through the rest of your photos. Still have a few things I want to tweak in this flow, but the experience is already feeling much smoother. Next up: widgets !!
Yahooooooo! Made some awesome progress! Added the Widgets feature Added a toggle function to open/close the Widgets list Added a Calendar widget Added a Clock widget Added toggle functionality for opening and closing widgets So happy to see it all coming together! 😄 🔥One step at a time, and the project is getting better and better! ✨ 💪
A little update on the Widgets section It’s already looking pretty cool , but I’m not quite done with it yet. There are still a few tweaks and some changes I want to make to how the widget system works under the hood. The goal is to make the whole experience feel cleaner, more flexible, and easier to build on as I keep adding more widgets. For now, though… I’m pretty happy with how it’s coming together. 🚀More tweaks incoming.
Update Made a few solid improvements to the widget experience: Widget positions are now stored globally and persisted in local storage, so the app restores exactly where you left it after a refresh. Tweaked the visuals for a cleaner, more polished look. Added resizable widgets for a more flexible, customizable layout. Small changes, but they make the overall experience feel much smoother. More to come!
Spent some more time working on the Widgets section 👀 Made the widgets draggable and closable only when the widgets menu the widgets top bar is being displayed.Also fixed up some CSS issues, added a right-click context menu, and added an Open option. So far, only one widget is actually openable; the rest will come later 😅 That’s enough UI work for today though — my shoulders and back are officially protesting. 💀 More to come!
Today was more focused on research and architecture than coding, but I still made some solid progress. I perfected the widgets, made the right-click menu fully functional, and built a basic music player that’s already working. I’ll be focusing on the CSS and visual polish for the music player tomorrow. Overall, another productive day on Kobayashi OS.
Worked on the adding more apps.. with functionality and zero css hehe but yeah add it later currently working on a ai chat box on my project apps
BIG ALERT IN KOBAYASHI OS I SUCCESSFULLY BUILT AN AI ASSISTANT FOR MY WEB OS! 🎉 It can actually understand commands and interact with the OS — opening apps, handling actions, and more.Another huge step for Kobayashi OS. I’m learning a LOT about AI while building this, and it’s honestly crazy seeing everything come together.
Making the UI of music player nicer ..
Damn !! Been a while !! Yup was working on the assistant.. yeah which actually works!!! changed the architecture of ai chatbot and yeah its much better now !! and Yeah some more tweaks ongoing
Another day on Kobayashi OS. Damn, I really turned the AI Assistant into what I actually wanted it to be. And yeah, now the Shorts app isn’t just some mere app with a icon sitting there — it actually has Shorts embedded hehe. And yeah… there’s a Kanvas app now too lol.
Added a lots of appppss!!! embeded few games, hackclub and typingtest.com … and Yeah added my own built apps (Json Lab , DevScope, and MoneyTrail)
Damnn!! Been a while haven’t posted anything bout my Work!!!!!! added a piano added a lots of Fun games improved the architecture and UI/UX improved the response of the Kobai added Terminal and Code editor.. added a proper and nice widget system changed the whole UI of my apps_ and more features are coming soon!!!!!
Kobayashi-chan is here! Chat, open apps, change settings. She remembers, reacts, and doesn’t mind a little flirting. :) Major changes!! A summary of everything I’ve done over the past 5 days. Lots of design work too—especially Figma stuff. StarDance doesn’t log my Figma hours though… too bad.
Polished the UI of the widgets, improved wallpaper customization, refined the app UX, resized the apps, added a bunch of new features, and made countless small tweaks across the OS. A lot has gone into this project, and I really hope it becomes the star project considering how much time I’ve poured into it. 🥹 Still more to come!
Ships:
Kobayashi OS v1.0 is finally live! Kobayashi OS is a lightweight, anime-inspired Web Operating System built to bring a desktop-like experience to the browser. This first release focuses on a smooth window management system, allowing multiple instances of the same application, along with wallpaper, icon, and brightness customization. It uses React, TypeScript, Bun, Tailwind CSS, Zustand, and Local Storage to provide a persistent experience. The custom logo and launch banner were also designed specifically for this release. Some applications currently contain placeholder alerts and are still under development, with more features and apps planned for future updates. Highlights Anime-inspired light theme Interactive multi-window desktop Multiple instances of the same app Wallpaper, icon & brightness customization Zustand + Local Storage More apps and features coming soon
What did you make? Kobayashi OS — a web OS themed around Miss Kobayashi’s Dragon Maid . I wanted to make one of the most feature-rich and polished web OS experiences possible, something that actually feels like you’re using a PC. And yeah, this is Kobayashi’s PC, so don’t be surprised if you find something interesting related to her. The main thing I focused on was making everything feel connected, just like a real OS. Apps don’t just exist separately — Camera connects to Gallery and Files, downloads go into Files, Kanvas can save things to Files, widgets remember where you put them, and Kobayashi-chan can actually interact with the system. Basically, it’s not just a collection of apps. It’s one big little OS. What was challenging? Interconnecting all the apps and keeping everything persistent was definitely a challenge. I wanted things to behave like an actual OS instead of just being separate demos. Making the Kobayashi-chan AI work was one of the toughest hurdles. Getting tool calling, memory, emotions, and system interaction to work together took a lot of trial and error. Designing and building the widget system was another tough one. Making widgets draggable, positionable, persistent, and actually useful took quite a bit of work. Honestly, getting all the small details and polish right took way more time than I expected. What am I proud of? First — Kobayashi-chan AI. This is probably my favorite part of the whole project. She has tool calling, memory, emotions, and can actually interact with the OS. I genuinely didn’t expect I would be able to make something like this. It’s basically a little Jarvis, but Kobayashi-chan. The piano. I spent way more time on this than I probably should have. Not building it — playing it. It’s such a stupidly fun little feature that I keep losing track of time playing on it. The overall polish. I’ve been working on this for so long that I’ve honestly lost count of all the little things I added. I designed the UI in Figma, made a lot of the icons myself, kept redesigning things, learned a ridiculous amount along the way, and kept adding small details until it finally started feeling like a real OS. I’m genuinely proud of how it turned out. There are a lot of things packed into this project, and I think the best way to understand the amount of work that went into it is to actually explore it yourself. What should you know before testing? The project: https://kobayashi.cawai.site/ Please explore the widgets. This is one of the parts I spent a lot of time on. Please try the piano. Seriously. On the first load, some images may take 1–2 seconds to appear. Give it a moment. Wallpaper customization, live wallpapers, and icon customization may also take a little time on the first load. There are a LOT of games: Thor, Spider-Man, Minecraft, etc. If you open one and see a black screen, don’t panic. Some of them just take a little while to load. Come on, we’re talking about Minecraft here. Give it some time. And obviously, click around. Open things. Break things. Try stuff. A lot of the fun is finding the little details hidden around the OS. That’s Kobayashi OS. I started with the idea of making a web OS, but somewhere along the way it turned into this huge little world with its own apps, games, music, memories, AI, and way too many tiny details. Hope you have fun exploring it....
|
1792878436.301216
|
1793742436.301216
|
|
950
|
Volvo API playground by @Kl | Stardance
|
Kl
|
1
|
130.69
|
2165
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-06T20:19:02Z", "hours": 113.0, "multiplier": 19.09, "payout": 2165, "blessing": "neutral", "text": "A Milestone Welcome everybody to the first ship of this project. What is this project? This project simulates how the Volvo API works. Why was this project created in the first place? So it’s easier to create and test your app that uses the Volvo API without using ready-made libraries. I can’t find the features you mentioned in the devlog? Check the scope branch or the upcoming dev branch. What I’m proud of: I learned a lot of things (this is my first big public project): Tailwind Python stuff (I started with C++) Writing documentation (Markdown) I also learned the basics of OAuth2 and how APIs work. Making a project with all the features needed to get started. I created an additional document for you, Stardancers: Stardance PATH What is still on the TODO list? More APIs Scopes docker image See the roadmap . What to see? error logger recreated endpoints dashboard web socket realtime changes internal endpints interactivity of the car", "repo": "https://github.com/klswar0/Volvo-API-playground", "demo": "https://playground.kls.hackclub.app/"}]...
|
[{"post_id": 79861, "ts": "202 [{"post_id": 79861, "ts": "2026-10-15T17:17:04Z", "hours": 7.1881, "text": "Devlog A very long time no see. I have made a lot of progress on adding an SQL database. Testing on MySQL The backup server provider gives me access to one. SQL changes A lot of BIG changes. The reason why I haven’t posted for so long is that I didn’t want to post about something that doesn’t work. Created new classes to intercept data changes, both in case of direct dict changes and when going through the SQL model library. (I didn’t change much in the code, just imported it under the same name as the old database.) And it works! At the start, only reading data worked, but now it can send data back to the database. Added a regen function to make sure built-in API keys are always the same after a restart. Fixed the car creation function (but when I started storing the additional data in SQL, it broke AGAIN). Added configuration attributes. At first, just the database type, but then all the information needed to connect to a MySQL database. Fixed the scenario readconfig (wasn’t it updated in the past?). A really small number of things I added? Yes, but the amount of debugging and changing built-in functions in classes took me so long. (Could be because of school and not having time to do everything in one sitting.) But I learned how to make a dummy dict with a class, as I called it in the commit: proxy . Problems The SQL database can’t create new cars. Need to check all internal endpoints to make sure they work. Still haven’t merged the DEV branch (TODO). All information is stored in one column as JSON. It works, buuuut I don’t like it that way. Need to clean up the proxy classes. updating docs What failed this time? The second photo attached shows it. Have a look before reading more. _contains__ If you see it, congrats! But if you have a screen full of code, it’s harder to spot. It should be __contains__ , and I spent, I think, two days debugging why all in statements just didn’t work. I was so happy when I finally found it! XAMPP and Apple Silicon The manager app doesn’t open after a restart, so after consulting Google and AI, I found a command that I use: sudo /Applications/XAMPP/xamppfiles/xampp start xampp If someone is asking why I didn’t use the server provided one it just wasn’t practical for now."}, {"post_id": 73730, "ts": "2026-09-25T19:56:38Z", "hours": 4.9217, "text": "Devlog A lot of breaking changes later and getting closer to PR and going to 2 ship Token lifetime WORKS made time when token is expired is rounded to int endpoint for invalidating token possibility for enabling expiring token for a specific token when it’s disabled for all in config file misc pytest for location and energy API fix the url for the enrgy API (it started with connectivity url not wi the energy api) cleanup import created new files to make the code more readable dashboard added location values added capabilities and values auto token generation and expiration in dashboard"}, {"post_id": 69307, "ts": "2026-09-16T19:32:57Z", "hours": 5.58, "text": "Read till the end PLEASE 🥺 Devlog A lot of changes from the last devlog only 5 hrs Mostly bc I add stuff on top of but I will suffer in the future (See dev branch for these changes) Change all connectivity API to start with /connected-vehicle/v2/ to make room for different APIs After that I fixed pytest to reflect that I added a location API with a ONE endpoint There were few iterations Added scopes for this API location:read If I remember correctly Unique error responses (because location error look like old (v1) connectivity API Fixed that operationID could be a constant Added a config option to use longer API keys About here I Fixed the url for location api because it used the connectivity scheme Started working on energy API I added all data from it to this project In short one endpoints says what this car is capable of And the other says the values TODO: add its unique error its half done Scopes corresponding to energy API Fixed that some values and capabilities had the same name (bc of that some bool values where number so a it was important) WIP Oauth2 update: JWT tokens for access tokens WIP token can expire! what are JWT token? There consist of three parts header payload and signature The two first is important for my project the 3 isn’t . They store info about issuer, when token is active, scopes… A lot of useless data for this project or useful? We will see Life Bc of school I didn’t have a lot of time to write devlog (and write code) but I try to do my best before the end of stardance The next ship is planned for 28 September BIRTHDAY TODAY (16 September) Im celebrating my birthday 😄 If you write me a few good words It would be motivating for me."}, {"post_id": 63130, "ts": "2026-09-06T19:20:58Z", "hours": 1.6042, "text": "Devlog MAIN added a startup baner fixed snapshots not saving if website was used scope If you didn’t follow from start this branch contains the experimental scope support which is mostly done but I can guarantee stability that’s why it isn’t pushed to main in fist ship made the scope page work added a back button added button to scope on main page fixed snapshots loading/saving"}, {"post_id": 61052, "ts": "2026-09-03T19:22:00Z", "hours": 2.8836, "text": "Long time no see… The school started aaand I didn’t have time I had low motivation The only thing to do before first ship is docs but I could find time to finish them. Buut I back now. AND I promise to ship it before 7 of September. If you are voting on this project PLEASE do not skip. I have my birthday coming and if the shipwrights doesn’t have a long list it could mean this project payout could be my birthday gift. If I ofc ship it 😅 devlog Small marketing changes everywhere to say that this project doesn’t have any ready code to use Added info about error logger on the landing page Scopes A long way from last devlog Fixed pytest ( A second time) TEMPORARY FIX added so the scope error doesn’t - throw just internal error FIXed the Oauth2 endpoint at least 3 times Added a WIP endpoint to edit scope data from API Fixed how cars are created so they work with both - Oauth and scopes stuff Only looking dashboard page for scopes compare I think I forgot to say something in last devlog config file if you would like to use different instance Toml oillevel to oilLever AI disclaimer that I used this project to learn tailwind Make the doors have different statuses in mean time Untracked WIKI Redo the home page Started working on stardance path A lot of misc that I don’t remember other I created a small modified volvo example app to show that my app works like the real one"}, {"post_id": 55226, "ts": "2026-08-26T20:27:11Z", "hours": 4.2503, "text": "Devlog Error logger added colors to the terminal print out using: \\033[31m \\033[0m Good to know that it is so easy to add colors to text added timestamps to log file and - between errors Changes how it reads body once again and fixed url encoded requests logging My additional information I put in detail in the json response (the real API can send it like that buttty I didn’t see it. info from docs ) additional changes: New scenarios mostly about service warnings You can add notes to the website thru config files Scopes I started working on scopes. What are they? They are really permissions (you can know them from discord bots or if you login thru GitHub etc.) I don’t want to put them in this first ship but I needed to work on something (while I work on wiki) and I CAN’T guarantee every thing works after adding them. You can see it in the scopes branch. what is done: I have made preparation so the additional database (dict) I use for OAuth can store more data have updated website func to work with changes and also pytest added all possible conve (connectivity API) scopes WIKI when I add everything to them I will finally try making a ship added the error logger page updated the sidebar scenario and snapshots page a lot of misc Bonus photos from vacation on baltic sea"}, {"post_id": 49931, "ts": "2026-08-18T21:59:53Z", "hours": 3.1292, "text": "Devlog There was a small (or big) problem in my playground. If an error was returned in the response, you could only see it if your app handled it or by printing the response. That’s why I added an error logger. It can show errors in two ways: Terminal Log file How it works There were two ways of doing it (from what I learned): Middleware that captures all responses (this could be helpful in the future). Exception handlers (this is what I chose). I use two handlers: @app.exception_handler(RequestValidationError) @app.exception_handler(HTTPException) It was a horrible time searching for why it didn’t work. At first, I worked in a separate file, but I couldn’t get the (fastapi) app variable into those functions. So I copied them into main file to make them work first. I had to change some JSON responses to HTTPException to make the second handler work. After I captured the first request and printed it, I worked on one function that writes a log and another that prints to the terminal. I also created a class to store useful data. It works like this: Exception handler-> ->Put data into class -> ->Create response -> ->Return response ->Create a background task that logs the error I create a background task so the response doesn’t wait or even worse fails In the end I found that I can wrap these func with this simple func to make them work in different file def setup_error_logging(app: FastAPI): Added a config option: To disable it completely. To disable only the log file. It also bypasses all internal endpoints to make the logs more readable. The best fail… 😅 I returned an exception instead of raising it. I spent a good 15 minutes wondering why the response had status code 200 with a JSON body saying status code 400 . response changes I also checked how the authorization errors look and added two new ones: Missing Authorization header. Invalid vcc-api-key header. WIKI (not counted) I focus on making a GitHub wiki (new docs) After ending them and the error logger. Its time for the first ship !!!!!!! Nest instability: I made a backup server : https://frog01-21185.wykr.es/ Its not ideal one, bc some asian countries are blocked but its shouldn’t have any downtime (I hope so) If an Admin read it why I must copy enter from different text input 😭"}, {"post_id": 48444, "ts": "2026-08-16T19:51:20Z", "hours": 2.4822, "text": "Devlog SITE changes I found that some number inputs didn’t use the utility classes. I gave them inputText because they are really the same; the only difference is the HTML type . I also forgot to update the reloadable fuel section. It now uses the shorter utility class. Made sure that all text in the header is the same size (they weren’t). I copied all changes back to the main branch. config changes Then I added a config file using the configparser library. also added an option to disable the FastAPI docs. I started working on Wiki: reworking docs.md into a GitHub Wiki with up to date information. Error logger, so you can see what’s wrong without printing the API response in your code. I had some problems with catching the fastapi automatic response but I will leave it for next devlog"}, {"post_id": 46236, "ts": "2026-08-13T10:31:45Z", "hours": 4.6175, "text": "Devlog I forgot to add that I worked on the tests in the test branch, not the main one. OAuth2 PKCE testing. Helped me find an error where, if the code was used (it was reset to \"\" ), it was accepted as \"\" . Now it correctly returns an error. OAuth2 flow testing. Warnings and diagnostics now have some simple checks too. And I merged it into main . Then I started cleaning up the Tailwind CSS. NOTE: they are in new branch dashboard/cleanup Why? Because I used the Play CDN in the past, so I couldn’t create utility classes in a CSS file. Soooo I didn’t. Andddd there were a lot of Tailwind classes that didn’t fit on my screen. Now that I started precompiling it, I could add them. I added 5 unique utility classes. All of them combined are used around ~120 times across all HTMLs. The longest one: @utility inputSelection { @apply w-full px-4 py-2 .5 bg-zinc-950 border border-zinc-800 rounded-xl text-zinc-100 focus : outline-none focus : ring-2 focus : ring-blue-300 focus : border-transparent transition-all appearance-none text-center [ text-align-last : center ] cursor-pointer ; } I also minified the CSS file. If I understand it, it removes anything the browser doesn’t need to understand the CSS (new lines, unnecessary spaces…). It’s better because those characters are still sent over the network, and fewer bytes mean less traffic. While using the new utility classes, I tried to preserve the layout, so everything should look the same as before."}, {"post_id": 44802, "ts": "2026-08-10T20:28:29Z", "hours": 3.7639, "text": "Devlog Working hard on pytest tests. I learn how assert works and how to name . I never used or created test in any language so I think they aren’t perfect (not like they should),but they work😄. I looked like AI made few and how other people and read some stuff online Tests created for these endpoints Around 25 of them List cars About car Engine info Engine start/stop Climate start/stop Windows Doors Lock/Unlock Reduced Guard Lock Flash, Honk, and Combination Tyres Statistics Fuel Odometer Engine diagnostics Brakes Command accessibility Still to do Warnings and diagnostics Commands More changes The tests helped me find and clean up several issues: Documentation updates. The honk endpoint was ../horn but should be /honk . Some values ( odometer , fuel ) are int , just like in the OpenAPI specification, not as described in the official docs. Fixed spelling mistakes: - oillevel to oilLevel - coolantLever to coolantLevel Want to help and has access to volvo with active VOC I need to test engine and climate endpoints but I don’t have an access to a car with it. Soooo if you can contact me on slack"}, {"post_id": 42512, "ts": "2026-08-07T09:41:54Z", "hours": 4.2411, "text": "Devlog Tracking headers implemented : There are two vcc-api-operationId - UUID traceparent - W3C traceparent (for now only sends it back) dashboard should look good on small screen (its very long but I don’t want to redesign it now) This is the reason why I there is much time in this devlog. It was a lot of try and error before something looked good both on mobile and desktop and I liked it . But at least it works know 🙃. some small cleanup of comments I worked again on internal updates endpoint (hopefully works now) started working on pytests (but I will talk about in next devlog (I gave my self 2 days for it) I really want to get the first ship out, so it isn’t going to be perfect. I still have a lot of features and improvements I’d like to add."}, {"post_id": 40711, "ts": "2026-08-04T12:41:43Z", "hours": 4.4231, "text": "Devlog I had a problem when I wanted to rewrite the scenario system. It only changed the local version of the Car (It means it really didn’t update anything). I wanted to update a backup version first, and only if everything was correct, replace the original with the backup. In the end, I used an already created function to first test and then apply to the car . Main PKCE misspelling fixed. Added a landing page with an option to disable it and redirect directly to the login screen (like in the last devlog I have photos of making it). Worked on the lights section. Fixed the docs URLs. Dashboard and WebSocket toggles now work. Rewrote and enabled the updates endpoint. Validation now catches values that can’t be converted to int . Scenario loading into a car instance should now be more consistent with the other functions. Improved mobile responsiveness (and then fixed the desktop one). Some elements were outside the screen on mobile (nothing important, but it didn’t look good). NOTE: the dashboard with car attributes still needs to be adapted. Added windows (because I forgot to 😅) to the dashboard and organised the lighting section. OAuth2 and Snapshots buttons should now always be centred. TODO Debug and tracing headers (from the real API). Additional instructions. Then I think it’s finally ready for the first ship. There are still a lot of things I want to add, but I can’t work indefinitely. Compare The compare app now has the Content-Type fix enabled (like the official API). Compiled the Tailwind CSS for the compare app. NOTE: I will add here more screenshots as link later Also thinking about adding it frictionless mission but I’m not sure."}, {"post_id": 39642, "ts": "2026-08-02T19:24:37Z", "hours": 3.62, "text": "Devlog Snapshots loading page (screenshots while I worked. I had more but the limit was 4). As suggested by the Tailwind CSS tools, changed some classes to more canonical ones. You can now delete cars through both the API and the dashboard. Snapshot corruption (when the app is force quit) should be fixed. Started working on the landing page, but I’ll leave it for the next devlog (mostly because I have on my other laptop). Fixes to do Sometimes the new OAuth2 and Snapshots buttons are off-center. Compare app needs fixing (need to enable the Content-Type fix from the official API). PKCE spelling in the internal API."}, {"post_id": 37827, "ts": "2026-07-30T19:39:54Z", "hours": 4.1028, "text": "Devlog The Content-Type problem is SOLVED …… What was the problem? (My reading skills? ) there are two headers with application/json : Content-Type (POST) Accept (GET) The Accept header isn’t required ( can be */* , application/* or application/json ). So the Content-Type mystery is mostly FIXED but I still need to check with a real Volvo car if Content-Type is actually required. (I’ll do it tomorrow.) Changes: Accept is now handled by my API like in the official API. Added Content-Type checks (like the docs say, meaning it’s required). While proofreading the docs, I found that PKCE is written as PCKE in one internal endpoint. (Not fixed yet.) Small README update (I try to keep it up to date). Scenario page: You can now load a scenario using the GUI. Recompiled the Tailwind CSS. I attached screenshots showing it (you can also see snapshot button but its not implemented YET)"}, {"post_id": 36608, "ts": "2026-07-28T20:31:07Z", "hours": 0.5122, "text": "The comparison app is now online! Comparison app: https://compareplay.kls.hackclub.app/ I also updated the main app with the new dashboard design: https://playground.kls.hackclub.app/internal/welcome devlog Tailwind CSS is no longer loaded from the CDN. I think its now precompiled. Note to others: Remember to update your banner to feature your app (see #stardance on Slack). Otherwise, your ship will be rejected. EDIT: A lot of bots try to connect to my apps do you think I should make a honeypot?"}, {"post_id": 36297, "ts": "2026-07-28T09:47:40Z", "hours": 3.2881, "text": "Devlog I found another way to hide the fuel stat when it isn’t useful for a particular type of car: the HTML hidden attribute. At first, I thought I should add or remove the element hidden, but that turned out to be more complicated than I expected. I think using hidden is still a cleaner solution but I still using templates files. While working on the dashboard, I wanted to add units like km , L , and % to some values. Instead of handling that in Python, I added another div with some margins and, in a few places, used flex so everything stays on the same line without adding more backend logic. Added more page changes thru HTMX (nearly all pages use it). Creating a new car now refreshes the page. when an error occurs, I use HX-Reswap and the HX-Retarget response header (when creating new car as proof of concept). Added HTMX transitions to the OAuth2 settings page.(all pages have transitions) What to do before the first release (Mostly a checklist for myself 😅) Content-Type checks. Scenario and snapshot system support in the dashboard. Main showcase page. Finish the remaining documentation. Two READMEs: one for the main repository and one for the companion app repository. I’m thinking about having one technical README and another one that’s easier to understand for people who don’t code. Better error handling in the dashboard. Right now, most errors are just displayed as plain text instead of being part of the page. deploy updated version on nest I wanted to add a video but MacOS made me a half gig and I don’t think stardance would handle"}, {"post_id": 35043, "ts": "2026-07-26T06:29:01Z", "hours": 5.5947, "text": "Devlog Most of my time was spent working on the dashboard with Tailwind CSS. It took a lot of experimenting to find a design I actually like. I also changed how HTMX updates the dashboard through WebSockets. Before: A dedicated template was rendered every time to update that part of the dashboard. Now: Only the text containing the updated value is replaced. That said, in the future it won’t always be just text. For example, if the fuel type changes from hybrid to electric , the fuel level should disappear from the dashboard instead of just changing its value. While working on this, I found a bug caused by HTMX sending boolean values as strings. This caused climate settings to be marked as invalid. I need to distinguish between an invalid value and an invalid attribute instead of always treating the entire attribute as invalid. Note to myself Add transitions. Make all HTML pages use the same CSS file from now on. Update the version on nest server and make a public companion instance Aaand that’s all. Making websites is painfully slow."}, {"post_id": 33472, "ts": "2026-07-23T13:34:25Z", "hours": 4.2786, "text": "Devlog I don’t know if I mentioned it before, but for now the Content-Type checks are disabled. I need to learn more about them and implement better validation. Created an updated OAuth2 settings page and a car selection screen (with Tailwind CSS, of course). Started experimenting with a new dashboard. It’s still a work in progress, but it will most likely become the main design. I’m also thinking about adding a second dashboard style, although I’m not sure if I’ll do that before the first release. I definitely want to clean up the HTML/Tailwind code by moving repeated styles into reusable classes or something similar. I’m also thinking about using more HTMX so that more pages can update data without needing a full page reload. Wrote more documentation. I still need to verify the fuel endpoint because I don’t remember whether it handles different engine types correctly. ( The new OAuth2 settings page and the car selection screen. For next develop I think I will make a video of how everything works)"}, {"post_id": 32303, "ts": "2026-07-21T11:58:32Z", "hours": 2.6278, "text": "Devlog Companion app I said it was finished for now, but I forgot to add one more thing (the one on the left in the screenshots): a dashboard redirect. Main app I’m still investigating the Content-Type problem. I verified that the official Volvo API behaves correctly, so I’m working on matching that behavior. Added work-in-progress Content-Type checks. Started reworking the CSS using Tailwind CSS. It’s still mixed with some plain CSS for now. Enabled support for the reduced guard lock command. You have to manually mark it as supported, and for now it behaves the same as the normal lock command. Let me know which design you like more: the new one (center) or the old one (right)."}, {"post_id": 31979, "ts": "2026-07-20T20:18:13Z", "hours": 3.7667, "text": "Devlog I’m mainly focused on finishing the companion app. I started working on the CSS. Most of my time was spent learning Tailwind CSS (so I didn’t track it). I think it’s a better fit for me than writing plain CSS. Added Tailwind CSS to all pages of the companion app. (I think I need to redo the main app now. 😅) Added a small README with information about the main app. I think it done now but I will come back to it before first ship Main app While working on the companion app, I found another issue. The Content-Type: application/json behavior doesn’t match the official API. I verified that the official API works as expected, checks for it mine doesn’t (I think)"}, {"post_id": 30890, "ts": "2026-07-18T21:12:58Z", "hours": 3.2169, "text": "Devlog Companion app Added manual mode for comparison. Engine start/stop now works in normal mode. Before pushing, I forgot to fix one thing: { \"error\" : \"Failed to retrieve data from unofficial API.\" , \"detail\" :{ \"detail\" :[{ \"type\" : \"dict_type\" , \"loc\" :[ \"body\" ], \"msg\" : \"Input should be a valid dictionary\" , \"input\" : \"{ \\\" runtimeMinutes \\\" : 10}\" }]}} The fix was simple: I forgot to use json.loads() . I pushed a quick fix commit right after. The photo shows the manual comparison page. I’m still working on the comparison logic, which is why it doesn’t have any CSS yet. Sorry for not adding Volvo API keys so you can see the differences between both APIs, but that would have taken too much time today. Its also the reason why Im creating this app Main app Worked on the documentation. The notifier now supports more than one updated attribute at the same time. It’s not the best implementation, but I’ll improve it after the first ship. Fixed snapshot loading and added exception handling. Scenario loading now reports malformed JSON files. Fixed a dashboard bug where tire information was shown three times. I think I planned to add more data there… and then forgot. I should probably test everything before making a devlog or committing, but I also don’t want my devlogs to have to much time."}, {"post_id": 29435, "ts": "2026-07-16T11:46:44Z", "hours": 0.5936, "text": "A public online demo!!!!! The project is finally available online! https://playground.kls.hackclub.app/internal/welcome Please don’t be the bad guy and fight with other people over access. ❤️ That’s all I wanted to say because this is a really big milestone for me. There will also be another commit today to make sure everyone can run their own instance of the project. I found a few issues that only appeared outside of my local environment: Some WebSocket features break when using HTTPS. The dashboard had problems when the instance wasn’t running on the same computer. Those should be fixed in today’s commit. If you find any errors please comment or contact me on slack Also thanks to nest hackclub for hosting"}, {"post_id": 29164, "ts": "2026-07-15T21:37:24Z", "hours": 2.8483, "text": "Devlog Authorization was my mistake. It should have been accessToken , not Authorization . Why I thought that? I have no idea. No it was good before I was sleepy I think when I did that The snapshots system now works. Why it didn’t work as expected: I forgot to use copy(deep=True) . One of the small dictionaries was written incorrectly. Added saving and loading snapshots from a file. The scenarios system now works and has been tested. Difference between snapshots and scenarios Snapshots copy all data about a car. They are persistent and can be saved to a file. Scenarios only change selected attributes. They are designed to be created and edited manually in a JSON file. Main app The main app is mostly ready. Before the first release, I still need to: Finish the documentation. Add a roadmap with future updates. Verify error responses against the real API. Finish the comparison feature in the companion app. Add more ready-to-use scenarios and API keys. Companion app Manual login now works, so only the comparison logic is left. I found a bug where api_key_p was None because one endpoint redirected using api_key instead. Started working on the comparison feature. PS: A photo of why the api_key_p was none"}, {"post_id": 27883, "ts": "2026-07-13T19:57:06Z", "hours": 3.8994, "text": "Devlog Writing documentation is a good way to check whether the code you wrote actually works. I already found four bugs while documenting the project. For example, I forgot to pass the redirect URI in a function in main.py , even though it was already implemented in internal.py . I also fixed a bug where notifications could sometimes contain an older value. The dashboard has been moved into a separate file. Snapshots currently have a problem. They are very similar to the Car class, so I’ll debug it and explain what the issue was in the next devlog. Companion app The companion app is meant to showcase the differences between my implementation and the official Volvo Demo Car Sandbox. It also makes testing easier, since you don’t have to write your own application just to try the API. I had a problem with the built-in LibreSSL because one of the dependencies didn’t support it. I had to reinstall Python so that uv would detect the new OpenSSL installation. After that, I was finally able to start the app and get it working. Auto-login and automatic creation of a test car are now working. There’s is no css but I will do it after logic works One more thing: the reason the devlogs have been quieter recently is that I’ve been dealing with some administrative paperwork. I’ll get back to posting them more regularly once that’s sorted out."}, {"post_id": 25868, "ts": "2026-07-10T10:58:56Z", "hours": 4.3936, "text": "Devlog How I don’t like web development… did I already say that? I’ll say it again. I’m working on the OAuth2 settings, and I had a problem where one of the query parameters wasn’t reaching the backend. I still don’t know what actually fixed it. Then I had another problem. I have a function that changes values in the backend, but only one button worked while everything else didn’t. It turned out to be because I debugged the first problem with AI. Always trust your own mind before trusting AI. The problem was hx-trigger . I also had problems applying CSS through HTMX. In the end, I solved it by using hx-redirect . But in the end everything works (you can see it one the phtoto) I also worked on the scenario system, which loads scenarios from a JSON file. It isn’t tested yet, and I still need to work on state snapshots. The idea is that you’ll be able to save a moment in time and restore it later, so you can test the same scenario as many times as you want without setting up all the data again. I also started working on a companion app to showcase the differences between my implementation and the official demo car sandbox. I’ll write more about it in the next devlog."}, {"post_id": 24338, "ts": "2026-07-07T20:58:43Z", "hours": 3.7069, "text": "Devlog A small error from the last devlog: it’s PKCE , not PCKE . I had to rename a lot of variables because of that. More customizable data Gearbox Model year More diagnostic data for lights (hazard, fog, brake, high beam, low beam, and more) Other additions Added a new default API key with 3 cars, each having different values. Wrote more docs. Started working on scenarios (templates for new or existing cars to make setup faster). I’m thinking about loading them from a file so users can create their own. Started working on setting up OAuth2 through the dashboard. Fixed most command responses because when I first created them, I forgot to wrap everything inside { \"data\": {} } . Added light options to the dashboard. Working: PKCE How does it work? The application generates a random secret. Before redirecting the user to the login page, it sends only a hashed version of that secret. After the user logs in, the application receives an authorization code. When exchanging the code for tokens, it sends the original secret. The server checks whether it matches the previously received hash. If it does, the tokens are issued. It normally protects from having the tokens stolen New promoting picture I made in canva have a look"}, {"post_id": 23100, "ts": "2026-07-05T20:54:08Z", "hours": 3.3289, "text": "Devlog Small additions to the new documentation. changes how the api handles errors BIG ADDITION OAuth2 without PKCE. I started working on PKCE, but I thought I should write a devlog before adding it. Added a login website (I know I mentioned it last time). Added a way to enable and disable OAuth2. Authentication now checks whether OAuth2 is enabled. If it is, requests are authenticated using OAuth2. Tokens don’t expire yet, but that will be added soon. Added endpoints for refreshing tokens and exchanging an authorization code for tokens. How does OAuth2 work? The app redirects the user to a login page. After logging in, the website redirects the user back to the callback URL provided by the app. The app receives an authorization code, which it exchanges for two tokens: a long-lived refresh token and a short-lived access token. When the access token expires, the app can use the refresh endpoint to obtain a new access token. What is PKCE? I’ll write more about it once it’s added to the project. In short, PKCE protects the authorization flow by ensuring that only the application that started the login process can exchange the authorization code for tokens. The application first generates a random secret (called a code verifier). Before the login request is sent, a hashed version of that secret (the code challenge) is sent to the server. Later, when exchanging the authorization code for tokens, the application sends the original secret. The server verifies that it matches the previously received hash before issuing any tokens. I’ll explain the complete flow in the next devlog."}, {"post_id": 20221, "ts": "2026-07-01T19:28:27Z", "hours": 5.3022, "text": "Devlog This devlog will be a short one because I’ve been focusing on implementing OAuth 2.0. I’ll cover that in more detail in the next update but I will add photo of a “login” screen that I created for it (it looks bad on purpose). What’s new The terminal now works with more than one static car. The dashboard can (once again) create new cars. The codebase has been split into multiple files instead of a single large file: main still contains the public API endpoints. internal contains the dashboard logic and internal API endpoints. database will contain multiple predefined car scenarios. I also started writing a new manual that documents the quirks of the Volvo API and my implementation ( and edge cases). I will write more about in next 2 devlogs What’s left before the first ship An example application demonstrating the differences between the official Volvo Sandbox and this project. OAuth 2.0 with PKCE (it would be great to have before the first ship). Documentation. A major code cleanup and refactoring."}, {"post_id": 17924, "ts": "2026-06-28T21:18:15Z", "hours": 2.7358, "text": "Devlog I added two static (for now) endpoints: statistics and warning . The statistics endpoint mostly returns data, so there isn’t much to test. The warning endpoint has a very large response that would require a lot of new code, and for now I don’t want to implement all of it. I started working on adding cars through the dashboard (you could already see part of it in the last devlog), but I found out it doesn’t work, so I need to fix it before the next devlog. Climate and engine STOP commands now respond correctly. In the last invoice update, they incorrectly returned RUNNING . Added checks for the new command endpoints to verify whether the car supports a given command. Added a small terminal page that outputs changes. In the future, you’ll be able to choose whether to display only Volvo changes, all changes, or all information (for example, if you checked whether the windows status). I also used it to verify that the normal WebSocket status works. Added the foundations for disabling WebSockets on startup. Only a configuration file is left to implement. Added UNAVAILABLE reason invoice logic mostly something like this: If the reason is NO_INTERNET , the invoice becomes CONNECTION_FAILURE . If the reason is POWER_SAVING_MODE , the invoice becomes VEHICLE_IN_SLEEP . Made some improvements to the dashboard’s appearance."}, {"post_id": 15774, "ts": "2026-06-25T17:19:10Z", "hours": 7.1422, "text": "Devlog A funny story: I built the invoice system but didn’t always assign values correctly, so the values got mixed up. I spent a long time debugging before realizing that was the cause. { \"error\" : { \"message\" : \"VALUE_ERROR\" , \"description\" : \" \\\" Car \\\" object has no field \\\" 123 \\\" \" } } I also spent a lot of time on CSS. Most of that time went into learning: classes IDs box shadows CSS Grid The reason it took so long since the last devlog is CSS. As I said before, I don’t really like web development, so my motivation was pretty low. I used some AI, but I worked hard to remove most of the generated code. At this point, most of the site’s design looks the way I want it to and will probably stay that way until the end of the project. Made invoices have some logic instead of always sending the same value. That means: If no invoice status is set, it sends COMPLETED or RUNNING depending on whether the engine or climate is running. Loc like actions can’t have a RUNNING invoice status. Added a distinction between successful and failed invoices. PS: Always remember to stop the server with Ctrl+C , not Ctrl+Z , because Ctrl+Z can leave the process running and keep the port blocked."}, {"post_id": 14241, "ts": "2026-06-23T07:56:55Z", "hours": 6.0522, "text": "Devlog It has been a long time since my last devlog, but I was more focused on learning than adding new stuff. Right now, I am focusing on learning HTML, htmx, and Jinja. The welcome page logic is mostly working. I had some problems with it because I used htmx to add new code, but the JavaScript from the is not reloaded with that. Now, I use the HX-Redirect response. I also learned how WebSockets work with FastAPI and htmx. I also designed how the dashboard will look (I attached my drawings. Good luck reading them!)."}, {"post_id": 11274, "ts": "2026-06-18T13:16:22Z", "hours": 3.5742, "text": "Devlog centralLock is called carLocked in the docs. The docs seem to be outdated. I think the OpenAPI specification is more accurate and contains fewer errors. I added a way to validate data using class functions. Implemented timestamps. Using datetime function from python Added tyre endpoints. Added a way to generate new API keys and create new cars (I used python secrets). (getting ready to make first public running version) Roadmap.md file with status of this project What is next to do Start using the updated method for changing data. Update the dashboard to reflect and modify the new data. Add WebSocket support. Add the remaining 2 vehicle and warning endpoints. Create an example app for testers. Redesign dashboard. It looks awful I had a 2 days off because I was on school trip but I back. Next thing on my list is an updated dashboard"}, {"post_id": 9202, "ts": "2026-06-15T13:28:28Z", "hours": 1.9225, "text": "Devlog You can edit data through the dashboard now. It’s not the best solution, and I want to change how it works (probably start from scratch), but not now. Diagnostics endpoints. I had a very good time with them today. Why? Because of the “/diagnostics” docs. I attached a screenshot showing an example from the official website and data from a real car (left: real API, right: docs). If you look at them, you can see two errors and one very small issue that you would only notice if you read the whole documentation: In serviceWarning, you can see the value is NORMAL, but NORMAL is not a valid value for it. It should be NO_WARNING. This is the small one. In engineHoursToService, the API response contains a unit, but the docs don’t mention it at all. And the worst one (and the only real error): there is no information about washerFluidLevelWarning in the docs, but it appears in the data from the car. What do you think I should do? Should I write to them about it? I think you can comment on the post, so let me know what you think."}, {"post_id": 8961, "ts": "2026-06-14T22:15:21Z", "hours": 1.7606, "text": "Devlog Added odometer and fuel endpoints. Funny thing is that Volvo sends in what unit the data is, but the docs say that only metric units are valid, so it really sends always the same unit. Most likely they wanted to add imperial later, or they left it like this for simplicity. Added first version of dashboard. For now, it’s using polling every 5 seconds (I have planned to change it to WebSocket). It only displays some information and can’t edit anything. Also, I wrote some HTML and JavaScript. I never liked web development, so I don’t know a lot (I’m learning while I code 😅). It could be that it will look very rough till the end because I don’t have any patience for HTML and CSS. I “will” do it when I have a very good day, or AI will do it? I would like not to use AI in this way, but I will see. Edit: Forgot to push the updated version to GitHub I will do it tomorrow because it’s late (it’s tomorrow )"}, {"post_id": 8322, "ts": "2026-06-13T20:45:50Z", "hours": 2.8264, "text": "Devlog Added a command accessibility endpoint (it tells if the car can receive commands). I refactored duplicate code in the climate endpoint. Added engine endpoints (they aren’t perfect, but this isn’t the final code). It was also a frustrating day because I repeatedly forgot to save my code before testing (my bad). A photo of the error that cost me way too much time today. (I changed it to “/vehicles/{VIN}/engine-status”, but I didn’t save the file.)"}, {"post_id": 7410, "ts": "2026-06-12T10:41:57Z", "hours": 0.9136, "text": "I setup my codespace and started working on first few endpoints. Additionally I looked how most of Volvos apis looks that gave me direction to go. That was all time I had today. Also I could add screenshot here because of macOS :("}]...
|
Title: Volvo API playground by @Kl | Stardance
De Title: Volvo API playground by @Kl | Stardance
Devlogs:
I setup my codespace and started working on first few endpoints. Additionally I looked how most of Volvos apis looks that gave me direction to go. That was all time I had today. Also I could add screenshot here because of macOS :(
Devlog Added a command accessibility endpoint (it tells if the car can receive commands). I refactored duplicate code in the climate endpoint. Added engine endpoints (they aren’t perfect, but this isn’t the final code). It was also a frustrating day because I repeatedly forgot to save my code before testing (my bad). A photo of the error that cost me way too much time today. (I changed it to “/vehicles/{VIN}/engine-status”, but I didn’t save the file.)
Devlog Added odometer and fuel endpoints. Funny thing is that Volvo sends in what unit the data is, but the docs say that only metric units are valid, so it really sends always the same unit. Most likely they wanted to add imperial later, or they left it like this for simplicity. Added first version of dashboard. For now, it’s using polling every 5 seconds (I have planned to change it to WebSocket). It only displays some information and can’t edit anything. Also, I wrote some HTML and JavaScript. I never liked web development, so I don’t know a lot (I’m learning while I code 😅). It could be that it will look very rough till the end because I don’t have any patience for HTML and CSS. I “will” do it when I have a very good day, or AI will do it? I would like not to use AI in this way, but I will see. Edit: Forgot to push the updated version to GitHub I will do it tomorrow because it’s late (it’s tomorrow )
Devlog You can edit data through the dashboard now. It’s not the best solution, and I want to change how it works (probably start from scratch), but not now. Diagnostics endpoints. I had a very good time with them today. Why? Because of the “/diagnostics” docs. I attached a screenshot showing an example from the official website and data from a real car (left: real API, right: docs). If you look at them, you can see two errors and one very small issue that you would only notice if you read the whole documentation: In serviceWarning, you can see the value is NORMAL, but NORMAL is not a valid value for it. It should be NO_WARNING. This is the small one. In engineHoursToService, the API response contains a unit, but the docs don’t mention it at all. And the worst one (and the only real error): there is no information about washerFluidLevelWarning in the docs, but it appears in the data from the car. What do you think I should do? Should I write to them about it? I think you can comment on the post, so let me know what you think.
Devlog centralLock is called carLocked in the docs. The docs seem to be outdated. I think the OpenAPI specification is more accurate and contains fewer errors. I added a way to validate data using class functions. Implemented timestamps. Using datetime function from python Added tyre endpoints. Added a way to generate new API keys and create new cars (I used python secrets). (getting ready to make first public running version) Roadmap.md file with status of this project What is next to do Start using the updated method for changing data. Update the dashboard to reflect and modify the new data. Add WebSocket support. Add the remaining 2 vehicle and warning endpoints. Create an example app for testers. Redesign dashboard. It looks awful I had a 2 days off because I was on school trip but I back. Next thing on my list is an updated dashboard
Devlog It has been a long time since my last devlog, but I was more focused on learning than adding new stuff. Right now, I am focusing on learning HTML, htmx, and Jinja. The welcome page logic is mostly working. I had some problems with it because I used htmx to add new code, but the JavaScript from the is not reloaded with that. Now, I use the HX-Redirect response. I also learned how WebSockets work with FastAPI and htmx. I also designed how the dashboard will look (I attached my drawings. Good luck reading them!).
Devlog A funny story: I built the invoice system but didn’t always assign values correctly, so the values got mixed up. I spent a long time debugging before realizing that was the cause. { "error" : { "message" : "VALUE_ERROR" , "description" : " \" Car \" object has no field \" 123 \" " } } I also spent a lot of time on CSS. Most of that time went into learning: classes IDs box shadows CSS Grid The reason it took so long since the last devlog is CSS. As I said before, I don’t really like web development, so my motivation was pretty low. I used some AI, but I worked hard to remove most of the generated code. At this point, most of the site’s design looks the way I want it to and will probably stay that way until the end of the project. Made invoices have some logic instead of always sending the same value. That means: If no invoice status is set, it sends COMPLETED or RUNNING depending on whether the engine or climate is running. Loc like actions can’t have a RUNNING invoice status. Added a distinction between successful and failed invoices. PS: Always remember to stop the server with Ctrl+C , not Ctrl+Z , because Ctrl+Z can leave the process running and keep the port blocked.
Devlog I added two static (for now) endpoints: statistics and warning . The statistics endpoint mostly returns data, so there isn’t much to test. The warning endpoint has a very large response that would require a lot of new code, and for now I don’t want to implement all of it. I started working on adding cars through the dashboard (you could already see part of it in the last devlog), but I found out it doesn’t work, so I need to fix it before the next devlog. Climate and engine STOP commands now respond correctly. In the last invoice update, they incorrectly returned RUNNING . Added checks for the new command endpoints to verify whether the car supports a given command. Added a small terminal page that outputs changes. In the future, you’ll be able to choose whether to display only Volvo changes, all changes, or all information (for example, if you checked whether the windows status). I also used it to verify that the normal WebSocket status works. Added the foundations for disabling WebSockets on startup. Only a configuration file is left to implement. Added UNAVAILABLE reason invoice logic mostly something like this: If the reason is NO_INTERNET , the invoice becomes CONNECTION_FAILURE . If the reason is POWER_SAVING_MODE , the invoice becomes VEHICLE_IN_SLEEP . Made some improvements to the dashboard’s appearance.
Devlog This devlog will be a short one because I’ve been focusing on implementing OAuth 2.0. I’ll cover that in more detail in the next update but I will add photo of a “login” screen that I created for it (it looks bad on purpose). What’s new The terminal now works with more than one static car. The dashboard can (once again) create new cars. The codebase has been split into multiple files instead of a single large file: main still contains the public API endpoints. internal contains the dashboard logic and internal API endpoints. database will contain multiple predefined car scenarios. I also started writing a new manual that documents the quirks of the Volvo API and my implementation ( and edge cases). I will write more about in next 2 devlogs What’s left before the first ship An example application demonstrating the differences between the official Volvo Sandbox and this project. OAuth 2.0 with PKCE (it would be great to have before the first ship). Documentation. A major code cleanup and refactoring.
Devlog Small additions to the new documentation. changes how the api handles errors BIG ADDITION OAuth2 without PKCE. I started working on PKCE, but I thought I should write a devlog before adding it. Added a login website (I know I mentioned it last time). Added a way to enable and disable OAuth2. Authentication now checks whether OAuth2 is enabled. If it is, requests are authenticated using OAuth2. Tokens don’t expire yet, but that will be added soon. Added endpoints for refreshing tokens and exchanging an authorization code for tokens. How does OAuth2 work? The app redirects the user to a login page. After logging in, the website redirects the user back to the callback URL provided by the app. The app receives an authorization code, which it exchanges for two tokens: a long-lived refresh token and a short-lived access token. When the access token expires, the app can use the refresh endpoint to obtain a new access token. What is PKCE? I’ll write more about it once it’s added to the project. In short, PKCE protects the authorization flow by ensuring that only the application that started the login process can exchange the authorization code for tokens. The application first generates a random secret (called a code verifier). Before the login request is sent, a hashed version of that secret (the code challenge) is sent to the server. Later, when exchanging the authorization code for tokens, the application sends the original secret. The server verifies that it matches the previously received hash before issuing any tokens. I’ll explain the complete flow in the next devlog.
Devlog A small error from the last devlog: it’s PKCE , not PCKE . I had to rename a lot of variables because of that. More customizable data Gearbox Model year More diagnostic data for lights (hazard, fog, brake, high beam, low beam, and more) Other additions Added a new default API key with 3 cars, each having different values. Wrote more docs. Started working on scenarios (templates for new or existing cars to make setup faster). I’m thinking about loading them from a file so users can create their own. Started working on setting up OAuth2 through the dashboard. Fixed most command responses because when I first created them, I forgot to wrap everything inside { "data": {} } . Added light options to the dashboard. Working: PKCE How does it work? The application generates a random secret. Before redirecting the user to the login page, it sends only a hashed version of that secret. After the user logs in, the application receives an authorization code. When exchanging the code for tokens, it sends the original secret. The server checks whether it matches the previously received hash. If it does, the tokens are issued. It normally protects from having the tokens stolen New promoting picture I made in canva have a look
Devlog How I don’t like web development… did I already say that? I’ll say it again. I’m working on the OAuth2 settings, and I had a problem where one of the query parameters wasn’t reaching the backend. I still don’t know what actually fixed it. Then I had another problem. I have a function that changes values in the backend, but only one button worked while everything else didn’t. It turned out to be because I debugged the first problem with AI. Always trust your own mind before trusting AI. The problem was hx-trigger . I also had problems applying CSS through HTMX. In the end, I solved it by using hx-redirect . But in the end everything works (you can see it one the phtoto) I also worked on the scenario system, which loads scenarios from a JSON file. It isn’t tested yet, and I still need to work on state snapshots. The idea is that you’ll be able to save a moment in time and restore it later, so you can test the same scenario as many times as you want without setting up all the data again. I also started working on a companion app to showcase the differences between my implementation and the official demo car sandbox. I’ll write more about it in the next devlog.
Devlog Writing documentation is a good way to check whether the code you wrote actually works. I already found four bugs while documenting the project. For example, I forgot to pass the redirect URI in a function in main.py , even though it was already implemented in internal.py . I also fixed a bug where notifications could sometimes contain an older value. The dashboard has been moved into a separate file. Snapshots currently have a problem. They are very similar to the Car class, so I’ll debug it and explain what the issue was in the next devlog. Companion app The companion app is meant to showcase the differences between my implementation and the official Volvo Demo Car Sandbox. It also makes testing easier, since you don’t have to write your own application just to try the API. I had a problem with the built-in LibreSSL because one of the dependencies didn’t support it. I had to reinstall Python so that uv would detect the new OpenSSL installation. After that, I was finally able to start the app and get it working. Auto-login and automatic creation of a test car are now working. There’s is no css but I will do it after logic works One more thing: the reason the devlogs have been quieter recently is that I’ve been dealing with some administrative paperwork. I’ll get back to posting them more regularly once that’s sorted out.
Devlog Authorization was my mistake. It should have been accessToken , not Authorization . Why I thought that? I have no idea. No it was good before I was sleepy I think when I did that The snapshots system now works. Why it didn’t work as expected: I forgot to use copy(deep=True) . One of the small dictionaries was written incorrectly. Added saving and loading snapshots from a file. The scenarios system now works and has been tested. Difference between snapshots and scenarios Snapshots copy all data about a car. They are persistent and can be saved to a file. Scenarios only change selected attributes. They are designed to be created and edited manually in a JSON file. Main app The main app is mostly ready. Before the first release, I still need to: Finish the documentation. Add a roadmap with future updates. Verify error responses against the real API. Finish the comparison feature in the companion app. Add more ready-to-use scenarios and API keys. Companion app Manual login now works, so only the comparison logic is left. I found a bug where api_key_p was None because one endpoint redirected using api_key instead. Started working on the comparison feature. PS: A photo of why the api_key_p was none
A public online demo!!!!! The project is finally available online! https://playground.kls.hackclub.app/internal/welcome Please don’t be the bad guy and fight with other people over access. ❤️ That’s all I wanted to say because this is a really big milestone for me. There will also be another commit today to make sure everyone can run their own instance of the project. I found a few issues that only appeared outside of my local environment: Some WebSocket features break when using HTTPS. The dashboard had problems when the instance wasn’t running on the same computer. Those should be fixed in today’s commit. If you find any errors please comment or contact me on slack Also thanks to nest hackclub for hosting
Devlog Companion app Added manual mode for comparison. Engine start/stop now works in normal mode. Before pushing, I forgot to fix one thing: { "error" : "Failed to retrieve data from unofficial API." , "detail" :{ "detail" :[{ "type" : "dict_type" , "loc" :[ "body" ], "msg" : "Input should be a valid dictionary" , "input" : "{ \" runtimeMinutes \" : 10}" }]}} The fix was simple: I forgot to use json.loads() . I pushed a quick fix commit right after. The photo shows the manual comparison page. I’m still working on the comparison logic, which is why it doesn’t have any CSS yet. Sorry for not adding Volvo API keys so you can see the differences between both APIs, but that would have taken too much time today. Its also the reason why Im creating this app Main app Worked on the documentation. The notifier now supports more than one updated attribute at the same time. It’s not the best implementation, but I’ll improve it after the first ship. Fixed snapshot loading and added exception handling. Scenario loading now reports malformed JSON files. Fixed a dashboard bug where tire information was shown three times. I think I planned to add more data there… and then forgot. I should probably test everything before making a devlog or committing, but I also don’t want my devlogs to have to much time.
Devlog I’m mainly focused on finishing the companion app. I started working on the CSS. Most of my time was spent learning Tailwind CSS (so I didn’t track it). I think it’s a better fit for me than writing plain CSS. Added Tailwind CSS to all pages of the companion app. (I think I need to redo the main app now. 😅) Added a small README with information about the main app. I think it done now but I will come back to it before first ship Main app While working on the companion app, I found another issue. The Content-Type: application/json behavior doesn’t match the official API. I verified that the official API works as expected, checks for it mine doesn’t (I think)
Devlog Companion app I said it was finished for now, but I forgot to add one more thing (the one on the left in the screenshots): a dashboard redirect. Main app I’m still investigating the Content-Type problem. I verified that the official Volvo API behaves correctly, so I’m working on matching that behavior. Added work-in-progress Content-Type checks. Started reworking the CSS using Tailwind CSS. It’s still mixed with some plain CSS for now. Enabled support for the reduced guard lock command. You have to manually mark it as supported, and for now it behaves the same as the normal lock command. Let me know which design you like more: the new one (center) or the old one (right).
Devlog I don’t know if I mentioned it before, but for now the Content-Type checks are disabled. I need to learn more about them and implement better validation. Created an updated OAuth2 settings page and a car selection screen (with Tailwind CSS, of course). Started experimenting with a new dashboard. It’s still a work in progress, but it will most likely become the main design. I’m also thinking about adding a second dashboard style, although I’m not sure if I’ll do that before the first release. I definitely want to clean up the HTML/Tailwind code by moving repeated styles into reusable classes or something similar. I’m also thinking about using more HTMX so that more pages can update data without needing a full page reload. Wrote more documentation. I still need to verify the fuel endpoint because I don’t remember whether it handles different engine types correctly. ( The new OAuth2 settings page and the car selection screen. For next develop I think I will make a video of how everything works)
Devlog Most of my time was spent working on the dashboard with Tailwind CSS. It took a lot of experimenting to find a design I actually like. I also changed how HTMX updates the dashboard through WebSockets. Before: A dedicated template was rendered every time to update that part of the dashboard. Now: Only the text containing the updated value is replaced. That said, in the future it won’t always be just text. For example, if the fuel type changes from hybrid to electric , the fuel level should disappear from the dashboard instead of just changing its value. While working on this, I found a bug caused by HTMX sending boolean values as strings. This caused climate settings to be marked as invalid. I need to distinguish between an invalid value and an invalid attribute instead of always treating the entire attribute as invalid. Note to myself Add transitions. Make all HTML pages use the same CSS file from now on. Update the version on nest server and make a public companion instance Aaand that’s all. Making websites is painfully slow.
Devlog I found another way to hide the fuel stat when it isn’t useful for a particular type of car: the HTML hidden attribute. At first, I thought I should add or remove the element hidden, but that turned out to be more complicated than I expected. I think using hidden is still a cleaner solution but I still using templates files. While working on the dashboard, I wanted to add units like km , L , and % to some values. Instead of handling that in Python, I added another div with some margins and, in a few places, used flex so everything stays on the same line without adding more backend logic. Added more page changes thru HTMX (nearly all pages use it). Creating a new car now refreshes the page. when an error occurs, I use HX-Reswap and the HX-Retarget response header (when creating new car as proof of concept). Added HTMX transitions to the OAuth2 settings page.(all pages have transitions) What to do before the first release (Mostly a checklist for myself 😅) Content-Type checks. Scenario and snapshot system support in the dashboard. Main showcase page. Finish the remaining documentation. Two READMEs: one for the main repository and one for the companion app repository. I’m thinking about having one technical README and another one that’s easier to understand for people who don’t code. Better error handling in the dashboard. Right now, most errors are just displayed as plain text instead of being part of the page. deploy updated version on nest I wanted to add a video but MacOS made me a half gig and I don’t think stardance would handle
The comparison app is now online! Comparison app: https://compareplay.kls.hackclub.app/ I also updated the main app with the new dashboard design: https://playground.kls.hackclub.app/internal/welcome devlog Tailwind CSS is no longer loaded from the CDN. I think its now precompiled. Note to others: Remember to update your banner to feature your app (see #stardance on Slack). Otherwise, your ship will be rejected. EDIT: A lot of bots try to connect to my apps do you think I should make a honeypot?
Devlog The Content-Type problem is SOLVED …… What was the problem? (My reading skills? ) there are two headers with application/json : Content-Type (POST) Accept (GET) The Accept header isn’t required ( can be */* , application/* or application/json ). So the Content-Type mystery is mostly FIXED but I still need to check with a real Volvo car if Content-Type is actually required. (I’ll do it tomorrow.) Changes: Accept is now handled by my API like in the official API. Added Content-Type checks (like the docs say, meaning it’s required). While proofreading the docs, I found that PKCE is written as PCKE in one internal endpoint. (Not fixed yet.) Small README update (I try to keep it up to date). Scenario page: You can now load a scenario using the GUI. Recompiled the Tailwind CSS. I attached screenshots showing it (you can also see snapshot button but its not implemented YET)
Devlog Snapshots loading page (screenshots while I worked. I had more but the limit was 4). As suggested by the Tailwind CSS tools, changed some classes to more canonical ones. You can now delete cars through both the API and the dashboard. Snapshot corruption (when the app is force quit) should be fixed. Started working on the landing page, but I’ll leave it for the next devlog (mostly because I have on my other laptop). Fixes to do Sometimes the new OAuth2 and Snapshots buttons are off-center. Compare app needs fixing (need to enable the Content-Type fix from the official API). PKCE spelling in the internal API.
Devlog I had a problem when I wanted to rewrite the scenario system. It only changed the local version of the Car (It means it really didn’t update anything). I wanted to update a backup version first, and only if everything was correct, replace the original with the backup. In the end, I used an already created function to first test and then apply to the car . Main PKCE misspelling fixed. Added a landing page with an option to disable it and redirect directly to the login screen (like in the last devlog I have photos of making it). Worked on the lights section. Fixed the docs URLs. Dashboard and WebSocket toggles now work. Rewrote and enabled the updates endpoint. Validation now catches values that can’t be converted to int . Scenario loading into a car instance should now be more consistent with the other functions. Improved mobile responsiveness (and then fixed the desktop one). Some elements were outside the screen on mobile (nothing important, but it didn’t look good). NOTE: the dashboard with car attributes still needs to be adapted. Added windows (because I forgot to 😅) to the dashboard and organised the lighting section. OAuth2 and Snapshots buttons should now always be centred. TODO Debug and tracing headers (from the real API). Additional instructions. Then I think it’s finally ready for the first ship. There are still a lot of things I want to add, but I can’t work indefinitely. Compare The compare app now has the Content-Type fix enabled (like the official API). Compiled the Tailwind CSS for the compare app. NOTE: I will add here more screenshots as link later Also thinking about adding it frictionless mission but I’m not sure.
Devlog Tracking headers implemented : There are two vcc-api-operationId - UUID traceparent - W3C traceparent (for now only sends it back) dashboard should look good on small screen (its very long but I don’t want to redesign it now) This is the reason why I there is much time in this devlog. It was a lot of try and error before something looked good both on mobile and desktop and I liked it . But at least it works know 🙃. some small cleanup of comments I worked again on internal updates endpoint (hopefully works now) started working on pytests (but I will talk about in next devlog (I gave my self 2 days for it) I really want to get the first ship out, so it isn’t going to be perfect. I still have a lot of features and improvements I’d like to add.
Devlog Working hard on pytest tests. I learn how assert works and how to name . I never used or created test in any language so I think they aren’t perfect (not like they should),but they work😄. I looked like AI made few and how other people and read some stuff online Tests created for these endpoints Around 25 of them List cars About car Engine info Engine start/stop Climate start/stop Windows Doors Lock/Unlock Reduced Guard Lock Flash, Honk, and Combination Tyres Statistics Fuel Odometer Engine diagnostics Brakes Command accessibility Still to do Warnings and diagnostics Commands More changes The tests helped me find and clean up several issues: Documentation updates. The honk endpoint was ../horn but should be /honk . Some values ( odometer , fuel ) are int , just like in the OpenAPI specification, not as described in the official docs. Fixed spelling mistakes: - oillevel to oilLevel - coolantLever to coolantLevel Want to help and has access to volvo with active VOC I need to test engine and climate endpoints but I don’t have an access to a car with it. Soooo if you can contact me on slack
Devlog I forgot to add that I worked on the tests in the test branch, not the main one. OAuth2 PKCE testing. Helped me find an error where, if the code was used (it was reset to "" ), it was accepted as "" . Now it correctly returns an error. OAuth2 flow testing. Warnings and diagnostics now have some simple checks too. And I merged it into main . Then I started cleaning up the Tailwind CSS. NOTE: they are in new branch dashboard/cleanup Why? Because I used the Play CDN in the past, so I couldn’t create utility classes in a CSS file. Soooo I didn’t. Andddd there were a lot of Tailwind classes that didn’t fit on my screen. Now that I started precompiling it, I could add them. I added 5 unique utility classes. All of them combined are used around ~120 times across all HTMLs. The longest one: @utility inputSelection { @apply w-full px-4 py-2 .5 bg-zinc-950 border border-zinc-800 rounded-xl text-zinc-100 focus : outline-none focus : ring-2 focus : ring-blue-300 focus : border-transparent transition-all appearance-none text-center [ text-align-last : center ] cursor-pointer ; } I also minified the CSS file. If I understand it, it removes anything the browser doesn’t need to understand the CSS (new lines, unnecessary spaces…). It’s better because those characters are still sent over the network, and fewer bytes mean less traffic. While using the new utility classes, I tried to preserve the layout, so everything should look the same as before.
Devlog SITE changes I found that some number inputs didn’t use the utility classes. I gave them inputText because they are really the same; the only difference is the HTML type . I also forgot to update the reloadable fuel section. It now uses the shorter utility class. Made sure that all text in the header is the same size (they weren’t). I copied all changes back to the main branch. config changes Then I added a config file using the configparser library. also added an option to disable the FastAPI docs. I started working on Wiki: reworking docs.md into a GitHub Wiki with up to date information. Error logger, so you can see what’s wrong without printing the API response in your code. I had some problems with catching the fastapi automatic response but I will leave it for next devlog
Devlog There was a small (or big) problem in my playground. If an error was returned in the response, you could only see it if your app handled it or by printing the response. That’s why I added an error logger. It can show errors in two ways: Terminal Log file How it works There were two ways of doing it (from what I learned): Middleware that captures all responses (this could be helpful in the future). Exception handlers (this is what I chose). I use two handlers: @app.exception_handler(RequestValidationError) @app.exception_handler(HTTPException) It was a horrible time searching for why it didn’t work. At first, I worked in a separate file, but I couldn’t get the (fastapi) app variable into those functions. So I copied them into main file to make them work first. I had to change some JSON responses to HTTPException to make the second handler work. After I captured the first request and printed it, I worked on one function that writes a log and another that prints to the terminal. I also created a class to store useful data. It works like this: Exception handler-> ->Put data into class -> ->Create response -> ->Return response ->Create a background task that logs the error I create a background task so the response doesn’t wait or even worse fails In the end I found that I can wrap these func with this simple func to make them work in different file def setup_error_logging(app: FastAPI): Added a config option: To disable it completely. To disable only the log file. It also bypasses all internal endpoints to make the logs more readable. The best fail… 😅 I returned an exception instead of raising it. I spent a good 15 minutes wondering why the response had status code 200 with a JSON body saying status code 400 . response changes I also checked how the authorization errors look and added two new ones: Missing Authorization header. Invalid vcc-api-key header. WIKI (not counted) I focus on making a GitHub wiki (new docs) After ending them and the error logger. Its time for the first ship !!!!!!! Nest instability: I made a backup server : https://frog01-21185.wykr.es/ Its not ideal one, bc some asian countries are blocked but its shouldn’t have any downtime (I hope so) If an Admin read it why I must copy enter from different text input 😭
Devlog Error logger added colors to the terminal print out using: \033[31m \033[0m Good to know that it is so easy to add colors to text added timestamps to log file and - between errors Changes how it reads body once again and fixed url encoded requests logging My additional information I put in detail in the json response (the real API can send it like that buttty I didn’t see it. info from docs ) additional changes: New scenarios mostly about service warnings You can add notes to the website thru config files Scopes I started working on scopes. What are they? They are really permissions (you can know them from discord bots or if you login thru GitHub etc.) I don’t want to put them in this first ship but I needed to work on something (while I work on wiki) and I CAN’T guarantee every thing works after adding them. You can see it in the scopes branch. what is done: I have made preparation so the additional database (dict) I use for OAuth can store more data have updated website func to work with changes and also pytest added all possible conve (connectivity API) scopes WIKI when I add everything to them I will finally try making a ship added the error logger page updated the sidebar scenario and snapshots page a lot of misc Bonus photos from vacation on baltic sea
Long time no see… The school started aaand I didn’t have time I had low motivation The only thing to do before first ship is docs but I could find time to finish them. Buut I back now. AND I promise to ship it before 7 of September. If you are voting on this project PLEASE do not skip. I have my birthday coming and if the shipwrights doesn’t have a long list it could mean this project payout could be my birthday gift. If I ofc ship it 😅 devlog Small marketing changes everywhere to say that this project doesn’t have any ready code to use Added info about error logger on the landing page Scopes A long way from last devlog Fixed pytest ( A second time) TEMPORARY FIX added so the scope error doesn’t - throw just internal error FIXed the Oauth2 endpoint at least 3 times Added a WIP endpoint to edit scope data from API Fixed how cars are created so they work with both - Oauth and scopes stuff Only looking dashboard page for scopes compare I think I forgot to say something in last devlog config file if you would like to use different instance Toml oillevel to oilLever AI disclaimer that I used this project to learn tailwind Make the doors have different statuses in mean time Untracked WIKI Redo the home page Started working on stardance path A lot of misc that I don’t remember other I created a small modified volvo example app to show that my app works like the real one
Devlog MAIN added a startup baner fixed snapshots not saving if website was used scope If you didn’t follow from start this branch contains the experimental scope support which is mostly done but I can guarantee stability that’s why it isn’t pushed to main in fist ship made the scope page work added a back button added button to scope on main page fixed snapshots loading/saving
Read till the end PLEASE 🥺 Devlog A lot of changes from the last devlog only 5 hrs Mostly bc I add stuff on top of but I will suffer in the future (See dev branch for these changes) Change all connectivity API to start with /connected-vehicle/v2/ to make room for different APIs After that I fixed pytest to reflect that I added a location API with a ONE endpoint There were few iterations Added scopes for this API location:read If I remember correctly Unique error responses (because location error look like old (v1) connectivity API Fixed that operationID could be a constant Added a config option to use longer API keys About here I Fixed the url for location api because it used the connectivity scheme Started working on energy API I added all data from it to this project In short one endpoints says what this car is capable of And the other says the values TODO: add its unique error its half done Scopes corresponding to energy API Fixed that some values and capabilities had the same name (bc of that some bool values where number so a it was important) WIP Oauth2 update: JWT tokens for access tokens WIP token can expire! what are JWT token? There consist of three parts header payload and signature The two first is important for my project the 3 isn’t . They store info about issuer, when token is active, scopes… A lot of useless data for this project or useful? We will see Life Bc of school I didn’t have a lot of time to write devlog (and write code) but I try to do my best before the end of stardance The next ship is planned for 28 September BIRTHDAY TODAY (16 September) Im celebrating my birthday 😄 If you write me a few good words It would be motivating for me.
Devlog A lot of breaking changes later and getting closer to PR and going to 2 ship Token lifetime WORKS made time when token is expired is rounded to int endpoint for invalidating token possibility for enabling expiring token for a specific token when it’s disabled for all in config file misc pytest for location and energy API fix the url for the enrgy API (it started with connectivity url not wi the energy api) cleanup import created new files to make the code more readable dashboard added location values added capabilities and values auto token generation and expiration in dashboard
Devlog A very long time no see. I have made a lot of progress on adding an SQL database. Testing on MySQL The backup server provider gives me access to one. SQL changes A lot of BIG changes. The reason why I haven’t posted for so long is that I didn’t want to post about something that doesn’t work. Created new classes to intercept data changes, both in case of direct dict changes and when going through the SQL model library. (I didn’t change much in the code, just imported it under the same name as the old database.) And it works! At the start, only reading data worked, but now it can send data back to the database. Added a regen function to make sure built-in API keys are always the same after a restart. Fixed the car creation function (but when I started storing the additional data in SQL, it broke AGAIN). Added configuration attributes. At first, just the database type, but then all the information needed to connect to a MySQL database. Fixed the scenario readconfig (wasn’t it updated in the past?). A really small number of things I added? Yes, but the amount of debugging and changing built-in functions in classes took me so long. (Could be because of school and not having time to do everything in one sitting.) But I learned how to make a dummy dict with a class, as I called it in the commit: proxy . Problems The SQL database can’t create new cars. Need to check all internal endpoints to make sure they work. Still haven’t merged the DEV branch (TODO). All information is stored in one column as JSON. It works, buuuut I don’t like it that way. Need to clean up the proxy classes. updating docs What failed this time? The second photo attached shows it. Have a look before reading more. _contains__ If you see it, congrats! But if you have a screen full of code, it’s harder to spot. It should be __contains__ , and I spent, I think, two days debugging why all in statements just didn’t work. I was so happy when I finally found it! XAMPP and Apple Silicon The manager app doesn’t open after a restart, so after consulting Google and AI, I found a command that I use: sudo /Applications/XAMPP/xamppfiles/xampp start xampp If someone is asking why I didn’t use the server provided one it just wasn’t practical for now.
Ships:
A Milestone Welcome everybody to the first ship of this project. What is this project? This project simulates how the Volvo API works. Why was this project created in the first place? So it’s easier to create and test your app that uses the Volvo API without using ready-made libraries. I can’t find the features you mentioned in the devlog? Check the scope branch or the upcoming dev branch. What I’m proud of: I learned a lot of things (this is my first big public project): Tailwind Python stuff (I started with C++) Writing documentation (Markdown) I also learned the basics of OAuth2 and how APIs work. Making a project with all the features needed to get started. I created an additional document for you, Stardancers: Stardance PATH What is still on the TODO list? More APIs Scopes docker image See the roadmap . What to see? error logger recreated endpoints dashboard web socket realtime changes internal endpints interactivity of the car...
|
1792853461.4565907
|
1792939861.4565907
|
|
26626
|
Grapefruit by @tsunami014 | Stardance
|
tsunami014
|
2
|
135.0
|
2180
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-12T22:08:50Z", "hours": 25.0, "multiplier": 16.69, "payout": 421, "blessing": "neutral", "text": "FIXED THE UI with dynamic colours and themes! Fixed some layouts Improved how tasks are made (including a not overwhelming amount of qualities and changed the ambiguous “reasoning” into a much less so “goals” As well as many minor also cool things! (See the devlogs after ship 1 for the full account)", "repo": "https://github.com/Tsunami014/Grapefruit/tree/v2.0", "demo": "https://github.com/Tsunami014/Grapefruit/releases/tag/v2.0"}, {"ship_num": 2, "ts": "2026-08-20T11:10:17Z", "hours": 110.0, "multiplier": 15.99, "payout": 1759, "blessing": "neutral", "text": "I finally decided I had done enough and it was really good! This app contains the conversation, a scene with Grapefruit in it, a basic settings page with not much in it, a tasks manager with categories (including a today category) and tasks with importance, reasoning, qualities, items! Also has a great bottom bar for easier text editing and has everything layed out in a mobile-friendly manner! Installation instructions are in the README", "repo": "https://github.com/Tsunami014/Grapefruit/tree/v2.0", "demo": "https://github.com/Tsunami014/Grapefruit/releases/tag/v2.0"}]...
|
[{"post_id": 66920, "ts": "202 [{"post_id": 66920, "ts": "2026-09-12T21:50:02Z", "hours": 2.17, "text": "I improved how tasks are made, making the task overlay centred instead of to the side, changed “reasoning” into “goals” which is easier to understand and still useful, reduced the number of qualities and added some new ones similar to the old reasoning (e.g. ‘obligation’ & ‘reward’), came up with MUCH better sample tasks and fixed a small issue with the bottom bar!"}, {"post_id": 65770, "ts": "2026-09-11T04:14:17Z", "hours": 6.3225, "text": "I did a bunch of work on the settings and added a “theme”! (Different variations of the base colour - which is now changeable in the settings!) I also used HSLuv instead of just HSL (which I tried before and thought it didn’t do much but now I realise it did help make everything nicer). I also added an effect so when you press on buttons it decreases the border radius a bit! And lastly I thought I’d fix some issues super quick due to the increased layout diversity from the settings but ended up spending much longer on them than expected, those being the jumpyness of the settings dropdowns (so I removed the animations and fixed it up a bit more and also fixed the flowlayout because it turns out everything is broken), fixed scrollbars inside other scrollbars, and probably more I forgot."}, {"post_id": 65060, "ts": "2026-09-09T22:07:39Z", "hours": 4.7747, "text": "Tweaked the colours lots and I’m now quite happy with how it’s at! Added auto generating colours for everything I didn’t before (the calendar, settings, importance and some buttons in overlays) Saved the dark/light theme to a settings file And fixed a bug with the confirm and move overlays being a strange fixed width!"}, {"post_id": 64549, "ts": "2026-09-09T01:39:01Z", "hours": 7.5414, "text": "Added dynamic colours! Don’t worry that it looks kinda bad right now, I had to learn UI design from scratch for this, and I will improve it soon. Made all the colours (well, most of them for now) generate based on a base colour and added a light and dark theme! I also made the Android navigation icons and the svgs change between light and dark properly. I spent quite some time trying to implement HSLuv or HCT in the hopes it would improve the colours but ended up scrapping that due to many reasons, including too much extra stuff, wasn’t making much (or any) difference, and my HCT implementation was just so broken and I wasn’t bothered to try and fix it. Also some parts are now extra broken, I’ll fix them soon too don’t worry! I had to devlog this in case I went over 10h by accident, hopefully will be resolved before the next one"}, {"post_id": 62540, "ts": "2026-09-05T23:38:38Z", "hours": 4.4194, "text": "Improved some UI layouts, clarified a sentence or two in the conversation, reordered the tasks page, made selecting the title in the task overlay hide the buttons (to make it easier to see), fixed some visual bugs (maybe?), improved some icons, changed ‘today’ to ‘starred’ (and made it not clear at the end of the day; I wanted to plan for the future) and last but not least I made the grey background for some of the overlays reach past the navigation AT LAST! So now the title bar doesn’t look off when the overlays are open!"}, {"post_id": 50885, "ts": "2026-08-20T10:54:28Z", "hours": 3.4444, "text": "Added an app icon and FINALLY got around to actually drawing the Grapefruit character! Also improved some parts of the conversation a bit more, improved the default tasks, improved the date importance calculations a smidge and fixed many tiny issues. It should now be DONE!"}, {"post_id": 47411, "ts": "2026-08-15T10:28:21Z", "hours": 0.8222, "text": "I thought I was done but turns out I forgot to add scrolling to the tasks list, so it would cause large issues if there were many tasks (or if the screen height was very low, as it does get on mobile when the keyboard is up)"}, {"post_id": 47355, "ts": "2026-08-15T07:43:42Z", "hours": 1.3553, "text": "Improved the “X weeks away” text (which was just wrong before) and added a today toggle and category button!"}, {"post_id": 46825, "ts": "2026-08-14T10:57:19Z", "hours": 6.6328, "text": "Did various small improvements, including: Many many bugfixes, rearranging the task and settings display to have buttons on the bottom (from user feedback), a help screen, a ‘move task to another category’ button and dialogue (which I cannot believe I forgot about until now) and added another purpose in the conversation for the user designated reason (so it actually gets shown sometimes)!"}, {"post_id": 42346, "ts": "2026-08-07T00:53:14Z", "hours": 5.9806, "text": "Added all sorts of cool things, including info in the settings page, bullet points to the text edits, changed the preset times and tasks, extra conversation features (failsafes and external functions), and improved the conversation some more (because it was fun)!"}, {"post_id": 41181, "ts": "2026-08-05T07:11:58Z", "hours": 8.2414, "text": "Finished the conversation! (It may change/get improved more later, but for now I’m happy with it!) I made many changes to some terrible phrasing choices I made previously (e.g. “But why won’t you do xyz? It’s super fun!” -> “You don’t have to do it if you don’t want to”), rewriting huge chunks of it and adding other huge chunks. (I hope you appreciate the dialogue, I’ve apparently spent 20 hours by now JUST on that, not even the code behind it) Also changed times to use +...m as well as +...h and included a preset range of times which are more on the short side to incentavise shorter tasks."}, {"post_id": 39244, "ts": "2026-08-02T02:43:56Z", "hours": 1.5244, "text": "Added buttons to insert new lines above/below, saving information to an external file automatically and trimming whitespace off of some things (a small convenience when on mobile)"}, {"post_id": 38611, "ts": "2026-08-01T02:54:26Z", "hours": 7.6272, "text": "Finalised the connection between the task engine and the conversation including adding variety, conversation suggestions knowing about the qualities and reasons, a significantly improved conversation (that’s almost done!!), a lot of conversation backend (including a custom parser for recursive synonym choices) and heaps more!"}, {"post_id": 36925, "ts": "2026-07-29T10:13:07Z", "hours": 6.4594, "text": "Spent pretty much the entire time working on the conversation choices and options (yes it’s that difficult). Also made some improvements to the backend (extra features making it easier/possible to do some things, fixed bugs). Still not done the conversation, will be another long stretch until I finish it but it’s nearly there!"}, {"post_id": 35517, "ts": "2026-07-27T00:18:06Z", "hours": 4.7739, "text": "Worked on the conversation, improving the quality of texts and options, and added some new options and features! Also added some cool mathy functions for determining task urgency/load!"}, {"post_id": 33452, "ts": "2026-07-23T12:45:03Z", "hours": 3.1211, "text": "Added the beginnings to the task importance system and implemented a cool task bottom text including progress, and also included that task progress in the task overlay popup at the bottom!"}, {"post_id": 33268, "ts": "2026-07-23T01:41:19Z", "hours": 1.11, "text": "Implemented a bunch of small improvements and fixes to the calendar popup and date highlight!"}, {"post_id": 32915, "ts": "2026-07-22T11:46:31Z", "hours": 4.1114, "text": "Spent the whole time working on a date selector! Also added text about the due date, e.g. “was due yesterday”, “due next Monday (in 5 days)”, etc."}, {"post_id": 32801, "ts": "2026-07-22T05:52:27Z", "hours": 1.6331, "text": "Implemented many extremely minor things brought up from user feedback, including: adding titles to the category and task list, using e.g. +2.5h instead of #E for counting time, improved the importance selection layout, ordering tasks, improving done task formatting (with tick and strikethrough) and other even more minor things!"}, {"post_id": 32262, "ts": "2026-07-21T10:09:04Z", "hours": 4.2289, "text": "Added a qualities screen to add qualities to tasks by clicking on the buttons and a lot of backend work to make everything run smoother and easier to code!"}, {"post_id": 31592, "ts": "2026-07-20T03:27:25Z", "hours": 3.4722, "text": "Added an importance slider, an info text and some minor things to the task overlay"}, {"post_id": 31054, "ts": "2026-07-19T04:15:30Z", "hours": 3.5669, "text": "Fixed a lot of bugs in the tasks area; including resizing issues, inability to scroll, and wrapping problems."}, {"post_id": 30597, "ts": "2026-07-18T09:33:18Z", "hours": 6.4275, "text": "Added task groups and an add, rename, and delete task group button that do things! Deleting, naming collisions and other problems are also handled with dialogues! Also added a slightly better colour scheme"}, {"post_id": 30005, "ts": "2026-07-17T07:38:26Z", "hours": 3.5383, "text": "Added a basic scene!!"}, {"post_id": 23344, "ts": "2026-07-06T07:27:06Z", "hours": 5.0297, "text": "Dramatically improved the backend for the conversation, adding many new features!"}, {"post_id": 23221, "ts": "2026-07-06T01:25:52Z", "hours": 5.4508, "text": "Added a parser for conversation backend data and an options list and text box to display it in!"}, {"post_id": 20674, "ts": "2026-07-02T10:21:27Z", "hours": 4.2228, "text": "Added a bottom bar to the task input including some utility functions like move up and down, a sample highlight that can get modified with the + and - timer buttons and a scrollbar!"}, {"post_id": 20454, "ts": "2026-07-02T01:36:55Z", "hours": 7.5497, "text": "Added an item input field with a bottom bar with utilities in it!"}, {"post_id": 19643, "ts": "2026-07-01T00:49:45Z", "hours": 4.1286, "text": "Added more to the UI layout, including a settings (with accordian sections) and new tasks (currently empty) page!"}, {"post_id": 19012, "ts": "2026-06-30T05:31:27Z", "hours": 5.6044, "text": "Added the very basic interface! The reason it took so long was because I had zero idea how to compile anything and took way too long figuring that out. But it can compile for desktop or mobile now! (although desktop is only for testing)"}]...
|
Title: Grapefruit by @tsunami014 | Stardance
Devl Title: Grapefruit by @tsunami014 | Stardance
Devlogs:
Added the very basic interface! The reason it took so long was because I had zero idea how to compile anything and took way too long figuring that out. But it can compile for desktop or mobile now! (although desktop is only for testing)
Added more to the UI layout, including a settings (with accordian sections) and new tasks (currently empty) page!
Added an item input field with a bottom bar with utilities in it!
Added a bottom bar to the task input including some utility functions like move up and down, a sample highlight that can get modified with the + and - timer buttons and a scrollbar!
Added a parser for conversation backend data and an options list and text box to display it in!
Dramatically improved the backend for the conversation, adding many new features!
Added a basic scene!!
Added task groups and an add, rename, and delete task group button that do things! Deleting, naming collisions and other problems are also handled with dialogues! Also added a slightly better colour scheme
Fixed a lot of bugs in the tasks area; including resizing issues, inability to scroll, and wrapping problems.
Added an importance slider, an info text and some minor things to the task overlay
Added a qualities screen to add qualities to tasks by clicking on the buttons and a lot of backend work to make everything run smoother and easier to code!
Implemented many extremely minor things brought up from user feedback, including: adding titles to the category and task list, using e.g. +2.5h instead of #E for counting time, improved the importance selection layout, ordering tasks, improving done task formatting (with tick and strikethrough) and other even more minor things!
Spent the whole time working on a date selector! Also added text about the due date, e.g. “was due yesterday”, “due next Monday (in 5 days)”, etc.
Implemented a bunch of small improvements and fixes to the calendar popup and date highlight!
Added the beginnings to the task importance system and implemented a cool task bottom text including progress, and also included that task progress in the task overlay popup at the bottom!
Worked on the conversation, improving the quality of texts and options, and added some new options and features! Also added some cool mathy functions for determining task urgency/load!
Spent pretty much the entire time working on the conversation choices and options (yes it’s that difficult). Also made some improvements to the backend (extra features making it easier/possible to do some things, fixed bugs). Still not done the conversation, will be another long stretch until I finish it but it’s nearly there!
Finalised the connection between the task engine and the conversation including adding variety, conversation suggestions knowing about the qualities and reasons, a significantly improved conversation (that’s almost done!!), a lot of conversation backend (including a custom parser for recursive synonym choices) and heaps more!
Added buttons to insert new lines above/below, saving information to an external file automatically and trimming whitespace off of some things (a small convenience when on mobile)
Finished the conversation! (It may change/get improved more later, but for now I’m happy with it!) I made many changes to some terrible phrasing choices I made previously (e.g. “But why won’t you do xyz? It’s super fun!” -> “You don’t have to do it if you don’t want to”), rewriting huge chunks of it and adding other huge chunks. (I hope you appreciate the dialogue, I’ve apparently spent 20 hours by now JUST on that, not even the code behind it) Also changed times to use +...m as well as +...h and included a preset range of times which are more on the short side to incentavise shorter tasks.
Added all sorts of cool things, including info in the settings page, bullet points to the text edits, changed the preset times and tasks, extra conversation features (failsafes and external functions), and improved the conversation some more (because it was fun)!
Did various small improvements, including: Many many bugfixes, rearranging the task and settings display to have buttons on the bottom (from user feedback), a help screen, a ‘move task to another category’ button and dialogue (which I cannot believe I forgot about until now) and added another purpose in the conversation for the user designated reason (so it actually gets shown sometimes)!
Improved the “X weeks away” text (which was just wrong before) and added a today toggle and category button!
I thought I was done but turns out I forgot to add scrolling to the tasks list, so it would cause large issues if there were many tasks (or if the screen height was very low, as it does get on mobile when the keyboard is up)
Added an app icon and FINALLY got around to actually drawing the Grapefruit character! Also improved some parts of the conversation a bit more, improved the default tasks, improved the date importance calculations a smidge and fixed many tiny issues. It should now be DONE!
Improved some UI layouts, clarified a sentence or two in the conversation, reordered the tasks page, made selecting the title in the task overlay hide the buttons (to make it easier to see), fixed some visual bugs (maybe?), improved some icons, changed ‘today’ to ‘starred’ (and made it not clear at the end of the day; I wanted to plan for the future) and last but not least I made the grey background for some of the overlays reach past the navigation AT LAST! So now the title bar doesn’t look off when the overlays are open!
Added dynamic colours! Don’t worry that it looks kinda bad right now, I had to learn UI design from scratch for this, and I will improve it soon. Made all the colours (well, most of them for now) generate based on a base colour and added a light and dark theme! I also made the Android navigation icons and the svgs change between light and dark properly. I spent quite some time trying to implement HSLuv or HCT in the hopes it would improve the colours but ended up scrapping that due to many reasons, including too much extra stuff, wasn’t making much (or any) difference, and my HCT implementation was just so broken and I wasn’t bothered to try and fix it. Also some parts are now extra broken, I’ll fix them soon too don’t worry! I had to devlog this in case I went over 10h by accident, hopefully will be resolved before the next one
Tweaked the colours lots and I’m now quite happy with how it’s at! Added auto generating colours for everything I didn’t before (the calendar, settings, importance and some buttons in overlays) Saved the dark/light theme to a settings file And fixed a bug with the confirm and move overlays being a strange fixed width!
I did a bunch of work on the settings and added a “theme”! (Different variations of the base colour - which is now changeable in the settings!) I also used HSLuv instead of just HSL (which I tried before and thought it didn’t do much but now I realise it did help make everything nicer). I also added an effect so when you press on buttons it decreases the border radius a bit! And lastly I thought I’d fix some issues super quick due to the increased layout diversity from the settings but ended up spending much longer on them than expected, those being the jumpyness of the settings dropdowns (so I removed the animations and fixed it up a bit more and also fixed the flowlayout because it turns out everything is broken), fixed scrollbars inside other scrollbars, and probably more I forgot.
I improved how tasks are made, making the task overlay centred instead of to the side, changed “reasoning” into “goals” which is easier to understand and still useful, reduced the number of qualities and added some new ones similar to the old reasoning (e.g. ‘obligation’ & ‘reward’), came up with MUCH better sample tasks and fixed a small issue with the bottom bar!
Ships:
I finally decided I had done enough and it was really good! This app contains the conversation, a scene with Grapefruit in it, a basic settings page with not much in it, a tasks manager with categories (including a today category) and tasks with importance, reasoning, qualities, items! Also has a great bottom bar for easier text editing and has everything layed out in a mobile-friendly manner! Installation instructions are in the README
FIXED THE UI with dynamic colours and themes! Fixed some layouts Improved how tasks are made (including a not overwhelming amount of qualities and changed the ambiguous “reasoning” into a much less so “goals” As well as many minor also cool things! (See the devlogs after ship 1 for the full account)...
|
1792849706.283899
|
1792936106.283899
|
|
30836
|
calc82: Web Scientific Calculator by @rigel | Star calc82: Web Scientific Calculator by @rigel | Stardance...
|
rigel
|
1
|
120.0
|
2248
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-09T04:20:09Z", "hours": 120.0, "multiplier": 19.41, "payout": 2248, "blessing": "neutral", "text": "What did you make? calc82: A calculator web-app inspired by the Casio fx-82 series of scientific calculators. These calculators are common in high schools in my country. My project simulates the behaviour of the Casio calculator, while maintaining a good user experience on both desktop and mobile. What was challenging? Creating reliable algebraic (non-linear) input parsing was the most difficult part of the project. This was because it required some difficult array traversal to avoid invalid states - even one mistake would break the whole input. It took a lot of iterations to get to a working input system that passed all my tests. Close contenders for most challenging were the sheer volume of functions I needed to implement, as well as all possible states the calculator can be in. However, the challenge for this was finding time to get around to everything, rather than technical challenge. What are you proud of? I’m most proud of my implementation of the input-to-result pipeline. I was able to incorporate new-to-me concepts such as tokenisers and abstract syntax trees, yet the resulting code is arguably the cleanest part of the program. I’m also proud of the responsive layout, which supports desktop and mobile well, and that the user experience is similar enough to the Casio that my muscle memory carries over. Finally, I’m proud that I managed to finish the project, as it’s the largest software project I’ve ever managed to complete. Demo: https://rigelseven.github.io/calc82/ Source: https://github.com/rigelseven/calc82/", "repo": "https://github.com/rigelseven/calc82", "demo": "https://rigelseven.github.io/calc82/"}]...
|
[{"post_id": 64600, "ts": "202 [{"post_id": 64600, "ts": "2026-09-09T03:36:33Z", "hours": 1.0264, "text": "calc82: Devlog #14 9/09/2026 calc82: because calculators are for everyone Final devlog. It’s done!! This last stretch was writing the readme and publishing everything to Github pages. You can now access it at https://rigelseven.github.io/calc82/ Now for a short reflection calc82 is the largest personal software project I have ever completed. This project taught me a lot about input parsing - specifically, tokenisers and syntax trees - and the importance of keeping a large codebase tidy . Overall, the structure of the project is well laid out. However, there are architectural decisions I made early on that I came to regret later (such as the fact that input is represented as a string, whereas it should probably be a tree). Developing calc82 also showed me that I am capable of putting together such an app from scratch. I’m pleased to have participated in Stardance and be given this opportunity."}, {"post_id": 64551, "ts": "2026-09-09T01:44:48Z", "hours": 8.6039, "text": "calc82: Devlog #13 9/09/2026 calc82: because calculators are for everyone This devlog follows the addition of help and about menus to my calculator, as well as bundling into one js file. 🌟 New functionality summary Help menu Lookup function by calculator button (reuses key bind selector logic) Q&A About page About the calculator Contribute Legal License All JS files are bundled into one file Service worker makes app available offline 📦 Bundling and service worker I chose to use esbuild for bundling. This allows the many JS files to be condensed down into one file, reducing the number of requests that need to be made. This build system is much simpler than other options such as node.js. I also added a simple service worker that caches all requests locally. This makes the calculator available offline. ⚖️ Licensing & Legal I chose GPLv3 for this project as it is an end-user product. Essentially, this means others are free to modify and distribute the project as long as they make the source available. I also added legal disclaimers to the about page of the calculator. 📈 Next steps Write the readme, publicise the repo, and host! Thanks for reading :)"}, {"post_id": 63421, "ts": "2026-09-07T07:56:19Z", "hours": 9.6403, "text": "calc82: Devlog #12 7/09/2026 calc82: because calculators are for everyone This devlog follows the addition of customisable and accessible keyboard bindings to my calculator. 🌟 New functionality summary Settings menu Switches between sidebar and popup dependent on screen width Key rebinding Flow of choosing button, then pressing key to rebind Stores in local storage Help hotkey Shows all currently bound keys. Key hint consideration The default keyboard map has been implemented as a const dictionary for a while now, allowing lookup of buttons from keyboard keys. This was extended with a user dictionary that can be dynamically updated. However, generating the help hotkey hints needed to go in the opposite direction of the dictionary. The naive approach of iterating through values to find a key for each would perform poorly with O(n^2). Instead, we precalculate a reversed dictionary to lookup keyboard keys from each button. This precalculation is O(n), and setting the keys is also O(n), resulting in O(n) time overall. 📈 Next steps Development Brief manual for each calculator function (considering reusing the on click functionality from key mapper) ) Info menubar button with author & project information, and disclaimers Fullscreen button for mobile devices Preparation for shipping Webpack, choose a license, write readme, publicise repo, host. Thanks for reading :)"}, {"post_id": 62611, "ts": "2026-09-06T02:35:54Z", "hours": 8.5919, "text": "calc82: Devlog #11 6/09/2026 calc82: because calculators are for everyone This devlog follows the addition of a few final features to my calculator, and then my worst nightmare, frontend UI 😧 🌟 New functionality summary Prime factorisation using Pollard’s rho algorithm Engineering notation button Degree/minute/second output button CSS styling!! + menu bar buttons Fixed some input quirks Dark and light mode (based on system default) with manual toggle 🐚 Pollards rho algorithm for prime factorisation Prime factorisation or integer factorisation is the decomposition of a positive integer into a product of integers. The simplest way to implement this is trial division , which is straightforward but has O(√n) time complexity. I thought this would be too slow, so I decided to implement Pollard’s rho algorithm. This has a nicer complexity of O(√p) where p is the smallest prime factor of the number. However, further observation showed that that the Casio calculator probably doesn’t do this - for numbers without easy factors, it just doesn’t bother. Despite this, I’ve already implemented the algorithm, so I’m not going to remove functionality for the sake of exactly replicating the calculator’s behaviour. 🎨 CSS and styling My goal with the styling was to make the calculator as similar across browsers as possible. I bundled the Inter font (best font) into the program and removed browser-specific button styling. Implementing the CSS styling was mostly painless. I opted for a simple design with a menubar that adapts to horizontal or vertical depending on the window’s aspect ratio for the web app functionality. Additionally the css uses the system theme to automatically choose light or dark mode. 📈 Next steps This project is nearly finished - should only be one or two devlogs left until I ship. Here’s what I have left to do: Development Keybind show and edit Brief manual for each calculator function Info menubar button with author & project information, and disclaimers: that I am not affiliated with casio that the calculator is in a beta state and not guaranteed to be correct for all inputs Fullscreen button for mobile devices Preparation for shipping Webpack or similar Choose a license and publicise repo Write a readme Host on github pages (?) Hope that I did enough to not receive legal action from casio 🙃 Thanks for reading :)"}, {"post_id": 60028, "ts": "2026-09-02T04:16:18Z", "hours": 9.8953, "text": "calc82: Devlog #10 2/09/2026 calc82: because calculators are for everyone This devlog follows the addition of a lot of small features to my calculator that were last on my to-do list, as well as a slight shift in scope. 🌟 New functionality summary Colon operator for multiple operations Saving variables and settings to LocalStorage Clearing this memory Polar and rectangular coordinates (finally!) Forward delete key (keyboard only) Scrolling screen with a nicer cursor! Colon operator This is an operator I’ve never used on my calculator, but its quite powerful. you can type Ans+1:Ans*2:Ans^2 and it will calculate the first expression, then the second, and so on until it loops back to the start. ➡️ Forward delete Although this functionality is not part of the original calculator, it makes it much more pleasant to use on a computer keyboard. This was implemented as a hidden button. Scrolling Scrolling was surprisingly easy to implement! The browser handles all of the hard work, and all I had to do was set the right CSS tags. Granted, with my CSS experience, this was still difficult, but I made it work in the end. 📈 Next steps I have decided to shift the current scope of the project (before shipping) to just be implementing the main compute mode . This means I will not need to do STAT, VERIFY or LINEIO mode. This is for three reasons: With my semester starting, I will not have as much time to work on this project before the deadline I have very little experience with using these other modes I want to focus my time on the user experience. With this shift in scope, the calculator part of the project is all but done - I only have three buttons remaining. (I had to push this devlog out before 10 hours, which is why they’re not done). Then, I can focus on adding the surrounding UI and UX, which should make it actually possible for other people to use my project. Thanks for reading :)"}, {"post_id": 58608, "ts": "2026-08-31T02:44:52Z", "hours": 8.6944, "text": "calc82: Devlog #9 31/08/2026 calc82: because calculators are for everyone This devlog follows the addition of menus and the status bar to my calculator. 🌟 New functionality summary Extensible menu system that allows for easy creation of paginated and nested menus Status bar with indicators that change based on the current calculator state M+ and M- special variables Mixed fraction display 📋 Menu system The menu system uses a dictionary to encode the menu pages and their entries, making it easy to add new menus. However, I couldn’t find a way to easily encode functions and arguments in this structure, so the actual actions are handled by a big switch statement. When the menu is active, most buttons have no action and the input/output display is hidden. 🧀 Status bar The status bar consists of a row of elements with adjustable opacity (to represent their active state). It is handled by a class which allows items to be toggled with a single method call, meaning it can retroactively be integrated into other components. The original calculator has some menu elements that can never be activated - for example, there is a complex mode indicator, but the calculator cannot show complex numbers. I omitted these on calc82, as they took up unnecessary space. 📈 Next steps The project is almost nearing completion :) I made complete list of every feature missing from the calculator (too long to post here). It should should get shorter every devlog from now! Hopefully I can finally ship this project in the next couple of weeks. Thanks for reading :)"}, {"post_id": 45453, "ts": "2026-08-11T22:22:45Z", "hours": 10.3792, "text": "calc82: Devlog #8 12/08/2026 calc82: because calculators are for everyone Sorry its been a while since the last devlog, I’ve had this one sitting for a while and not had the chance to finish and post it. This devlog follows the improvement of the user interface to my calculator, as well as the addition of variables . 🌟 New functionality summary Add keyboard mappings for buttons Variables - assign and recall Navigate through history Recall history and edit it. 🦋 Modifier keys It was difficult porting the modifier (shift/alpha) keys to keyboard because Shift is used to type symbols such as + and *, and there is also a Shift key on the calculator… My solution was making tapping shift without any other input to toggle the calculator shift modifier, and combining it with another key to not toggle it. 🗒️ Notes Use of the calculator I’ve actually started using the calculator in class, and it’s been faithful to the original so far (for implemented functionality). I still don’t really trust it though and want to run it through some formalised tests before shipping. Keyboard mappings So far, I have been hardcoding keyboard mappings based on what feels natural to me. However, it would probably be better to have user-editable mappings for other people to customise. 📈 Next steps Immediate: M+ and M- special variable Variable and history persistence in the browser Implement polar/rectangualr conversion Medium: Add menu system and settings Add other modes (STAT, VERIFY) Create a test suite to ensure there is no unwanted behaviour Long-term: Tidy up visuals Ship :)"}, {"post_id": 32188, "ts": "2026-07-21T05:53:53Z", "hours": 9.9386, "text": "calc82: Devlog #7 21/07/2026 calc82: because calculators are for everyone This devlog follows the introduction of an actual user interface to my calculator. 🌟 New functionality summary Grid of calculator buttons Different button output when modifiers pressed Navigation buttons work Calculator resembles a real calculator 👇 Button handling The calculator needed buttons resembling that of the Casio to fulfil my purpose. Buttons are dynamically built from an array, which defines their labels and actions. This allows easy changes. For most buttons, the area surrounding the button also acts as a clickable area for better touch input. However, I didn’t find an easy way to do this for the navigation buttons (which are positioned off the grid). 🎨 CSS CSS Grid allows a 2D layout system based on rows and columns. It has been supported by all major browsers since October 2017. CSS Grid was used, as it allows consistent positioning across browsers. In addition, relative units were used to prevent resizing the calculator from affecting it. This should make it easier to make dynamic sizing in the future. 🗒️ Notes Accessibility <button> s are preferred over clickable <div> s because they work with screen readers and legacy browsers . However, I also made the surrounding elements clickable for a better touch experience. Also, keyboard input will make use significantly easier for computer users. Aesthetics The CSS applied so far is purely functional. In the future, I will improve the aesthetics of the calculator through CSS - but for now, this barebones look makes development easier and more focused. 📈 Next steps The todo list was getting too empty, so it has been updated with new tasks Immediate: Add remaining functions Add keyboard shortcuts Medium: Add menu system and settings Multi-line calculation (Ans) and setting variables Implement polar/rectangualr conversion Add other modes (STAT, VERIFY) Add Long-term: Create a test suite to ensure there is no unwanted behaviour Ship :)"}, {"post_id": 30511, "ts": "2026-07-18T04:36:43Z", "hours": 9.605, "text": "calc82: Devlog #6 18/07/2026 calc82: because calculators are for everyone This devlog follows the further development of algebraic I/O to my calculator, including turning this into an actual result. 🌟 New functionality summary Input and output formatting through KaTeX Square root, arbitrary root, mixed fraction, and absolute values Tokeniser now directly reads input tokens Errors now move the cursor to the position where it occurred 🌊 New program flow inputHandler -> [input tokens] -> tokeniser -> [calculator tokens] -> parser -> AST -> evaluator -> result This: improves speed (compared to parsing text) allows cursor to be moved to error location since we never flatten to text You might notice I have two sets of tokens. They are similar, but input tokens deal with digits and combined symbols ( sin( ), and calculator tokens are whole numbers and separated symbols. 🗒️ Notes Avoiding the lazy route My first approach was turning the input tokens into a string, which my tokeniser already knew how to deal with. However, this added much processing overhead and made it harder to find out the position at which errors occurred. Spending the time to implement the token conversion made this step much easier Misplaced math errors When implementing error handling, I passed down the original position of each token in the input token array down to each step of the calculation process. However, because my evaluator is recursive, it would constantly update the error position to the latest token, meaning the errors were always placed at the end. This was an easy fix in the end - but hard to spot! 📈 Next steps Immediate: Buttons input Add remaining functions (once buttons are added can be done) Medium: Multi-line calculation (Ans) and setting variables Implement polar/rectangualr conversion (delayed until UI is more fleshed out) Build UI Long-term (but getting closer!): Create a usable UX Ship :)"}, {"post_id": 29405, "ts": "2026-07-16T10:32:06Z", "hours": 9.6708, "text": "calc82: Devlog #5 16/07/2026 calc82: because calculators are for everyone This devlog mainly follows the addition of algebraic I/O to my calculator. This is just a check-in since I was getting close to 10 hours since the last devlog - I still have some work to do on this aspect before I move on. 🌟 New functionality summary Input and output formatting through KaTeX Fractions and powers formatted correctly in the input Ability to intuitively traverse the input with arrow keys ⚖️ Algebraic IO with KaTeX I decided on KaTeX because it is both fast (no reflow!) and does not rely on dependencies . KaTeX is a math formatting library that uses LaTeX commands to create beautiful equations from code. For example, \\frac{2^{\\frac{3}{4}}}{4\\sin(30)}\\times 2\\pi turns into the attached image. Input is currently captured directly from the keyboard to build a 1D array of tokens. The tokens are then converted into KaTeX formatting for algebraic display. In the future, there will also be buttons onscreen as an alternative. Fractions and powers Fractions and powers cannot be represented as a single token. Rather, fractions have a beginning, middle and end, and powers have a beginning and end. The program traverses the array to decide where to put them (and take them out for deletion). 🗒️ Notes The cursor It is surprisingly difficult to make a vertical bar to act as a cursor in KaTeX, without affecting the spacing of the rest of the expression. For now, I am using a \\clap{\\rule{0.1em}{0.5em}} for the cursor, but I am looking to replace this with custom CSS in the future. Replicating exact behaviour? The fx-82 has some interesting behaviour wherein an empty power is not allowed to exist directly after another power. I am unsure whether I should replicate this - but for now, I am leaving it out. Dealing with broken LaTeX I have been able to get the display pretty bulletproof when it comes to not producing broken LaTeX. However, I’m sure there’s something I haven’t run into in debugging! I want to have this be dealt with gracefully rather than blowing up in the user’s face. 📈 Next steps Immediate: Implement mixed fractions, roots, and Abs to algebraic display Make the input token array able to be parsed into the AST to be calculated Medium: Multi-line calculation (Ans) and setting variables Implement polar/rectangualr conversion (delayed until UI is more fleshed out) Build UI Long-term (but getting closer!): Create a usable UX Ship :)"}, {"post_id": 27701, "ts": "2026-07-13T14:20:52Z", "hours": 7.1211, "text": "calc82: Devlog #4 14/07/2026 calc82: because calculators are for everyone This devlog mainly follows the addition of fractional I/O to my calculator. 🌟 New functionality summary Fractional input, including fractions Computation of fractions - add/sub,div/mult,power,root other operations convert the fraction to a decimal Fractional output (temporary UI) LCM/GCD separate execute and fraction/decimal converting buttons 🔢 fractional io :) I defined a separate fraction data type: it’s like a decimal, but with a numerator and denominator, and optionally a whole component: for example, 1 and 1/3, or 4/3. Using fractions means that numbers can be represented more naturally and precisely. I.e. 1/7 instead of 0.142857143 🧮 Fractional calculation Additionally calculations can be made more precise. For example (1/7) * (2/3) can be directly computed by multiplying the numerators and denominators. My implementation attempts to convert user input and the products of divisions into fractions wherever possible in order to chase this precision. 🗒️ Notes Web design is not my thing I realised the importance of UI and UX (user experience) by looking at other projects on Stardance. As of the current iteration, this project lacks this a bit.. But I will give it a shot My next developments will begin to focus more on this - starting with the algebraic input, and eventually moving onto the CSS and design aspects. I am also considering whether I should use a Javascript framework. 📈 Next steps Immediate: Create algebraic display functionality Medium: Multi-line calculation (Ans) and setting variables Implement polar/rectangualr conversion (delayed until UI is more fleshed out) Build UI Long-term (but getting closer!): Create a usable UX Ship :)"}, {"post_id": 25807, "ts": "2026-07-10T08:35:45Z", "hours": 6.5419, "text": "calc82: Devlog #3 10/07/2026 calc82: because calculators are for everyone Oh dear, looks like I lost 4 hours of counted time in the last devlog… let’s try to make this one a bit shorter! This devlog follows the implementation of the other inline functions of the calculator: 🌟 New functionality summary inverse and hyperbolic trig arbitrary roots absolute value percent random numbers: Ran and RanInt scientific notation: *10^x / E combinatorics: nPr and nCr variables (not yet adjustable) 📋 Implementation details Implementing most of this functionality followed the same general steps: identify implement test. As I undertook this process. other dependent requirements popped up - such as the implementation of multivariable functions , which in turn required the expansion of the tokeniser and parser. Also, I implemented degrees, radians, and gradians modes into the calculator, and the associated functions (as postfix expressions - e.g. sin(30d) for degrees) . 🗄️ decimal.js changes Finally, I applied some further changes to decimal.js.: Rounding now depends on the closeness of the output to a known value, rather than the input, reducing unnecessary rounding Near-decimal values close to 0, 0.25, 0.5, 0.75 and 1 are now caught. 🗒️ Notes: Remembering that Javascript is weird NaN === NaN is FALSE! Spent a good 10 minutes figuring this one out. The solution was to use isNaN() . Fixing negative-base powers: (-8)^(1/3) should equal 2 but returns NaN Fixed by taking the denominator from the output of a decimal.js toFraction() function, which attempts to create a rational fraction. This overcomes the tiny precision loss and evaluates the function correctly 📈 Next steps Immediate: Add fractional I/O Implement polar/rectangualr conversion Medium: Create algebraic display functionality Multi-line calculation (Ans) and setting variables Long-term: Build UI Ship :) This has been a bit of a shorter devlog. But I’m still proud of what I achieved! Thanks so much for reading. If you have any suggestions, please leave me a comment. Take care"}, {"post_id": 25217, "ts": "2026-07-09T10:31:56Z", "hours": 14.0967, "text": "calc82: Devlog #2 08/07/2026 calc82: because calculators are for everyone This devlog follows the handling of nasty floating point errors in my web calculator - inspired by and designed to work with Casio’s fx-82au. I realised that relying purely on the Javascript math system was unsuitable for a scientific calculator that works with decimal numbers. This is due to binary floating point not translating well to decimal. 0.1+0.2=0.30000000000000004 >:( I researched and considered a few approaches. 🥧 Symbolic simplifier? The idea behind this is to perform algebra and avoid evaluating constants and functions to values until strictly necessary. However, the scope of this seemed massive, and I did not observe this behaviour in the Casio. 🔟 Decimal arithmetic Instead, I stumbled upon the fact that decimal arithmetic can be implemented in a computer. While IEEE floats use binary representation, there is no reason we cannot use decimals internally, avoiding errors that arise from conversion. Decimal floats can be stored by: Sign: +/- Mantissa: the number itself, in my case an array of digits Exponent: what power of 10 the number should be multiplied by. I started implementation, made decent progress, but found out that I was re-doing work that was already done by other people. 🗄️ Decimal.js I found the decimal.js library after researching how to handle decimal addition. Implementing this quickly fixed my floating point errors, but did not fix trig approximation. 👀 Observing the calculator I observed some of the behaviour of the real calculator to work out how it functions. Handles small-angle approximation based on a threshold Drops precision as the trig function argument value increases Appears to use a 15-digit mantissa Refuses to evaluate trig functions with argument above a certain limit I tried my best to implement the behaviour I observed, some of which required editing the code of the decimal.js library. 📝 Editing decimal.js The decimal.js library uses more than the set precision for some internal calculations. However, arithmetic with pi is otherwise only the set precision, causing drift. My fix for this was to adjust the internal pi value to match the mantissa size of the real calculator. Troubles with the library When given a less accurate value for pi (in line with that of the real calculator) sine quadrant is incorrectly calculated. I found that the isOdd function is flawed! function isOdd(n) { return n.d[n.d.length - 1] & 1; } I replaced it with one that works for my use case (if less efficient): function isOdd(n) { return n.mod(2).eq(1); } I need to see if this is just due to my low precision pi, or an actual problem in the library, in the future. But for now my issue is fixed. I also found an error in the cosine function: if (x.isZero()) return x needed to be changed to if (x.isZero()) return new Ctor(1) . Again, I’m going to have to look into this more before submitting a pr or anything, since decimal.js is not made for such an imprecise pi. 🗒️ Notes Deviations There are still small deviations between my calculator and the real one at really, really large trig angles. One idea to reduce error could be optimising the order of operations in the AST to prevent dropping precision unnecessarily. I might explore this later However, I want to press on with other features, instead of tiny inaccuracies that would never show up in real-world use. I have slightly rearranged the to-do list below. 📈 Next steps Immediate: Implement the other calculator buttons and functions Add fractional I/O Medium: Create algebraic display functionality Multi-line calculation (Ans) and variables Long-term: Build UI Ship :) Thanks so much for reading! If you have any suggestions, please leave me a comment. Until next time"}, {"post_id": 23363, "ts": "2026-07-06T09:05:57Z", "hours": 6.4844, "text": "calc82: Project Introduction and Devlog #1 calc82: because calculators are for everyone The aim of this project is to create a free, software-based browser calculator which mimics the behaviour of the Casio fx-82au. This is the most common calculator in high schools in my country. 🔥 Motivation My motivation for this project is the following: calculators are cool i dont always have my calculator on me (most notably) not everyone has access to a scientific calculator 🎯 Approach I will take a black-box reverse engineering approach . This means analysing the inputs and outputs of the calculator and attempting to replicate the behaviour without looking at the underlying code. This along with avoiding patents and copyright should keep the project okay legally. 📈 Goals and scope The final goal for the project is to create a fully functional calculator (obviously) which works on most types of devices. This means both touch and keyboard input, resolution scaling, wide browser support… I have moderate experience with creating web apps. and a lot of experience using this calculator. so this project should be pretty fun :) Devlog #1 06/07/2026 This devlog covers the initial development of the parts of the calculator that do math. Essentially turning an input expression into an output. I chose a high-level structure similar to that used by programming language syntax analysers. That is: Input -> Tokeniser -> Parser -> Evaluator -> Output 🪙 Tokeniser yes, with an s >:( The tokeniser converts the input into a list of tokens (think individual pieces of the expression). It does this by scanning the input string and identifying what each character corresponds to. The tokeniser only knows what each symbol is , not what it does . Then it passes the token array to the… 🌲 Parser The parser converts the token array into an Abstract Syntax Tree (AST). Essentially this is a tree which shows how the expressions should be evaluated in order to produce the desired output. This properly lets me implement order of operations. The exact type of parser I am using is a recursive descent parser . It attempts to match the tokens with known symbols recursively, meaning i can rely on the call stack :) The order of operations can be defined by the order of function calls within the parser. 🧮 Evaluator The evaluator’s job is easy: it just traverses the tree made by the parser and runs the necessary operations. Because all of the hard work regarding order of operations has been done by the other components, implementing the evaluator was really easy. Its also recursive. your call stack is gonna love me for this 🗒️ Notes Why not eval? It’s true that JavaScript has a perfectly good expression parser, which I could have used. However, its behaviour is more suited to a programming language than a calculator. For example, 4(2+3) should implicitly multiply , but will instead complain TypeError: 4 is not a function . Writing my own system gives me more flexibility to make the calculator how I want. Floating point precision Because it uses Javascript’s internal math engine, i have floating-point problems. This results in expressions like sin(2pi) = -2.44929360e-16 I will likely fix this by using a math library, or a novel approach. Last-minute catch I was just writing an example for this devlog when I found that .3ln(4)*5^2 raised an error. In fact, ANYTHING * or / followed by x^n would error - but other operators wouldn’t. This was a quick fix, but I’m glad I caught it! 📈 Next steps Immediate: Fix math imprecision Add fractional I/O Medium: Create algebraic display functionality Multi-line calculation (Ans) and variables Long-term: Make the calculator functionally equivalent to the fx-82 Build UI Ship :) Thanks so much for reading! If you have any suggestions, please leave me a comment"}]...
|
Title: calc82: Web Scientific Calculator by @rigel Title: calc82: Web Scientific Calculator by @rigel | Stardance
Devlogs:
calc82: Project Introduction and Devlog #1 calc82: because calculators are for everyone The aim of this project is to create a free, software-based browser calculator which mimics the behaviour of the Casio fx-82au. This is the most common calculator in high schools in my country. 🔥 Motivation My motivation for this project is the following: calculators are cool i dont always have my calculator on me (most notably) not everyone has access to a scientific calculator 🎯 Approach I will take a black-box reverse engineering approach . This means analysing the inputs and outputs of the calculator and attempting to replicate the behaviour without looking at the underlying code. This along with avoiding patents and copyright should keep the project okay legally. 📈 Goals and scope The final goal for the project is to create a fully functional calculator (obviously) which works on most types of devices. This means both touch and keyboard input, resolution scaling, wide browser support… I have moderate experience with creating web apps. and a lot of experience using this calculator. so this project should be pretty fun :) Devlog #1 06/07/2026 This devlog covers the initial development of the parts of the calculator that do math. Essentially turning an input expression into an output. I chose a high-level structure similar to that used by programming language syntax analysers. That is: Input -> Tokeniser -> Parser -> Evaluator -> Output 🪙 Tokeniser yes, with an s >:( The tokeniser converts the input into a list of tokens (think individual pieces of the expression). It does this by scanning the input string and identifying what each character corresponds to. The tokeniser only knows what each symbol is , not what it does . Then it passes the token array to the… 🌲 Parser The parser converts the token array into an Abstract Syntax Tree (AST). Essentially this is a tree which shows how the expressions should be evaluated in order to produce the desired output. This properly lets me implement order of operations. The exact type of parser I am using is a recursive descent parser . It attempts to match the tokens with known symbols recursively, meaning i can rely on the call stack :) The order of operations can be defined by the order of function calls within the parser. 🧮 Evaluator The evaluator’s job is easy: it just traverses the tree made by the parser and runs the necessary operations. Because all of the hard work regarding order of operations has been done by the other components, implementing the evaluator was really easy. Its also recursive. your call stack is gonna love me for this 🗒️ Notes Why not eval? It’s true that JavaScript has a perfectly good expression parser, which I could have used. However, its behaviour is more suited to a programming language than a calculator. For example, 4(2+3) should implicitly multiply , but will instead complain TypeError: 4 is not a function . Writing my own system gives me more flexibility to make the calculator how I want. Floating point precision Because it uses Javascript’s internal math engine, i have floating-point problems. This results in expressions like sin(2pi) = -2.44929360e-16 I will likely fix this by using a math library, or a novel approach. Last-minute catch I was just writing an example for this devlog when I found that .3ln(4)*5^2 raised an error. In fact, ANYTHING * or / followed by x^n would error - but other operators wouldn’t. This was a quick fix, but I’m glad I caught it! 📈 Next steps Immediate: Fix math imprecision Add fractional I/O Medium: Create algebraic display functionality Multi-line calculation (Ans) and variables Long-term: Make the calculator functionally equivalent to the fx-82 Build UI Ship :) Thanks so much for reading! If you have any suggestions, please leave me a comment
calc82: Devlog #2 08/07/2026 calc82: because calculators are for everyone This devlog follows the handling of nasty floating point errors in my web calculator - inspired by and designed to work with Casio’s fx-82au. I realised that relying purely on the Javascript math system was unsuitable for a scientific calculator that works with decimal numbers. This is due to binary floating point not translating well to decimal. 0.1+0.2=0.30000000000000004 >:( I researched and considered a few approaches. 🥧 Symbolic simplifier? The idea behind this is to perform algebra and avoid evaluating constants and functions to values until strictly necessary. However, the scope of this seemed massive, and I did not observe this behaviour in the Casio. 🔟 Decimal arithmetic Instead, I stumbled upon the fact that decimal arithmetic can be implemented in a computer. While IEEE floats use binary representation, there is no reason we cannot use decimals internally, avoiding errors that arise from conversion. Decimal floats can be stored by: Sign: +/- Mantissa: the number itself, in my case an array of digits Exponent: what power of 10 the number should be multiplied by. I started implementation, made decent progress, but found out that I was re-doing work that was already done by other people. 🗄️ Decimal.js I found the decimal.js library after researching how to handle decimal addition. Implementing this quickly fixed my floating point errors, but did not fix trig approximation. 👀 Observing the calculator I observed some of the behaviour of the real calculator to work out how it functions. Handles small-angle approximation based on a threshold Drops precision as the trig function argument value increases Appears to use a 15-digit mantissa Refuses to evaluate trig functions with argument above a certain limit I tried my best to implement the behaviour I observed, some of which required editing the code of the decimal.js library. 📝 Editing decimal.js The decimal.js library uses more than the set precision for some internal calculations. However, arithmetic with pi is otherwise only the set precision, causing drift. My fix for this was to adjust the internal pi value to match the mantissa size of the real calculator. Troubles with the library When given a less accurate value for pi (in line with that of the real calculator) sine quadrant is incorrectly calculated. I found that the isOdd function is flawed! function isOdd(n) { return n.d[n.d.length - 1] & 1; } I replaced it with one that works for my use case (if less efficient): function isOdd(n) { return n.mod(2).eq(1); } I need to see if this is just due to my low precision pi, or an actual problem in the library, in the future. But for now my issue is fixed. I also found an error in the cosine function: if (x.isZero()) return x needed to be changed to if (x.isZero()) return new Ctor(1) . Again, I’m going to have to look into this more before submitting a pr or anything, since decimal.js is not made for such an imprecise pi. 🗒️ Notes Deviations There are still small deviations between my calculator and the real one at really, really large trig angles. One idea to reduce error could be optimising the order of operations in the AST to prevent dropping precision unnecessarily. I might explore this later However, I want to press on with other features, instead of tiny inaccuracies that would never show up in real-world use. I have slightly rearranged the to-do list below. 📈 Next steps Immediate: Implement the other calculator buttons and functions Add fractional I/O Medium: Create algebraic display functionality Multi-line calculation (Ans) and variables Long-term: Build UI Ship :) Thanks so much for reading! If you have any suggestions, please leave me a comment. Until next time
calc82: Devlog #3 10/07/2026 calc82: because calculators are for everyone Oh dear, looks like I lost 4 hours of counted time in the last devlog… let’s try to make this one a bit shorter! This devlog follows the implementation of the other inline functions of the calculator: 🌟 New functionality summary inverse and hyperbolic trig arbitrary roots absolute value percent random numbers: Ran and RanInt scientific notation: *10^x / E combinatorics: nPr and nCr variables (not yet adjustable) 📋 Implementation details Implementing most of this functionality followed the same general steps: identify implement test. As I undertook this process. other dependent requirements popped up - such as the implementation of multivariable functions , which in turn required the expansion of the tokeniser and parser. Also, I implemented degrees, radians, and gradians modes into the calculator, and the associated functions (as postfix expressions - e.g. sin(30d) for degrees) . 🗄️ decimal.js changes Finally, I applied some further changes to decimal.js.: Rounding now depends on the closeness of the output to a known value, rather than the input, reducing unnecessary rounding Near-decimal values close to 0, 0.25, 0.5, 0.75 and 1 are now caught. 🗒️ Notes: Remembering that Javascript is weird NaN === NaN is FALSE! Spent a good 10 minutes figuring this one out. The solution was to use isNaN() . Fixing negative-base powers: (-8)^(1/3) should equal 2 but returns NaN Fixed by taking the denominator from the output of a decimal.js toFraction() function, which attempts to create a rational fraction. This overcomes the tiny precision loss and evaluates the function correctly 📈 Next steps Immediate: Add fractional I/O Implement polar/rectangualr conversion Medium: Create algebraic display functionality Multi-line calculation (Ans) and setting variables Long-term: Build UI Ship :) This has been a bit of a shorter devlog. But I’m still proud of what I achieved! Thanks so much for reading. If you have any suggestions, please leave me a comment. Take care
calc82: Devlog #4 14/07/2026 calc82: because calculators are for everyone This devlog mainly follows the addition of fractional I/O to my calculator. 🌟 New functionality summary Fractional input, including fractions Computation of fractions - add/sub,div/mult,power,root other operations convert the fraction to a decimal Fractional output (temporary UI) LCM/GCD separate execute and fraction/decimal converting buttons 🔢 fractional io :) I defined a separate fraction data type: it’s like a decimal, but with a numerator and denominator, and optionally a whole component: for example, 1 and 1/3, or 4/3. Using fractions means that numbers can be represented more naturally and precisely. I.e. 1/7 instead of 0.142857143 🧮 Fractional calculation Additionally calculations can be made more precise. For example (1/7) * (2/3) can be directly computed by multiplying the numerators and denominators. My implementation attempts to convert user input and the products of divisions into fractions wherever possible in order to chase this precision. 🗒️ Notes Web design is not my thing I realised the importance of UI and UX (user experience) by looking at other projects on Stardance. As of the current iteration, this project lacks this a bit.. But I will give it a shot My next developments will begin to focus more on this - starting with the algebraic input, and eventually moving onto the CSS and design aspects. I am also considering whether I should use a Javascript framework. 📈 Next steps Immediate: Create algebraic display functionality Medium: Multi-line calculation (Ans) and setting variables Implement polar/rectangualr conversion (delayed until UI is more fleshed out) Build UI Long-term (but getting closer!): Create a usable UX Ship :)
calc82: Devlog #5 16/07/2026 calc82: because calculators are for everyone This devlog mainly follows the addition of algebraic I/O to my calculator. This is just a check-in since I was getting close to 10 hours since the last devlog - I still have some work to do on this aspect before I move on. 🌟 New functionality summary Input and output formatting through KaTeX Fractions and powers formatted correctly in the input Ability to intuitively traverse the input with arrow keys ⚖️ Algebraic IO with KaTeX I decided on KaTeX because it is both fast (no reflow!) and does not rely on dependencies . KaTeX is a math formatting library that uses LaTeX commands to create beautiful equations from code. For example, \frac{2^{\frac{3}{4}}}{4\sin(30)}\times 2\pi turns into the attached image. Input is currently captured directly from the keyboard to build a 1D array of tokens. The tokens are then converted into KaTeX formatting for algebraic display. In the future, there will also be buttons onscreen as an alternative. Fractions and powers Fractions and powers cannot be represented as a single token. Rather, fractions have a beginning, middle and end, and powers have a beginning and end. The program traverses the array to decide where to put them (and take them out for deletion). 🗒️ Notes The cursor It is surprisingly difficult to make a vertical bar to act as a cursor in KaTeX, without affecting the spacing of the rest of the expression. For now, I am using a \clap{\rule{0.1em}{0.5em}} for the cursor, but I am looking to replace this with custom CSS in the future. Replicating exact behaviour? The fx-82 has some interesting behaviour wherein an empty power is not allowed to exist directly after another power. I am unsure whether I should replicate this - but for now, I am leaving it out. Dealing with broken LaTeX I have been able to get the display pretty bulletproof when it comes to not producing broken LaTeX. However, I’m sure there’s something I haven’t run into in debugging! I want to have this be dealt with gracefully rather than blowing up in the user’s face. 📈 Next steps Immediate: Implement mixed fractions, roots, and Abs to algebraic display Make the input token array able to be parsed into the AST to be calculated Medium: Multi-line calculation (Ans) and setting variables Implement polar/rectangualr conversion (delayed until UI is more fleshed out) Build UI Long-term (but getting closer!): Create a usable UX Ship :)
calc82: Devlog #6 18/07/2026 calc82: because calculators are for everyone This devlog follows the further development of algebraic I/O to my calculator, including turning this into an actual result. 🌟 New functionality summary Input and output formatting through KaTeX Square root, arbitrary root, mixed fraction, and absolute values Tokeniser now directly reads input tokens Errors now move the cursor to the position where it occurred 🌊 New program flow inputHandler -> [input tokens] -> tokeniser -> [calculator tokens] -> parser -> AST -> evaluator -> result This: improves speed (compared to parsing text) allows cursor to be moved to error location since we never flatten to text You might notice I have two sets of tokens. They are similar, but input tokens deal with digits and combined symbols ( sin( ), and calculator tokens are whole numbers and separated symbols. 🗒️ Notes Avoiding the lazy route My first approach was turning the input tokens into a string, which my tokeniser already knew how to deal with. However, this added much processing overhead and made it harder to find out the position at which errors occurred. Spending the time to implement the token conversion made this step much easier Misplaced math errors When implementing error handling, I passed down the original position of each token in the input token array down to each step of the calculation process. However, because my evaluator is recursive, it would constantly update the error position to the latest token, meaning the errors were always placed at the end. This was an easy fix in the end - but hard to spot! 📈 Next steps Immediate: Buttons input Add remaining functions (once buttons are added can be done) Medium: Multi-line calculation (Ans) and setting variables Implement polar/rectangualr conversion (delayed until UI is more fleshed out) Build UI Long-term (but getting closer!): Create a usable UX Ship :)
calc82: Devlog #7 21/07/2026 calc82: because calculators are for everyone This devlog follows the introduction of an actual user interface to my calculator. 🌟 New functionality summary Grid of calculator buttons Different button output when modifiers pressed Navigation buttons work Calculator resembles a real calculator 👇 Button handling The calculator needed buttons resembling that of the Casio to fulfil my purpose. Buttons are dynamically built from an array, which defines their labels and actions. This allows easy changes. For most buttons, the area surrounding the button also acts as a clickable area for better touch input. However, I didn’t find an easy way to do this for the navigation buttons (which are positioned off the grid). 🎨 CSS CSS Grid allows a 2D layout system based on rows and columns. It has been supported by all major browsers since October 2017. CSS Grid was used, as it allows consistent positioning across browsers. In addition, relative units were used to prevent resizing the calculator from affecting it. This should make it easier to make dynamic sizing in the future. 🗒️ Notes Accessibility <button> s are preferred over clickable <div> s because they work with screen readers and legacy browsers . However, I also made the surrounding elements clickable for a better touch experience. Also, keyboard input will make use significantly easier for computer users. Aesthetics The CSS applied so far is purely functional. In the future, I will improve the aesthetics of the calculator through CSS - but for now, this barebones look makes development easier and more focused. 📈 Next steps The todo list was getting too empty, so it has been updated with new tasks Immediate: Add remaining functions Add keyboard shortcuts Medium: Add menu system and settings Multi-line calculation (Ans) and setting variables Implement polar/rectangualr conversion Add other modes (STAT, VERIFY) Add Long-term: Create a test suite to ensure there is no unwanted behaviour Ship :)
calc82: Devlog #8 12/08/2026 calc82: because calculators are for everyone Sorry its been a while since the last devlog, I’ve had this one sitting for a while and not had the chance to finish and post it. This devlog follows the improvement of the user interface to my calculator, as well as the addition of variables . 🌟 New functionality summary Add keyboard mappings for buttons Variables - assign and recall Navigate through history Recall history and edit it. 🦋 Modifier keys It was difficult porting the modifier (shift/alpha) keys to keyboard because Shift is used to type symbols such as + and *, and there is also a Shift key on the calculator… My solution was making tapping shift without any other input to toggle the calculator shift modifier, and combining it with another key to not toggle it. 🗒️ Notes Use of the calculator I’ve actually started using the calculator in class, and it’s been faithful to the original so far (for implemented functionality). I still don’t really trust it though and want to run it through some formalised tests before shipping. Keyboard mappings So far, I have been hardcoding keyboard mappings based on what feels natural to me. However, it would probably be better to have user-editable mappings for other people to customise. 📈 Next steps Immediate: M+ and M- special variable Variable and history persistence in the browser Implement polar/rectangualr conversion Medium: Add menu system and settings Add other modes (STAT, VERIFY) Create a test suite to ensure there is no unwanted behaviour Long-term: Tidy up visuals Ship :)
calc82: Devlog #9 31/08/2026 calc82: because calculators are for everyone This devlog follows the addition of menus and the status bar to my calculator. 🌟 New functionality summary Extensible menu system that allows for easy creation of paginated and nested menus Status bar with indicators that change based on the current calculator state M+ and M- special variables Mixed fraction display 📋 Menu system The menu system uses a dictionary to encode the menu pages and their entries, making it easy to add new menus. However, I couldn’t find a way to easily encode functions and arguments in this structure, so the actual actions are handled by a big switch statement. When the menu is active, most buttons have no action and the input/output display is hidden. 🧀 Status bar The status bar consists of a row of elements with adjustable opacity (to represent their active state). It is handled by a class which allows items to be toggled with a single method call, meaning it can retroactively be integrated into other components. The original calculator has some menu elements that can never be activated - for example, there is a complex mode indicator, but the calculator cannot show complex numbers. I omitted these on calc82, as they took up unnecessary space. 📈 Next steps The project is almost nearing completion :) I made complete list of every feature missing from the calculator (too long to post here). It should should get shorter every devlog from now! Hopefully I can finally ship this project in the next couple of weeks. Thanks for reading :)
calc82: Devlog #10 2/09/2026 calc82: because calculators are for everyone This devlog follows the addition of a lot of small features to my calculator that were last on my to-do list, as well as a slight shift in scope. 🌟 New functionality summary Colon operator for multiple operations Saving variables and settings to LocalStorage Clearing this memory Polar and rectangular coordinates (finally!) Forward delete key (keyboard only) Scrolling screen with a nicer cursor! Colon operator This is an operator I’ve never used on my calculator, but its quite powerful. you can type Ans+1:Ans*2:Ans^2 and it will calculate the first expression, then the second, and so on until it loops back to the start. ➡️ Forward delete Although this functionality is not part of the original calculator, it makes it much more pleasant to use on a computer keyboard. This was implemented as a hidden button. Scrolling Scrolling was surprisingly easy to implement! The browser handles all of the hard work, and all I had to do was set the right CSS tags. Granted, with my CSS experience, this was still difficult, but I made it work in the end. 📈 Next steps I have decided to shift the current scope of the project (before shipping) to just be implementing the main compute mode . This means I will not need to do STAT, VERIFY or LINEIO mode. This is for three reasons: With my semester starting, I will not have as much time to work on this project before the deadline I have very little experience with using these other modes I want to focus my time on the user experience. With this shift in scope, the calculator part of the project is all but done - I only have three buttons remaining. (I had to push this devlog out before 10 hours, which is why they’re not done). Then, I can focus on adding the surrounding UI and UX, which should make it actually possible for other people to use my project. Thanks for reading :)
calc82: Devlog #11 6/09/2026 calc82: because calculators are for everyone This devlog follows the addition of a few final features to my calculator, and then my worst nightmare, frontend UI 😧 🌟 New functionality summary Prime factorisation using Pollard’s rho algorithm Engineering notation button Degree/minute/second output button CSS styling!! + menu bar buttons Fixed some input quirks Dark and light mode (based on system default) with manual toggle 🐚 Pollards rho algorithm for prime factorisation Prime factorisation or integer factorisation is the decomposition of a positive integer into a product of integers. The simplest way to implement this is trial division , which is straightforward but has O(√n) time complexity. I thought this would be too slow, so I decided to implement Pollard’s rho algorithm. This has a nicer complexity of O(√p) where p is the smallest prime factor of the number. However, further observation showed that that the Casio calculator probably doesn’t do this - for numbers without easy factors, it just doesn’t bother. Despite this, I’ve already implemented the algorithm, so I’m not going to remove functionality for the sake of exactly replicating the calculator’s behaviour. 🎨 CSS and styling My goal with the styling was to make the calculator as similar across browsers as possible. I bundled the Inter font (best font) into the program and removed browser-specific button styling. Implementing the CSS styling was mostly painless. I opted for a simple design with a menubar that adapts to horizontal or vertical depending on the window’s aspect ratio for the web app functionality. Additionally the css uses the system theme to automatically choose light or dark mode. 📈 Next steps This project is nearly finished - should only be one or two devlogs left until I ship. Here’s what I have left to do: Development Keybind show and edit Brief manual for each calculator function Info menubar button with author & project information, and disclaimers: that I am not affiliated with casio that the calculator is in a beta state and not guaranteed to be correct for all inputs Fullscreen button for mobile devices Preparation for shipping Webpack or similar Choose a license and publicise repo Write a readme Host on github pages (?) Hope that I did enough to not receive legal action from casio 🙃 Thanks for reading :)
calc82: Devlog #12 7/09/2026 calc82: because calculators are for everyone This devlog follows the addition of customisable and accessible keyboard bindings to my calculator. 🌟 New functionality summary Settings menu Switches between sidebar and popup dependent on screen width Key rebinding Flow of choosing button, then pressing key to rebind Stores in local storage Help hotkey Shows all currently bound keys. Key hint consideration The default keyboard map has been implemented as a const dictionary for a while now, allowing lookup of buttons from keyboard keys. This was extended with a user dictionary that can be dynamically updated. However, generating the help hotkey hints needed to go in the opposite direction of the dictionary. The naive approach of iterating through values to find a key for each would perform poorly with O(n^2). Instead, we precalculate a reversed dictionary to lookup keyboard keys from each button. This precalculation is O(n), and setting the keys is also O(n), resulting in O(n) time overall. 📈 Next steps Development Brief manual for each calculator function (considering reusing the on click functionality from key mapper) ) Info menubar button with author & project information, and disclaimers Fullscreen button for mobile devices Preparation for shipping Webpack, choose a license, write readme, publicise repo, host. Thanks for reading :)
calc82: Devlog #13 9/09/2026 calc82: because calculators are for everyone This devlog follows the addition of help and about menus to my calculator, as well as bundling into one js file. 🌟 New functionality summary Help menu Lookup function by calculator button (reuses key bind selector logic) Q&A About page About the calculator Contribute Legal License All JS files are bundled into one file Service worker makes app available offline 📦 Bundling and service worker I chose to use esbuild for bundling. This allows the many JS files to be condensed down into one file, reducing the number of requests that need to be made. This build system is much simpler than other options such as node.js. I also added a simple service worker that caches all requests locally. This makes the calculator available offline. ⚖️ Licensing & Legal I chose GPLv3 for this project as it is an end-user product. Essentially, this means others are free to modify and distribute the project as long as they make the source available. I also added legal disclaimers to the about page of the calculator. 📈 Next steps Write the readme, publicise the repo, and host! Thanks for reading :)
calc82: Devlog #14 9/09/2026 calc82: because calculators are for everyone Final devlog. It’s done!! This last stretch was writing the readme and publishing everything to Github pages. You can now access it at https://rigelseven.github.io/calc82/ Now for a short reflection calc82 is the largest personal software project I have ever completed. This project taught me a lot about input parsing - specifically, tokenisers and syntax trees - and the importance of keeping a large codebase tidy . Overall, the structure of the project is well laid out. However, there are architectural decisions I made early on that I came to regret later (such as the fact that input is represented as a string, whereas it should probably be a tree). Developing calc82 also showed me that I am capable of putting together such an app from scratch. I’m pleased to have participated in Stardance and be given this opportunity.
Ships:
What did you make? calc82: A calculator web-app inspired by the Casio fx-82 series of scientific calculators. These calculators are common in high schools in my country. My project simulates the behaviour of the Casio calculator, while maintaining a good user experience on both desktop and mobile. What was challenging? Creating reliable algebraic (non-linear) input parsing was the most difficult part of the project. This was because it required some difficult array traversal to avoid invalid states - even one mistake would break the whole input. It took a lot of iterations to get to a working input system that passed all my tests. Close contenders for most challenging were the sheer volume of functions I needed to implement, as well as all possible states the calculator can be in. However, the challenge for this was finding time to get around to everything, rather than technical challenge. What are you proud of? I’m most proud of my implementation of the input-to-result pipeline. I was able to incorporate new-to-me concepts such as tokenisers and abstract syntax trees, yet the resulting code is arguably the cleanest part of the program. I’m also proud of the responsive layout, which supports desktop and mobile well, and that the user experience is similar enough to the Casio that my muscle memory carries over. Finally, I’m proud that I managed to finish the project, as it’s the largest software project I’ve ever managed to complete. Demo: https://rigelseven.github.io/calc82/ Source: https://github.com/rigelseven/calc82/...
|
1792853601.783349
|
1792940001.783349
|
|
26398
|
200 MPH Drone RTOS by @Guagyyy | Stardance
|
Guagyyy
|
2
|
129.28
|
2267
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-22T00:49:05Z", "hours": 106.0, "multiplier": 19.18, "payout": 2024, "blessing": "neutral", "text": "200 MPH Drone RTOS: How it went Simulation to Silicon! When I published the first major update for this project at the 15-hour mark, I essentially had a proof-of-concept. I had managed to write a custom hybrid cooperative/preemptive scheduler and get an ARM Cortex-M7 (on the STM32f756VGTx) assembly context switcher functioning inside the Renode simulator. Although this looked like a massive leap, the project had barely started. Over 100 hours of development have gone into this project since then. The transition from a simulated kernel to a bare-metal flight controller capable of keeping a 200 MPH drone in the air required stripping the system down to its bare components, rewriting the memory architecture, and debugging some of the most frustrating hardware faults I have ever encountered-especially whenever the project just crashed, leaving me no traces as to what went wrong. Software Limitations The biggest turning point was realizing that software simulation can only take you so far. Renode is an amazing tool, but it hid a massive amount of race conditions and timing flaws that only exposed themselves when I finally flashed the code to physical STM32F756 Nucleo board. Sometimes, the MCU would have to reboot every 2 seconds. I spent dozens of hours tracking down massive architectural bugs. One of the worst was a context-switching fault where floating-point math was corrupting the return address in the CPU registers, causing the processor to execute raw garbage data. To fix this, I had to completely restructure the boot sequence and overhaul the memory management. I moved away from static arrays to a dynamic per-task stack allocation system, and implemented a dual-guard memory system. Arguably, this was the most important change as it allowed me to debug tasks way quicker as I instantly could know when the canary values were corrupted. Overhauling the Data Pipelines In order to avoid the 10ms delay of my original blocking pipline (for data transfer), I entirely rewrote the hardware data pipelines multiple times to use a semi-blocking, circular Direct Memory Access (DMA) architecture. Instead of the processor handling the data transfer, the hardware itself moves the bytes from the sensors directly into memory in the background. The DMA streams now trigger precise interrupts at the halfway and full-transfer points, allowing the RTOS to safely parse incoming radio packets and sensor reads without ever risking data overwrites or blocking the main flight loop. Building a Flight Controller I integrated Betaflight’s Actual Rates algorithm with custom expo curves, ensuring that physical stick inputs map perfectly to target velocities. I built a custom SPI driver to pull 24-bit raw pressure and temperature data from a BMP390 barometer, passing it through hypsometric formulas to calculate altitude. For video and telemetry, I moved away from raw UART strings and implemented native MSP DisplayPort communication (for true digital Walksnail Avatar connection). I also built an interactive USB command-line interface. Instead of having to recompile and re-flash the firmware every time a PID value needs to be adjusted, I can plug into the board, pull up a terminal, and manually tune gains, remap CRSF radio channels, or adjust IMU orientation offsets in real time. Final Version The last few weeks have been about refinement and consistency, removing race conditions and overall polishing the code. Now that the RTOS is fully functional, the only things to add are extra features, like a permanent + more expanded CLI, as well as finishing the external RM and linking the ESC drivers. As these are pretty insignificant, I have linked the source of this shipment to the Github project rather than a specific release so that I can update these during review!", "repo": "https://github.com/Guag914/200-MPH-Drone-RTOS/", "demo": "https://github.com/Guag914/200-MPH-Drone-RTOS#interactive--simulation-demo"}, {"ship_num": 2, "ts": "2026-07-15T04:02:12Z", "hours": 15.0, "multiplier": 16.44, "payout": 243, "blessing": "neutral", "text": "Phase 1 (The Custom RTOS Kernel) I am building a custom FPV drone from scratch with my friend in an attempt to achieve 200 mph . At those speeds, standard super loops are far too slow, as a single microsecond of lag means the drone travels feet before making a PID correction. To solve this, I built a custom, hybrid cooperative/preemptive Real-Time Operating System (RTOS) from scratch for the ARM Cortex-M7 (STM32F7)! What Was Challenging? The absolute hardest part of this phase was writing the low-level assembly context switcher ( PendSV_Handler.S ). Hacking the ARM Cortex-M7 registers to physically hot-swap stack pointers ( PSP ) mid-execution without crashing the CPU or corrupting the program state was a massive headache. I had to ensure that when an asynchronous preemption event fires, the assembly code perfectly preserves the execution registers ( R4-R11 plus the hardware-stacked registers), jumps to the high-priority task, and then seamlessly restores the background task right where it left off. Getting the compiler-enforced task overloading working so the kernel cleanly separates periodic tasks from raw interrupts was another huge hurdle, but it makes the whole codebase infinitely more robust. Want to Test It or Write Your Own Tasks? You don’t need physical hardware to watch this run! I’ve packaged the entire project with a Renode simulation script. You can run the interactive emulator with a single command to see the preemption scheduler hijack our counter task live, or you can jump into the user sandbox file and write your own custom tasks. Check out the GitHub Repository to Run the Demo! The README has a quick 5-minute setup guide to get you compiling and simulating your own code in no time.", "repo": "https://github.com/Guag914/200-MPH-Drone-RTOS/", "demo": "https://github.com/Guag914/200-MPH-Drone-RTOS#interactive--simulation-demo"}]...
|
[{"post_id": 78931, "ts": "202 [{"post_id": 78931, "ts": "2026-10-12T02:34:08Z", "hours": 8.2783, "text": "Although I haven’t been able to make much progress on the project due to school over the past weeks I did manage to make some substantial project mostly with the scheduler, allowing for fairly good performance on my STM Nucleo boards, rather than it just crashing instantly. 1. Issues with the Old Design The flight controller’s RTOS scheduler wasn’t working under real hardware timing because global variables like currTaskIndex, topOfStack, and excReturn were being modified from multiple entry points simultaneously. Yield calls, interrupt handlers, and the main task-selection logic were all making independent writes to the same shared task control blocks. Whenever a hardware interrupt fired mid-write, stack pointers and exception return values were saved into the wrong taskControlBlocks slot. This created edge cases where preempted tasks were silently double-queued, state tracking completely desynchronized, and time-critical hardware events were dropped during flight. 2. Centralizing Context Switches in PendSV To eliminate these race conditions, all state-selection decisions were moved out of individual execution contexts and consolidated into decideNextTask(), which now runs exclusively inside the PendSV assembly handler. Functions like yieldCurrentTask(), decideNextInterruptTask(), and decideNextScheduledTask() no longer touch global scheduler state or choose which task runs next; they simply update local status flags like TaskState::BLOCKED or TaskState::READY inside brief __disable_irq() critical sections and trigger PendSV using SCB_ICSR_PENDSVSET_Msk. When PendSV fires, decideNextTask() saves outgoingSP and outgoingExcReturn to the active block, sets RUNNING tasks to READY, and runs a two-pass check over taskControlBlocks[]—evaluating high-priority TaskType::INTERRUPT tasks first, then TaskType::SCHEDULED tasks, and falling back to index 0 for idle. Since PendSV is the only place allowed to modify currTaskIndex, concurrent state corruption is structurally impossible."}, {"post_id": 71997, "ts": "2026-09-21T23:26:43Z", "hours": 7.2761, "text": "For the past couple weeks I have been mostly refining small bugs, which were originally rendering the RTOS usless, as well as refactoring the code for simplicity rather than elegancy. 1. Transition to Actual Hardware Renode is great for simulation, but it ended up hiding a bunch of race conditions in the population methods and the main scheduler that led to no code actually running during the IRQ handler calls. I spent a lot of time securing those resources and finally got the scheduler mostly finished up. Also, I decided to just take out the double preempts entirely since they were adding way too much complexity for absolutely zero speed benefits in practice (plus they were creating detrimental but rare race conditions). 2. Code Refactor To make things run a bit more consistent, I restructured how the control loops operate. I ended up merging the dShotGeneration task with the parent IMU control loop, so now everything from reading the sensors to pushing motor commands happens in one clean sequence (rather than including an unnecessary preempt). I also built out a brand new CRSF control loop to handle all the radio parsing and state machine updates in its own dedicated space (just for consistency). Lastly, while doing a final pass on the code, I realized that in my dShotGeneration helper, I had forgot to scale the values by a factor of 1/2000, as the inputs require the value to be between 0 and 1 (not 0 and 2000). 3. Final DMA Iteration The biggest relief was finally getting rid of the old blocking USART system. I finally transitioned away from manually handling the streaming by polling flags in a loop, which was tying up the processor way more than it should have. Everything has been converted over to a blocking DMA system, so the hardware can just handle all the memory transfers in the background while the CPU focuses on actually keeping the drone in the air. Overall, I think that this will be the final iteration of the RTOS DMA pipeline, as now that it is solid and works with all the edge cases, theres no need to change it. 4. Timeline With almost all the major bugs fixed, I am going to ship the project! While it is not 100% done, it will likely be as close as it will get during the timeframe of the Stardance hackathon, and with it so close, theres no reason not to ship. Anyway, I will keep the source as the main project rather than a release, so if I do end up fixing any major bugs, they will get patched either before or during project review (besides most of these bugs are only detectable on actual hardware). I will most likely finish the RTOS in the next couple weeks (by the end of October), and will finish the drivers for the ESC and RM by latest end of November (for more timing refer to the README). Thanks to everyone who supported me throughout this project (hopefully me and my friend can get this drone flying in another Hack Club Hackathon!)."}, {"post_id": 63202, "ts": "2026-09-06T21:25:57Z", "hours": 9.6606, "text": "1. Scheduler Hardening and Task Discovery Spent part of this session making the RTOS scheduler itself more robust. I added a findTaskByName() function so interrupt-driven task lookups happen dynamically instead of relying on hardcoded task indices, which was a fragile setup just waiting to break the moment task registration order changed. Alongside that, I wrapped every one of those lookups with lambdas that throw a proper warning if a task can’t be found, so a missing task fails loudly instead of silently dereferencing a null pointer somewhere downstream. 2. Blocking vs Non-Blocking Scheduled Tasks After a lot of painful debugging, I traced a string of issues (including interrupt tasks silently failing to fire and scheduled tasks stepping on each other) back to non-blocking statements I’d introduced inside scheduled tasks in the previous devlog. I ended up taking those out and reverting scheduled tasks fully back to blocking, which is genuinely what the scheduled zone was designed for in the first place: tasks that don’t need to run in polynomial time and can safely block without putting the drone at risk of crashing. Once that was sorted, I converted the raw USART byte-pushing into a blocking DMA system instead, so streaming is handled by DMA hardware rather than manually pushed byte-by-byte over USART. 3. Flight Loop Refactor and VTX Communication On the flight logic side, I refactored flightLoop() to use lambdas and a state machine so I would never have to yield in the middle of my tasks (which was used previousely for zeroing motor outputs). I also converted the error handling into a proper state machine, so different types of warnings can be caught and handled distinctly instead of lumping every issue into one path, and turned on full debug printing whenever the system is running. Last but not least, I built out a dedicated injector for respondToVTX so I can properly test and simulate VTX communication going forward. 4. Real Hardware Testing Since, I am almost 100% done with the RTOS I bought two NUCLEO-F756ZG’s which will serve as testing the 100% production code rather than the simulation version. I bought two so that one of the boards will be running the real RTOS code, testing DMA reading from USART, SPI, and emitting real motor signals, while the second will be emulating all of my peripherals. When the boards come, if the code does work, it will also mean that the real PCB’s will also work when my friend finishes with them. 5. Next Steps As of now there are a few issues with the double preempt system (for the interrupt tasks) I designed a while back, so I will need to debug that before they arrive. Right now before the boards arrive, I will be finishing up the RTOS blocking DMA pipelines (stripping out IRQ, removing NVIC etc. for scheduled tasks), and performing a bunch of baseline testing in order to prove that the RTOS is capable of flying an actual drone!"}, {"post_id": 52761, "ts": "2026-08-23T03:11:04Z", "hours": 9.6356, "text": "1. CLI Upgrades and Channel Mapping Over the past 5 days, I knocked out some major quality-of-life upgrades for the flight controller. I added customizable channel mapping for CRSF directly through the CLI. By utilizing a combination of references and pointers, I was able to point a volatile alias to certain channel mappings, allowing for completely customizable CRSF channels. While I was in the CLI logic, I also added the ability to configure custom IMU orientations around the z-axis, making it way easier to mount the board in different directions without having to recompile the firmware. 2. DMA Pipeline Fixes and Baro Optimization A big chunk of this session went into debugging and refactoring the hardware data pipelines. I adjusted the ADC population pipeline in order to fix some stream parsing issues, and gave the barometer a massive overhaul. The baro now uses a non-blocking, non-circular DMA setup that relies on a semi-interrupt-driven task call rather than a continuous loop. This enabled me to yield in the middle of the function, and call back later as soon as DMA is finished transferring. I also fixed a massive bug in the DMA setup: the DMA_SxCR_HTIE and DMA_SxCR_TCIE flags were accidentally enabled for the GPS and OSD ring buffers, which would have crashed the whole RTOS by firing unhandled interrupts, causing default HAL and IRQ handlers to run. 3. Walksnail Two-Way Communication Finally, I built out the respondToVTX task to get the drone properly communicating with the Walksnail VTX. Instead of just blindly sending video data out, this sets up true two-way communication over asynchronous UART. By writing a persistent byte-by-byte state machine, the flight controller can now safely parse incoming requests from the VTX without dropping half-packets, allowing me to send back live stick positions and armed status for the OSD menus. The only thing left to do now is handle persistent CLI storage, the logToBlackBox task, integrating the semi-interrupt pipeline with telemetryTX and the OSD, and a few other system tweaks. After that the RTOS will be 100% ready to fly the actual drone."}, {"post_id": 49360, "ts": "2026-08-18T04:16:35Z", "hours": 4.0211, "text": "Complete RTOS Overhaul, Circular DMA Pipelines, and CPU Abort Fixes This update focuses on fine-tuning the RTOS, organizing the scheduler, and rewriting microcontroller memory handling. Renode’s simulated DMA restrictions make software-only pipeline testing nearly impossible, so I plan to buy a physical dev board and Raspberry Pi to validate on silicon. While the Git diff might not look massive, the architecture has evolved from a blocking system to a true preemptive RTOS with precise polynomial timing. 1. Reworking DMA Flow & Standardizing Ring Buffers Sensor and receiver data pipelines are now driven by circular DMA, enabling non-blocking, high-frequency transfers with response times as fast as 0.3 ms (without printToUSART enabled). Everything now relies on ring buffers. Instead of generating complete packets instantly, mock injectors stream bytes directly into the buffers while updating the simulated NDTR register to mirror hardware behavior. if ( byteIdx >= frameLen ) { byteIdx = 0 ; } crsfRingBuffer [ head ] = frameBuf [ byteIdx ++ ]; head = ( head + 1 ) % CRSF_RING_BUFFER_SIZE ; currentBoardConfig . crsf_dma_stream -> NDTR = CRSF_RING_BUFFER_SIZE - head ; Feeding bytes incrementally moves the write head gradually, ensuring the simulation mimics a physical UART and allowing population functions to safely pull data within interrupt locks. 2. DMA Interrupts for Safe Parsing To prevent data overwrites, DMA streams trigger interrupts at the halfway (HTIE) and full-transfer (TCIE) points to queue tasks. Because registers like LISR are read-only in hardware, I implemented a software mock flag system (mock_LISR) for simulation: extern \"C\" void DMA1_Stream0_IRQHandler ( void ) { #ifdef SIMULATION uint32_t flags = mock_LISR ; mock_LISR = 0 ; #else uint32_t flags = DMA1 -> LISR ; #endif if ( flags & DMA_LISR_HTIF0 ) { DMA1 -> LIFCR = DMA_LIFCR_CHTIF0 ; decideNextInterruptTask ( & taskControlBlocks [ 1 ]); } } Functions safely extract data with interrupts disabled, ensuring the CPU never blocks waiting for peripheral transfers. 3. Assembly Bugs & CPU Aborts Debugging nested hardware interrupts exposed massive faults: The context-switching bug: FPU usage or large stack frames corrupted the return address, causing the CPU to execute BX LR with garbage data. Fixed in PendSV_Handler.S by explicitly storing excReturn inside the TaskControlBlock rather than relying on stacked registers. Second, a 0x00000000 Null Return Crash: Scheduled tasks attempted to return natively, popping 0x00000000 from the zero-initialized Link Register and causing a fetch fault. Every task now runs inside an infinite while(true) loop calling yieldCurrentTask() . 4. Clock PLLs & Hardware Re-routing After configuring the STM32CubeMX PLL for a 25 MHz HSE clock, the MCU runs at its full 216 MHz. I added a standardized initSystemGPIOClocks() function to enable peripheral clocks consistently. I also moved motor 3 from TIM1 to TIM4, synchronizing it with the 216MHz clock and freeing up a TIM1 DMA stream exclusively for the upcoming BlackBox logging. Future Updates With the core RTOS stabilized, development shifts to flight-facing systems: hooking the SPI pipeline to the video overlay for live OSD goggle telemetry, adding permanent flash storage for PID tunes/configs, exposing MCU controls via CLI, supporting programmable transmitter bind buttons, building a desktop GUI, and using the freed TIM1 DMA for BlackBox logging. Below, I have attached a screenshot of every single task working, and outputting values in the simulation, something that wasn’t possible for the interrupt tasks until now."}, {"post_id": 48647, "ts": "2026-08-17T03:57:01Z", "hours": 9.6761, "text": "1. Reworking the DMA Flow for Speed So, a lot has been going on lately, starting with a massive rework of the entire DMA flow. The functions are now entirely populated by circular DMA, which is a huge upgrade for the system’s overall performance. This architectural change allows for completely non-blocking, high-frequency calls, hitting response times as fast as 0.03 milliseconds. It basically means the whole data pipeline is significantly faster, and much more responsive than it was in previous versions. 2. Standardizing Ring Buffers and Mock Injectors To make everything more reliable, the DMA now follows a very specific and predictable pattern for both scheduled and interrupt tasks. Everything relies on ring buffers now, whether they are being injected by actual hardware (or simulated) DMA or by my custom simulation scripts. I also reworked the mock injectors so they no longer just return a pre-formatted packet. Instead, they write directly into the ring buffer, which lets me test the exact same parsing pipeline in software, simulating the hardware flow almost exactly like Renode (if only they would ever fix that USART DMA bug…). 3. Assembly BX LR Bug + STMCubeMX Clock PLL I also finally solved the long term BX LR return bug that I literally spent over 20 hours trying to find. Whenever tasks used the FPU or had slightly larger stacks, the return address in the r0 register would just get completely corrupted by the extra data. I fixed this by storing the return address in a dedicated uint value instead of blindly trusting the registers to hold it. That fix alone allowed me to safely re-add telemetryTX and make a bunch of other function logic much more robust. On top of that, I went into STM32CubeMX and reworked the clock PLL manually (it took over 3 hours to solve by hand). By feeding in a 25 MHz HSE clock, I managed to unlock the MCU’s internal clocks to run at their full 216 MHz.I also took some time to clean up the codebase to improve overall readability and commenting. 4. DMA Interrupts for Safe Parsing Another feature is that DMA now triggers interrupts when the ring buffers hit exactly halfway and when they are fully populated. This gives me the time to parse all the incoming values safely without having the risk about data getting overwritten by the next DMA pass before I am done reading it. I set up the IRQ handlers in the code to call the interrupt methods automatically, which ensures the CPU stays completely unblocked and free to handle other flight control tasks almost all the time (overall decreasing headroom). 5. Current Status: NVIC Bug Sadly, the code is actually not functional right now because the NVIC and IRQ pipeline is malfunctioning and just refusing to call the interrupts for reasons I cannot figure out yet. Because of this, I am holding off on pushing the code until I can track down the bug, give everything a final polish, and run some benchmark testing (since I don’t want to commit broken code). Also, sorry for promising a commit a day or two after my last devlog. I got super busy, especially with vacation, but I will try my best to get this sorted. Depending on how long it takes to figure out this NVIC issue, the next commit might drop anywhere from tomorrow to a few weeks from now."}, {"post_id": 41654, "ts": "2026-08-06T00:44:12Z", "hours": 9.5336, "text": "This week was heavily focused on the fine tuning and organization of the RTOS. I spent numerous hours of research and untangling environment setups. I originally tried to build out a complete framework for the drone code without relying on any simulation code, but Renode’s restrictions, specifically with its ability to perform DMA requests, quickly made it clear that path was impossible. To fix this I’m looking into picking up a dev board and a Raspberry Pi so I can test and debug everything on an actual MCU before finally moving the codebase over to the drone. Even though the git won’t look a whole lot different and not a lot of actual code changed, getting these configs finalized (especially in STM32CubeMX) in was a huge step forward for the project. I expect to commit the next version of the code either today or tomorrow, with improvements specifically in TelemetryTX, BlackBoxLogging, and a few other minor changes!"}, {"post_id": 37983, "ts": "2026-07-31T02:30:16Z", "hours": 8.6756, "text": "Major Architecture Upgrade : OSD, Betaflight Rates & Build System Refactor 1. OSD, DMA + SYS First off on the hardware side, I added native MSP-based OSD support for Walksnail video transmitters, built the SPI barometer driver for altitude tracking, and spun up a low-level health task that constantly monitors MPU registers and stack usage in the background. On top of that, I finally fixed the DMA stream conflicts (mainly in STMCubeMX) between TIM1 DShot motor outputs , ADC1, and SPI peripherals, so everything runs without collisions now. 2. SYS Health + Debugging I also implemented a few other low level tasks, allowing me to monitor system health, based upon ram usage and storage used. This task prints out the amount at which each tasks stack is being used, allowing me to effectively debug whether a task was actually overflowing, vs an unrestricted read/write. Furthermore, the original canary values that I used, were completely replaced as they in fact were causing some of the “stack overflow” bugs (via unrestricted reads/write every 1 ms in SysTick_Handler ). 3. Betaflight Rates + CLI Update For flight feel, I implemented Betaflight’s Actual Rates algorithm with custom expo curves, so stick inputs map to target angular velocities with center-stick precision. I also completely separated serial communications by moving the interactive CLI to USART1 (accessible via nc -C localhost 1234 in terminal) and pushing system logs to USART3. Additionally, I removed the old telemetryTX task because its unauthorized reads/writes were completely breaking the RTOS scheduler, and expanded the CLI with a ton of commands for live sensor readings and more PID tuning. Speaking of which, I am planning to create a persistent file in /bin/ , allowing for rates to be stored between runs, rather than being reset each during runtime, and having to be manually configured through the CLI. 4. Overhauled Building Workflow Finally, I overhauled the whole developer workflow and build automation setup. The build.sh and build.bat scripts now auto-configure custom CMake profiles and generate a full disassembly file in /bin/ after every build for fast low-level debugging, while run.sh and run.bat automatically launch the right terminal windows on launch. 5. Future Additions: I’m planning to build a closed-loop Renode simulation matrix to stream hardware data into every peripheral externally, letting me run 100% real production code during SIL testing! For this, I will utilize the currently blank simulate.py as well as certain commands in simulate.resc to create properly formatted dynamic buffers(which are not directly injected into the code), allowing me to properly test the DMA drivers, and many of the memory management helpers."}, {"post_id": 35605, "ts": "2026-07-27T04:22:30Z", "hours": 9.44, "text": "Over the last few days, I wrapped up two major tasks for the flight controller’s core sensor and telemetry stack: the on-screen display (OSD) renderer and the BMP390 barometer subsystem. The OSD engine is now fully hooked up to the state system, giving real-time visual downlinks for critical metrics like flight battery voltage, active flight modes, and height statistics over UART. To keep the execution completely non-blocking, all frame updates are dispatched asynchronously, preventing rendering delays from hindering the performance of the high-frequency control loops. On the barometer side, I implemented altitude tracking using Bosch’s BMP390 sensor over SPI with non-blocking DMA burst transfers. In the 50Hz task loop, incoming 24-bit raw pressure and temperature bytes are assembled and passed through the hypsometric formula to calculate smooth, relative height above ground level (AGL). Although the barometer task is a bit flawed due to floating point register stack errors with the header and end canary values, they don’t seem to be affecting the system in anyway (nor is any data being corrupted). I will find a way to fix these issues before the next commit, as well as the race condition in the interrupt tasks in the next Github commit. After that, it is just system polish and extensive testing before the RTOS will be complete!"}, {"post_id": 33865, "ts": "2026-07-24T04:03:21Z", "hours": 7.1808, "text": "1. Fixing the Stack Overflows at Boot After an entire 25-hour debugging period across 4 days, the RTOS kernel is finally done (for the scheduled tasks). I tracked down a silent bug where several critical scheduled tasks—like powerManagement , lowLevelFailSafe , and telemetryTX —were crashing the MCU on boot. The issue came down to a boot-time dependency lock: tasks were trying to poll hardware registers (like UART TX flags) and read shared drone state variables before the peripherals or producer tasks had time to initialize on Tick 0. By adding an initial yieldCurrentTask() right at the top of these methods, Task Phase Alignment was officially added. This gives the hardware a full cycle to stabilize, preventing buffer overflows and eliminating the cascading task state corruptions that were locking up the scheduler. 2. Custom Stack Sizing & Real-Time Guard Checks Alongside the scheduler fix, I pushed major upgrades to memory safety and task management. Instead of assigning a static stack array to every task, I transitioned to dynamic per-task stack allocations during initialization ( new (std::nothrow) ). Heavy string-parsing and math tasks get larger stacks, while simple toggle tasks stay lightweight. To catch memory issues before they corrupt the heap, I implemented a custom dual guarding system: 0xDEADBEEF is appended at the bottom of the stack to catch standard stack overflows, while a new 0xBEEFCAFE canary value is written to the very top index ( stackSizeWords ) to instantly flag memory breaches in the SysTick_Handler . Furthermore, I refactored powerManagement to use ADC2 in Circular DMA Mode, writing battery telemetry directly to RAM in the background for zero CPU overhead. 3. Transitioning to Walksnail Avatar HD Looking ahead, my and my friend are officially transitioning our existing analog video setup over to a fully integrated Walksnail Avatar HD digital ecosystem. Rather than keeping my custom telemetry task ( telemetryTX ) with heavy string formatting over raw UART, Walksnail allows me to stream standard MSP (MultiWii Serial Protocol) DisplayPort frames straight to the VTX. The Walksnail system will serve as our primary onboard logging source, giving us full OSD telemetry, high-framerate HD video, and precise blackbox data logging. With the RTOS core now stable and non-blocking, our next focus shifts toward “premium” flight controller features, e.g. including custom RC stick expo curves, an expanded USB CLI, and an integrated simulator interface."}, {"post_id": 32665, "ts": "2026-07-21T23:24:15Z", "hours": 9.0794, "text": "I just finished expanding the RTOS architecture, filling out all of the scheduled background tasks to handle real-time flight telemetry, peripheral hardware, and terminal configuration. On the telemetry side, I built out telemetryTX to package battery, status, and GPS data into standard CRSF frames over UART, alongside an NMEA gpsParser that decodes $GNGGA and $GNRMC sentences for live location fixes. I also made powerManagement into its own standalone task so ADC voltage and current metrics can feed into the failsafe logic and telemetry concurrently. To make bench testing and tuning significantly easier, I added usbCLI over USART1, giving me a full interactive shell to tweak PID gains (Kp, Ki, Kd), dump raw IMU data, and inspect hardware states on the fly without needing to reflash firmware. To keep the physical quad safe and responsive during flight, I added updatePeripherals for LED status patterns and buzzer warnings, along with a dedicated Independent Watchdog (IWDG) task running as a low-priority fail-safe to trigger hardware MCU resets if the scheduler ever freezes. On the project structure side, CMake now routes all output binaries straight into a clean ./bin/ directory so nobody has to compile the source manually just to run the .elf target in Renode. I also introduced a -DENABLE_DEBUG flag, allowing me to cleanly toggle between complete USART log prints across every loop or a blank terminal environment meant purely for the CLI shell. While all the background subsystems and scheduled task priorities are fully mapped out, I’m currently figuring out a few lingering RTOS bugs—specifically around stack allocation, causing stack overflow flags on certain scheduled tasks, along with scheduling starvation where context switching isn’t releasing task blocks properly. Because I want to ensure the scheduler kernel is 100% complete before pushing broken stack frames to the main branch, the GitHub repository will be updated with the complete, bug-fixed code later today. Everything is moving in the right direction, and getting these background tasks finalized brings me one step closer to full flight hardware deployment!"}, {"post_id": 31067, "ts": "2026-07-19T04:58:26Z", "hours": 2.5139, "text": "I’ve spent the last 20 hours of coding basically staring at bare-metal memory allocations and tracking down why the drone’s context switcher was triggering CPU drops under the Renode simulation environment. Moving away from manual Python injection scripts to a cleaner C++ conditional compilation framework using CMake was supposed to simplify the testing layout, but instead, it exposed structural design flaws in how the scheduler kernel boots up. Running a multi-sample sensorCalibration() routine at cold boot was forcing hidden task yields before the OS kernel was fully mapped out, which was throwing unmapped register address errors and wiping out index-0 entries. To solve this, I decoupled the entire state machine sequence so that hardware allocations, peripheral registers, and core tracking counters now clear before any operational loops drop into the registry. I also added a critical rtosStarted gatekeeper flag to yieldCurrentTask() so calibration math runs cleanly in sequence without triggering early PendSV handler switches. On top of that, the task stack pointers are completely realigned. The assembly context swapper now maps a precise 32-word boundary allocation utilizing 0xFFFFFFFD as a basic exception return code, which completely eliminates the data corruption that was misaligning our Process Stack Pointer. With the fundamental kernel stabilized, I shifted entirely into clean architecture organization. The massive, cluttered code blocks have been split up into independent tracking files (BufferPopulation.cpp, Tasks.cpp, and SimInjector.cpp). High-speed SPI reads for the IMU, UART ring buffers for decoding CRSF radio channel frames, battery ADC sampling, and DShot600 motor output mixers are now fully broken out and functional. There is still a nagging preemption lockout issue inside the simulator where a single interrupt task attempts to starve out the other concurrent loops during a millisecond window, but the baseline operating system is locked in, meaning I can confidently verify the PID flight mixing tables and safety code blocks safely before the code ever touches a physical quadcopter. If you would like to run your own tasks, I also added support in the .bat and .sh files to build code for the simulation (flag=sim), user task code (flag=user), and actual drone upload code (no flags). Example MacOS Commands: ./build.sh sim ./build.sh user ./build.sh This makes it so that I don’t have to constantly modify code to run either the user tasks or simulation code, instead using a flag. Overall, this RTOS is not done yet, however, I plan to add the rest of the scheduled tasks later today, and fixing the sole bug keeping this simulation back! I expect a full ship to be comming out in the next week or so, along with all ESC, RM, and TM code complete!"}, {"post_id": 30963, "ts": "2026-07-18T23:42:07Z", "hours": 9.2461, "text": "I’ve been doing a lot of debugging for the RTOS scheduler inside the simulation environment, and it’s been very difficult for me to identify many bugs in teh core architecture of my tasks. Moving away from Python scripts to a cleaner C++ conditional compilation framework using CMake was supposed to simplify things, but instead, it exposed some nasty architectural bugs in how tasks and context switching interact. There has also been a massive priority inversion and preemption lockup where the CRSF parsing loop completely starves out the lower-priority threads. Also, running a raw sensor calibration loop at boot was forcing thread switches before the OS kernel was even fully initialized, completely corrupting task indexes, throwing null pointer warnings, and leaving half of my PID calculations at zero. Still working on many fixes, but it has been a lot of work (9 hours), but I hope to get the full RTOS with at least bare minimum flight tasks out by tomorrow! The GitHub repo still won’t be fully up-to-date until these structural bugs are figured out, but I plan to push the corrected scheduler files and mock drivers very soon. The screenshot below shows an image of the CRSF task completely dominating, without any processes interrupting it."}, {"post_id": 30245, "ts": "2026-07-17T17:45:35Z", "hours": 9.5911, "text": "I just wrapped up the core architecture of the drone’s flight controller, including mapping out all 7 interrupt methods into a far more optimized RTOS scheduler. The updated version makes use of a FIFO stack, to keep track of nested interrupts. I also protected the main code from data corruption during pendSV switches by enabling and disabling irq in certain areas of vulnerable code. Other small changes to the assembly to save floating point registers as well as better memory allocation was also done in this update. From high-speed IMU sensor integration and state estimation calculations to CRSF packet decoding and DShot motor generation, the essential tasks are fully written and compiled. I’ve officially shifted gears into the testing phase, working on simulated environments to debug DMA transfers, registers, and the flight state machine’s arming sequences. As of now, I am writing python scripts by hand, in order to inject “dummy” values into the GPIO, SPI, and USART registers in order to populate the buffers, and simulate the calculations. As the code is becoming longer and longer, I will try to refactor a lot of the files into smaller more organized portions, to increase readability (often I have a hard time traversing everything). Note: The current code pushed to GitHub isn’t quite the latest since I’m in the middle of troubleshooting a few simulation-specific register bugs, but I wanted to get this update out to meet the 10-hour devlog requirement on Stardance. Everything is moving in the right direction, and having a virtual environment all working means I can safely verify the PID mixer and safety flags before this code ever touches a physical quad. This officially marks the end of both phases 2 and 3, and now its a matter of finishing extra scheduled telemetry tasks (e.g. OSD and EdgeTX logging), but I estimate that the flight controller portion of the code (around 60% of all logic in the drone) will be done between now and Sunday, July 19th! I will also post a much more in depth devlog about how the methods work, as well as an updated README.md on Github ASAP."}, {"post_id": 28703, "ts": "2026-07-15T03:44:43Z", "hours": 1.4603, "text": "To make my hybrid RTOS accessible and easy to test, I designed a modular sandbox task registry system that isolates the core kernel from custom user code. Developers can write standard non-returning tasks in an isolated file ( User_Tasks/user_tasks.cpp ), while the kernel exposes a registration hook that allocates a dedicated 1024-word stack space. This decoupling means anyone can plug in their own cooperative or preemptive tasks, set execution periods or trigger bounds, and run them instantly on our virtual STM32F7 without risking memory corruption or touching the underlying context-switching assembly. For more information on how to make your own tasks refer to the README.md ."}, {"post_id": 28651, "ts": "2026-07-15T01:05:47Z", "hours": 1.0922, "text": "I just updated a few build files and restructured the project, so code and simulation separation would be better. I also added a few executable files (build.sh, run.bat, and run.sh) to easily compile and run the project."}, {"post_id": 28615, "ts": "2026-07-14T23:38:20Z", "hours": 5.5942, "text": "I finally reached a massive milestone with the kernel architecture and got the scheduler firing exactly how it needs to. Even though I thought the RTOS portion was completely wrapped up a bit ago, now it is officially done. I ended up doing a massive revamp on how scheduled tasks execute, routing them through PendSV so that the background worker states get completely backed up and saved by my assembly code just like the preemptive ones. I also cleaned up the initialization API by throwing in an overloaded function to separate timed loops from raw hardware events (the interrupt tasks). Overall most of the testing logic is now gone, and now the system is being more and more focused on the actual drone tasks. On the hardware side of things, I built out the actual drone tasks and the underlying SPI and UART DMA drivers that populate my local data packets. Even though they are not in use right now as all the tasks (which are not fully completed) require the support of each other for full testing. With the core OS completely checked off, the focus is shifting entirely over to the actual flight control logic. Over the next couple of days, I’m going to wrap up the final flight controller tasks, and get the core stabilization algorithms running. Once the flight controller application layer is fully put together, I’m moving straight onto building out complete simulations for the receiver, transmitter, and finally the ESC modules to get the whole drone network interacting together!"}, {"post_id": 27365, "ts": "2026-07-12T21:17:48Z", "hours": 3.8289, "text": "I finally finished the most difficult part of the project so far and got a hybrid cooperative/preemptive scheduler running from scratch. After a ton of debugging with the assembly memory layout, the core RTOS kernel shell is officially stable, verified inside the Renode simulator, and completely ready to handle flight data. The architecture divides the CPU’s brain into two execution pathways to maximize calculation speeds while keeping latency near zero. Standard background tasks, like handling low-priority peripheral updates, run sequentially inside a cooperative loop based on their relative priority. They execute and then drop out without wasting an overhead time. But for high-priority hardware event such as a critical radio packet arriving over UART or raw sensor data from the IMU, the system completely bypasses the standard queue. It pulls a physical hardware lever (PendSV) that forces an instant stack swap. When an interrupt task fires through PendSV, the CPU pauses the background scheduled loop, and my assembly code packs up the core registers, saves that exact memory address to RAM, and hot-swaps the Process Stack Pointer to launch the interrupt task. Right now, there is just a dummy delay loop inside the interrupt task to visually show the execution break in the console logs. Once it finishes printing, it hits a yield function that throws the assembly switch backward, pops the background registers, and hands control straight back to the flight loop. The repository currenly has a lot of diagnostic test code because I needed to prove the pointer indirection and stack-faking logic worked without blowing up the memory alignment. Now that the plumbing is completely verified, the next step is to strip out the test code and start writing the actual flight infrastructure. I am moving straight into coding the PID control loops, signal mixers, Kalman filters, and live motor generation."}, {"post_id": 26996, "ts": "2026-07-12T03:54:25Z", "hours": 2.8228, "text": "I finally added minimum task scheduling for the RTOS. I had originally designed a simple kernel to create a buffer of scheduled tasks in QEMU, but after learning that the simulation didn’t actually support the specific MCU that my friend and I are using for the real drone, I had to pivot. I switched over to using STM32CubeMX for the actual bare-metal configuration and Renode to handle running the emulation. Right now, the kernel just executes a task based on a basic timing loop and priority, waits for it to completely finish, and then moves on to the next task. To be honest, it isn’t super useful yet because it only covers tasks in what I call the “scheduled zone” of the drone. This includes background stuff like blackbox flight data management, but it leaves out the most critical parts like the PID control loops and streaming real-time UART data from the IMU. Those features need to fire their own asynchronous interrupt signals at the highest possible hardware priority so they can instantly pause the optional background tasks and execute the critical code that actually keeps the drone stable and flying. Next up, I need to write a short piece of assembly to handle saving the current CPU state and registers of whatever task is currently running when an interrupt hits. It shouldn’t be too bad since it will only take about 30 lines of code. I know I haven’t been posting devlogs for the past couple of weeks even though I’ve been grinding on this, but that’s mostly because we spent a ton of time initially planning out the architecture of the drone. We wanted to map out the software boundaries early so my friend and I could go our separate ways working on different systems without having massive merge conflicts later on."}]...
|
Title: 200 MPH Drone RTOS by @Guagyyy | Stardance
Title: 200 MPH Drone RTOS by @Guagyyy | Stardance
Devlogs:
I finally added minimum task scheduling for the RTOS. I had originally designed a simple kernel to create a buffer of scheduled tasks in QEMU, but after learning that the simulation didn’t actually support the specific MCU that my friend and I are using for the real drone, I had to pivot. I switched over to using STM32CubeMX for the actual bare-metal configuration and Renode to handle running the emulation. Right now, the kernel just executes a task based on a basic timing loop and priority, waits for it to completely finish, and then moves on to the next task. To be honest, it isn’t super useful yet because it only covers tasks in what I call the “scheduled zone” of the drone. This includes background stuff like blackbox flight data management, but it leaves out the most critical parts like the PID control loops and streaming real-time UART data from the IMU. Those features need to fire their own asynchronous interrupt signals at the highest possible hardware priority so they can instantly pause the optional background tasks and execute the critical code that actually keeps the drone stable and flying. Next up, I need to write a short piece of assembly to handle saving the current CPU state and registers of whatever task is currently running when an interrupt hits. It shouldn’t be too bad since it will only take about 30 lines of code. I know I haven’t been posting devlogs for the past couple of weeks even though I’ve been grinding on this, but that’s mostly because we spent a ton of time initially planning out the architecture of the drone. We wanted to map out the software boundaries early so my friend and I could go our separate ways working on different systems without having massive merge conflicts later on.
I finally finished the most difficult part of the project so far and got a hybrid cooperative/preemptive scheduler running from scratch. After a ton of debugging with the assembly memory layout, the core RTOS kernel shell is officially stable, verified inside the Renode simulator, and completely ready to handle flight data. The architecture divides the CPU’s brain into two execution pathways to maximize calculation speeds while keeping latency near zero. Standard background tasks, like handling low-priority peripheral updates, run sequentially inside a cooperative loop based on their relative priority. They execute and then drop out without wasting an overhead time. But for high-priority hardware event such as a critical radio packet arriving over UART or raw sensor data from the IMU, the system completely bypasses the standard queue. It pulls a physical hardware lever (PendSV) that forces an instant stack swap. When an interrupt task fires through PendSV, the CPU pauses the background scheduled loop, and my assembly code packs up the core registers, saves that exact memory address to RAM, and hot-swaps the Process Stack Pointer to launch the interrupt task. Right now, there is just a dummy delay loop inside the interrupt task to visually show the execution break in the console logs. Once it finishes printing, it hits a yield function that throws the assembly switch backward, pops the background registers, and hands control straight back to the flight loop. The repository currenly has a lot of diagnostic test code because I needed to prove the pointer indirection and stack-faking logic worked without blowing up the memory alignment. Now that the plumbing is completely verified, the next step is to strip out the test code and start writing the actual flight infrastructure. I am moving straight into coding the PID control loops, signal mixers, Kalman filters, and live motor generation.
I finally reached a massive milestone with the kernel architecture and got the scheduler firing exactly how it needs to. Even though I thought the RTOS portion was completely wrapped up a bit ago, now it is officially done. I ended up doing a massive revamp on how scheduled tasks execute, routing them through PendSV so that the background worker states get completely backed up and saved by my assembly code just like the preemptive ones. I also cleaned up the initialization API by throwing in an overloaded function to separate timed loops from raw hardware events (the interrupt tasks). Overall most of the testing logic is now gone, and now the system is being more and more focused on the actual drone tasks. On the hardware side of things, I built out the actual drone tasks and the underlying SPI and UART DMA drivers that populate my local data packets. Even though they are not in use right now as all the tasks (which are not fully completed) require the support of each other for full testing. With the core OS completely checked off, the focus is shifting entirely over to the actual flight control logic. Over the next couple of days, I’m going to wrap up the final flight controller tasks, and get the core stabilization algorithms running. Once the flight controller application layer is fully put together, I’m moving straight onto building out complete simulations for the receiver, transmitter, and finally the ESC modules to get the whole drone network interacting together!
I just updated a few build files and restructured the project, so code and simulation separation would be better. I also added a few executable files (build.sh, run.bat, and run.sh) to easily compile and run the project.
To make my hybrid RTOS accessible and easy to test, I designed a modular sandbox task registry system that isolates the core kernel from custom user code. Developers can write standard non-returning tasks in an isolated file ( User_Tasks/user_tasks.cpp ), while the kernel exposes a registration hook that allocates a dedicated 1024-word stack space. This decoupling means anyone can plug in their own cooperative or preemptive tasks, set execution periods or trigger bounds, and run them instantly on our virtual STM32F7 without risking memory corruption or touching the underlying context-switching assembly. For more information on how to make your own tasks refer to the README.md .
I just wrapped up the core architecture of the drone’s flight controller, including mapping out all 7 interrupt methods into a far more optimized RTOS scheduler. The updated version makes use of a FIFO stack, to keep track of nested interrupts. I also protected the main code from data corruption during pendSV switches by enabling and disabling irq in certain areas of vulnerable code. Other small changes to the assembly to save floating point registers as well as better memory allocation was also done in this update. From high-speed IMU sensor integration and state estimation calculations to CRSF packet decoding and DShot motor generation, the essential tasks are fully written and compiled. I’ve officially shifted gears into the testing phase, working on simulated environments to debug DMA transfers, registers, and the flight state machine’s arming sequences. As of now, I am writing python scripts by hand, in order to inject “dummy” values into the GPIO, SPI, and USART registers in order to populate the buffers, and simulate the calculations. As the code is becoming longer and longer, I will try to refactor a lot of the files into smaller more organized portions, to increase readability (often I have a hard time traversing everything). Note: The current code pushed to GitHub isn’t quite the latest since I’m in the middle of troubleshooting a few simulation-specific register bugs, but I wanted to get this update out to meet the 10-hour devlog requirement on Stardance. Everything is moving in the right direction, and having a virtual environment all working means I can safely verify the PID mixer and safety flags before this code ever touches a physical quad. This officially marks the end of both phases 2 and 3, and now its a matter of finishing extra scheduled telemetry tasks (e.g. OSD and EdgeTX logging), but I estimate that the flight controller portion of the code (around 60% of all logic in the drone) will be done between now and Sunday, July 19th! I will also post a much more in depth devlog about how the methods work, as well as an updated README.md on Github ASAP.
I’ve been doing a lot of debugging for the RTOS scheduler inside the simulation environment, and it’s been very difficult for me to identify many bugs in teh core architecture of my tasks. Moving away from Python scripts to a cleaner C++ conditional compilation framework using CMake was supposed to simplify things, but instead, it exposed some nasty architectural bugs in how tasks and context switching interact. There has also been a massive priority inversion and preemption lockup where the CRSF parsing loop completely starves out the lower-priority threads. Also, running a raw sensor calibration loop at boot was forcing thread switches before the OS kernel was even fully initialized, completely corrupting task indexes, throwing null pointer warnings, and leaving half of my PID calculations at zero. Still working on many fixes, but it has been a lot of work (9 hours), but I hope to get the full RTOS with at least bare minimum flight tasks out by tomorrow! The GitHub repo still won’t be fully up-to-date until these structural bugs are figured out, but I plan to push the corrected scheduler files and mock drivers very soon. The screenshot below shows an image of the CRSF task completely dominating, without any processes interrupting it.
I’ve spent the last 20 hours of coding basically staring at bare-metal memory allocations and tracking down why the drone’s context switcher was triggering CPU drops under the Renode simulation environment. Moving away from manual Python injection scripts to a cleaner C++ conditional compilation framework using CMake was supposed to simplify the testing layout, but instead, it exposed structural design flaws in how the scheduler kernel boots up. Running a multi-sample sensorCalibration() routine at cold boot was forcing hidden task yields before the OS kernel was fully mapped out, which was throwing unmapped register address errors and wiping out index-0 entries. To solve this, I decoupled the entire state machine sequence so that hardware allocations, peripheral registers, and core tracking counters now clear before any operational loops drop into the registry. I also added a critical rtosStarted gatekeeper flag to yieldCurrentTask() so calibration math runs cleanly in sequence without triggering early PendSV handler switches. On top of that, the task stack pointers are completely realigned. The assembly context swapper now maps a precise 32-word boundary allocation utilizing 0xFFFFFFFD as a basic exception return code, which completely eliminates the data corruption that was misaligning our Process Stack Pointer. With the fundamental kernel stabilized, I shifted entirely into clean architecture organization. The massive, cluttered code blocks have been split up into independent tracking files (BufferPopulation.cpp, Tasks.cpp, and SimInjector.cpp). High-speed SPI reads for the IMU, UART ring buffers for decoding CRSF radio channel frames, battery ADC sampling, and DShot600 motor output mixers are now fully broken out and functional. There is still a nagging preemption lockout issue inside the simulator where a single interrupt task attempts to starve out the other concurrent loops during a millisecond window, but the baseline operating system is locked in, meaning I can confidently verify the PID flight mixing tables and safety code blocks safely before the code ever touches a physical quadcopter. If you would like to run your own tasks, I also added support in the .bat and .sh files to build code for the simulation (flag=sim), user task code (flag=user), and actual drone upload code (no flags). Example MacOS Commands: ./build.sh sim ./build.sh user ./build.sh This makes it so that I don’t have to constantly modify code to run either the user tasks or simulation code, instead using a flag. Overall, this RTOS is not done yet, however, I plan to add the rest of the scheduled tasks later today, and fixing the sole bug keeping this simulation back! I expect a full ship to be comming out in the next week or so, along with all ESC, RM, and TM code complete!
I just finished expanding the RTOS architecture, filling out all of the scheduled background tasks to handle real-time flight telemetry, peripheral hardware, and terminal configuration. On the telemetry side, I built out telemetryTX to package battery, status, and GPS data into standard CRSF frames over UART, alongside an NMEA gpsParser that decodes $GNGGA and $GNRMC sentences for live location fixes. I also made powerManagement into its own standalone task so ADC voltage and current metrics can feed into the failsafe logic and telemetry concurrently. To make bench testing and tuning significantly easier, I added usbCLI over USART1, giving me a full interactive shell to tweak PID gains (Kp, Ki, Kd), dump raw IMU data, and inspect hardware states on the fly without needing to reflash firmware. To keep the physical quad safe and responsive during flight, I added updatePeripherals for LED status patterns and buzzer warnings, along with a dedicated Independent Watchdog (IWDG) task running as a low-priority fail-safe to trigger hardware MCU resets if the scheduler ever freezes. On the project structure side, CMake now routes all output binaries straight into a clean ./bin/ directory so nobody has to compile the source manually just to run the .elf target in Renode. I also introduced a -DENABLE_DEBUG flag, allowing me to cleanly toggle between complete USART log prints across every loop or a blank terminal environment meant purely for the CLI shell. While all the background subsystems and scheduled task priorities are fully mapped out, I’m currently figuring out a few lingering RTOS bugs—specifically around stack allocation, causing stack overflow flags on certain scheduled tasks, along with scheduling starvation where context switching isn’t releasing task blocks properly. Because I want to ensure the scheduler kernel is 100% complete before pushing broken stack frames to the main branch, the GitHub repository will be updated with the complete, bug-fixed code later today. Everything is moving in the right direction, and getting these background tasks finalized brings me one step closer to full flight hardware deployment!
1. Fixing the Stack Overflows at Boot After an entire 25-hour debugging period across 4 days, the RTOS kernel is finally done (for the scheduled tasks). I tracked down a silent bug where several critical scheduled tasks—like powerManagement , lowLevelFailSafe , and telemetryTX —were crashing the MCU on boot. The issue came down to a boot-time dependency lock: tasks were trying to poll hardware registers (like UART TX flags) and read shared drone state variables before the peripherals or producer tasks had time to initialize on Tick 0. By adding an initial yieldCurrentTask() right at the top of these methods, Task Phase Alignment was officially added. This gives the hardware a full cycle to stabilize, preventing buffer overflows and eliminating the cascading task state corruptions that were locking up the scheduler. 2. Custom Stack Sizing & Real-Time Guard Checks Alongside the scheduler fix, I pushed major upgrades to memory safety and task management. Instead of assigning a static stack array to every task, I transitioned to dynamic per-task stack allocations during initialization ( new (std::nothrow) ). Heavy string-parsing and math tasks get larger stacks, while simple toggle tasks stay lightweight. To catch memory issues before they corrupt the heap, I implemented a custom dual guarding system: 0xDEADBEEF is appended at the bottom of the stack to catch standard stack overflows, while a new 0xBEEFCAFE canary value is written to the very top index ( stackSizeWords ) to instantly flag memory breaches in the SysTick_Handler . Furthermore, I refactored powerManagement to use ADC2 in Circular DMA Mode, writing battery telemetry directly to RAM in the background for zero CPU overhead. 3. Transitioning to Walksnail Avatar HD Looking ahead, my and my friend are officially transitioning our existing analog video setup over to a fully integrated Walksnail Avatar HD digital ecosystem. Rather than keeping my custom telemetry task ( telemetryTX ) with heavy string formatting over raw UART, Walksnail allows me to stream standard MSP (MultiWii Serial Protocol) DisplayPort frames straight to the VTX. The Walksnail system will serve as our primary onboard logging source, giving us full OSD telemetry, high-framerate HD video, and precise blackbox data logging. With the RTOS core now stable and non-blocking, our next focus shifts toward “premium” flight controller features, e.g. including custom RC stick expo curves, an expanded USB CLI, and an integrated simulator interface.
Over the last few days, I wrapped up two major tasks for the flight controller’s core sensor and telemetry stack: the on-screen display (OSD) renderer and the BMP390 barometer subsystem. The OSD engine is now fully hooked up to the state system, giving real-time visual downlinks for critical metrics like flight battery voltage, active flight modes, and height statistics over UART. To keep the execution completely non-blocking, all frame updates are dispatched asynchronously, preventing rendering delays from hindering the performance of the high-frequency control loops. On the barometer side, I implemented altitude tracking using Bosch’s BMP390 sensor over SPI with non-blocking DMA burst transfers. In the 50Hz task loop, incoming 24-bit raw pressure and temperature bytes are assembled and passed through the hypsometric formula to calculate smooth, relative height above ground level (AGL). Although the barometer task is a bit flawed due to floating point register stack errors with the header and end canary values, they don’t seem to be affecting the system in anyway (nor is any data being corrupted). I will find a way to fix these issues before the next commit, as well as the race condition in the interrupt tasks in the next Github commit. After that, it is just system polish and extensive testing before the RTOS will be complete!
Major Architecture Upgrade : OSD, Betaflight Rates & Build System Refactor 1. OSD, DMA + SYS First off on the hardware side, I added native MSP-based OSD support for Walksnail video transmitters, built the SPI barometer driver for altitude tracking, and spun up a low-level health task that constantly monitors MPU registers and stack usage in the background. On top of that, I finally fixed the DMA stream conflicts (mainly in STMCubeMX) between TIM1 DShot motor outputs , ADC1, and SPI peripherals, so everything runs without collisions now. 2. SYS Health + Debugging I also implemented a few other low level tasks, allowing me to monitor system health, based upon ram usage and storage used. This task prints out the amount at which each tasks stack is being used, allowing me to effectively debug whether a task was actually overflowing, vs an unrestricted read/write. Furthermore, the original canary values that I used, were completely replaced as they in fact were causing some of the “stack overflow” bugs (via unrestricted reads/write every 1 ms in SysTick_Handler ). 3. Betaflight Rates + CLI Update For flight feel, I implemented Betaflight’s Actual Rates algorithm with custom expo curves, so stick inputs map to target angular velocities with center-stick precision. I also completely separated serial communications by moving the interactive CLI to USART1 (accessible via nc -C localhost 1234 in terminal) and pushing system logs to USART3. Additionally, I removed the old telemetryTX task because its unauthorized reads/writes were completely breaking the RTOS scheduler, and expanded the CLI with a ton of commands for live sensor readings and more PID tuning. Speaking of which, I am planning to create a persistent file in /bin/ , allowing for rates to be stored between runs, rather than being reset each during runtime, and having to be manually configured through the CLI. 4. Overhauled Building Workflow Finally, I overhauled the whole developer workflow and build automation setup. The build.sh and build.bat scripts now auto-configure custom CMake profiles and generate a full disassembly file in /bin/ after every build for fast low-level debugging, while run.sh and run.bat automatically launch the right terminal windows on launch. 5. Future Additions: I’m planning to build a closed-loop Renode simulation matrix to stream hardware data into every peripheral externally, letting me run 100% real production code during SIL testing! For this, I will utilize the currently blank simulate.py as well as certain commands in simulate.resc to create properly formatted dynamic buffers(which are not directly injected into the code), allowing me to properly test the DMA drivers, and many of the memory management helpers.
This week was heavily focused on the fine tuning and organization of the RTOS. I spent numerous hours of research and untangling environment setups. I originally tried to build out a complete framework for the drone code without relying on any simulation code, but Renode’s restrictions, specifically with its ability to perform DMA requests, quickly made it clear that path was impossible. To fix this I’m looking into picking up a dev board and a Raspberry Pi so I can test and debug everything on an actual MCU before finally moving the codebase over to the drone. Even though the git won’t look a whole lot different and not a lot of actual code changed, getting these configs finalized (especially in STM32CubeMX) in was a huge step forward for the project. I expect to commit the next version of the code either today or tomorrow, with improvements specifically in TelemetryTX, BlackBoxLogging, and a few other minor changes!
1. Reworking the DMA Flow for Speed So, a lot has been going on lately, starting with a massive rework of the entire DMA flow. The functions are now entirely populated by circular DMA, which is a huge upgrade for the system’s overall performance. This architectural change allows for completely non-blocking, high-frequency calls, hitting response times as fast as 0.03 milliseconds. It basically means the whole data pipeline is significantly faster, and much more responsive than it was in previous versions. 2. Standardizing Ring Buffers and Mock Injectors To make everything more reliable, the DMA now follows a very specific and predictable pattern for both scheduled and interrupt tasks. Everything relies on ring buffers now, whether they are being injected by actual hardware (or simulated) DMA or by my custom simulation scripts. I also reworked the mock injectors so they no longer just return a pre-formatted packet. Instead, they write directly into the ring buffer, which lets me test the exact same parsing pipeline in software, simulating the hardware flow almost exactly like Renode (if only they would ever fix that USART DMA bug…). 3. Assembly BX LR Bug + STMCubeMX Clock PLL I also finally solved the long term BX LR return bug that I literally spent over 20 hours trying to find. Whenever tasks used the FPU or had slightly larger stacks, the return address in the r0 register would just get completely corrupted by the extra data. I fixed this by storing the return address in a dedicated uint value instead of blindly trusting the registers to hold it. That fix alone allowed me to safely re-add telemetryTX and make a bunch of other function logic much more robust. On top of that, I went into STM32CubeMX and reworked the clock PLL manually (it took over 3 hours to solve by hand). By feeding in a 25 MHz HSE clock, I managed to unlock the MCU’s internal clocks to run at their full 216 MHz.I also took some time to clean up the codebase to improve overall readability and commenting. 4. DMA Interrupts for Safe Parsing Another feature is that DMA now triggers interrupts when the ring buffers hit exactly halfway and when they are fully populated. This gives me the time to parse all the incoming values safely without having the risk about data getting overwritten by the next DMA pass before I am done reading it. I set up the IRQ handlers in the code to call the interrupt methods automatically, which ensures the CPU stays completely unblocked and free to handle other flight control tasks almost all the time (overall decreasing headroom). 5. Current Status: NVIC Bug Sadly, the code is actually not functional right now because the NVIC and IRQ pipeline is malfunctioning and just refusing to call the interrupts for reasons I cannot figure out yet. Because of this, I am holding off on pushing the code until I can track down the bug, give everything a final polish, and run some benchmark testing (since I don’t want to commit broken code). Also, sorry for promising a commit a day or two after my last devlog. I got super busy, especially with vacation, but I will try my best to get this sorted. Depending on how long it takes to figure out this NVIC issue, the next commit might drop anywhere from tomorrow to a few weeks from now.
Complete RTOS Overhaul, Circular DMA Pipelines, and CPU Abort Fixes This update focuses on fine-tuning the RTOS, organizing the scheduler, and rewriting microcontroller memory handling. Renode’s simulated DMA restrictions make software-only pipeline testing nearly impossible, so I plan to buy a physical dev board and Raspberry Pi to validate on silicon. While the Git diff might not look massive, the architecture has evolved from a blocking system to a true preemptive RTOS with precise polynomial timing. 1. Reworking DMA Flow & Standardizing Ring Buffers Sensor and receiver data pipelines are now driven by circular DMA, enabling non-blocking, high-frequency transfers with response times as fast as 0.3 ms (without printToUSART enabled). Everything now relies on ring buffers. Instead of generating complete packets instantly, mock injectors stream bytes directly into the buffers while updating the simulated NDTR register to mirror hardware behavior. if ( byteIdx >= frameLen ) { byteIdx = 0 ; } crsfRingBuffer [ head ] = frameBuf [ byteIdx ++ ]; head = ( head + 1 ) % CRSF_RING_BUFFER_SIZE ; currentBoardConfig . crsf_dma_stream -> NDTR = CRSF_RING_BUFFER_SIZE - head ; Feeding bytes incrementally moves the write head gradually, ensuring the simulation mimics a physical UART and allowing population functions to safely pull data within interrupt locks. 2. DMA Interrupts for Safe Parsing To prevent data overwrites, DMA streams trigger interrupts at the halfway (HTIE) and full-transfer (TCIE) points to queue tasks. Because registers like LISR are read-only in hardware, I implemented a software mock flag system (mock_LISR) for simulation: extern "C" void DMA1_Stream0_IRQHandler ( void ) { #ifdef SIMULATION uint32_t flags = mock_LISR ; mock_LISR = 0 ; #else uint32_t flags = DMA1 -> LISR ; #endif if ( flags & DMA_LISR_HTIF0 ) { DMA1 -> LIFCR = DMA_LIFCR_CHTIF0 ; decideNextInterruptTask ( & taskControlBlocks [ 1 ]); } } Functions safely extract data with interrupts disabled, ensuring the CPU never blocks waiting for peripheral transfers. 3. Assembly Bugs & CPU Aborts Debugging nested hardware interrupts exposed massive faults: The context-switching bug: FPU usage or large stack frames corrupted the return address, causing the CPU to execute BX LR with garbage data. Fixed in PendSV_Handler.S by explicitly storing excReturn inside the TaskControlBlock rather than relying on stacked registers. Second, a 0x00000000 Null Return Crash: Scheduled tasks attempted to return natively, popping 0x00000000 from the zero-initialized Link Register and causing a fetch fault. Every task now runs inside an infinite while(true) loop calling yieldCurrentTask() . 4. Clock PLLs & Hardware Re-routing After configuring the STM32CubeMX PLL for a 25 MHz HSE clock, the MCU runs at its full 216 MHz. I added a standardized initSystemGPIOClocks() function to enable peripheral clocks consistently. I also moved motor 3 from TIM1 to TIM4, synchronizing it with the 216MHz clock and freeing up a TIM1 DMA stream exclusively for the upcoming BlackBox logging. Future Updates With the core RTOS stabilized, development shifts to flight-facing systems: hooking the SPI pipeline to the video overlay for live OSD goggle telemetry, adding permanent flash storage for PID tunes/configs, exposing MCU controls via CLI, supporting programmable transmitter bind buttons, building a desktop GUI, and using the freed TIM1 DMA for BlackBox logging. Below, I have attached a screenshot of every single task working, and outputting values in the simulation, something that wasn’t possible for the interrupt tasks until now.
1. CLI Upgrades and Channel Mapping Over the past 5 days, I knocked out some major quality-of-life upgrades for the flight controller. I added customizable channel mapping for CRSF directly through the CLI. By utilizing a combination of references and pointers, I was able to point a volatile alias to certain channel mappings, allowing for completely customizable CRSF channels. While I was in the CLI logic, I also added the ability to configure custom IMU orientations around the z-axis, making it way easier to mount the board in different directions without having to recompile the firmware. 2. DMA Pipeline Fixes and Baro Optimization A big chunk of this session went into debugging and refactoring the hardware data pipelines. I adjusted the ADC population pipeline in order to fix some stream parsing issues, and gave the barometer a massive overhaul. The baro now uses a non-blocking, non-circular DMA setup that relies on a semi-interrupt-driven task call rather than a continuous loop. This enabled me to yield in the middle of the function, and call back later as soon as DMA is finished transferring. I also fixed a massive bug in the DMA setup: the DMA_SxCR_HTIE and DMA_SxCR_TCIE flags were accidentally enabled for the GPS and OSD ring buffers, which would have crashed the whole RTOS by firing unhandled interrupts, causing default HAL and IRQ handlers to run. 3. Walksnail Two-Way Communication Finally, I built out the respondToVTX task to get the drone properly communicating with the Walksnail VTX. Instead of just blindly sending video data out, this sets up true two-way communication over asynchronous UART. By writing a persistent byte-by-byte state machine, the flight controller can now safely parse incoming requests from the VTX without dropping half-packets, allowing me to send back live stick positions and armed status for the OSD menus. The only thing left to do now is handle persistent CLI storage, the logToBlackBox task, integrating the semi-interrupt pipeline with telemetryTX and the OSD, and a few other system tweaks. After that the RTOS will be 100% ready to fly the actual drone.
1. Scheduler Hardening and Task Discovery Spent part of this session making the RTOS scheduler itself more robust. I added a findTaskByName() function so interrupt-driven task lookups happen dynamically instead of relying on hardcoded task indices, which was a fragile setup just waiting to break the moment task registration order changed. Alongside that, I wrapped every one of those lookups with lambdas that throw a proper warning if a task can’t be found, so a missing task fails loudly instead of silently dereferencing a null pointer somewhere downstream. 2. Blocking vs Non-Blocking Scheduled Tasks After a lot of painful debugging, I traced a string of issues (including interrupt tasks silently failing to fire and scheduled tasks stepping on each other) back to non-blocking statements I’d introduced inside scheduled tasks in the previous devlog. I ended up taking those out and reverting scheduled tasks fully back to blocking, which is genuinely what the scheduled zone was designed for in the first place: tasks that don’t need to run in polynomial time and can safely block without putting the drone at risk of crashing. Once that was sorted, I converted the raw USART byte-pushing into a blocking DMA system instead, so streaming is handled by DMA hardware rather than manually pushed byte-by-byte over USART. 3. Flight Loop Refactor and VTX Communication On the flight logic side, I refactored flightLoop() to use lambdas and a state machine so I would never have to yield in the middle of my tasks (which was used previousely for zeroing motor outputs). I also converted the error handling into a proper state machine, so different types of warnings can be caught and handled distinctly instead of lumping every issue into one path, and turned on full debug printing whenever the system is running. Last but not least, I built out a dedicated injector for respondToVTX so I can properly test and simulate VTX communication going forward. 4. Real Hardware Testing Since, I am almost 100% done with the RTOS I bought two NUCLEO-F756ZG’s which will serve as testing the 100% production code rather than the simulation version. I bought two so that one of the boards will be running the real RTOS code, testing DMA reading from USART, SPI, and emitting real motor signals, while the second will be emulating all of my peripherals. When the boards come, if the code does work, it will also mean that the real PCB’s will also work when my friend finishes with them. 5. Next Steps As of now there are a few issues with the double preempt system (for the interrupt tasks) I designed a while back, so I will need to debug that before they arrive. Right now before the boards arrive, I will be finishing up the RTOS blocking DMA pipelines (stripping out IRQ, removing NVIC etc. for scheduled tasks), and performing a bunch of baseline testing in order to prove that the RTOS is capable of flying an actual drone!
For the past couple weeks I have been mostly refining small bugs, which were originally rendering the RTOS usless, as well as refactoring the code for simplicity rather than elegancy. 1. Transition to Actual Hardware Renode is great for simulation, but it ended up hiding a bunch of race conditions in the population methods and the main scheduler that led to no code actually running during the IRQ handler calls. I spent a lot of time securing those resources and finally got the scheduler mostly finished up. Also, I decided to just take out the double preempts entirely since they were adding way too much complexity for absolutely zero speed benefits in practice (plus they were creating detrimental but rare race conditions). 2. Code Refactor To make things run a bit more consistent, I restructured how the control loops operate. I ended up merging the dShotGeneration task with the parent IMU control loop, so now everything from reading the sensors to pushing motor commands happens in one clean sequence (rather than including an unnecessary preempt). I also built out a brand new CRSF control loop to handle all the radio parsing and state machine updates in its own dedicated space (just for consistency). Lastly, while doing a final pass on the code, I realized that in my dShotGeneration helper, I had forgot to scale the values by a factor of 1/2000, as the inputs require the value to be between 0 and 1 (not 0 and 2000). 3. Final DMA Iteration The biggest relief was finally getting rid of the old blocking USART system. I finally transitioned away from manually handling the streaming by polling flags in a loop, which was tying up the processor way more than it should have. Everything has been converted over to a blocking DMA system, so the hardware can just handle all the memory transfers in the background while the CPU focuses on actually keeping the drone in the air. Overall, I think that this will be the final iteration of the RTOS DMA pipeline, as now that it is solid and works with all the edge cases, theres no need to change it. 4. Timeline With almost all the major bugs fixed, I am going to ship the project! While it is not 100% done, it will likely be as close as it will get during the timeframe of the Stardance hackathon, and with it so close, theres no reason not to ship. Anyway, I will keep the source as the main project rather than a release, so if I do end up fixing any major bugs, they will get patched either before or during project review (besides most of these bugs are only detectable on actual hardware). I will most likely finish the RTOS in the next couple weeks (by the end of October), and will finish the drivers for the ESC and RM by latest end of November (for more timing refer to the README). Thanks to everyone who supported me throughout this project (hopefully me and my friend can get this drone flying in another Hack Club Hackathon!).
Although I haven’t been able to make much progress on the project due to school over the past weeks I did manage to make some substantial project mostly with the scheduler, allowing for fairly good performance on my STM Nucleo boards, rather than it just crashing instantly. 1. Issues with the Old Design The flight controller’s RTOS scheduler wasn’t working under real hardware timing because global variables like currTaskIndex, topOfStack, and excReturn were being modified from multiple entry points simultaneously. Yield calls, interrupt handlers, and the main task-selection logic were all making independent writes to the same shared task control blocks. Whenever a hardware interrupt fired mid-write, stack pointers and exception return values were saved into the wrong taskControlBlocks slot. This created edge cases where preempted tasks were silently double-queued, state tracking completely desynchronized, and time-critical hardware events were dropped during flight. 2. Centralizing Context Switches in PendSV To eliminate these race conditions, all state-selection decisions were moved out of individual execution contexts and consolidated into decideNextTask(), which now runs exclusively inside the PendSV assembly handler. Functions like yieldCurrentTask(), decideNextInterruptTask(), and decideNextScheduledTask() no longer touch global scheduler state or choose which task runs next; they simply update local status flags like TaskState::BLOCKED or TaskState::READY inside brief __disable_irq() critical sections and trigger PendSV using SCB_ICSR_PENDSVSET_Msk. When PendSV fires, decideNextTask() saves outgoingSP and outgoingExcReturn to the active block, sets RUNNING tasks to READY, and runs a two-pass check over taskControlBlocks[]—evaluating high-priority TaskType::INTERRUPT tasks first, then TaskType::SCHEDULED tasks, and falling back to index 0 for idle. Since PendSV is the only place allowed to modify currTaskIndex, concurrent state corruption is structurally impossible.
Ships:
Phase 1 (The Custom RTOS Kernel) I am building a custom FPV drone from scratch with my friend in an attempt to achieve 200 mph . At those speeds, standard super loops are far too slow, as a single microsecond of lag means the drone travels feet before making a PID correction. To solve this, I built a custom, hybrid cooperative/preemptive Real-Time Operating System (RTOS) from scratch for the ARM Cortex-M7 (STM32F7)! What Was Challenging? The absolute hardest part of this phase was writing the low-level assembly context switcher ( PendSV_Handler.S ). Hacking the ARM Cortex-M7 registers to physically hot-swap stack pointers ( PSP ) mid-execution without crashing the CPU or corrupting the program state was a massive headache. I had to ensure that when an asynchronous preemption event fires, the assembly code perfectly preserves the execution registers ( R4-R11 plus the hardware-stacked registers), jumps to the high-priority task, and then seamlessly restores the background task right where it left off. Getting the compiler-enforced task overloading working so the kernel cleanly separates periodic tasks from raw interrupts was another huge hurdle, but it makes the whole codebase infinitely more robust. Want to Test It or Write Your Own Tasks? You don’t need physical hardware to watch this run! I’ve packaged the entire project with a Renode simulation script. You can run the interactive emulator with a single command to see the preemption scheduler hijack our counter task live, or you can jump into the user sandbox file and write your own custom tasks. Check out the GitHub Repository to Run the Demo! The README has a quick 5-minute setup guide to get you compiling and simulating your own code in no time.
200 MPH Drone RTOS: How it went Simulation to Silicon! When I published the first major update for this project at the 15-hour mark, I essentially had a proof-of-concept. I had managed to write a custom hybrid cooperative/preemptive scheduler and get an ARM Cortex-M7 (on the STM32f756VGTx) assembly context switcher functioning inside the Renode simulator. Although this looked like a massive leap, the project had barely started. Over 100 hours of development have gone into this project since then. The transition from a simulated kernel to a bare-metal flight controller capable of keeping a 200 MPH drone in the air required stripping the system down to its bare components, rewriting the memory architecture, and debugging some of the most frustrating hardware faults I have ever encountered-especially whenever the project just crashed, leaving me no traces as to what went wrong. Software Limitations The biggest turning point was realizing that software simulation can only take you so far. Renode is an amazing tool, but it hid a massive amount of race conditions and timing flaws that only exposed themselves when I finally flashed the code to physical STM32F756 Nucleo board. Sometimes, the MCU would have to reboot every 2 seconds. I spent dozens of hours tracking down massive architectural bugs. One of the worst was a context-switching fault where floating-point math was corrupting the return address in the CPU registers, causing the processor to execute raw garbage data. To fix this, I had to completely restructure the boot sequence and overhaul the memory management. I moved away from static arrays to a dynamic per-task stack allocation system, and implemented a dual-guard memory system. Arguably, this was the most important change as it allowed me to debug tasks way quicker as I instantly could know when the canary values were corrupted. Overhauling the Data Pipelines In order to avoid the 10ms delay of my original blocking pipline (for data transfer), I entirely rewrote the hardware data pipelines multiple times to use a semi-blocking, circular Direct Memory Access (DMA) architecture. Instead of the processor handling the data transfer, the hardware itself moves the bytes from the sensors directly into memory in the background. The DMA streams now trigger precise interrupts at the halfway and full-transfer points, allowing the RTOS to safely parse incoming radio packets and sensor reads without ever risking data overwrites or blocking the main flight loop. Building a Flight Controller I integrated Betaflight’s Actual Rates algorithm with custom expo curves, ensuring that physical stick inputs map perfectly to target velocities. I built a custom SPI driver to pull 24-bit raw pressure and temperature data from a BMP390 barometer, passing it through hypsometric formulas to calculate altitude. For video and telemetry, I moved away from raw UART strings and implemented native MSP DisplayPort communication (for true digital Walksnail Avatar connection). I also built an interactive USB command-line interface. Instead of having to recompile and re-flash the firmware every time a PID value needs to be adjusted, I can plug into the board, pull up a terminal, and manually tune gains, remap CRSF radio channels, or adjust IMU orientation offsets in real time. Final Version The last few weeks have been about refinement and consistency, removing race conditions and overall polishing the code. Now that the RTOS is fully functional, the only things to add are extra features, like a permanent + more expanded CLI, as well as finishing the external RM and linking the ESC drivers. As these are pretty insignificant, I have linked the source of this shipment to the Github project rather than a specific release so that I can update these during review!...
|
1792842857.8059814
|
1792929257.8059814
|
|
5322
|
Kopuz by @temidaradev | Stardance
|
temidaradev
|
5
|
139.0
|
2306
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-14T16:31:49Z", "hours": 29.0, "multiplier": 19.98, "payout": 572, "blessing": "neutral", "text": "Two parts of the player stop lying to you: Recently Added lists what you actually added, and shuffle and repeat go dark when you switch them off. Apple Music takes any storefront, and Kopuz is now EUPL-1.2. Highlights Recently Added means recently added. The row was the alphabetical album list read backwards, so it showed the tail of your alphabet forever. Albums now rank by when their music arrived, stamped per file from the filesystem while the library is scanned, and the library’s own date added sort reads the same stamp. Rescan once after upgrading to fill it in. Shuffle and repeat clear their highlight. Dioxus merges an inline style instead of replacing it, so the empty “off” style could never unset the accent color and the button stayed lit for the rest of the session, with only the tooltip telling the truth. Both toggles carry their state in the class attribute now. Apple Music takes any storefront. Pick one or type the country code yourself, validated before it saves. Apple serves far more regions than the shortlist, and the storefront API is gated behind a developer account. EUPL-1.2. Kopuz was MIT, and is now licensed under the European Union Public Licence 1.2. Fixes Unsynced albums asked Subsonic for the wrong cover and fell back to an uncached request, so covers came back soft, and the three dots menu opened in the wrong place. Brave’s newer packaging ships the browser as brave-origin , which cookie import could not find. Windows with an app-drawn titlebar resize from any edge or corner on Linux. Flathub and Google Play badges on the README.", "repo": "https://github.com/Kopuz-org/kopuz", "demo": "https://github.com/Kopuz-org/kopuz/releases"}, {"ship_num": 2, "ts": "2026-08-24T14:51:45Z", "hours": 25.0, "multiplier": 17.59, "payout": 352, "blessing": "neutral", "text": "We released v0.16.0!!! Android is back and shippable, two new sources (Apple Music, Nextcloud), lyrics grew depth blur and instrumental breaks, and remote tracks start faster. The app identity finished its move to moe.kopuz.kopuz , so your data directory moves with it on macOS and Windows. Highlights Android builds again. arm64 APK on the releases page (API 24+), signed release job that fails a tagged build rather than shipping unsigned, F-Droid recipe, just android-release . Phone UI too: two line track rows, swipe gestures (up for fullscreen, left/right for next/prev), notification shuffle and repeat buttons, media permission flow, a keepalive waker so the player task keeps turning while hidden, WebView based YouTube deciphering, and an AMOLED theme (#634). Apple Music. Browser sign in, catalog and library browsing, favorites, playlists, downloads, word timed lyrics, per server storefront and language. Playback is hand rolled Widevine using a CDM borrowed from a browser you already have installed (never shipped with Kopuz); Android goes through MediaDrm . Streams decrypt progressively instead of pulling the whole file first (#455, closes #404). Nextcloud over WebDAV. App password auth. No music API there, so the library is read off the tree: folder is album, level above is artist. Listings carry no duration, so the scanner range requests the file head. Per server library folders with a PROPFIND picker and autodetect. Covers go embedded, then sidecar, then the preview endpoint. Use the Subsonic source if your instance runs the Music app (#629). Lyrics. Depth of field blur with a strength slider, synthesized instrumental breaks that fill left to right, the active line stays centered, changing songs no longer reads as a scroll, tab switches no longer desync, and a manual offset that auto fills from the backend’s reported output latency (#643, #647, #648). Remote tracks start faster. HTTP clients are pooled across tracks instead of one handshake per song, and the next 512 KiB window prefetches once reading passes the middle of the current one (#634). Radio uses the server’s analysis. OpenSubsonic sonicSimilarity (AudioMuse on Navidrome) when advertised, song seeded getSimilarSongs otherwise, seed at the head of the queue, and a 90s budget since cold metadata agent lookups were timing out silently (#647, 15615f36). Untrusted paths. Offline filenames are SHA-256 derived, extensions restricted, downloads staged before publication. Deletion only touches direct children of the offline cache or canonical files under a configured library root. Cancellation tombstones close the race where a worker finishing after a cancel re-registered the track (#650).", "repo": "https://github.com/Kopuz-org/kopuz", "demo": "https://github.com/Kopuz-org/kopuz/releases"}, {"ship_num": 3, "ts": "2026-08-04T16:26:49Z", "hours": 10.0, "multiplier": 19.86, "payout": 207, "blessing": "neutral", "text": "v0.14.0 is here!!! Now we are using automated builds with github actions! This one is mostly playlists and looks. Radio can start from a whole playlist now, the settings screen got rebuilt (prefer using top bar view in settings menu rather than cd if you are a linux user), and Kopuz can follow your wallpaper’s colors live. Releases finally ship proper packages for all three desktops. Highlights Radio from playlists: Sources can now seed a mix from an entire playlist instead of one track. YouTube Music does it first, and the button shows up on the playlist grid and the playlist page wherever a source supports it. YouTube liked music is also listed as a playlist of its own, so it gets the same treatment (#591, #592, #593). Matugen and pywal, live: Pick Matugen / Pywal (live) in Settings > Appearance and Kopuz recolors itself about half a second after the palette is regenerated. No restart. pywal needs nothing configured, matugen needs a small template. (#572). Settings rebuilt: The page is split up properly and there are now two layouts to choose from, CD (default) and top bar (#588). Helium for Spotify: Helium joins Chrome, Edge, Brave, Chromium, Vivaldi and Safari as a Web Playback SDK host. It needs Widevine pointed at manually; the README has the config (#574). Track numbers from tags: Album lists use the real metadata track number when there is one, instead of just counting rows (#581). Search in favorites: The favorites list filters as you type, with a proper no-results state (#587). Real release packages: One workflow now builds AppImage, DEB and RPM for Linux, a DMG for macOS, and EXE and MSI for Windows, with checksums. (probably no space will left for macos but eh) Fixes Selection bar was unreadable on light accents like Ayu Dark and Mirage (#599). Long album titles pushed the entire song list off screen (#580). Dots menus were getting clipped inside scrolling containers (#586). Fullscreen forgot the active tab when you hid and unhid the tabs panel (#585).", "repo": "https://github.com/Kopuz-org/kopuz", "demo": "https://github.com/Kopuz-org/kopuz/releases"}, {"ship_num": 4, "ts": "2026-07-24T21:24:05Z", "hours": 42.0, "multiplier": 19.65, "payout": 772, "blessing": "neutral", "text": "kopuz v0.12.0 is out. this one’s got some solid stuff. added isolated local music libraries so separate folders stay separate instead of all blending into one big pile. settings page got a full revision, it needed it. the cover art loading is a lot faster now since we defer cover indexing until after the metadata scan, so big libraries scan way quicker. also local artwork scales properly per view so no more blurry thumbnails. trickiest part was keeping the library scan from lagging everything, that’s sorted now. to test: point it at a couple different music folders and watch them stay isolated, covers should load smooth and settings should feel cleaner. (warning, parallelization: so uhh if you have a big lib, when you scroll in album page it will hurt your cpu a little because of the rendering but dont worry its a one time thing .d)", "repo": "https://github.com/Kopuz-org/kopuz", "demo": "https://github.com/Kopuz-org/kopuz/releases"}, {"ship_num": 5, "ts": "2026-06-27T18:33:59Z", "hours": 33.0, "multiplier": 15.36, "payout": 403, "blessing": "neutral", "text": "I made kopuz music player with the maintainers!! I submitted this project last event too! It got waaay better than first time also i will ship everytime we publish new version from now on! This release is mostly cleanup and refactor work: a big code split across server, utils, sources, and the playback controller, native Windows cookie decryption for sign-in, assets baked into the binary, and a bunch of new translations. Highlights Native Windows cookie decryption. YouTube Music and SoundCloud sign-in now read browser cookies natively on Windows instead of going through the rookie crate (which is now off on Windows). Sign-in works without the third-party cookie reader. Assets are baked into the binary. CSS, fonts, and the favicon now ship inside the kopuz binary, so it doesn’t need any external files at runtime. Big refactor. Server and utils are split up, the source model, page runtimes, backend modules, and playback controller are all broken out, and audio init, playback parsing, and config views got reworked. Dependencies are deduplicated through a virtual manifest to get ready for publishing on crates.io. Features yt-music showcase refactor. Focus indicators on interactive elements that didn’t have them. Matroska audio content-types now map to the mka decode hint. CSS, fonts, and favicon embedded into the binary. Dropped panicky .unwrap() calls, added crate docs, and moved eprintln! over to tracing . Deduplicated shared deps via a virtual manifest to prep for publish. Added contributing guidelines. New locales: Dutch, Malayalam, Tamil, Filipino, and European Portuguese (pt-PT), plus an updated Indonesian one. Fixes ytdlp : give yt-dlp a valid stdin so downloads work on Windows. queue : don’t split the queue when shuffling. server : gate the rookie browser-cookie import to non-Windows. db : tolerate line-ending-only migration checksum differences. lyrics : drop negative cache TTL from 7 days to 1 day. styles : stop the console warnings from re-diffing the stylesheet.", "repo": "https://github.com/Kopuz-org/kopuz", "demo": "https://github.com/Kopuz-org/kopuz/releases"}]...
|
[{"post_id": 68150, "ts": "202 [{"post_id": 68150, "ts": "2026-09-14T16:30:19Z", "hours": 9.9761, "text": "Eh i fixed some little bugs and reviewed prs, all these hours is just because i worked on daemon-frontend split i deployed the bugs fixed version for now, daemon is way harder than i expected thats why its taking sooooo long and too much effort. Fixed bugs are shuffle and repeat button werent updating their states but they now update .d"}, {"post_id": 60743, "ts": "2026-09-03T09:44:44Z", "hours": 10.7572, "text": "All right, so we got accepted to flathub and properly setted up our page, also now it releases on google play store properly too!!! I fixed some bugs and worked a lot for splitting daemon and frontend, hopefully it will be implemented soon. Lastly we switched to EUPL v1.2 license from MIT because i want to protect the daemon…"}, {"post_id": 54324, "ts": "2026-08-25T08:43:21Z", "hours": 8.6461, "text": "All right im in the middle of splitting the daemon from frontend, get ready for the holy kopuzd, we may release an official tui version too!!"}, {"post_id": 53815, "ts": "2026-08-24T14:49:03Z", "hours": 15.3031, "text": "I finally released android version again!! even its on google play store, also we did some improvements to the app. I started split daemon from the frontend, which will allow custom frontends soon, I dont have much photos to show and no long descrips because im too busy atm sorry .d we are mostly working on the backend currently."}, {"post_id": 49105, "ts": "2026-08-17T18:48:25Z", "hours": 10.1075, "text": "All right new log is here, so i was really busy with my job but i def worked on kopuz besides that. Firstly i added version and commit id to general settings, added progress stuff like in youtube progress bar to http streamed musics. Did a little bit of codebase cleanup, fixed a lot of RTL issues and now i splitted configs from db and now they are toml configable (hjem supported)."}, {"post_id": 40678, "ts": "2026-08-04T11:25:14Z", "hours": 3.0694, "text": "all right so i partially migrated CI/CD to self hosted ones because github actions SUCKS, also now Linux and Windows builds are made with github actions. Also added favorite, and 3 dots menu to fullscreen multimedia controller .d added search bar to favorites page, and i also made when listen from youtube music, discord presence will directly get the youtube music photo and doesnt fetch form musicbrainz, lastly some little bug fixes has made :3"}, {"post_id": 39386, "ts": "2026-08-02T10:23:53Z", "hours": 1.6589, "text": "I was so busy last 5 days for interview project but, good news i passed it! I wasnt able to develop kopuz at that time but its over, right after interview arc i redesigned the settings menu for better visibility and this is not the only option you can make it constant topbar but the default is cd selector so cope with it .d"}, {"post_id": 36306, "ts": "2026-07-28T10:21:27Z", "hours": 5.7181, "text": "so uhhh spotify integration is finally in master branch, people were just asking me when spotify when spotify and yeah its here, but for avoiding lawsuits i had to use public api which will give users some bad experience, but eh this can be used as “download your own music” propaganda, besides this i did some codebase cleanup and lil bug fixes"}, {"post_id": 34279, "ts": "2026-07-24T21:02:07Z", "hours": 7.8978, "text": "all right, so i was like super bored and randomly started add stuff, so uhh we now have isolated local music libraries, so like if you have 2 different folders which contains different kinds of music and you dont want to mix it with your main library, i had that issue so added this option, also people were complaining about settings menu so i made exactly how they wanted, also when i woke up this morning i saw a discussion opened in the repo which said, “kopuz individually takes images of flac files” which is true, i didnt expect anyone with 5k songs to use this app .d Anyways i fixed that issue and the app got faster (i was so stupid while i was enabling individual image scanning)."}, {"post_id": 32862, "ts": "2026-07-22T09:32:47Z", "hours": 8.7542, "text": "spotify support is postponed to v0.12.0, but uhh we got some solid stuff for v0.11.0 fullscreen got reworked, now with cover art backgrounds and a general cleanup pass added quick search so you can actually find your stuff fast custom UI font support, use whatever font you want redesigned the normal radio page radio-browser.info search, ICY now-playing metadata, and playlist resolution EQ now has 10 bands instead of the old setup auto-scroll pauses when you scroll manually, plus a sync button added Helium browser for browser sign-in app now checks if the media server is actually reachable instead of assuming it is added Swedish locale"}, {"post_id": 30196, "ts": "2026-07-17T16:06:51Z", "hours": 5.7239, "text": "I added spotify support with Public API, since this is a big app, im afraid of using the illegal way, so for using the spotify integration there MUST be a browser which has widevine capability… Is it annoying? yes. But is it working? yes."}, {"post_id": 28454, "ts": "2026-07-14T18:23:33Z", "hours": 8.9486, "text": "Okay so, firstly i added list view to album and artist menu, its kinda a cheat for better performance since the images are getting smaller, users always complain about bad performance on higher resolutions so its a step against it, also i added highly customazible sorting options because it was a pr back then and the author of that pr couldnt reach to his pc so i took over his task, also not MPRIS and darwin now playing integration supports seeking, lastly i started on TIDAL integration because vaxry requested it .d"}, {"post_id": 23726, "ts": "2026-07-06T20:51:28Z", "hours": 2.9472, "text": "Revised settings page for better understandability for users. Yeah so vaxry told me that settings menu sucks. So i made the components like this in the photo, easily understandable (idiotproofing)"}, {"post_id": 22262, "ts": "2026-07-04T17:15:09Z", "hours": 3.3267, "text": "I reinforced ListenBrainz scrobbling because vaxry reported that it sucks, so apperantly it was half my issue and half LB’s issue because BTS listeners migrated to libre.fm and listenbrainz from last.fm. So scrobbling was a bit wrong in my side, so fixed that. Also im waiting for a contributor to add offline scrobbling ability which will fully fix this issue since it will cache listening and when the LB server is awake again it will dump scrobbles… Ah also now playing was a bit broken so i fully fixed it too, now the app has great logs for scrobble stuff…"}, {"post_id": 20754, "ts": "2026-07-02T13:28:30Z", "hours": 4.5308, "text": "Added enhanced discord presence which now has the option to show the source of your music, also i added clear image cache and rescan buttons for easier image handling."}, {"post_id": 17070, "ts": "2026-06-27T18:31:27Z", "hours": 1.8081, "text": "fixed source selector part styling and with contributors we fixed login issue on windows, established ai policy, and a lot more!!"}, {"post_id": 15158, "ts": "2026-06-24T16:58:45Z", "hours": 4.4406, "text": "worked on adding librespot backend (kinda), since spotify isnt giving us any music or music data bytes we cant decode anything, so i made librespot to fetch the stuff in logged in profile and play via anon yt music backend with metadata matching, its still a pr but eh hopefully it will be good"}, {"post_id": 13216, "ts": "2026-06-21T17:24:11Z", "hours": 2.4389, "text": "better album view in yt music, fixed search for yt music, discover menu is now better, any album available can now viewable. Also we have migrated to sqlite from json so the app became waaay faster and now there is no seperation between local and server now everything is in one place."}, {"post_id": 12648, "ts": "2026-06-20T17:42:21Z", "hours": 0.8142, "text": "made last touches with the contributor and made it ready to release! hopefully first release in stardance will be v0.7.0, who knows kopuz may become stable in stardance…"}, {"post_id": 12101, "ts": "2026-06-19T19:09:14Z", "hours": 1.3692, "text": "fixed fullscreen view, it was really poor and multimedia controls were so bad, i took the audio control to top right corner so it looks like apple music now."}, {"post_id": 11511, "ts": "2026-06-18T20:02:54Z", "hours": 3.7036, "text": "i added mini player and tray implementation for users!!"}, {"post_id": 9168, "ts": "2026-06-15T11:15:59Z", "hours": 10.3256, "text": "I worked on adding spotify but failed, same for apple music too but at least i added soundcloud to kopuz!!! This music player will be the best music player ever created for every platform user!"}, {"post_id": 5936, "ts": "2026-06-09T22:34:46Z", "hours": 1.9461, "text": "local metadata viewer and editor added"}, {"post_id": 4334, "ts": "2026-06-07T16:45:21Z", "hours": 4.0619, "text": "we got youtube music support now!! with a lot of bug fixes"}, {"post_id": 942, "ts": "2026-06-02T18:20:14Z", "hours": 1.8019, "text": "Making kopuz better this time huh?"}]...
|
Title: Kopuz by @temidaradev | Stardance
Devlogs: Title: Kopuz by @temidaradev | Stardance
Devlogs:
Making kopuz better this time huh?
we got youtube music support now!! with a lot of bug fixes
local metadata viewer and editor added
I worked on adding spotify but failed, same for apple music too but at least i added soundcloud to kopuz!!! This music player will be the best music player ever created for every platform user!
i added mini player and tray implementation for users!!
fixed fullscreen view, it was really poor and multimedia controls were so bad, i took the audio control to top right corner so it looks like apple music now.
made last touches with the contributor and made it ready to release! hopefully first release in stardance will be v0.7.0, who knows kopuz may become stable in stardance…
better album view in yt music, fixed search for yt music, discover menu is now better, any album available can now viewable. Also we have migrated to sqlite from json so the app became waaay faster and now there is no seperation between local and server now everything is in one place.
worked on adding librespot backend (kinda), since spotify isnt giving us any music or music data bytes we cant decode anything, so i made librespot to fetch the stuff in logged in profile and play via anon yt music backend with metadata matching, its still a pr but eh hopefully it will be good
fixed source selector part styling and with contributors we fixed login issue on windows, established ai policy, and a lot more!!
Added enhanced discord presence which now has the option to show the source of your music, also i added clear image cache and rescan buttons for easier image handling.
I reinforced ListenBrainz scrobbling because vaxry reported that it sucks, so apperantly it was half my issue and half LB’s issue because BTS listeners migrated to libre.fm and listenbrainz from last.fm. So scrobbling was a bit wrong in my side, so fixed that. Also im waiting for a contributor to add offline scrobbling ability which will fully fix this issue since it will cache listening and when the LB server is awake again it will dump scrobbles… Ah also now playing was a bit broken so i fully fixed it too, now the app has great logs for scrobble stuff…
Revised settings page for better understandability for users. Yeah so vaxry told me that settings menu sucks. So i made the components like this in the photo, easily understandable (idiotproofing)
Okay so, firstly i added list view to album and artist menu, its kinda a cheat for better performance since the images are getting smaller, users always complain about bad performance on higher resolutions so its a step against it, also i added highly customazible sorting options because it was a pr back then and the author of that pr couldnt reach to his pc so i took over his task, also not MPRIS and darwin now playing integration supports seeking, lastly i started on TIDAL integration because vaxry requested it .d
I added spotify support with Public API, since this is a big app, im afraid of using the illegal way, so for using the spotify integration there MUST be a browser which has widevine capability… Is it annoying? yes. But is it working? yes.
spotify support is postponed to v0.12.0, but uhh we got some solid stuff for v0.11.0 fullscreen got reworked, now with cover art backgrounds and a general cleanup pass added quick search so you can actually find your stuff fast custom UI font support, use whatever font you want redesigned the normal radio page radio-browser.info search, ICY now-playing metadata, and playlist resolution EQ now has 10 bands instead of the old setup auto-scroll pauses when you scroll manually, plus a sync button added Helium browser for browser sign-in app now checks if the media server is actually reachable instead of assuming it is added Swedish locale
all right, so i was like super bored and randomly started add stuff, so uhh we now have isolated local music libraries, so like if you have 2 different folders which contains different kinds of music and you dont want to mix it with your main library, i had that issue so added this option, also people were complaining about settings menu so i made exactly how they wanted, also when i woke up this morning i saw a discussion opened in the repo which said, “kopuz individually takes images of flac files” which is true, i didnt expect anyone with 5k songs to use this app .d Anyways i fixed that issue and the app got faster (i was so stupid while i was enabling individual image scanning).
so uhhh spotify integration is finally in master branch, people were just asking me when spotify when spotify and yeah its here, but for avoiding lawsuits i had to use public api which will give users some bad experience, but eh this can be used as “download your own music” propaganda, besides this i did some codebase cleanup and lil bug fixes
I was so busy last 5 days for interview project but, good news i passed it! I wasnt able to develop kopuz at that time but its over, right after interview arc i redesigned the settings menu for better visibility and this is not the only option you can make it constant topbar but the default is cd selector so cope with it .d
all right so i partially migrated CI/CD to self hosted ones because github actions SUCKS, also now Linux and Windows builds are made with github actions. Also added favorite, and 3 dots menu to fullscreen multimedia controller .d added search bar to favorites page, and i also made when listen from youtube music, discord presence will directly get the youtube music photo and doesnt fetch form musicbrainz, lastly some little bug fixes has made :3
All right new log is here, so i was really busy with my job but i def worked on kopuz besides that. Firstly i added version and commit id to general settings, added progress stuff like in youtube progress bar to http streamed musics. Did a little bit of codebase cleanup, fixed a lot of RTL issues and now i splitted configs from db and now they are toml configable (hjem supported).
I finally released android version again!! even its on google play store, also we did some improvements to the app. I started split daemon from the frontend, which will allow custom frontends soon, I dont have much photos to show and no long descrips because im too busy atm sorry .d we are mostly working on the backend currently.
All right im in the middle of splitting the daemon from frontend, get ready for the holy kopuzd, we may release an official tui version too!!
All right, so we got accepted to flathub and properly setted up our page, also now it releases on google play store properly too!!! I fixed some bugs and worked a lot for splitting daemon and frontend, hopefully it will be implemented soon. Lastly we switched to EUPL v1.2 license from MIT because i want to protect the daemon…
Eh i fixed some little bugs and reviewed prs, all these hours is just because i worked on daemon-frontend split i deployed the bugs fixed version for now, daemon is way harder than i expected thats why its taking sooooo long and too much effort. Fixed bugs are shuffle and repeat button werent updating their states but they now update .d
Ships:
I made kopuz music player with the maintainers!! I submitted this project last event too! It got waaay better than first time also i will ship everytime we publish new version from now on! This release is mostly cleanup and refactor work: a big code split across server, utils, sources, and the playback controller, native Windows cookie decryption for sign-in, assets baked into the binary, and a bunch of new translations. Highlights Native Windows cookie decryption. YouTube Music and SoundCloud sign-in now read browser cookies natively on Windows instead of going through the rookie crate (which is now off on Windows). Sign-in works without the third-party cookie reader. Assets are baked into the binary. CSS, fonts, and the favicon now ship inside the kopuz binary, so it doesn’t need any external files at runtime. Big refactor. Server and utils are split up, the source model, page runtimes, backend modules, and playback controller are all broken out, and audio init, playback parsing, and config views got reworked. Dependencies are deduplicated through a virtual manifest to get ready for publishing on crates.io. Features yt-music showcase refactor. Focus indicators on interactive elements that didn’t have them. Matroska audio content-types now map to the mka decode hint. CSS, fonts, and favicon embedded into the binary. Dropped panicky .unwrap() calls, added crate docs, and moved eprintln! over to tracing . Deduplicated shared deps via a virtual manifest to prep for publish. Added contributing guidelines. New locales: Dutch, Malayalam, Tamil, Filipino, and European Portuguese (pt-PT), plus an updated Indonesian one. Fixes ytdlp : give yt-dlp a valid stdin so downloads work on Windows. queue : don’t split the queue when shuffling. server : gate the rookie browser-cookie import to non-Windows. db : tolerate line-ending-only migration checksum differences. lyrics : drop negative cache TTL from 7 days to 1 day. styles : stop the console warnings from re-diffing the stylesheet.
kopuz v0.12.0 is out. this one’s got some solid stuff. added isolated local music libraries so separate folders stay separate instead of all blending into one big pile. settings page got a full revision, it needed it. the cover art loading is a lot faster now since we defer cover indexing until after the metadata scan, so big libraries scan way quicker. also local artwork scales properly per view so no more blurry thumbnails. trickiest part was keeping the library scan from lagging everything, that’s sorted now. to test: point it at a couple different music folders and watch them stay isolated, covers should load smooth and settings should feel cleaner. (warning, parallelization: so uhh if you have a big lib, when you scroll in album page it will hurt your cpu a little because of the rendering but dont worry its a one time thing .d)
v0.14.0 is here!!! Now we are using automated builds with github actions! This one is mostly playlists and looks. Radio can start from a whole playlist now, the settings screen got rebuilt (prefer using top bar view in settings menu rather than cd if you are a linux user), and Kopuz can follow your wallpaper’s colors live. Releases finally ship proper packages for all three desktops. Highlights Radio from playlists: Sources can now seed a mix from an entire playlist instead of one track. YouTube Music does it first, and the button shows up on the playlist grid and the playlist page wherever a source supports it. YouTube liked music is also listed as a playlist of its own, so it gets the same treatment (#591, #592, #593). Matugen and pywal, live: Pick Matugen / Pywal (live) in Settings > Appearance and Kopuz recolors itself about half a second after the palette is regenerated. No restart. pywal needs nothing configured, matugen needs a small template. (#572). Settings rebuilt: The page is split up properly and there are now two layouts to choose from, CD (default) and top bar (#588). Helium for Spotify: Helium joins Chrome, Edge, Brave, Chromium, Vivaldi and Safari as a Web Playback SDK host. It needs Widevine pointed at manually; the README has the config (#574). Track numbers from tags: Album lists use the real metadata track number when there is one, instead of just counting rows (#581). Search in favorites: The favorites list filters as you type, with a proper no-results state (#587). Real release packages: One workflow now builds AppImage, DEB and RPM for Linux, a DMG for macOS, and EXE and MSI for Windows, with checksums. (probably no space will left for macos but eh) Fixes Selection bar was unreadable on light accents like Ayu Dark and Mirage (#599). Long album titles pushed the entire song list off screen (#580). Dots menus were getting clipped inside scrolling containers (#586). Fullscreen forgot the active tab when you hid and unhid the tabs panel (#585).
We released v0.16.0!!! Android is back and shippable, two new sources (Apple Music, Nextcloud), lyrics grew depth blur and instrumental breaks, and remote tracks start faster. The app identity finished its move to moe.kopuz.kopuz , so your data directory moves with it on macOS and Windows. Highlights Android builds again. arm64 APK on the releases page (API 24+), signed release job that fails a tagged build rather than shipping unsigned, F-Droid recipe, just android-release . Phone UI too: two line track rows, swipe gestures (up for fullscreen, left/right for next/prev), notification shuffle and repeat buttons, media permission flow, a keepalive waker so the player task keeps turning while hidden, WebView based YouTube deciphering, and an AMOLED theme (#634). Apple Music. Browser sign in, catalog and library browsing, favorites, playlists, downloads, word timed lyrics, per server storefront and language. Playback is hand rolled Widevine using a CDM borrowed from a browser you already have installed (never shipped with Kopuz); Android goes through MediaDrm . Streams decrypt progressively instead of pulling the whole file first (#455, closes #404). Nextcloud over WebDAV. App password auth. No music API there, so the library is read off the tree: folder is album, level above is artist. Listings carry no duration, so the scanner range requests the file head. Per server library folders with a PROPFIND picker and autodetect. Covers go embedded, then sidecar, then the preview endpoint. Use the Subsonic source if your instance runs the Music app (#629). Lyrics. Depth of field blur with a strength slider, synthesized instrumental breaks that fill left to right, the active line stays centered, changing songs no longer reads as a scroll, tab switches no longer desync, and a manual offset that auto fills from the backend’s reported output latency (#643, #647, #648). Remote tracks start faster. HTTP clients are pooled across tracks instead of one handshake per song, and the next 512 KiB window prefetches once reading passes the middle of the current one (#634). Radio uses the server’s analysis. OpenSubsonic sonicSimilarity (AudioMuse on Navidrome) when advertised, song seeded getSimilarSongs otherwise, seed at the head of the queue, and a 90s budget since cold metadata agent lookups were timing out silently (#647, 15615f36). Untrusted paths. Offline filenames are SHA-256 derived, extensions restricted, downloads staged before publication. Deletion only touches direct children of the offline cache or canonical files under a configured library root. Cancellation tombstones close the race where a worker finishing after a cancel re-registered the track (#650).
Two parts of the player stop lying to you: Recently Added lists what you actually added, and shuffle and repeat go dark when you switch them off. Apple Music takes any storefront, and Kopuz is now EUPL-1.2. Highlights Recently Added means recently added. The row was the alphabetical album list read backwards, so it showed the tail of your alphabet forever. Albums now rank by when their music arrived, stamped per file from the filesystem while the library is scanned, and the library’s own date added sort reads the same stamp. Rescan once after upgrading to fill it in. Shuffle and repeat clear their highlight. Dioxus merges an inline style instead of replacing it, so the empty “off” style could never unset the accent color and the button stayed lit for the rest of the session, with only the tooltip telling the truth. Both toggles carry their state in the class attribute now. Apple Music takes any storefront. Pick one or type the country code yourself, validated before it saves. Apple serves far more regions than the shortlist, and the storefront API is gated behind a developer account. EUPL-1.2. Kopuz was MIT, and is now licensed under the European Union Public Licence 1.2. Fixes Unsynced albums asked Subsonic for the wrong cover and fell back to an uncached request, so covers came back soft, and the three dots menu opened in the wrong place. Brave’s newer packaging ships the browser as brave-origin , which cookie import could not find. Windows with an app-drawn titlebar resize from any edge or corner on Linux. Flathub and Google Play badges on the README....
|
1792842622.5745435
|
1792929022.5745435
|
|
21103
|
Ritualia by @gabriel_ferreira | Stardance
|
gabriel_ferreira
|
1
|
148.7
|
2310
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-23T23:45:29Z", "hours": 148.0, "multiplier": 18.45, "payout": 2310, "blessing": "neutral", "text": "What did i made I made an complete music play system that will help users to learn while listening to musics! I used youtube, flask, python, mysql, js and hope to make this! What else Solved a lot of painful bugs that were stopping the project from working Finished and made the music queue work Added music description labels Improved a lot the performance Made the website responsive Added a keyboard based navigation Fixed so much errors at the cover-flow that now i forgot how many Added bug checks before the play of each video on the player Created an toast component to show errors or infos Added 54 musics to choose and listen Challenges The most painful code was the player and the cover-flow, they were with a lot of hidden bugs that i had to figure out, feats that i had to make and pain to suffer! Now i figured out that i love and HATE making a website responsive! What im proud of MutationObserver: An observer that loads / hides an image based on its position at the cover-flow, this system took a while and worked very well. Error checks at player: The system can handle the error that happen and dont crash! Keyboard navigation: Everyone can use the keyboard to navigate now! Oracle VM: For the first time i used an ssh and hosted an website in my own machine (oracle, not mine)! How to test Access http://ritualia.duckdns.org/ , when you join and the page loads you will find a screen to choose an genre, select which one you want, after you will see an emotion selector, select the emotion that you wanna feel! You will see the player screen and an audio explaining the music (The audio is in portuguese), after the audio the music will play. Notice: The github and the website are in portuguese, please use your browser built-in translator or any that you want to use the software properly! Follow the installation guides at github if you want to install", "repo": "https://github.com/GF-Silva/Ritualia", "demo": "https://ritualia.hackclub.app"}]...
|
[{"post_id": 73067, "ts": "202 [{"post_id": 73067, "ts": "2026-09-24T09:47:16Z", "hours": 0.6983, "text": "Added english readme I created an english readme, api and install Guide, so it will be easier to read and more accessible for worl-wide users"}, {"post_id": 72881, "ts": "2026-09-23T22:36:56Z", "hours": 0.3906, "text": "It is time to ship! Now the system is working perfectly fine running at a vm in oracle cloud with a public domain, and a dns with duckdns at http://ritualia.duckdns.org/ Warning: It is just HTTP!"}, {"post_id": 72810, "ts": "2026-09-23T19:36:13Z", "hours": 1.3461, "text": "Configuring an ssh server! I configured an oracle cloud vm with ubuntu to host my website 24/7, that was because nest wasnt working in a while. Im running it at a local IP with http only, i will configure https today and maybe an domain, the IP is http://164.152.55.252 , notice that some browsers may block you from accessing and http website. UPDATE AFTER THE DEVLOG: I put an domain using duck dns: http://ritualia.duckdns.org Hardwork I had absolutely not a single knowledge about oracle cloud vm, so configuring it was an hell. Sometime my internet stopped working so i had to use my smartphone, this lead me to configuring an invalid ssh key and i had do configure everything from scratch, i spent 5 hours configuring everything, but that was ssh and wasnt tracked. But now everything is working fine. Thx oracle This vm is a 24/7 entire OS (Virtual Machine) that has some good free plans, without any cold start. Thx stardance Stardance now will have one more mount!!!!!! I still has roughly 40 hours of deep development to do after this ship, i will love to finish that in stardance!"}, {"post_id": 70936, "ts": "2026-09-20T02:22:48Z", "hours": 2.9706, "text": "Added install guides Now there is guides to help the user install for ubuntu, arch and windows. Notice that im a linux user and my pc is weak, so i could not test it on another operational system. Also the guide is in portuguese (all of them), please use your browser built-in translator or any of them to read if u dont understands portuguese I could test it on another linux distro, but i would have to go through all the install steps. Also i cannot try installing windows because it normally wipe out another OS installed on the same disc (i know that it just replaces the bootloader) and using a VM was not possible due to the amount of RAM and the processor that i have."}, {"post_id": 69913, "ts": "2026-09-18T01:53:38Z", "hours": 0.3256, "text": "All done, it is time to ship Every metric at lighthouse it nearly perfect, im so exited to ship it!"}, {"post_id": 69904, "ts": "2026-09-18T01:19:42Z", "hours": 4.9561, "text": "The accessibility workings is done Features Now the system has a new navigation system that allow users to navigate with just the keyboard! (The video was with just the keyboard) Why Why not? It was meant to improve the accessibility for users without mouse, or any another problem and because i was tired of having to use the mouse to debug something. How it was made Again with a lot of pain, the feature itself was easy but i had to fix some errors that went unnoticed, so it took more time. The feature detects when the user press a key and do an action based on wich key was. The accessibility was easy to get 100, but the metrics at lighthouse dont give all what the users will need, i had to think about the website usage and how would be the easiest way for the user. Results The accessibility went from nearly 69 to 100! What next Now i will work on the best practices! Update after the devlog: Nearly every metric is already maxed out lol, i will ship it very soon!"}, {"post_id": 69444, "ts": "2026-09-17T02:13:13Z", "hours": 1.6906, "text": "The performance workings is finished and bug fix Fixes Now the logo z-index is lower, that is because the logo was ‘eating’ the click in more important elements. Also i did a small change at the cover-flow, that change fix the bug of the scroll at the element sudently stoping when at a certain position. The copa script had some old references to images that were leading to bugs, i changed it. Performance I already finished it in the past devlog, i was just checking if there was anything worth improving, but everything is working fine and now is time to improve acessibility. Most of the logged time was me trying to improve more some metrics at the lighthouse, but the work was too much for anything that is already good, so i decided to stop before i started focusing too much in it."}, {"post_id": 69395, "ts": "2026-09-16T23:43:00Z", "hours": 1.505, "text": "Fixing an error at the youtubeHelper Now the youtubeHelpers checks if the youtube API is ready before sending commands. Why Sometimes the API maybe is not finished yet, that was leaving an untreated error that was braking the entire website. How was made With a lot of pain and suffer. I thought “Oh hey, that will be a 15 minutes fix” - i spent 1 HOUR FIGHTING with the iframe itself, nothing was working and at some point i started thinking that even the API of YOUTUBE wasnt working, even the most basic function that should be triggered when the youtube finished the loading wasnt beeing activated, even the console.log(“Api READY!”) wasnt working, even when it worked it wasnt working well, the variable of the player was a promise and not the result. At the end i shut down my PC, defeated, without any energy left, with just hope that in the next day (this) that would be fixed (if not i was planning to ignore and make it a feature “Easter egg, if u dont join the website for a while it will not load!”. The problem here was just the position were the iframe api was in the HTML, it was being loaded before the helper script, so the helper was not there to check if it the iframe was ready or not, the fix was just move it a little down. Architecture It was just an promise, if the function checks that the iframe isnt available it await for it to be available. The check if it was available use the onYoutubeIframeAPIReady, easy easy (except for all the suffer that i went into)."}, {"post_id": 68896, "ts": "2026-09-15T23:59:43Z", "hours": 1.1389, "text": "The loading is done and working! Fix I fixed the error that were happening when the cover had a certain amount of elements. Problems The fix itself was very easy to do, but doing it in a readable or without using 10 lines of code (i want things concise) was way harder than i expected. So i spent this entire time trying different ways to do it, each of them making everything worse. Reasoning The bug were with less than 14 elements, the script were calculating the first and last element index, it happened that these elements were behind the screen focus. Why? Because the values that the system was using were leaving these values, so i had to fix the way it was calculating things."}, {"post_id": 68865, "ts": "2026-09-15T22:15:27Z", "hours": 1.3303, "text": "The loading is done Features Now the loading at the mutationObserver is finished, it finally loads or unloads the images that should be (or not) loaded! The new observer is way faster, because it can detect the image way before it enters the screen, loading it before and having more time to do it. Also the system loads just a maximum of images (with the configs that i put it is 13), so it will not fry an cellphone. Problems The loading part was easy to do, i already done it before in the past observer (intersectionObserver), so i just had to pass the old code to the new part. But when the cover-flow element dont got atleast 13 elements the mutationObserver code breaks completely! Im still pondering how to solve it, when i do i will post about! Results The performance went from 78 to 100! The system is way faster! The user does not see a blank image anymore! Why The old method was slow even with a good internet connection, because it was loading the images just when the element was already in the screen, leaving to a perceptive delay for the user and a blank image to the user. Also i thought about creating an observer from scratch (maybe i was a little off my ideas, because that was insane), but the browser already had exactly what i wanted (the mutationObserver) Videos The new features The performance of the new feats The old features Reasoning While i was trying to sleep i thought about a system that fill the cover-flow with a maximum of images (like 10, or 13, or the code decides) at the DOM, using less memory to run. That system will free a lot of memory based on how many cards the cover-flow have. But that will have noticeable effects just with a lot of elements and probably would be hard to develop, maybe i will do in next updates. What next Im leading to the shipping, so i will improve metrics about the lighthouse, improve the readme and post it."}, {"post_id": 68449, "ts": "2026-09-15T04:25:35Z", "hours": 7.2278, "text": "Adding a mutationObserver Now, instead of an intersectionObserver, the system use a mutationObserver that monitors the angle of the cylinder itself. With that the loading of the images will be insanely better, faster and user-friendly. Now the changes in the cover-flow is observed at the cylinder angle, not at each card. There was some problems in the journey like, for some reason, unexpected cards being loaded or not, the loading script at the observer dont triggering at all (that was caused by the speed of the observer) and an insane amount of cards being triggered at the same time (i still did not figured out why, but that isnt ‘harmful’). But man, i had to be creative here and remember about some concepts like concurrent programming, buffer / queue and apply some delays (because the mutationObserver is insanely fast and can trigger every millisecond). That all was meant to decrease the speed of the mutationObserver, because it was triggering with the most small change in the cylinder, so i made it trigger just when an expected amount of movement was made. The red/yellow collor is for me to visualize the loading state, it is just for debug The code isnt finished, i still need to implement the loading part, for now i just implemented the observer and basics of the loading part"}, {"post_id": 67841, "ts": "2026-09-14T03:19:48Z", "hours": 4.2825, "text": "The observer is finished (nearly) Now the cover-flow has an observer that checks the position of the images and changes it styles based on that, so the images that the user is seeing is loaded while the others is hide. It still has some bugs and space for improvements that im still figuring out how to solve, like the image loading too late on the screen or, in slow internet connections, the image takes too long to load. Most of these bugs are because the observer (an intersectionObserver ) was designed for 2d contexts, not 3d (that were and still is an giant problem to solve). For this reason i was thinking about creating an observer from scratch in C++ that can work better in my 3d element, but the overhead would be high so im trying to solve in other ways before that. The feature was made using fetchPriority, contentVisibility and src (the system add the source just when the image is near the screen). OBS: I found about MutationObserver after this post, maybe i will use that instead of insersectionObserver. Oh man, at least if had found about this before… Aaaaaahhhhh i spent 9 hours in that, but at least a Lot of the new logic will be used. Anyway, lets cook"}, {"post_id": 67151, "ts": "2026-09-13T06:53:12Z", "hours": 5.4219, "text": "Adding an observer Now the script observe the card elements at the cover-flow component, classify their position and changes it visibility based on that. Im using an IntersectionObserver to observe every card, but it was designed to observe the position of 2d elements, so i had to figure out how to make it work well in an 3d element. The way it works is when the observe activates (it basically means that some card is in the range to load) it get the card info (like position and angle) and changes it visibility state based on that. Simple, right? No, it was a headache for the start to the top, nearly 4 hours of what i did was to fix the fact that it was meant for 2d. The observer were activating for cards that were in the back of the element, so i had to classify the card position into back or front by using its angle. But if i tried to use the card angle without anything else the script would broke (and did for 3 hours until i realized how to fix), so i had to use an second angle which is 360 - cardAngle (the 360 is the angle of an circle), so this new angle is based on the circle end while the other is based on the circle start. But the system still broke, because at some point one of these values would become negative and makes the if that classify the elements fail. The fix was using the absolute value in the if (it took 1 hour until i figured that; oh i were so happy when it worked). Why To improve the performance, so the browser will just load what is really important and not 50 images that the user cant even see. What else All that work definitely improved a lot my logic thinking and for the first time i used the truth table well. Now i just need to use the new code to change more the style of the images that are not in the screen. I did not deleted the code that i wrote in the past devlog, it was used in the new code to select how many images should be loaded in the same time. ** The first video is the result, the others is some problems that i had **"}, {"post_id": 66316, "ts": "2026-09-12T02:31:12Z", "hours": 4.5481, "text": "Improving the loading performance Now the system selects some images that needs to be shown faster than the others and making them load with priority. It was made by selecting the images that the user is seeing and defining some params like fetchPriority = \"high\" and decoding=\"sync\" , the other images have the params: decoding=\"async\"; loading=\"lazy\"; contentVisibility=\"auto\"; . With that config the LCP went from 2.4s to 0.5s . Also it loads the image in the start and dont change that config again, so the browser will be lazy while downloading these images. The problem is: only the first images are chosen as high priority, but their positions will be changed while the configs stays the same, that makes the browser lazy while loading them and makes the runtime performance became worse. To fix that i found about IntersectionObserver, that are meant to solve the problem of updating the images position fast. It was not applied yet, i found about it like 1 hour ago. What else Now the perspective of the emotionDrum is based on the elements that it have, before it was based just in the screen and would broke if something changes. I did a little change in the way that the script checks for clicks in the screen, now it has more accuracy (I changed the round system)."}, {"post_id": 64533, "ts": "2026-09-09T00:41:52Z", "hours": 7.6869, "text": "Improving the LCP (Largest content paint) performance I am improving the way that the website create and downloads the images, the main reason is to make the user see something faster. Before the system were doing 2 main things: Go trough the entire list of images, creating the elements and placing them into the page. Position them. But the position of the items were being done after the creation of the images, in another function. Now they are in the same function: it create the element, position it and add it to the page. That does not seem like much, but the code got way faster with that, probably because it dont need to go item by item in an list twice just to create an element. I tested the time to load the first element and it went from 8.63s to 6.43s , the test was made with 2200 elements (Yeah ik, it is a lot and normally it isnt that much, but i had to see how they were holding with more than 22 items). Also i fixed a bug that passed unnoticed while improving the responsiveness: At some point of images the visibility of the elements broke, that was because the perspective (what makes the 3D perspective of the component, and makes it visible with 3D effects) was based on the screen size, not the elements itself. What was the problem in that: Each element takes a size in the screen ‘makes the circle that shows the element be more and more near of our point of view’ (i cant explain it any better, search what is ‘perspective in an 3d element at HTML’ ). While it was approaching our point of view (POV), our POV were exactly at the same position (based on the screen size), so at some point the circle perspective would pass the POV and we would be unable of seeing it well. Now it is based on the elements: The 3d elements were basically a circle, i just used the diameter to change the perspective based on it. TODO: Maybe i lowered the image quality too much… I will fix it in the next updates. Also i were trying to improve the font settings to improve the performance, but that wast working so i decided to move on to this because it was more critical (took a while for me to jump to this, maybe like 2 hours trying and trying values in the font settings). i am also working in a way to load the images in parallel, with that it will take way less time (I didnt known about LCP before so i spent a while figuring out the way it works)."}, {"post_id": 63656, "ts": "2026-09-07T16:11:33Z", "hours": 2.6633, "text": "Improving the performance After finishing the improvements in the responsiveness, now i decided to improve the performance. I used lighthouse to get insights (i learned about it in an tiktok video) and figured out that the images size were too high (were an png of 1280x1280px), so i saw more about that in the page: https://developer.chrome.com/docs/performance/insights/image-delivery (an link that google lighthouse gave). With that i saw how to decrease the size while staying with quality, i reached up to the sharp-cli tool, that makes the work of resize, convert and compress the image for me. The command used was that: npx sharp-cli -i * .png -o ./output resize 320 -f avif -q 50 --effort 6 --smartDeblock --preset photo The 320 is the size that i want it to be at the end, i got that value by seeing what was the computed value (the value that is being used in the website) in an high resolution pc (not the most higher one, the high but normal pc) with the resolution of 2500x1714px . With this simple changing the image went from 2mb to 40Kb! Nearly 100% decrease, and take in mind that there is more than one img, so the change were even higher. Also i created 5 different images: 320px, 480px, 640px, 960px e 1280px. With them the browser can choose which one is better for each device. With these changes i went from 35 points of performance to 59."}, {"post_id": 63459, "ts": "2026-09-07T10:10:31Z", "hours": 0.8717, "text": "The home is now fully responsive Ah that took a while, but finally it is fully responsive. Now the description at the player UI resizes based on the screen size and active a scroll behaviour when need, also i did some minor change at the emotionDrum perspective to make it show more emotions at the same time, removed the padding in the arrows at the emotionDrum so they will have more space and fixed an error in the genre drum that was making it perspective broke. After all these devlogs i improved how i make a code responsive."}, {"post_id": 63436, "ts": "2026-09-07T08:55:04Z", "hours": 2.5378, "text": "The emotionDrum is now responsive! Now the buttons that you use to select the emotion are in the same side as the div that displays the emotion, so they dont fight for space anymore. This change is meant to fix the low size of the items in screens that are too small, in the new way we have more free space to display the emotions, there is not much to say. What else I did some minor changes in the size of some items at the player area, now they are easier to read! (I increased the size of some items)"}, {"post_id": 63379, "ts": "2026-09-07T05:17:01Z", "hours": 6.6125, "text": "Im nearly finishing the workings on the responsiveness. Now the entire player screen is responsive and do not breaks the texts anymore (except for the description area), also the buttons that show you the next screen (the ones that displays ‘player’ and ‘generos’) are responsive too, the music queue is working perfectly fine, and the area that is used to select an emotion is nearly responsive too, it just needs some adjusts in the two buttons that change the current emotion because they become too small and uses a lot of space when the screen is too small, after that this screen will be finished. It is taking a really long time, the fact of how many different screen sizes exists makes it harder to finish, but now there is times that i even cannot see if i changed the resolution in some areas, because the system looks the same. I spent quite a while testing different resolutions and combinations of size, i didnt even noticed that i where 6 hours here, but now ik more about css (things like container-type + container based sizes and more ways to set the size of an text) The video shows how it is now, if u want to see the before just checks the past devlog."}, {"post_id": 62723, "ts": "2026-09-06T06:59:19Z", "hours": 0.7094, "text": "Finished the correction of the errors at the perspective and click in the cover-flow component. Now the perspective stays the same 150vw value (that is based on the screen width) and stays normal, with everything working. Oh man, that needed a lot of logic and out of box thinking finding another ways to check where the user clicked without using an normal click event listener (for those who lost the past devlog or didnt understood, i cannot use a normal eventListener in that because the clicks is detected in another element or in nothing, even with z-index or more in css, so the solution should be done entirely on javascript logic). The first video is the new way, the second is how it was before all changes in it"}, {"post_id": 62679, "ts": "2026-09-06T05:10:34Z", "hours": 5.5194, "text": "i finished the workings on the section of the home page that i where doing before, now has a good responsiveness for pc and a decent one for mobile. Now im working on the main area of the home page, the one where the user selects the desired genre for the music (second img). It may looks completely fine, but that same element already was a headache before and is here again. The given area is the cover-flow component, before i already fixed it (or so i thought), but it was looking bad (the 3d perspective where a bit strange) and would probably broken if i added new genres. I were trying to figure out a way to listen to the clicks in the card without any problems, that seems easy at first glance, but the 3d perspective in the element make other elements eat the click from one another, make the clicks dont be listened and so many problems that i nearly decided to erase it and write from scratch. I already found a way to do it by using the mouse position, the center of the screen and the card width (the genre img) to transform it in an value that can be used to select the exact card without any dependencies on the doom selector. It basically uses just some values, put in some calcs and get the difference between the current card (genre) index and the clicked. Im nearly finishing it, but i still need to figure out some values and more."}, {"post_id": 61879, "ts": "2026-09-05T01:17:53Z", "hours": 1.1772, "text": "Im improving the responsiveness at the home page (before was the player page), but for some reason that idk the emotion selection div is having a strange behavior, i will update what it is after i fix it. Take a look: (the item in the center should be centered)"}, {"post_id": 61218, "ts": "2026-09-04T01:30:11Z", "hours": 0.725, "text": "Hi again! Like said in the past devlog, im improving the responsiveness of the website, specifically in the player part. But it had some problems and where distorting when playing an video, now it resizes based on the screen size in a way that it stays ¨normal¨. The first video is the new way, the second is the old way. It still needs a lot of improvements, but it is going!"}, {"post_id": 60619, "ts": "2026-09-03T02:22:12Z", "hours": 1.4631, "text": "Making the website responsive Hi again! Like i said in some devlog, the website dont have support for mobile, that was because it was designed to be at kiosk mode and work just in desktops. but i decided to change that. First of all: the site where using a lot of absolute values of dimensions, so it where braking even in the desktops (it wasnt responsive at all). But i spent a while changing it, it is isnt ready and has some problems, but is better than before. (The mobile is still strange, i did not started fixing it yet). Credits: https://css-tricks.com/snippets/css/fluid-typography/ - This website shows about a way to make the texts become responsive for the screen using some calcs, it is worth seeing. The first video is how it was before, the second is how it is now"}, {"post_id": 60559, "ts": "2026-09-02T23:48:07Z", "hours": 0.7944, "text": "Creating a new helper Context: There was an class called youtubeFrameControls , this class basically where designed as an structure to help using the youtube iframe API, but with the time this class where becoming basically to hold just an function (and in a very inefficient way), because the methods that it had before (like the one that runs when the iframe is loaded) had to have more and more specific logic in the codes that used it, so they where useless (because the codes that where using it where rewriting it). What i did: I picked the only function that where being used and transformed it in an helpers (that can easily be customized). This function was the one that creates the player of the musics, and the function where called createPlayer . Also i removed the old class (youtubeFrameControls) and replaced it for this helper in every place that used it. It now is way more simple than before and can me more customized."}, {"post_id": 60001, "ts": "2026-09-02T02:58:53Z", "hours": 2.1603, "text": "Refactoring the copa script I where placing some scripts in a class. These scripts are related with the player functions of the copa script, so i pick all of them and placed in the same class. I did it to follow best practices, but i confess that i still got some doubts about when to create an class and when the variable or method should be static or private (#property), i will search and learn more about because maybe i will have to refactor some parts of the code following these rules of best practices. That was all for now, see ya!"}, {"post_id": 59339, "ts": "2026-09-01T02:28:57Z", "hours": 2.4744, "text": "Adding more bug checks I added some checks in the player class at the startExplication function that checks if the src (the url for the audio) is valid or not by doing an fetch with the HEAD method and checking if the return is an valid audio before trying anything in this function. Also i solved this error in the same function: Uncaught (in promise) AbortError: The play() request was interrupted because the media was removed from the document. https://goo.gl/LdLk22 This error was because the startExplication function where trying to play the audio before it was loaded, i solved it by making it play the audio just after it was load with the event listener canplaythrough . There was another error at the playMusic function where the code where trying to play the youtube video before it was loaded, i solved it by making it wait until it was CUED (Where the video isnt playing, but is loaded and showed). (The website was not created to be in mobile and dont has a lot of support, the video where recorded in my smartphone because i had to record the audio and the audio on my pc dont work. In the Future i Will add mobile suport, but right now im finishing the bugs and etc)"}, {"post_id": 58653, "ts": "2026-08-31T04:27:35Z", "hours": 2.7947, "text": "Adding a new description feature So basically there was an place where was designed to have the description about an music, but that was empty and where only finished today What it do It is petty simple, it just show an text about the music that is currently playing, also there is an audio that plays before the music starts playing, but this audios is played just one time before the music so if someone loses it or didnt listen well there was not a second chance to listen for that audio. Now there is this place that holds the same content, but in the format of an text that can be read whenever they want while the music is being played, that was what i added. Also that text can be hidden, so it will not stay using half of the screen every time (in the screenshot it is active) What this audios do This audio / text is part of the main purpose of the website, they give some fun facts about the music that may be useful someday in some kind of quiz or essay. Also the audio is played before the music and the music plays just after the audio finishes. That is to make whoever is listening listen to the entire audio before having what he (or she) wants, so they will not listen to the music and skip the audio."}, {"post_id": 58526, "ts": "2026-08-30T23:20:27Z", "hours": 1.3911, "text": "Studing about cache So basically i where studing about cache, the main ideia was to implement it in the sistem, but then i realized something: Theres is nearly no difference between cache and a normal request in an localhost project, adding the cache would not improve anything, sometimes it maybe even slow the website, because the page would need load more code. I realized it afther a while studing about it, but anyway lets focus on another thing. Also i where studing with google for devs: https://developer.chrome.com/docs/workbox/caching-strategies-overview"}, {"post_id": 56374, "ts": "2026-08-28T03:45:15Z", "hours": 1.0169, "text": "Toast applied and tested The toast notification component is now being used at the player class, i did some tests and it is working very nice, hopefully the user will not see it very often (because that would be a problem, the user must not see it unless there is an error playing the music). But why did i make it? It is used to show more about what is going on for the user, so they will not become anxious if it something is working or not. Why not use another notification system? Each notification system has its own use cases, the others would be very painful for the user. Imagine every time a simple error (that is simple for me) like the music fail to play there was an error that interrupt the use of the app with an popup or alert, that would be painful, dont it? That is why i used an toast notification, because it is temporary (disappears after some seconds) and dont stop the use of the website. Also there is a feature that i implemented for the same reason a few devlogs ago that add a fallback in the music search, so it wont show a message at every single combination. Lets calculate how many combinations we have: there is around 50 musics in the database, 22 genres and around 40 emotions, multiplying the genres and the music 880 combinations that the user can make. Now lets see how many musics we can get: each music have around 1.2 emotions and 1.2 genres, so we get 72 combinations that lead to an music . With that in mind, we can see that from 880 combinations, just 72 of them are useful combinations, so we get a 8.18% for getting a music, and 91,12% of not getting one. Consider that each failed attempt shows an error that stop the use flow of the website, but that was before the past devlog, now it tries again and again and only afther failing everything it shows an error, at that point it must really show an error. Thats all, sorry for the long boring text and thanks everyone that read, see yall later"}, {"post_id": 56331, "ts": "2026-08-28T01:58:42Z", "hours": 3.1336, "text": "The toast notification is finished So i finished it, it is a component that u adds in the code that u wants to use. I added 2 icons, 1 for infos and another for warnings. What i used and did The element that holds it all is an dialog , the icons are svg , the text is a span and the element that shows the time left is an progress . To update the time left i used an setInterval that runs at a 10ms delay and deduce 0.01 of the dialog value, so it will be smooth to see. Also there is an if inside that destroy the element and clear the interval when the value of the dialog reaches zero or less (In the past devlog i said about not using an if, but considering how low the cost for an if in that time is i decided to use it anyway). The function that creates the toast receives some params that will let it be customized by whoever is calling it: const icons = Object . freeze ({ INFO : infoIcon (), WARNING : warningIcon () }); function createToast ({ message , time = 5 , styles , icon = icons . INFO }) // the `message` is the displayed message // the `time` is the time until close // the `styles` is custom css styles for the element, it uses the dictionary format {} // the `icon` is the svg icon What else? I will apply it in some elements and post about. See you later!"}, {"post_id": 56188, "ts": "2026-08-27T20:27:52Z", "hours": 1.5956, "text": "Creating a toast notification system So rn im creating what i said in the past devlog about a toast navigation. This isnt finished yet, im still figuring out an way to check the end of the timer, i found some ways to do it, like using an simple if inside the countdown. I didnt comment but i am using an setInterval to decrease the time and an <progress> tag to show the value but that is a bad ideia, imagine doing 1 if every 50 ms? that dont cost a lot of processing power, but i still will search for other ways to do it just to check, if yall got any hints or ideas leave a comment. Also i will improve the design, the design is petty poor."}, {"post_id": 55334, "ts": "2026-08-27T02:23:29Z", "hours": 4.2383, "text": "Fixing errors and adding bug checks Hi everyone, so i were fixing some bugs that i saw that may broke the app, i fixed all of them (for now), here they are: There was a logic bug that a class (the one that controls the youtube iframe) where doing stuff that it wasnt supposed to do (not an unexpected behavior, but a logic that should be outside of it), it was an easy fix. There was a bug at the player class that when the provided sourceId (for the youtube iframe) where wrong or unable to use it crash and stopped doing anything else (like playing another musics). I tryied solving it in various ways, one was beffore the changes that i did in my last devlog, but i failed because the class that holds the player where hard to fix, this devlog fix it. I fixed it by adding some bug checks and, when some error ocurred, it play the next music. There was also a bug at the player class and youtube-iframe-controls class, that for a couple seconds in the start of the website it would broke if u tried to play a music. It was because in the start of the program the youtube API where unable to be used. To fix it i just made it wait until the API where ready using an ASYNC function. There was also a bug that, afther the past devlog, it was doing and request at the /api/songs with params at the wrong format. Afther the past devlog the API started using the params genre_id and emotion_id , but the frontend where passing with the incorrect name (genre, emotion). Something that i implemented I upgraded the mysql query that where being used to get more infos about the music, before it where just returning infos like name, author, sourceId, etc, but now it also returns the genre and emotion from that given music. I added a bug check at the player class, now if it fails it pass to the next music. Something that i want implement I want to implement a simple toast notification system that will apear when something fails, like the playing of some music. Others The youtube docs for the iframe where very helpful for this changes, check it out: https://developers.google.com/youtube/iframe_api_reference?hl=pt-br"}, {"post_id": 54690, "ts": "2026-08-25T19:06:05Z", "hours": 3.2633, "text": "Optimizating some piece of code So there was a certain part of the code responsible for the songs queue in the main route, that piece is a core function but where running a while true loop for no reason , here is the part: async start () { while ( true ) { // { emotion, genre, author, name, sourceId } const musicData = await this . #musicQueue . get (); this . createPlayer ( musicData [ ' sourceId ' ], null ); this . #showMusicInfos ( musicData [ ' name ' ], musicData [ ' author ' ]); this . #queueList . removeChild ( this . #queueList . children [ 0 ]); await this . #startExplication ( `/storage/ ${ musicData [ ' explicationSource ' ]} ` ); this . player . playVideo (); await this . #musicFinished . when ( true ); this . #musicFinished . set ( false ); } } Basically the code were calling it at the start and running it forever, but that code where a nightmare to maintain / implement, i tried to implement a safe check here for over 2 hours, but wasnt possible. I replaced it for a more efficient approach that do a loop in a different way, here it is: when adding a music, it checks if it is already playing, if no starts to play. when start to play it checks if there is a music in the queue for it to play, if no it stops playing, if yes it get it and play. When the music that is playing ends, it call the play function (from the above topic). That is just it, no while or constant loops, no overhead, it works by basically connecting all the codes in a way that they work together to maintain (or stop) the loop (notice how i said loop, it uses a loop but isnt a while or for loop, it connects the end of one code and the start of another, like a chain . I made it in the pull request #2, check it out: here"}, {"post_id": 54151, "ts": "2026-08-24T23:51:28Z", "hours": 5.8114, "text": "Fixing some forgoten code and more So at this devlog i were fixing some bugs in a specific ui / route called ¨copa¨, this is a special route added because a teacher asked our team to create them to use at some football games in our school. But since it was a hiddend route and mostly like a easter egg it hasnt been updated in a while and wasnt working anymore. What i fixed i was following a pattern where most of the images that each route used should be in a special foulder of storage (literally called /storage), but this mode (copa) where created before it and was following the old way Also there was some errors ocurred afther i changed the entire folder structure, so the copa mode where completely broken, i fixed it too. What i added I had a class about PHP + Laravel | API | Controlers in my course, afther that class i realized that the way the API (copa) where searching for data based on ID where wrong (was doing copa?id=…), i changed it to /copa/id There is a function that show the teams to the user to select one that he wants, but the teams list where hard coded and wasnt synced with the database. I made it use the database data instead of a hardcoded value ** That where all for that mode, but i didnt spent 5 hours just on it, i made more: ** Fixing (or making) some other bugs There is a script that controls the database that where holding and infinite single connection with the database, something like this conn = mysql . connector . connect ( ** configs ) cursor = conn . cursor ( Dictionary = True ) But all the codes where using the same connection and cursor, so i decided to apply a connecton pool and make each database call get a connection and a new cursor. Also i added some functions to abstrac the connection and query part: def __get_connection ( self ): conn = self . db_pool . get_connection () conn . ping ( reconnect = True , attempts = 3 , delay = 1 ) return conn def __execute_query ( self , query : str , params : list | None = None , dictionary = True , query_type : QueryTypes = QueryTypes . ALL ): conn = self . __get_connection () try : with conn . cursor ( dictionary = dictionary ) as cursor : cursor . execute ( query , ( params ) or ()) match query_type : case QueryTypes . ALL : return cursor . fetchall () case QueryTypes . ONE : return cursor . fetchone () case QueryTypes . EXECUTE : cursor . commit () return cursor . lastrowid or cursor . rowcount case _ : raise ValueError ( f \" Tipo de consulta não suportado: { query_type } \" ) If yall want to see it check here at my repo That was also the first time that i used a Enum (on code) and branchs (on github, but i didnt used them properly) Others There was also some other changes, check the repo GF-Silva/Ritualia What next Now i will add some bug checks on a piece of code that handle the video display using an youtube iframe."}, {"post_id": 52754, "ts": "2026-08-23T03:00:03Z", "hours": 4.8206, "text": "Changing some values to be relative I spent a while (more than i expected) changing some strange values that control some settings of a component called cover-flow (this component create and control the images that are displayed in the home screen). I spent more time figuring out what where each variable and lhe logic behind than acually writing.Before it had some hardcoded values that would probably broke if anything changes, i saw it and solved. I wasnt here for it, i was fixing another bug and fixed it before it broke. I also used some basic math of circles like angle of an arc. That is all for today"}, {"post_id": 52465, "ts": "2026-08-22T16:18:22Z", "hours": 3.1097, "text": "I spent some time correcting errors and logic problems, here they are: Error Correction Music playback would freeze when the music queue ended : This problem would break the app until you restarted it, but it was very simple to solve. I had simply made it remove the first instance of music from the HTML twice, which caused it to try to remove an element that didn’t exist, thus freezing the app. Removed an unnecessary loop : In the player section, there was a loop that iterated through all the elements (emotions) in a list to toggle the state of ONLY 1 ELEMENT. With the few elements it had (there were 3), this was minimal, but adding more could be detrimental to functionality. It only did this to toggle the state of the PREVIOUS element from active to inactive. I solved this simply by making it save the index of the last element and use that to access it. It took a while to work because javascript was treating 0 (the first indice / old indice when u start) as false in the if, but afther i figured out why it was simple to solve (if oldIndice != null) Implementations / Changes I separated the API/WEB routes : Previously, the routes exposed by the backend (such as /songs) were in the same file. This wasn’t a problem before, but with the addition of new functions, it could become difficult to maintain and prone to various errors, as the routes weren’t separated (a name could be the same). Therefore, I separated them into: /api (backend API codes) and / (frontend web codes). I put the genres in the database : Previously, the genres were in the frontend, and to add a new one, I would have to update both the backend and the frontend. To solve this, I simply added a route that retrieves the current genres (from the database) and uses the data (name / location) to load them into the frontend. I added the emotions to the database : The emotions had the same problem; although both (they and the genres) were in the database, the frontend wasn’t based on that data, so I did the same thing I did with the genres. I changed the name of where the music explanations were saved : I must have mentioned in a devlog that the folder inside storage was called /explication_source, and I also mentioned that the name was incorrect (because the audio source wasn’t there, nor would it be; the audio files themselves are there), so I changed it to /explication_audios"}, {"post_id": 48602, "ts": "2026-08-17T02:01:56Z", "hours": 3.6708, "text": "Updating the README I saw a post about how to structure a README, how to make it clear and etc. Afther i realized how wrong the old README was (it was confusing, and also was months out of date). So I chose some topics that would be interesting to include in and filled in a skeleton, spending some time learning what to do and what not to do. I also didn’t fill in some fields because they aren’t ready yet (they now are stored in my memory to add later). How it was before: https://github.com/GF-Silva/RitualIa/blob/9a2a7756c777a7042eca28309924e5a408bd561f/README.md How it is now: https://github.com/GF-Silva/RitualIa/blob/2dea5f80266f06e8633af1aa3c9430065cde9231/README.md There is a huge difference. Also i did some bugs and noticed how bad my commits are"}, {"post_id": 47776, "ts": "2026-08-15T22:55:35Z", "hours": 32.5314, "text": "After a development pause, here are the various changes made. Also, I never mentioned it, but this project was made by students focused on the school environment. (This time I finally got around to writing the devlog myself): Structure Moved main.py to the root Replaced mysql-connector with the official version : The added library was a version I didn’t recognize; I added the official one instead. Cleanup Removed some Code that wasnt being used. Backend Change the return value of the SQL cursor : Previously, the cursor returned an array, but for code readability and security, I opted to change it to an array. Structured Error 404 : The backend used abort in certain parts, but it returns HTML and certain parts of the frontend expected JSON, so I formatted the abort to JSON. This caused a headache, I hadn’t tested it (again lol) and when I saw it, it was time to present the project at school and I was having this error. frontend Fixed the CoverFlow component : An error went unnoticed in the creation of the component, this made the size and spacing of the images look strange, it was fixed to a certain extent. I implemented a new playback policy : The text about it got so long that I decided to open an extra topic. Playback Policy Now it search for the requested emotion + genre that the user choose, If It fails It search Just for the genre, if It fails again it search for anything. Now it falls into a fallback: This policy change was motivated by having to find a song to show in a presentation and failing. I reflected that if it was annoying for me, it would be for the end user (students) as well. Database Added new songs : I added 50 extras and their respective genres/emotions. (Also i wrote some helpers in python to help me categorize and search for the musics in youtube and get and structured sql output, that took quite a while) Saved the songs locally : Topic local saving Local saving But why would saving the songs in the cloud be a problem? Nothing comes for free, the server we were using to host the music had a monthly access limit, which was a silent problem that, thankfully, was noticed before it happened. My mistake, I didn’t even think about the possibility of saving locally and went straight to saving in the cloud, it must have been due to haste and inattention (always plan well what you are going to do before you do it, weigh the risks and benefits). Now, how it works The audios are saved inside the /storage folder. The database still saves the location, but this time it saves the relative path (e.g., /explication_audiis/fun_audio.extension). Why save the folder path as well? Won’t the audios always be there? Yes, but at some point the path might change (e.g., explication_source/youtube/audio_legal.extension). Future plans I’m going to improve my devlogs lol, this one got huge"}, {"post_id": 12818, "ts": "2026-06-20T23:46:13Z", "hours": 5.5386, "text": "RitualIa in Evolution: Refactoring, Optimization, and New Features 🎶 Hey everyone! I’m back with a cool update on what’s been happening here at RitualIa. After that commit where we transformed some scripts into helpers, things have evolved quite a bit. We’ve been doing a heavy refactoring of the project, focusing on organization, performance, and better code architecture . What’s changed: Structure & Organization: I removed legacy folders that weren’t being used, did a mega merge bringing everything from /frontend (the folder that where holding ALL the frontend logics) to the project root (with that the frontend and backend are in the same folder), and switched from FastAPI to Flask on the backend. Why the change of FastAPI to Flask: Because my supervisor or mentor (something like this) said and said again to, because there was other guys in the project (still is, but im the main developer, the others stopped doing anything like mounths Ago, and even while they where doing something i still was the main dev), these other guys where total starters and could not hold the learning curve of FastAPI (even with the fact that was Just me that where using It, because it was at the backend and i was the only developing at back). Code Quality: We made several methods private in the PlayerControls class, making the API cleaner and more secure. We also fixed the “enclosing class errors” that appeared. These small fixes make a huge difference in code reliability. UI/UX Improvements: We created a new CoverFlow component to replace GenreCylinder on the homepage – it’s much smoother and prettier now. We added support for async onClick, grab + touch in CoverFlow, and adjusted visual positioning to keep everything aligned. Oh, and we removed that unnecessary playerText that was cluttering the interface. New Features: A really cool feature that was added was the checking for duplicate songs in the queue . Nothing worse than accidentally playing the same song twice, right? Now that doesn’t happen anymore. Maintenance & Updates: We updated the fetches to call the new routes, moved the favicon to assets (because everything has its place), and focused on the details. What’s coming next: We are in a consolidation phase, laying a solid foundation for the upcoming features. The focus now is on ensuring that each component is doing exactly what it needs to do, nothing more, nothing less. Thanks for following along!"}, {"post_id": 11702, "ts": "2026-06-19T02:03:07Z", "hours": 1.0236, "text": "I’m transforming some duplicate code into helpers so they can be more easily used in new code."}, {"post_id": 11412, "ts": "2026-06-18T17:53:37Z", "hours": 1.2881, "text": "Introducing: The ‘Ritualia’ project is a project developed by me and some colleagues with the help of the school. In it, we have done and continue to do research and assembly with the aim of impacting the daily lives of students in our school and (in the future) other schools. It is an open-source project with an article soon to be published detailing the foundations used, etc. The readme is currently outdated because I am redoing part of the current architecture, but I will update it later to include information on how to assemble and create your own version. The project is divided into hardware and software. I, along with other members, am responsible for the software (which is usable on most computers), and the hardware is relatively simple (it only depends on a display + sound + a controller with an OS + the preparations for installation)."}]...
|
Title: Ritualia by @gabriel_ferreira | Stardance
Title: Ritualia by @gabriel_ferreira | Stardance
Devlogs:
Introducing: The ‘Ritualia’ project is a project developed by me and some colleagues with the help of the school. In it, we have done and continue to do research and assembly with the aim of impacting the daily lives of students in our school and (in the future) other schools. It is an open-source project with an article soon to be published detailing the foundations used, etc. The readme is currently outdated because I am redoing part of the current architecture, but I will update it later to include information on how to assemble and create your own version. The project is divided into hardware and software. I, along with other members, am responsible for the software (which is usable on most computers), and the hardware is relatively simple (it only depends on a display + sound + a controller with an OS + the preparations for installation).
I’m transforming some duplicate code into helpers so they can be more easily used in new code.
RitualIa in Evolution: Refactoring, Optimization, and New Features 🎶 Hey everyone! I’m back with a cool update on what’s been happening here at RitualIa. After that commit where we transformed some scripts into helpers, things have evolved quite a bit. We’ve been doing a heavy refactoring of the project, focusing on organization, performance, and better code architecture . What’s changed: Structure & Organization: I removed legacy folders that weren’t being used, did a mega merge bringing everything from /frontend (the folder that where holding ALL the frontend logics) to the project root (with that the frontend and backend are in the same folder), and switched from FastAPI to Flask on the backend. Why the change of FastAPI to Flask: Because my supervisor or mentor (something like this) said and said again to, because there was other guys in the project (still is, but im the main developer, the others stopped doing anything like mounths Ago, and even while they where doing something i still was the main dev), these other guys where total starters and could not hold the learning curve of FastAPI (even with the fact that was Just me that where using It, because it was at the backend and i was the only developing at back). Code Quality: We made several methods private in the PlayerControls class, making the API cleaner and more secure. We also fixed the “enclosing class errors” that appeared. These small fixes make a huge difference in code reliability. UI/UX Improvements: We created a new CoverFlow component to replace GenreCylinder on the homepage – it’s much smoother and prettier now. We added support for async onClick, grab + touch in CoverFlow, and adjusted visual positioning to keep everything aligned. Oh, and we removed that unnecessary playerText that was cluttering the interface. New Features: A really cool feature that was added was the checking for duplicate songs in the queue . Nothing worse than accidentally playing the same song twice, right? Now that doesn’t happen anymore. Maintenance & Updates: We updated the fetches to call the new routes, moved the favicon to assets (because everything has its place), and focused on the details. What’s coming next: We are in a consolidation phase, laying a solid foundation for the upcoming features. The focus now is on ensuring that each component is doing exactly what it needs to do, nothing more, nothing less. Thanks for following along!
After a development pause, here are the various changes made. Also, I never mentioned it, but this project was made by students focused on the school environment. (This time I finally got around to writing the devlog myself): Structure Moved main.py to the root Replaced mysql-connector with the official version : The added library was a version I didn’t recognize; I added the official one instead. Cleanup Removed some Code that wasnt being used. Backend Change the return value of the SQL cursor : Previously, the cursor returned an array, but for code readability and security, I opted to change it to an array. Structured Error 404 : The backend used abort in certain parts, but it returns HTML and certain parts of the frontend expected JSON, so I formatted the abort to JSON. This caused a headache, I hadn’t tested it (again lol) and when I saw it, it was time to present the project at school and I was having this error. frontend Fixed the CoverFlow component : An error went unnoticed in the creation of the component, this made the size and spacing of the images look strange, it was fixed to a certain extent. I implemented a new playback policy : The text about it got so long that I decided to open an extra topic. Playback Policy Now it search for the requested emotion + genre that the user choose, If It fails It search Just for the genre, if It fails again it search for anything. Now it falls into a fallback: This policy change was motivated by having to find a song to show in a presentation and failing. I reflected that if it was annoying for me, it would be for the end user (students) as well. Database Added new songs : I added 50 extras and their respective genres/emotions. (Also i wrote some helpers in python to help me categorize and search for the musics in youtube and get and structured sql output, that took quite a while) Saved the songs locally : Topic local saving Local saving But why would saving the songs in the cloud be a problem? Nothing comes for free, the server we were using to host the music had a monthly access limit, which was a silent problem that, thankfully, was noticed before it happened. My mistake, I didn’t even think about the possibility of saving locally and went straight to saving in the cloud, it must have been due to haste and inattention (always plan well what you are going to do before you do it, weigh the risks and benefits). Now, how it works The audios are saved inside the /storage folder. The database still saves the location, but this time it saves the relative path (e.g., /explication_audiis/fun_audio.extension). Why save the folder path as well? Won’t the audios always be there? Yes, but at some point the path might change (e.g., explication_source/youtube/audio_legal.extension). Future plans I’m going to improve my devlogs lol, this one got huge
Updating the README I saw a post about how to structure a README, how to make it clear and etc. Afther i realized how wrong the old README was (it was confusing, and also was months out of date). So I chose some topics that would be interesting to include in and filled in a skeleton, spending some time learning what to do and what not to do. I also didn’t fill in some fields because they aren’t ready yet (they now are stored in my memory to add later). How it was before: https://github.com/GF-Silva/RitualIa/blob/9a2a7756c777a7042eca28309924e5a408bd561f/README.md How it is now: https://github.com/GF-Silva/RitualIa/blob/2dea5f80266f06e8633af1aa3c9430065cde9231/README.md There is a huge difference. Also i did some bugs and noticed how bad my commits are
I spent some time correcting errors and logic problems, here they are: Error Correction Music playback would freeze when the music queue ended : This problem would break the app until you restarted it, but it was very simple to solve. I had simply made it remove the first instance of music from the HTML twice, which caused it to try to remove an element that didn’t exist, thus freezing the app. Removed an unnecessary loop : In the player section, there was a loop that iterated through all the elements (emotions) in a list to toggle the state of ONLY 1 ELEMENT. With the few elements it had (there were 3), this was minimal, but adding more could be detrimental to functionality. It only did this to toggle the state of the PREVIOUS element from active to inactive. I solved this simply by making it save the index of the last element and use that to access it. It took a while to work because javascript was treating 0 (the first indice / old indice when u start) as false in the if, but afther i figured out why it was simple to solve (if oldIndice != null) Implementations / Changes I separated the API/WEB routes : Previously, the routes exposed by the backend (such as /songs) were in the same file. This wasn’t a problem before, but with the addition of new functions, it could become difficult to maintain and prone to various errors, as the routes weren’t separated (a name could be the same). Therefore, I separated them into: /api (backend API codes) and / (frontend web codes). I put the genres in the database : Previously, the genres were in the frontend, and to add a new one, I would have to update both the backend and the frontend. To solve this, I simply added a route that retrieves the current genres (from the database) and uses the data (name / location) to load them into the frontend. I added the emotions to the database : The emotions had the same problem; although both (they and the genres) were in the database, the frontend wasn’t based on that data, so I did the same thing I did with the genres. I changed the name of where the music explanations were saved : I must have mentioned in a devlog that the folder inside storage was called /explication_source, and I also mentioned that the name was incorrect (because the audio source wasn’t there, nor would it be; the audio files themselves are there), so I changed it to /explication_audios
Changing some values to be relative I spent a while (more than i expected) changing some strange values that control some settings of a component called cover-flow (this component create and control the images that are displayed in the home screen). I spent more time figuring out what where each variable and lhe logic behind than acually writing.Before it had some hardcoded values that would probably broke if anything changes, i saw it and solved. I wasnt here for it, i was fixing another bug and fixed it before it broke. I also used some basic math of circles like angle of an arc. That is all for today
Fixing some forgoten code and more So at this devlog i were fixing some bugs in a specific ui / route called ¨copa¨, this is a special route added because a teacher asked our team to create them to use at some football games in our school. But since it was a hiddend route and mostly like a easter egg it hasnt been updated in a while and wasnt working anymore. What i fixed i was following a pattern where most of the images that each route used should be in a special foulder of storage (literally called /storage), but this mode (copa) where created before it and was following the old way Also there was some errors ocurred afther i changed the entire folder structure, so the copa mode where completely broken, i fixed it too. What i added I had a class about PHP + Laravel | API | Controlers in my course, afther that class i realized that the way the API (copa) where searching for data based on ID where wrong (was doing copa?id=…), i changed it to /copa/id There is a function that show the teams to the user to select one that he wants, but the teams list where hard coded and wasnt synced with the database. I made it use the database data instead of a hardcoded value ** That where all for that mode, but i didnt spent 5 hours just on it, i made more: ** Fixing (or making) some other bugs There is a script that controls the database that where holding and infinite single connection with the database, something like this conn = mysql . connector . connect ( ** configs ) cursor = conn . cursor ( Dictionary = True ) But all the codes where using the same connection and cursor, so i decided to apply a connecton pool and make each database call get a connection and a new cursor. Also i added some functions to abstrac the connection and query part: def __get_connection ( self ): conn = self . db_pool . get_connection () conn . ping ( reconnect = True , attempts = 3 , delay = 1 ) return conn def __execute_query ( self , query : str , params : list | None = None , dictionary = True , query_type : QueryTypes = QueryTypes . ALL ): conn = self . __get_connection () try : with conn . cursor ( dictionary = dictionary ) as cursor : cursor . execute ( query , ( params ) or ()) match query_type : case QueryTypes . ALL : return cursor . fetchall () case QueryTypes . ONE : return cursor . fetchone () case QueryTypes . EXECUTE : cursor . commit () return cursor . lastrowid or cursor . rowcount case _ : raise ValueError ( f " Tipo de consulta não suportado: { query_type } " ) If yall want to see it check here at my repo That was also the first time that i used a Enum (on code) and branchs (on github, but i didnt used them properly) Others There was also some other changes, check the repo GF-Silva/Ritualia What next Now i will add some bug checks on a piece of code that handle the video display using an youtube iframe.
Optimizating some piece of code So there was a certain part of the code responsible for the songs queue in the main route, that piece is a core function but where running a while true loop for no reason , here is the part: async start () { while ( true ) { // { emotion, genre, author, name, sourceId } const musicData = await this . #musicQueue . get (); this . createPlayer ( musicData [ ' sourceId ' ], null ); this . #showMusicInfos ( musicData [ ' name ' ], musicData [ ' author ' ]); this . #queueList . removeChild ( this . #queueList . children [ 0 ]); await this . #startExplication ( `/storage/ ${ musicData [ ' explicationSource ' ]} ` ); this . player . playVideo (); await this . #musicFinished . when ( true ); this . #musicFinished . set ( false ); } } Basically the code were calling it at the start and running it forever, but that code where a nightmare to maintain / implement, i tried to implement a safe check here for over 2 hours, but wasnt possible. I replaced it for a more efficient approach that do a loop in a different way, here it is: when adding a music, it checks if it is already playing, if no starts to play. when start to play it checks if there is a music in the queue for it to play, if no it stops playing, if yes it get it and play. When the music that is playing ends, it call the play function (from the above topic). That is just it, no while or constant loops, no overhead, it works by basically connecting all the codes in a way that they work together to maintain (or stop) the loop (notice how i said loop, it uses a loop but isnt a while or for loop, it connects the end of one code and the start of another, like a chain . I made it in the pull request #2, check it out: here
Fixing errors and adding bug checks Hi everyone, so i were fixing some bugs that i saw that may broke the app, i fixed all of them (for now), here they are: There was a logic bug that a class (the one that controls the youtube iframe) where doing stuff that it wasnt supposed to do (not an unexpected behavior, but a logic that should be outside of it), it was an easy fix. There was a bug at the player class that when the provided sourceId (for the youtube iframe) where wrong or unable to use it crash and stopped doing anything else (like playing another musics). I tryied solving it in various ways, one was beffore the changes that i did in my last devlog, but i failed because the class that holds the player where hard to fix, this devlog fix it. I fixed it by adding some bug checks and, when some error ocurred, it play the next music. There was also a bug at the player class and youtube-iframe-controls class, that for a couple seconds in the start of the website it would broke if u tried to play a music. It was because in the start of the program the youtube API where unable to be used. To fix it i just made it wait until the API where ready using an ASYNC function. There was also a bug that, afther the past devlog, it was doing and request at the /api/songs with params at the wrong format. Afther the past devlog the API started using the params genre_id and emotion_id , but the frontend where passing with the incorrect name (genre, emotion). Something that i implemented I upgraded the mysql query that where being used to get more infos about the music, before it where just returning infos like name, author, sourceId, etc, but now it also returns the genre and emotion from that given music. I added a bug check at the player class, now if it fails it pass to the next music. Something that i want implement I want to implement a simple toast notification system that will apear when something fails, like the playing of some music. Others The youtube docs for the iframe where very helpful for this changes, check it out: https://developers.google.com/youtube/iframe_api_reference?hl=pt-br
Creating a toast notification system So rn im creating what i said in the past devlog about a toast navigation. This isnt finished yet, im still figuring out an way to check the end of the timer, i found some ways to do it, like using an simple if inside the countdown. I didnt comment but i am using an setInterval to decrease the time and an <progress> tag to show the value but that is a bad ideia, imagine doing 1 if every 50 ms? that dont cost a lot of processing power, but i still will search for other ways to do it just to check, if yall got any hints or ideas leave a comment. Also i will improve the design, the design is petty poor.
The toast notification is finished So i finished it, it is a component that u adds in the code that u wants to use. I added 2 icons, 1 for infos and another for warnings. What i used and did The element that holds it all is an dialog , the icons are svg , the text is a span and the element that shows the time left is an progress . To update the time left i used an setInterval that runs at a 10ms delay and deduce 0.01 of the dialog value, so it will be smooth to see. Also there is an if inside that destroy the element and clear the interval when the value of the dialog reaches zero or less (In the past devlog i said about not using an if, but considering how low the cost for an if in that time is i decided to use it anyway). The function that creates the toast receives some params that will let it be customized by whoever is calling it: const icons = Object . freeze ({ INFO : infoIcon (), WARNING : warningIcon () }); function createToast ({ message , time = 5 , styles , icon = icons . INFO }) // the `message` is the displayed message // the `time` is the time until close // the `styles` is custom css styles for the element, it uses the dictionary format {} // the `icon` is the svg icon What else? I will apply it in some elements and post about. See you later!
Toast applied and tested The toast notification component is now being used at the player class, i did some tests and it is working very nice, hopefully the user will not see it very often (because that would be a problem, the user must not see it unless there is an error playing the music). But why did i make it? It is used to show more about what is going on for the user, so they will not become anxious if it something is working or not. Why not use another notification system? Each notification system has its own use cases, the others would be very painful for the user. Imagine every time a simple error (that is simple for me) like the music fail to play there was an error that interrupt the use of the app with an popup or alert, that would be painful, dont it? That is why i used an toast notification, because it is temporary (disappears after some seconds) and dont stop the use of the website. Also there is a feature that i implemented for the same reason a few devlogs ago that add a fallback in the music search, so it wont show a message at every single combination. Lets calculate how many combinations we have: there is around 50 musics in the database, 22 genres and around 40 emotions, multiplying the genres and the music 880 combinations that the user can make. Now lets see how many musics we can get: each music have around 1.2 emotions and 1.2 genres, so we get 72 combinations that lead to an music . With that in mind, we can see that from 880 combinations, just 72 of them are useful combinations, so we get a 8.18% for getting a music, and 91,12% of not getting one. Consider that each failed attempt shows an error that stop the use flow of the website, but that was before the past devlog, now it tries again and again and only afther failing everything it shows an error, at that point it must really show an error. Thats all, sorry for the long boring text and thanks everyone that read, see yall later
Studing about cache So basically i where studing about cache, the main ideia was to implement it in the sistem, but then i realized something: Theres is nearly no difference between cache and a normal request in an localhost project, adding the cache would not improve anything, sometimes it maybe even slow the website, because the page would need load more code. I realized it afther a while studing about it, but anyway lets focus on another thing. Also i where studing with google for devs: https://developer.chrome.com/docs/workbox/caching-strategies-overview
Adding a new description feature So basically there was an place where was designed to have the description about an music, but that was empty and where only finished today What it do It is petty simple, it just show an text about the music that is currently playing, also there is an audio that plays before the music starts playing, but this audios is played just one time before the music so if someone loses it or didnt listen well there was not a second chance to listen for that audio. Now there is this place that holds the same content, but in the format of an text that can be read whenever they want while the music is being played, that was what i added. Also that text can be hidden, so it will not stay using half of the screen every time (in the screenshot it is active) What this audios do This audio / text is part of the main purpose of the website, they give some fun facts about the music that may be useful someday in some kind of quiz or essay. Also the audio is played before the music and the music plays just after the audio finishes. That is to make whoever is listening listen to the entire audio before having what he (or she) wants, so they will not listen to the music and skip the audio.
Adding more bug checks I added some checks in the player class at the startExplication function that checks if the src (the url for the audio) is valid or not by doing an fetch with the HEAD method and checking if the return is an valid audio before trying anything in this function. Also i solved this error in the same function: Uncaught (in promise) AbortError: The play() request was interrupted because the media was removed from the document. https://goo.gl/LdLk22 This error was because the startExplication function where trying to play the audio before it was loaded, i solved it by making it play the audio just after it was load with the event listener canplaythrough . There was another error at the playMusic function where the code where trying to play the youtube video before it was loaded, i solved it by making it wait until it was CUED (Where the video isnt playing, but is loaded and showed). (The website was not created to be in mobile and dont has a lot of support, the video where recorded in my smartphone because i had to record the audio and the audio on my pc dont work. In the Future i Will add mobile suport, but right now im finishing the bugs and etc)
Refactoring the copa script I where placing some scripts in a class. These scripts are related with the player functions of the copa script, so i pick all of them and placed in the same class. I did it to follow best practices, but i confess that i still got some doubts about when to create an class and when the variable or method should be static or private (#property), i will search and learn more about because maybe i will have to refactor some parts of the code following these rules of best practices. That was all for now, see ya!
Creating a new helper Context: There was an class called youtubeFrameControls , this class basically where designed as an structure to help using the youtube iframe API, but with the time this class where becoming basically to hold just an function (and in a very inefficient way), because the methods that it had before (like the one that runs when the iframe is loaded) had to have more and more specific logic in the codes that used it, so they where useless (because the codes that where using it where rewriting it). What i did: I picked the only function that where being used and transformed it in an helpers (that can easily be customized). This function was the one that creates the player of the musics, and the function where called createPlayer . Also i removed the old class (youtubeFrameControls) and replaced it for this helper in every place that used it. It now is way more simple than before and can me more customized.
Making the website responsive Hi again! Like i said in some devlog, the website dont have support for mobile, that was because it was designed to be at kiosk mode and work just in desktops. but i decided to change that. First of all: the site where using a lot of absolute values of dimensions, so it where braking even in the desktops (it wasnt responsive at all). But i spent a while changing it, it is isnt ready and has some problems, but is better than before. (The mobile is still strange, i did not started fixing it yet). Credits: https://css-tricks.com/snippets/css/fluid-typography/ - This website shows about a way to make the texts become responsive for the screen using some calcs, it is worth seeing. The first video is how it was before, the second is how it is now
Hi again! Like said in the past devlog, im improving the responsiveness of the website, specifically in the player part. But it had some problems and where distorting when playing an video, now it resizes based on the screen size in a way that it stays ¨normal¨. The first video is the new way, the second is the old way. It still needs a lot of improvements, but it is going!
Im improving the responsiveness at the home page (before was the player page), but for some reason that idk the emotion selection div is having a strange behavior, i will update what it is after i fix it. Take a look: (the item in the center should be centered)
i finished the workings on the section of the home page that i where doing before, now has a good responsiveness for pc and a decent one for mobile. Now im working on the main area of the home page, the one where the user selects the desired genre for the music (second img). It may looks completely fine, but that same element already was a headache before and is here again. The given area is the cover-flow component, before i already fixed it (or so i thought), but it was looking bad (the 3d perspective where a bit strange) and would probably broken if i added new genres. I were trying to figure out a way to listen to the clicks in the card without any problems, that seems easy at first glance, but the 3d perspective in the element make other elements eat the click from one another, make the clicks dont be listened and so many problems that i nearly decided to erase it and write from scratch. I already found a way to do it by using the mouse position, the center of the screen and the card width (the genre img) to transform it in an value that can be used to select the exact card without any dependencies on the doom selector. It basically uses just some values, put in some calcs and get the difference between the current card (genre) index and the clicked. Im nearly finishing it, but i still need to figure out some values and more.
Finished the correction of the errors at the perspective and click in the cover-flow component. Now the perspective stays the same 150vw value (that is based on the screen width) and stays normal, with everything working. Oh man, that needed a lot of logic and out of box thinking finding another ways to check where the user clicked without using an normal click event listener (for those who lost the past devlog or didnt understood, i cannot use a normal eventListener in that because the clicks is detected in another element or in nothing, even with z-index or more in css, so the solution should be done entirely on javascript logic). The first video is the new way, the second is how it was before all changes in it
Im nearly finishing the workings on the responsiveness. Now the entire player screen is responsive and do not breaks the texts anymore (except for the description area), also the buttons that show you the next screen (the ones that displays ‘player’ and ‘generos’) are responsive too, the music queue is working perfectly fine, and the area that is used to select an emotion is nearly responsive too, it just needs some adjusts in the two buttons that change the current emotion because they become too small and uses a lot of space when the screen is too small, after that this screen will be finished. It is taking a really long time, the fact of how many different screen sizes exists makes it harder to finish, but now there is times that i even cannot see if i changed the resolution in some areas, because the system looks the same. I spent quite a while testing different resolutions and combinations of size, i didnt even noticed that i where 6 hours here, but now ik more about css (things like container-type + container based sizes and more ways to set the size of an text) The video shows how it is now, if u want to see the before just checks the past devlog.
The emotionDrum is now responsive! Now the buttons that you use to select the emotion are in the same side as the div that displays the emotion, so they dont fight for space anymore. This change is meant to fix the low size of the items in screens that are too small, in the new way we have more free space to display the emotions, there is not much to say. What else I did some minor changes in the size of some items at the player area, now they are easier to read! (I increased the size of some items)
The home is now fully responsive Ah that took a while, but finally it is fully responsive. Now the description at the player UI resizes based on the screen size and active a scroll behaviour when need, also i did some minor change at the emotionDrum perspective to make it show more emotions at the same time, removed the padding in the arrows at the emotionDrum so they will have more space and fixed an error in the genre drum that was making it perspective broke. After all these devlogs i improved how i make a code responsive.
Improving the performance After finishing the improvements in the responsiveness, now i decided to improve the performance. I used lighthouse to get insights (i learned about it in an tiktok video) and figured out that the images size were too high (were an png of 1280x1280px), so i saw more about that in the page: https://developer.chrome.com/docs/performance/insights/image-delivery (an link that google lighthouse gave). With that i saw how to decrease the size while staying with quality, i reached up to the sharp-cli tool, that makes the work of resize, convert and compress the image for me. The command used was that: npx sharp-cli -i * .png -o ./output resize 320 -f avif -q 50 --effort 6 --smartDeblock --preset photo The 320 is the size that i want it to be at the end, i got that value by seeing what was the computed value (the value that is being used in the website) in an high resolution pc (not the most higher one, the high but normal pc) with the resolution of 2500x1714px . With this simple changing the image went from 2mb to 40Kb! Nearly 100% decrease, and take in mind that there is more than one img, so the change were even higher. Also i created 5 different images: 320px, 480px, 640px, 960px e 1280px. With them the browser can choose which one is better for each device. With these changes i went from 35 points of performance to 59.
Improving the LCP (Largest content paint) performance I am improving the way that the website create and downloads the images, the main reason is to make the user see something faster. Before the system were doing 2 main things: Go trough the entire list of images, creating the elements and placing them into the page. Position them. But the position of the items were being done after the creation of the images, in another function. Now they are in the same function: it create the element, position it and add it to the page. That does not seem like much, but the code got way faster with that, probably because it dont need to go item by item in an list twice just to create an element. I tested the time to load the first element and it went from 8.63s to 6.43s , the test was made with 2200 elements (Yeah ik, it is a lot and normally it isnt that much, but i had to see how they were holding with more than 22 items). Also i fixed a bug that passed unnoticed while improving the responsiveness: At some point of images the visibility of the elements broke, that was because the perspective (what makes the 3D perspective of the component, and makes it visible with 3D effects) was based on the screen size, not the elements itself. What was the problem in that: Each element takes a size in the screen ‘makes the circle that shows the element be more and more near of our point of view’ (i cant explain it any better, search what is ‘perspective in an 3d element at HTML’ ). While it was approaching our point of view (POV), our POV were exactly at the same position (based on the screen size), so at some point the circle perspective would pass the POV and we would be unable of seeing it well. Now it is based on the elements: The 3d elements were basically a circle, i just used the diameter to change the perspective based on it. TODO: Maybe i lowered the image quality too much… I will fix it in the next updates. Also i were trying to improve the font settings to improve the performance, but that wast working so i decided to move on to this because it was more critical (took a while for me to jump to this, maybe like 2 hours trying and trying values in the font settings). i am also working in a way to load the images in parallel, with that it will take way less time (I didnt known about LCP before so i spent a while figuring out the way it works).
Improving the loading performance Now the system selects some images that needs to be shown faster than the others and making them load with priority. It was made by selecting the images that the user is seeing and defining some params like fetchPriority = "high" and decoding="sync" , the other images have the params: decoding="async"; loading="lazy"; contentVisibility="auto"; . With that config the LCP went from 2.4s to 0.5s . Also it loads the image in the start and dont change that config again, so the browser will be lazy while downloading these images. The problem is: only the first images are chosen as high priority, but their positions will be changed while the configs stays the same, that makes the browser lazy while loading them and makes the runtime performance became worse. To fix that i found about IntersectionObserver, that are meant to solve the problem of updating the images position fast. It was not applied yet, i found about it like 1 hour ago. What else Now the perspective of the emotionDrum is based on the elements that it have, before it was based just in the screen and would broke if something changes. I did a little change in the way that the script checks for clicks in the screen, now it has more accuracy (I changed the round system).
Adding an observer Now the script observe the card elements at the cover-flow component, classify their position and changes it visibility based on that. Im using an IntersectionObserver to observe every card, but it was designed to observe the position of 2d elements, so i had to figure out how to make it work well in an 3d element. The way it works is when the observe activates (it basically means that some card is in the range to load) it get the card info (like position and angle) and changes it visibility state based on that. Simple, right? No, it was a headache for the start to the top, nearly 4 hours of what i did was to fix the fact that it was meant for 2d. The observer were activating for cards that were in the back of the element, so i had to classify the card position into back or front by using its angle. But if i tried to use the card angle without anything else the script would broke (and did for 3 hours until i realized how to fix), so i had to use an second angle which is 360 - cardAngle (the 360 is the angle of an circle), so this new angle is based on the circle end while the other is based on the circle start. But the system still broke, because at some point one of these values would become negative and makes the if that classify the elements fail. The fix was using the absolute value in the if (it took 1 hour until i figured that; oh i were so happy when it worked). Why To improve the performance, so the browser will just load what is really important and not 50 images that the user cant even see. What else All that work definitely improved a lot my logic thinking and for the first time i used the truth table well. Now i just need to use the new code to change more the style of the images that are not in the screen. I did not deleted the code that i wrote in the past devlog, it was used in the new code to select how many images should be loaded in the same time. ** The first video is the result, the others is some problems that i had **
The observer is finished (nearly) Now the cover-flow has an observer that checks the position of the images and changes it styles based on that, so the images that the user is seeing is loaded while the others is hide. It still has some bugs and space for improvements that im still figuring out how to solve, like the image loading too late on the screen or, in slow internet connections, the image takes too long to load. Most of these bugs are because the observer (an intersectionObserver ) was designed for 2d contexts, not 3d (that were and still is an giant problem to solve). For this reason i was thinking about creating an observer from scratch in C++ that can work better in my 3d element, but the overhead would be high so im trying to solve in other ways before that. The feature was made using fetchPriority, contentVisibility and src (the system add the source just when the image is near the screen). OBS: I found about MutationObserver after this post, maybe i will use that instead of insersectionObserver. Oh man, at least if had found about this before… Aaaaaahhhhh i spent 9 hours in that, but at least a Lot of the new logic will be used. Anyway, lets cook
Adding a mutationObserver Now, instead of an intersectionObserver, the system use a mutationObserver that monitors the angle of the cylinder itself. With that the loading of the images will be insanely better, faster and user-friendly. Now the changes in the cover-flow is observed at the cylinder angle, not at each card. There was some problems in the journey like, for some reason, unexpected cards being loaded or not, the loading script at the observer dont triggering at all (that was caused by the speed of the observer) and an insane amount of cards being triggered at the same time (i still did not figured out why, but that isnt ‘harmful’). But man, i had to be creative here and remember about some concepts like concurrent programming, buffer / queue and apply some delays (because the mutationObserver is insanely fast and can trigger every millisecond). That all was meant to decrease the speed of the mutationObserver, because it was triggering with the most small change in the cylinder, so i made it trigger just when an expected amount of movement was made. The red/yellow collor is for me to visualize the loading state, it is just for debug The code isnt finished, i still need to implement the loading part, for now i just implemented the observer and basics of the loading part
The loading is done Features Now the loading at the mutationObserver is finished, it finally loads or unloads the images that should be (or not) loaded! The new observer is way faster, because it can detect the image way before it enters the screen, loading it before and having more time to do it. Also the system loads just a maximum of images (with the configs that i put it is 13), so it will not fry an cellphone. Problems The loading part was easy to do, i already done it before in the past observer (intersectionObserver), so i just had to pass the old code to the new part. But when the cover-flow element dont got atleast 13 elements the mutationObserver code breaks completely! Im still pondering how to solve it, when i do i will post about! Results The performance went from 78 to 100! The system is way faster! The user does not see a blank image anymore! Why The old method was slow even with a good internet connection, because it was loading the images just when the element was already in the screen, leaving to a perceptive delay for the user and a blank image to the user. Also i thought about creating an observer from scratch (maybe i was a little off my ideas, because that was insane), but the browser already had exactly what i wanted (the mutationObserver) Videos The new features The performance of the new feats The old features Reasoning While i was trying to sleep i thought about a system that fill the cover-flow with a maximum of images (like 10, or 13, or the code decides) at the DOM, using less memory to run. That system will free a lot of memory based on how many cards the cover-flow have. But that will have noticeable effects just with a lot of elements and probably would be hard to develop, maybe i will do in next updates. What next Im leading to the shipping, so i will improve metrics about the lighthouse, improve the readme and post it.
The loading is done and working! Fix I fixed the error that were happening when the cover had a certain amount of elements. Problems The fix itself was very easy to do, but doing it in a readable or without using 10 lines of code (i want things concise) was way harder than i expected. So i spent this entire time trying different ways to do it, each of them making everything worse. Reasoning The bug were with less than 14 elements, the script were calculating the first and last element index, it happened that these elements were behind the screen focus. Why? Because the values that the system was using were leaving these values, so i had to fix the way it was calculating things.
Fixing an error at the youtubeHelper Now the youtubeHelpers checks if the youtube API is ready before sending commands. Why Sometimes the API maybe is not finished yet, that was leaving an untreated error that was braking the entire website. How was made With a lot of pain and suffer. I thought “Oh hey, that will be a 15 minutes fix” - i spent 1 HOUR FIGHTING with the iframe itself, nothing was working and at some point i started thinking that even the API of YOUTUBE wasnt working, even the most basic function that should be triggered when the youtube finished the loading wasnt beeing activated, even the console.log(“Api READY!”) wasnt working, even when it worked it wasnt working well, the variable of the player was a promise and not the result. At the end i shut down my PC, defeated, without any energy left, with just hope that in the next day (this) that would be fixed (if not i was planning to ignore and make it a feature “Easter egg, if u dont join the website for a while it will not load!”. The problem here was just the position were the iframe api was in the HTML, it was being loaded before the helper script, so the helper was not there to check if it the iframe was ready or not, the fix was just move it a little down. Architecture It was just an promise, if the function checks that the iframe isnt available it await for it to be available. The check if it was available use the onYoutubeIframeAPIReady, easy easy (except for all the suffer that i went into).
The performance workings is finished and bug fix Fixes Now the logo z-index is lower, that is because the logo was ‘eating’ the click in more important elements. Also i did a small change at the cover-flow, that change fix the bug of the scroll at the element sudently stoping when at a certain position. The copa script had some old references to images that were leading to bugs, i changed it. Performance I already finished it in the past devlog, i was just checking if there was anything worth improving, but everything is working fine and now is time to improve acessibility. Most of the logged time was me trying to improve more some metrics at the lighthouse, but the work was too much for anything that is already good, so i decided to stop before i started focusing too much in it.
The accessibility workings is done Features Now the system has a new navigation system that allow users to navigate with just the keyboard! (The video was with just the keyboard) Why Why not? It was meant to improve the accessibility for users without mouse, or any another problem and because i was tired of having to use the mouse to debug something. How it was made Again with a lot of pain, the feature itself was easy but i had to fix some errors that went unnoticed, so it took more time. The feature detects when the user press a key and do an action based on wich key was. The accessibility was easy to get 100, but the metrics at lighthouse dont give all what the users will need, i had to think about the website usage and how would be the easiest way for the user. Results The accessibility went from nearly 69 to 100! What next Now i will work on the best practices! Update after the devlog: Nearly every metric is already maxed out lol, i will ship it very soon!
All done, it is time to ship Every metric at lighthouse it nearly perfect, im so exited to ship it!
Added install guides Now there is guides to help the user install for ubuntu, arch and windows. Notice that im a linux user and my pc is weak, so i could not test it on another operational system. Also the guide is in portuguese (all of them), please use your browser built-in translator or any of them to read if u dont understands portuguese I could test it on another linux distro, but i would have to go through all the install steps. Also i cannot try installing windows because it normally wipe out another OS installed on the same disc (i know that it just replaces the bootloader) and using a VM was not possible due to the amount of RAM and the processor that i have.
Configuring an ssh server! I configured an oracle cloud vm with ubuntu to host my website 24/7, that was because nest wasnt working in a while. Im running it at a local IP with http only, i will configure https today and maybe an domain, the IP is http://164.152.55.252 , notice that some browsers may block you from accessing and http website. UPDATE AFTER THE DEVLOG: I put an domain using duck dns: http://ritualia.duckdns.org Hardwork I had absolutely not a single knowledge about oracle cloud vm, so configuring it was an hell. Sometime my internet stopped working so i had to use my smartphone, this lead me to configuring an invalid ssh key and i had do configure everything from scratch, i spent 5 hours configuring everything, but that was ssh and wasnt tracked. But now everything is working fine. Thx oracle This vm is a 24/7 entire OS (Virtual Machine) that has some good free plans, without any cold start. Thx stardance Stardance now will have one more mount!!!!!! I still has roughly 40 hours of deep development to do after this ship, i will love to finish that in stardance!
It is time to ship! Now the system is working perfectly fine running at a vm in oracle cloud with a public domain, and a dns with duckdns at http://ritualia.duckdns.org/ Warning: It is just HTTP!
Added english readme I created an english readme, api and install Guide, so it will be easier to read and more accessible for worl-wide users
Ships:
What did i made I made an complete music play system that will help users to learn while listening to musics! I used youtube, flask, python, mysql, js and hope to make this! What else Solved a lot of painful bugs that were stopping the project from working Finished and made the music queue work Added music description labels Improved a lot the performance Made the website responsive Added a keyboard based navigation Fixed so much errors at the cover-flow that now i forgot how many Added bug checks before the play of each video on the player Created an toast component to show errors or infos Added 54 musics to choose and listen Challenges The most painful code was the player and the cover-flow, they were with a lot of hidden bugs that i had to figure out, feats that i had to make and pain to suffer! Now i figured out that i love and HATE making a website responsive! What im proud of MutationObserver: An observer that loads / hides an image based on its position at the cover-flow, this system took a while and worked very well. Error checks at player: The system can handle the error that happen and dont crash! Keyboard navigation: Everyone can use the keyboard to navigate now! Oracle VM: For the first time i used an ssh and hosted an website in my own machine (oracle, not mine)! How to test Access http://ritualia.duckdns.org/ , when you join and the page loads you will find a screen to choose an genre, select which one you want, after you will see an emotion selector, select the emotion that you wanna feel! You will see the player screen and an audio explaining the music (The audio is in portuguese), after the audio the music will play. Notice: The github and the website are in portuguese, please use your browser built-in translator or any that you want to use the software properly! Follow the installation guides at github if you want to install...
|
1792856941.6754558
|
1792943341.6754558
|
|
13978
|
Roblox Minigolf by @ThatRandomMaker | Stardance
|
ThatRandomMaker
|
1
|
170.69
|
2416
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-13T09:33:14Z", "hours": 167.0, "multiplier": 15.65, "payout": 2416, "blessing": "neutral", "text": "I’ve made a minigolf game in Roblox studio, featuring 3 maps and 22 stages in total, with cosmetics that can be bought for your golf club or golf ball, and some nice QoL features like a music menu, or a hide UI hotkey In my opinion, the main challenging thing was building all the maps. I’m not a great map builder, so making even one map or all stages took a lot of time, plus taking on the task of making 3 maps for the first release was, admittedly, a not-so-thought-through idea. Of course, this doesn’t mean that there was just 1 challenge, this was just the main one for me. Please note: due to the Roblox guideline changes, you must have an account that is 16+ Facial Age Estimation or ID verified to play the game. This can only be changed if the game reaches 250 “active” players. There are alternatives, which is either setting up the game yourself in Roblox Studio (takes some time), or just by watching the small feature demo. These restrictions/alternatives are mentioned in the README. (written per default questions)", "repo": "https://github.com/ThatRandomMaker/Roblox-Minigolf", "demo": "https://www.roblox.com/games/11200475351/Minigolf"}]...
|
[{"post_id": 76096, "ts": "202 [{"post_id": 76096, "ts": "2026-10-02T09:52:34Z", "hours": 2.2314, "text": "Finished the first room in the new Factory map! What lighting style do you think is better? Realistic or soft? (shadowmap) Realistic is img 1-2, soft is 3-4 At the moment, there won’t be any minigolf courses, as I’d rather finish the building first. Also, I had a few new ideas for the game that may make it a bit more “immersive” to say the least.. Will experiment with them and post something in the future if it works out."}, {"post_id": 72599, "ts": "2026-09-23T09:50:33Z", "hours": 1.4561, "text": "After a few prototypes, (a lot) I’ve decided to make another map, which a factory/warehouse type of map. So far, I’ve made these props: Conveyor Structual beam Light Unloading zones At the moment, I’m not really sure how I’ll make the stages in the map, but I have an idea of making them more interactive (somewhat similar to the arcade map.) One small mention, the map will likely be in beta or not fully finished (when or if I ship again), as Stardance is likely going to end soon."}, {"post_id": 67234, "ts": "2026-09-13T09:16:00Z", "hours": 4.0808, "text": "FINALLY shipping! (after this devlog) After likely losing a few hairs here and there (/j) after these 3 (almost 3 and 1/2) months, I deem minigolf to be done. I’m kind of suprised myself that the project took so long. I believe that this, by far is the longest project I’ve ever made. During the process, I’ve learned A LOT more about studio and luau overall, which will definetly help make better games (with better implementations). I have to admit, coming closer to the end there was a bit of burnout, but the result, in my opinion, was definetly worth it. I also want to say thank you to everyone that has supported me and this project, it means a lot :) Since the last devlog, I fixed and updated the few rough edges left in the game, GitHub repository and Stardance which are: Stardance: Making a new banner (old one didn’t even match the style of the game anymore) Adding a demo link & github repository link GitHub repository: Made a README that, in my opinion, is nice. It follows the requirements that the shipping guide/README guide Stardance mentions (controls, images, demo link, features, etc) Game: Changing the teleport screen to one that blends in during teleport Changed badges for new ones (icons) and requirements (now 1, 10 and 22 stages) Made the maze in stage 8 (grass map) harder to complete, was too easy before Changed all loading music Removed the funFacts moduleScript (not needed anymore) Stage 9 sign fixed to show status for Arcade_9 instead of Arcade_3 Updated desertMap particles to be thinner Changed loadUI to have fake shadow text instead of a thick UIStroke"}, {"post_id": 65465, "ts": "2026-09-10T16:40:51Z", "hours": 1.6436, "text": "Desert map complete! Well.. that was way faster compared to the other maps, which makes sense due to a desert.. well, being a desert. Anyway, now that the main game is done*, I’ve also made thumbnails and an icon for the game. I still need to make a README and a proper description for the game, to ship , of course. *Will likely rework the tutorial gui a bit and the ui shown when teleporting between maps Anyway, look forward to seeing a few more updates soon, as the aforementioned updates/additions shouldn’t take a while"}, {"post_id": 64885, "ts": "2026-09-09T16:18:59Z", "hours": 1.3189, "text": "Started work on the “Desert” map. All stages are now built! There are only 5 stages due to school taking most of my time, as usual. (and, there’s already 2 other maps in the game, so that’s that)"}, {"post_id": 64261, "ts": "2026-09-08T15:10:07Z", "hours": 8.0694, "text": "Arcade map complete! New: the outside has now been fully finished (instead of just being a baseplate) Smaller changes/additions: the arcade map now has seats , shapes on the floor and ambiance zones. As the second map is done, I’m getting closer to (finally) shipping this project, and (hopefully) getting good enough reviews to get my goal from SD. The “Desert” map will likely be a bit shorter compared to the arcade map (or even grass map, undecided.), as I don’t have that much time anymore due to school starting."}, {"post_id": 61466, "ts": "2026-09-04T12:15:21Z", "hours": 10.2056, "text": "Arcade map update The indoor area is close to being finished! It still, of course needs a few things to be completed (for example, the food area, filling the empty space, etcetera.) Next step is, of course, the outdoors! I assume it shouldn’t take as long to make as the interior was, but who knows Another thing the game still needs is ambiance zones. (and a new ambiance sound for the indoors, of course) I’m thinking of implementing this with just 2 parts for the indoors and outdoors, which should do the trick. Every day this project is (hopefully) coming a bit closer to being shipped, but progress will slow down a bit due to school starting. In an ideal situation this’ll likely be shipped in a week, or atleast I hope to get it sort-of-ship ready by that time."}, {"post_id": 54531, "ts": "2026-08-25T15:39:57Z", "hours": 4.0231, "text": "Arcade Machines They have interactable buttons (which do nothing, except move up and down) Nothing else to say about them, really.. Changes/additions: Changed song2 (main menu) due to likely being made by AI (cover seems to be aigen) Light mode setting now also changes the main menu Changed buttonFrame in-game to have wrapper frames, in result being affected by the UIListLayout, and now they don’t clip together when using smaller screens, but they can still be animated."}, {"post_id": 51588, "ts": "2026-08-21T11:08:56Z", "hours": 8.1239, "text": "Overhauled main menu GUI including new songs and animations! Demo is in the attached video as usual! So, I’ve spent a bit of time reworking the main menu , since the old one looked “temporary” instead of finished. In my opinion, the result seems to be pretty nice . I’ve made/added/reworked: Esentially every menu New animations when moving pages or when going in-game Added hover effects for buttons Icons for the main buttons Added fake shadows to text instead of the bad-looking UIStroke like before Added image backgrounds Replaced (most) old songs! (song 1, song 3-5) It still isn’t fully finished, as I need to implement a light mode for it, but otherwise it’s fully functional! When light mode for the main menu and (maybe) loadUI is done, the focus will likely shift back to building the arcade map. Every time I test the game I somehow find bugs on accident, whoops! Anyway, there were a “few” fixes/updates that were made during development of this overhaul: Fixed spinnyCamera (script) to not repeat points Updated generateNumber for spinnyCamera (script) to go through all the points instead of randomly pick one and look repetitive Fixed autosaveUI appearing in the main menu Fixed hideUIHotkey setting (a lot of things which I won’t describe as this post isn’t meant to be a wall of text) Fixed mainMenuButton UIScale bug by resetting UIScale on click Updated both cameraFolder(s) to be models instead of folders, with ModelStreamingMode to be set to Atomic (fixes delay or infinite yielding on slower devices) Updated mainMenuUI image background transparency to 0.5 for settingsFrame, cameraModeFrame and creditsFrame Updated hideHotkey setting textColor3 when text is “Set Keybind” and added UIPadding to the button for text not to clip Fixed soundLogic volume bug that didn’t reset audio volume when going back to the main menu, in result making the song silent Updated soundLogic to fade in song volume instead of immediately start playing it at full volume And a lot more… (these are just ones found after the overhaul)"}, {"post_id": 48935, "ts": "2026-08-17T14:30:42Z", "hours": 4.1728, "text": "New camera mode for the main menu! Demo is in the video! Before remaking/overhauling the main menu UI into light/dark mode (and, to look nice, of course), I’ve decided to rework the camera as it’s a bit of a weak point in the menu. It features: Camera sway Camera switching between points 15 different points for the camera Now, this has also reminded me that the main menu needs a little bit different of a song selection, as drum and bass for a gentle camera sway obviously doesn’t work. Miscellanous changes/fixes: Flying trees fixed statsGui (naming fix soonTM) bgcolor and background transparency changed in light mode to that of the old UI."}, {"post_id": 48115, "ts": "2026-08-16T12:28:38Z", "hours": 9.935, "text": "In-game UI revamp is complete! *and a few miscellaneous fixes have been made The settings menu has been revamped to add the light mode setting, now featuring page 1 and 2, and a few other settings which are currently in progress of being made. In my opinion, light mode looks decent but I still prefer dark mode. A new setting that is still a bit of a work in progress, but mostly finished is a hide UI hotkey , which as the name states, hides ui (in-game only). I still need to implement that the setting saves, but overall it works just fine. It’s made to only apply a keybind if you’re playing on PC, though. Fixes: autosaveUI loading/saving icon was still spinning when not visible. Fixed by seeing if the frame is actually visible (instead of if the frame exists, small typo) Shadow button now just changes immediately instead of waiting for the server to change the variable, now it just fires the remoteEvent only to save the setting autosaveUI UIstroke clipping fixed by changing it to apply inner instead of outer Tree sway intensity has been changed to be a bit lower, otherwise it’d look unnatural. Tree pivots fixed to be on the bottom for tree sway (this was a pain) Tree pivot issues: Changing tree pivots manually always broke for some reason. It took a few hours to fix them, then when I dragged the trees down it reset them. Upon pressing undo the pivots were still reset, not like they were before. Then, I tried fixing them without dragging anything, and the next time I opened studio it reset again. I found that ctrl+l may work, but that didn’t work either. Had to end up cloning everything over again, which somehow has made the shadows more intense in the dense tree areas, even though nothing changed between the two. This was NOT fun When writing this devlog, I found out that the oak trees have decided to fly in the air, so that’s great"}, {"post_id": 41247, "ts": "2026-08-05T10:30:05Z", "hours": 9.6728, "text": "UI Revamp (W.I.P) I’ve started reworking the main UI for the game because well.. the old one is to say the least - not good. So far I’ve reworked basically everything in-game (except the tutorial, but it won’t be reworked anyway as it can only be seen one time) I’ve also experimented a bit with hover tweens (button getting larger on hover) and sound effects, which have been implemented now. Another thing I’ve experimented a bit with is viewport frames , which are now used in the shop to show golf balls and clubs/“sticks” spinning. I’d want to possibly implement a “Are you sure you want to buy (x) item for (x) amount” in the shop, but that’s not planned at the moment. Things still unfinished that I want to complete (for UIs): Setting to enable/disable dark mode Light mode UI (as at the moment it’s dark mode only) Sound changes: “song2” in the main menu has been replaced due to it being striked by Roblox (not sure why!) Sound in the tutorial UI before accepting/declining the tutorial has been changed (same issue)"}, {"post_id": 37696, "ts": "2026-07-30T16:22:40Z", "hours": 4.7486, "text": "Every stage in the Arcade (map) has been built! The arcade now consists of 9 stages in total! New thing is that some are a bit more.. interactive , and a few are a bit difficult or tedious .. to say the least. (example of changing stages the attached video) Now that the stages are done, the game is inching a bit closer to completion! Now, of course, there may be ~15 or more things to still complete in the roadmap , but any progress is great. You may (or may not) be wondering how I made all of these in 4 hours. Well, I only have one explanation. I uhh… forgot to enable the plugin after making something else. Oops! (factory gambler prototype) Anyway, during this time a few small misc changes have been done: stageLogic (new script) has been added to well.. control the stages. (Stage 5, 7 and 9.) Shop UI trail naming has been changed a little. Blinking activity on stage signs has been removed. Note: Video player in SD is bugged. You have to click on the devlog, then go and click on the video for it to play."}, {"post_id": 35256, "ts": "2026-07-26T15:40:53Z", "hours": 8.5958, "text": "Hello again! I’ve started working on the arcade map, as the grass map is pretty much complete (just need to fix the ui a bit) I’ve decided to rewrite the playSound script a bit to not be hardcoded and play a different sound (depending on what string is received from the remoteEvent) instead of creating a remoteEvent and a new script for each one For example, now it can play either the golfhole sound or the sound for the ball disappearing in stage 2. Also, for the new automated door, I’ve experimented a little with spatial-ish sound. Turns out it’s really easy (for what I need, atleast) So far I’ve made a few things in-game and outlined a few ideas and a roadmap. Currently built: First three stages (which are glow-in-the-dark!) mostly complete parking lot Front of the building (although unfinished) A road leading up to the parking lot with a small grass patch. Automated door There may not be as much devlogs now, but the game is still in development!"}, {"post_id": 30623, "ts": "2026-07-18T10:46:31Z", "hours": 6.6422, "text": "Devlog 7 Additions: Grass map is now complete! Added lamp scenery to the stages, so you can actually complete them during the night Tutorial is complete with music! Shop UI now has shadows behind the buttons Added an invisible hitbox extension to the golfstick (mainly fixes issue, although still may need to switch to r6 due to animation packs) UI with stats (Cash, stages won) and sounds + cash counting up/down The tutorial now has animations for hitting the ball Changes: Tutorial made more visually similar overall First tutorial animation changed to: Move the golfstick not as far back/forward Move the golfstick a bit faster when hitting the ball Tutorial second animation changed to: Not rotate the golfstick as far (60 degrees instead of 90) Fixes: Stats UI centering on screen Before starting to work on the next map which is the Arcade, a few other settings will be added to the settings menu. Music UI may also change."}, {"post_id": 27248, "ts": "2026-07-12T17:13:40Z", "hours": 10.0919, "text": "Small update/Devlog 6 New additions: A tutorial has been added and is fully working! (still needs sounds but otherwise fully complete) Main menu disallows the player to join the Arcade and Desert map if they haven’t completed the tutorial yet. Map scenery is done! Only need the stages now A boost pad has been added (and a golf ball loop will be made!) Colorcorrectioneffect has been added to make the game brighter in terms of colors instead of dull. Fixes: Trees were optimized a little in blender (the fir tree originally had 6.6k faces when I opened the file.. oof) Renderfidelity on leaf parts for trees was changed to automatic (otherwise the trees would look like twigs from far away) Lights turn off when daytime cycle setting gets turned off Daytime cycle script fixed to turn off after turning off the nighttime setting Changes: Lighting from invisible walls on stages removed (will use lights that the player can see instead) Main menu UI has been changed to have shadows on the buttons. Main menu UI text also has a “manual” shadow on the “Choose your destination!” text UIStroke on stage signs is now a bit thicker (text is easier to read) Need to add/fix: UI that shows your current leaderboard stats instead of the default one Arm swinging the golfstick when moving with it (will probably either switch to R6 or just make an invisible hitbox for the tool) Note: Ignore the last map building update. The upload system completely broke for me. I can’t add an attachment to the devlog (so I can’t edit it) and deleting it just results in an error."}, {"post_id": 25189, "ts": "2026-07-09T08:12:53Z", "hours": 21.9158, "text": "Map development update #2 I’ve developed the map and it’s outer scenery a lot , although I’m running into optimization regarding te trees. (haven’t worked on a lot of stages though, only added the 4th one) Maybe the tree has a lot of vertices and I could somehow optimize it in blender? If so, that could be the main factor why the game ran better with less trees. Sunrays, bloom and a shorter range detpth of field have been added And a small experiment for a tutorial cutscene has been added too. In the process of this “devlog” I’ve also lost 11h of work Also, a new loading screen has been added and the one from TP has been fixed!"}, {"post_id": 19276, "ts": "2026-06-30T15:27:41Z", "hours": 4.4606, "text": "Map development update I’ve been working on a few ideas recently and have been attempting to build something “decent”. With a bit of trial and error so far I’ve made A tree And 3 stages 🤞 Perfect development pace, isn’t it? Anyway, here are the images showing stages and the tree."}, {"post_id": 17522, "ts": "2026-06-28T10:34:21Z", "hours": 10.4989, "text": "Small update/Devlog 5.5 I’ve been working on a few things for the game before starting to build the map and in result wanted to share these. Changes: “New” spawnPad and clearBall models, both now display their cooldowns with text and colors (locally for the player) I’ve replaced the low quality music in the main menu and added a “few” more songs, instead of just 11 songs now the game has.. 87! Now the main menu is also controlled by one script only, instead of having one in each button (in result also making porting easier to the other places) Also, the side buttons have been redesigned! Now they have a collapse menu button, and a button for returning to the main menu. This is so that more of the screen is available for mobile players (and a bit of the screen on PC, too). Returning to the main menu will be useful for example, if the player completes every stage in the Grass “destination”/Environment and wants to continue to the next one. Also the music UI has been fixed to work on 4K (didn’t properly implement scale on the buttons) And, a very special thing in my opinion is that the shop is finally complete ! Consisting of golf balls, trails, effects and different golf clubs (for a visual representation, go to the video after reading this post) The Golf club preview image on the tool changes per the equipped cosmetic too!"}, {"post_id": 15173, "ts": "2026-06-24T17:30:12Z", "hours": 10.3753, "text": "Devlog 5! New fixes and additions also shown in the video Features: Parts now spin the same speed at any fps, and one main script is now controlling them all using CollectionService The GolfStick now has customization added in the shop! Autosave has been added (saves every 60sec with visual UI) Completed levels and main menu settings get saved Main menu now has transitions! Fixes: Shop and music menu now finally properly scale on ALL resolutions! Shop buttons fixed with scale instead of sizing Disabled the back button when attempting to teleport to a different place Lights are fixed for the nightTime setting (didn’t turn on/off before) Ambiance now plays with the nightTime setting on A saved table is now used instead of searching for lamp parts each time the alpha tween runs (dynamic lighting on/off tween), in result saving performance. Fixed golf ball trail and effect visibility (now you don’t see other player trails and effects, which reduced visibility before.) Main menu play button fixed to not start volume fade out from volume 1, instead now uses the current volume of the sound Commented out debug prints that aren’t needed anymore (kept incase something breaks though) Fixed saves when altf4-ing from the game or the server shutting down. PlayerRemoving and BindToClose double saving upon shutdown Still need to replace: Placeholder images and items in the shop UI. After that, time to start building!"}, {"post_id": 11863, "ts": "2026-06-19T09:53:37Z", "hours": 8.5456, "text": "Devlog 4 fixes and additions New additions and fixes also shown in the video Features: Added badge rewards on milestones (5 badges so far, 1-1000 stages won) Setting for daytime cycle in main menu Dynamic lighting system Replaced placeholder images in the main menu (main menu is fully complete now) Seperate play UI instead of one button Spinning parts Loading screen Day and night ambiance Fixes: Dynamic lighting fixed to not depend the animation on ClockTime, instead make a tween and play it in a certain time range. Dynamic lighting fixed to not read ClockTime every time it changes (inefficient) Teleport handler fixed to handle any errors with servers and re-enable the menu incase of an unsuccesful teleport. Music UI fixed to show volume slider properly (not to combine the button to stop the current song playing in the same line) Implemented proper join song rng (otherwise it’d usually pick the first or the 4th song) Credit menu scaling Needs fixing: Shop and music menu scaling on 1440p screens (Credit to ShootingCat for finding this bug, since I don’t have a 1440p monitor) Disabling the back button when attempting to teleport to a different place When enabling night time, to turn the lights on, since the current dynamic lighting system only checks 2 timeframes, and doesn’t turn on otherwise. Still need to add/replace: Replace placeholder items and images in the shop frame Adding customization options for the golf club (or as it’s named, golfstick) 3. Finally start building the map (if nothing else comes up that needs fixing, or another idea that needs to be implemented)"}, {"post_id": 10585, "ts": "2026-06-17T12:07:24Z", "hours": 7.51, "text": "Devlog 3, game additions and hotfixes New additions shown in the video Additions: Implemented most of the main menu. Includes: Credits, settings (shadows and night time) Camera spinning around a specific (target) part for main menu Button to stop current song in the music menu. Replaced placeholder images and sounds in the music menu Spinning parts using tween(s) Fixes: Menu proper scaling for devices Player input and backpack UI disabling when in main menu Shop has an error sound (instead of purchase sound) when not having enough money for an item. Added default/none options to the shop for disabling trails and effects. Still need to add: Badge rewards on a milestone (changed from reward per stage) Volume slider or manual volume entering for the music menu Replacing placeholder items and images in the shop frame Images for the buttons, separate play UI in the main menu"}, {"post_id": 9284, "ts": "2026-06-15T16:15:08Z", "hours": 6.1644, "text": "Devlog 2, a lot has changed! Project demo available in the video Features: Shop UI has now been fully implemented and saving works Golf balls are now customizable by buying cosmetics from the shop (with in-game cash), cosmetics consist of golf ball colors, trails and effects Music UI has been added to the game for listening songs during gameplay Now there was one bad thing, which is that I somehow accidentally deleted the whole shop UI and had to remake it since autosave (of course) had to save in that exact moment.. Still need to implement: Badge rewards when winning a stage Main menu with setting(s) Spinning and moving parts (for unique stages) Volume control for music UI Replacing placeholder sounds in the music frame Replacing placeholder items and images in the shop frame Adding materials as a customization option for golf balls"}, {"post_id": 7945, "ts": "2026-06-13T07:59:58Z", "hours": 6.6408, "text": "Hello, Minigolf! Implemented the core mechanics for the game to work which are: Custom collisiongroups to prevent griefing (for example, your golf ball hitting one that’s owned by another player, or the golf club hitting the ground making it hard to play) Transparency on different clients, to know which golf ball you own Working goal with a sound effect and tween to fade out the ball before destroying it Side mechanics added: Barebones datastore implementation, now rewards cash and golf hole scored/won UI test for music selection menu and shop (to get trails, custom golf ball colors, etc), full implementation soonTM Still working on to implement: Working shop with equippable cosmetics Working music selection Main menu"}]...
|
Title: Roblox Minigolf by @ThatRandomMaker | Stard Title: Roblox Minigolf by @ThatRandomMaker | Stardance
Devlogs:
Hello, Minigolf! Implemented the core mechanics for the game to work which are: Custom collisiongroups to prevent griefing (for example, your golf ball hitting one that’s owned by another player, or the golf club hitting the ground making it hard to play) Transparency on different clients, to know which golf ball you own Working goal with a sound effect and tween to fade out the ball before destroying it Side mechanics added: Barebones datastore implementation, now rewards cash and golf hole scored/won UI test for music selection menu and shop (to get trails, custom golf ball colors, etc), full implementation soonTM Still working on to implement: Working shop with equippable cosmetics Working music selection Main menu
Devlog 2, a lot has changed! Project demo available in the video Features: Shop UI has now been fully implemented and saving works Golf balls are now customizable by buying cosmetics from the shop (with in-game cash), cosmetics consist of golf ball colors, trails and effects Music UI has been added to the game for listening songs during gameplay Now there was one bad thing, which is that I somehow accidentally deleted the whole shop UI and had to remake it since autosave (of course) had to save in that exact moment.. Still need to implement: Badge rewards when winning a stage Main menu with setting(s) Spinning and moving parts (for unique stages) Volume control for music UI Replacing placeholder sounds in the music frame Replacing placeholder items and images in the shop frame Adding materials as a customization option for golf balls
Devlog 3, game additions and hotfixes New additions shown in the video Additions: Implemented most of the main menu. Includes: Credits, settings (shadows and night time) Camera spinning around a specific (target) part for main menu Button to stop current song in the music menu. Replaced placeholder images and sounds in the music menu Spinning parts using tween(s) Fixes: Menu proper scaling for devices Player input and backpack UI disabling when in main menu Shop has an error sound (instead of purchase sound) when not having enough money for an item. Added default/none options to the shop for disabling trails and effects. Still need to add: Badge rewards on a milestone (changed from reward per stage) Volume slider or manual volume entering for the music menu Replacing placeholder items and images in the shop frame Images for the buttons, separate play UI in the main menu
Devlog 4 fixes and additions New additions and fixes also shown in the video Features: Added badge rewards on milestones (5 badges so far, 1-1000 stages won) Setting for daytime cycle in main menu Dynamic lighting system Replaced placeholder images in the main menu (main menu is fully complete now) Seperate play UI instead of one button Spinning parts Loading screen Day and night ambiance Fixes: Dynamic lighting fixed to not depend the animation on ClockTime, instead make a tween and play it in a certain time range. Dynamic lighting fixed to not read ClockTime every time it changes (inefficient) Teleport handler fixed to handle any errors with servers and re-enable the menu incase of an unsuccesful teleport. Music UI fixed to show volume slider properly (not to combine the button to stop the current song playing in the same line) Implemented proper join song rng (otherwise it’d usually pick the first or the 4th song) Credit menu scaling Needs fixing: Shop and music menu scaling on 1440p screens (Credit to ShootingCat for finding this bug, since I don’t have a 1440p monitor) Disabling the back button when attempting to teleport to a different place When enabling night time, to turn the lights on, since the current dynamic lighting system only checks 2 timeframes, and doesn’t turn on otherwise. Still need to add/replace: Replace placeholder items and images in the shop frame Adding customization options for the golf club (or as it’s named, golfstick) 3. Finally start building the map (if nothing else comes up that needs fixing, or another idea that needs to be implemented)
Devlog 5! New fixes and additions also shown in the video Features: Parts now spin the same speed at any fps, and one main script is now controlling them all using CollectionService The GolfStick now has customization added in the shop! Autosave has been added (saves every 60sec with visual UI) Completed levels and main menu settings get saved Main menu now has transitions! Fixes: Shop and music menu now finally properly scale on ALL resolutions! Shop buttons fixed with scale instead of sizing Disabled the back button when attempting to teleport to a different place Lights are fixed for the nightTime setting (didn’t turn on/off before) Ambiance now plays with the nightTime setting on A saved table is now used instead of searching for lamp parts each time the alpha tween runs (dynamic lighting on/off tween), in result saving performance. Fixed golf ball trail and effect visibility (now you don’t see other player trails and effects, which reduced visibility before.) Main menu play button fixed to not start volume fade out from volume 1, instead now uses the current volume of the sound Commented out debug prints that aren’t needed anymore (kept incase something breaks though) Fixed saves when altf4-ing from the game or the server shutting down. PlayerRemoving and BindToClose double saving upon shutdown Still need to replace: Placeholder images and items in the shop UI. After that, time to start building!
Small update/Devlog 5.5 I’ve been working on a few things for the game before starting to build the map and in result wanted to share these. Changes: “New” spawnPad and clearBall models, both now display their cooldowns with text and colors (locally for the player) I’ve replaced the low quality music in the main menu and added a “few” more songs, instead of just 11 songs now the game has.. 87! Now the main menu is also controlled by one script only, instead of having one in each button (in result also making porting easier to the other places) Also, the side buttons have been redesigned! Now they have a collapse menu button, and a button for returning to the main menu. This is so that more of the screen is available for mobile players (and a bit of the screen on PC, too). Returning to the main menu will be useful for example, if the player completes every stage in the Grass “destination”/Environment and wants to continue to the next one. Also the music UI has been fixed to work on 4K (didn’t properly implement scale on the buttons) And, a very special thing in my opinion is that the shop is finally complete ! Consisting of golf balls, trails, effects and different golf clubs (for a visual representation, go to the video after reading this post) The Golf club preview image on the tool changes per the equipped cosmetic too!
Map development update I’ve been working on a few ideas recently and have been attempting to build something “decent”. With a bit of trial and error so far I’ve made A tree And 3 stages 🤞 Perfect development pace, isn’t it? Anyway, here are the images showing stages and the tree.
Map development update #2 I’ve developed the map and it’s outer scenery a lot , although I’m running into optimization regarding te trees. (haven’t worked on a lot of stages though, only added the 4th one) Maybe the tree has a lot of vertices and I could somehow optimize it in blender? If so, that could be the main factor why the game ran better with less trees. Sunrays, bloom and a shorter range detpth of field have been added And a small experiment for a tutorial cutscene has been added too. In the process of this “devlog” I’ve also lost 11h of work Also, a new loading screen has been added and the one from TP has been fixed!
Small update/Devlog 6 New additions: A tutorial has been added and is fully working! (still needs sounds but otherwise fully complete) Main menu disallows the player to join the Arcade and Desert map if they haven’t completed the tutorial yet. Map scenery is done! Only need the stages now A boost pad has been added (and a golf ball loop will be made!) Colorcorrectioneffect has been added to make the game brighter in terms of colors instead of dull. Fixes: Trees were optimized a little in blender (the fir tree originally had 6.6k faces when I opened the file.. oof) Renderfidelity on leaf parts for trees was changed to automatic (otherwise the trees would look like twigs from far away) Lights turn off when daytime cycle setting gets turned off Daytime cycle script fixed to turn off after turning off the nighttime setting Changes: Lighting from invisible walls on stages removed (will use lights that the player can see instead) Main menu UI has been changed to have shadows on the buttons. Main menu UI text also has a “manual” shadow on the “Choose your destination!” text UIStroke on stage signs is now a bit thicker (text is easier to read) Need to add/fix: UI that shows your current leaderboard stats instead of the default one Arm swinging the golfstick when moving with it (will probably either switch to R6 or just make an invisible hitbox for the tool) Note: Ignore the last map building update. The upload system completely broke for me. I can’t add an attachment to the devlog (so I can’t edit it) and deleting it just results in an error.
Devlog 7 Additions: Grass map is now complete! Added lamp scenery to the stages, so you can actually complete them during the night Tutorial is complete with music! Shop UI now has shadows behind the buttons Added an invisible hitbox extension to the golfstick (mainly fixes issue, although still may need to switch to r6 due to animation packs) UI with stats (Cash, stages won) and sounds + cash counting up/down The tutorial now has animations for hitting the ball Changes: Tutorial made more visually similar overall First tutorial animation changed to: Move the golfstick not as far back/forward Move the golfstick a bit faster when hitting the ball Tutorial second animation changed to: Not rotate the golfstick as far (60 degrees instead of 90) Fixes: Stats UI centering on screen Before starting to work on the next map which is the Arcade, a few other settings will be added to the settings menu. Music UI may also change.
Hello again! I’ve started working on the arcade map, as the grass map is pretty much complete (just need to fix the ui a bit) I’ve decided to rewrite the playSound script a bit to not be hardcoded and play a different sound (depending on what string is received from the remoteEvent) instead of creating a remoteEvent and a new script for each one For example, now it can play either the golfhole sound or the sound for the ball disappearing in stage 2. Also, for the new automated door, I’ve experimented a little with spatial-ish sound. Turns out it’s really easy (for what I need, atleast) So far I’ve made a few things in-game and outlined a few ideas and a roadmap. Currently built: First three stages (which are glow-in-the-dark!) mostly complete parking lot Front of the building (although unfinished) A road leading up to the parking lot with a small grass patch. Automated door There may not be as much devlogs now, but the game is still in development!
Every stage in the Arcade (map) has been built! The arcade now consists of 9 stages in total! New thing is that some are a bit more.. interactive , and a few are a bit difficult or tedious .. to say the least. (example of changing stages the attached video) Now that the stages are done, the game is inching a bit closer to completion! Now, of course, there may be ~15 or more things to still complete in the roadmap , but any progress is great. You may (or may not) be wondering how I made all of these in 4 hours. Well, I only have one explanation. I uhh… forgot to enable the plugin after making something else. Oops! (factory gambler prototype) Anyway, during this time a few small misc changes have been done: stageLogic (new script) has been added to well.. control the stages. (Stage 5, 7 and 9.) Shop UI trail naming has been changed a little. Blinking activity on stage signs has been removed. Note: Video player in SD is bugged. You have to click on the devlog, then go and click on the video for it to play.
UI Revamp (W.I.P) I’ve started reworking the main UI for the game because well.. the old one is to say the least - not good. So far I’ve reworked basically everything in-game (except the tutorial, but it won’t be reworked anyway as it can only be seen one time) I’ve also experimented a bit with hover tweens (button getting larger on hover) and sound effects, which have been implemented now. Another thing I’ve experimented a bit with is viewport frames , which are now used in the shop to show golf balls and clubs/“sticks” spinning. I’d want to possibly implement a “Are you sure you want to buy (x) item for (x) amount” in the shop, but that’s not planned at the moment. Things still unfinished that I want to complete (for UIs): Setting to enable/disable dark mode Light mode UI (as at the moment it’s dark mode only) Sound changes: “song2” in the main menu has been replaced due to it being striked by Roblox (not sure why!) Sound in the tutorial UI before accepting/declining the tutorial has been changed (same issue)
In-game UI revamp is complete! *and a few miscellaneous fixes have been made The settings menu has been revamped to add the light mode setting, now featuring page 1 and 2, and a few other settings which are currently in progress of being made. In my opinion, light mode looks decent but I still prefer dark mode. A new setting that is still a bit of a work in progress, but mostly finished is a hide UI hotkey , which as the name states, hides ui (in-game only). I still need to implement that the setting saves, but overall it works just fine. It’s made to only apply a keybind if you’re playing on PC, though. Fixes: autosaveUI loading/saving icon was still spinning when not visible. Fixed by seeing if the frame is actually visible (instead of if the frame exists, small typo) Shadow button now just changes immediately instead of waiting for the server to change the variable, now it just fires the remoteEvent only to save the setting autosaveUI UIstroke clipping fixed by changing it to apply inner instead of outer Tree sway intensity has been changed to be a bit lower, otherwise it’d look unnatural. Tree pivots fixed to be on the bottom for tree sway (this was a pain) Tree pivot issues: Changing tree pivots manually always broke for some reason. It took a few hours to fix them, then when I dragged the trees down it reset them. Upon pressing undo the pivots were still reset, not like they were before. Then, I tried fixing them without dragging anything, and the next time I opened studio it reset again. I found that ctrl+l may work, but that didn’t work either. Had to end up cloning everything over again, which somehow has made the shadows more intense in the dense tree areas, even though nothing changed between the two. This was NOT fun When writing this devlog, I found out that the oak trees have decided to fly in the air, so that’s great
New camera mode for the main menu! Demo is in the video! Before remaking/overhauling the main menu UI into light/dark mode (and, to look nice, of course), I’ve decided to rework the camera as it’s a bit of a weak point in the menu. It features: Camera sway Camera switching between points 15 different points for the camera Now, this has also reminded me that the main menu needs a little bit different of a song selection, as drum and bass for a gentle camera sway obviously doesn’t work. Miscellanous changes/fixes: Flying trees fixed statsGui (naming fix soonTM) bgcolor and background transparency changed in light mode to that of the old UI.
Overhauled main menu GUI including new songs and animations! Demo is in the attached video as usual! So, I’ve spent a bit of time reworking the main menu , since the old one looked “temporary” instead of finished. In my opinion, the result seems to be pretty nice . I’ve made/added/reworked: Esentially every menu New animations when moving pages or when going in-game Added hover effects for buttons Icons for the main buttons Added fake shadows to text instead of the bad-looking UIStroke like before Added image backgrounds Replaced (most) old songs! (song 1, song 3-5) It still isn’t fully finished, as I need to implement a light mode for it, but otherwise it’s fully functional! When light mode for the main menu and (maybe) loadUI is done, the focus will likely shift back to building the arcade map. Every time I test the game I somehow find bugs on accident, whoops! Anyway, there were a “few” fixes/updates that were made during development of this overhaul: Fixed spinnyCamera (script) to not repeat points Updated generateNumber for spinnyCamera (script) to go through all the points instead of randomly pick one and look repetitive Fixed autosaveUI appearing in the main menu Fixed hideUIHotkey setting (a lot of things which I won’t describe as this post isn’t meant to be a wall of text) Fixed mainMenuButton UIScale bug by resetting UIScale on click Updated both cameraFolder(s) to be models instead of folders, with ModelStreamingMode to be set to Atomic (fixes delay or infinite yielding on slower devices) Updated mainMenuUI image background transparency to 0.5 for settingsFrame, cameraModeFrame and creditsFrame Updated hideHotkey setting textColor3 when text is “Set Keybind” and added UIPadding to the button for text not to clip Fixed soundLogic volume bug that didn’t reset audio volume when going back to the main menu, in result making the song silent Updated soundLogic to fade in song volume instead of immediately start playing it at full volume And a lot more… (these are just ones found after the overhaul)
Arcade Machines They have interactable buttons (which do nothing, except move up and down) Nothing else to say about them, really.. Changes/additions: Changed song2 (main menu) due to likely being made by AI (cover seems to be aigen) Light mode setting now also changes the main menu Changed buttonFrame in-game to have wrapper frames, in result being affected by the UIListLayout, and now they don’t clip together when using smaller screens, but they can still be animated.
Arcade map update The indoor area is close to being finished! It still, of course needs a few things to be completed (for example, the food area, filling the empty space, etcetera.) Next step is, of course, the outdoors! I assume it shouldn’t take as long to make as the interior was, but who knows Another thing the game still needs is ambiance zones. (and a new ambiance sound for the indoors, of course) I’m thinking of implementing this with just 2 parts for the indoors and outdoors, which should do the trick. Every day this project is (hopefully) coming a bit closer to being shipped, but progress will slow down a bit due to school starting. In an ideal situation this’ll likely be shipped in a week, or atleast I hope to get it sort-of-ship ready by that time.
Arcade map complete! New: the outside has now been fully finished (instead of just being a baseplate) Smaller changes/additions: the arcade map now has seats , shapes on the floor and ambiance zones. As the second map is done, I’m getting closer to (finally) shipping this project, and (hopefully) getting good enough reviews to get my goal from SD. The “Desert” map will likely be a bit shorter compared to the arcade map (or even grass map, undecided.), as I don’t have that much time anymore due to school starting.
Started work on the “Desert” map. All stages are now built! There are only 5 stages due to school taking most of my time, as usual. (and, there’s already 2 other maps in the game, so that’s that)
Desert map complete! Well.. that was way faster compared to the other maps, which makes sense due to a desert.. well, being a desert. Anyway, now that the main game is done*, I’ve also made thumbnails and an icon for the game. I still need to make a README and a proper description for the game, to ship , of course. *Will likely rework the tutorial gui a bit and the ui shown when teleporting between maps Anyway, look forward to seeing a few more updates soon, as the aforementioned updates/additions shouldn’t take a while
FINALLY shipping! (after this devlog) After likely losing a few hairs here and there (/j) after these 3 (almost 3 and 1/2) months, I deem minigolf to be done. I’m kind of suprised myself that the project took so long. I believe that this, by far is the longest project I’ve ever made. During the process, I’ve learned A LOT more about studio and luau overall, which will definetly help make better games (with better implementations). I have to admit, coming closer to the end there was a bit of burnout, but the result, in my opinion, was definetly worth it. I also want to say thank you to everyone that has supported me and this project, it means a lot :) Since the last devlog, I fixed and updated the few rough edges left in the game, GitHub repository and Stardance which are: Stardance: Making a new banner (old one didn’t even match the style of the game anymore) Adding a demo link & github repository link GitHub repository: Made a README that, in my opinion, is nice. It follows the requirements that the shipping guide/README guide Stardance mentions (controls, images, demo link, features, etc) Game: Changing the teleport screen to one that blends in during teleport Changed badges for new ones (icons) and requirements (now 1, 10 and 22 stages) Made the maze in stage 8 (grass map) harder to complete, was too easy before Changed all loading music Removed the funFacts moduleScript (not needed anymore) Stage 9 sign fixed to show status for Arcade_9 instead of Arcade_3 Updated desertMap particles to be thinner Changed loadUI to have fake shadow text instead of a thick UIStroke
After a few prototypes, (a lot) I’ve decided to make another map, which a factory/warehouse type of map. So far, I’ve made these props: Conveyor Structual beam Light Unloading zones At the moment, I’m not really sure how I’ll make the stages in the map, but I have an idea of making them more interactive (somewhat similar to the arcade map.) One small mention, the map will likely be in beta or not fully finished (when or if I ship again), as Stardance is likely going to end soon.
Finished the first room in the new Factory map! What lighting style do you think is better? Realistic or soft? (shadowmap) Realistic is img 1-2, soft is 3-4 At the moment, there won’t be any minigolf courses, as I’d rather finish the building first. Also, I had a few new ideas for the game that may make it a bit more “immersive” to say the least.. Will experiment with them and post something in the future if it works out.
Ships:
I’ve made a minigolf game in Roblox studio, featuring 3 maps and 22 stages in total, with cosmetics that can be bought for your golf club or golf ball, and some nice QoL features like a music menu, or a hide UI hotkey In my opinion, the main challenging thing was building all the maps. I’m not a great map builder, so making even one map or all stages took a lot of time, plus taking on the task of making 3 maps for the first release was, admittedly, a not-so-thought-through idea. Of course, this doesn’t mean that there was just 1 challenge, this was just the main one for me. Please note: due to the Roblox guideline changes, you must have an account that is 16+ Facial Age Estimation or ID verified to play the game. This can only be changed if the game reaches 250 “active” players. There are alternatives, which is either setting up the game yourself in Roblox Studio (takes some time), or just by watching the small feature demo. These restrictions/alternatives are mentioned in the README. (written per default questions)...
|
1792853249.3186958
|
1792939649.3186958
|
|
10338
|
Liable For Damages by @wilson_brunner | Stardance
|
wilson_brunner
|
1
|
214.95
|
2560
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-20T17:08:06Z", "hours": 211.0, "multiplier": 13.61, "payout": 2560, "blessing": "neutral", "text": "I made something! This was my first time coding outside of Arduinos, and one of the biggest learning experiences of my life. There was stress, time crunches, and pain, but it all came down to the wire. The most challenging part was drawing, of course, I’m never going to do this again JUST because of the assets. Thanks for playing", "repo": "https://github.com/wilbot3000/Liable-For-Damages", "demo": "https://wilbot3000.itch.io/liable-for-damages"}]...
|
[{"post_id": 75085, "ts": "202 [{"post_id": 75085, "ts": "2026-09-29T03:15:45Z", "hours": 3.1931, "text": "Started working on Liable for Damages 2.0 Devlog #1 Started working on better settings, mostly just things for volume, fonhts, and scrolling things. Whipped up some basic sprites in aseprite and took a day to implement them and figure out bugs, which were very annoying, mostly just related to button sizing. Had to mess around with Godot’s “containers”, for the first time, and it was quite bad, I’ve got some more work to do before I can get the sliders to work, but I’m close! Next stuff’s: -format sliders -start creating settings related to different busses -create saves for the sliders -implement button to change font -make font-changed labels for all maps -do bum ahh drivers ed instead of W Stardance I’ll hopefully release 2.0 within October, and I’mma try and devlog more! ~Wil"}, {"post_id": 72459, "ts": "2026-09-23T00:48:57Z", "hours": 0.7572, "text": "devlog for projects i forgot to add, really just time from learning to export godot games, very annoying um, fun fact, if you create a web game, change the file to index.html, or it literally WON’T WORK!!! Play my game (now!)"}, {"post_id": 71208, "ts": "2026-09-20T13:27:09Z", "hours": 10.0756, "text": "Final Release (or close to it) Game will be out soon, I just gotta ship, but everythings done, I finished sounds, and the ending yesterday, like a 8 hour coding marathon, so i could get this out in time. PLEASE play it, it’s called Liable for Damages, I don’t know where I’ll post it yet, but It’ll probably be on Itch.io or just the game application file. It’s like 150,000 kilabytes, so it shouldn’t be too bad for any computer, hopefully (mines from like 2009 and it ran fine) P.S! Please, (if you do play), comment bugs, especially major things, EXCEPT: -Player dissapearing when opening menu in elevator (don’t try this, im not fixing it it’s funny) -Bugs on top of head, (js kill them) Anything else is bad and needs fix thanks. Also sorry no volume controls, I was crunching down to finish."}, {"post_id": 69943, "ts": "2026-09-18T03:13:43Z", "hours": 10.1883, "text": "SFX stuff, final thing before ending, just finishing sounds, really annoying though ngl. done soon, big update at end"}, {"post_id": 67708, "ts": "2026-09-13T22:09:54Z", "hours": 11.4017, "text": "FINAL STRETCH time to lock in please oh no Im finishing the last level, no time to talk, but got like 4 things to finish THINGS: -level -boss fight -sounds -ending -bugs"}, {"post_id": 59735, "ts": "2026-09-01T17:44:56Z", "hours": 10.84, "text": "WORKING ON MY FINAL STRETCH I’m going to be locked in for the next few days, school starts, so I’ll have less time, but I got a boss fight and then bug fixing and sound effects, hears a sneak peak and one of the many things ive worked on. Also, I came up for a name. Looked up the universal laws for space and saw something about how “Countries of Origin are Liable for Damages caused by their space debris” and said “dang, thas dope” so now i have a name. In my next log ill have a longer devlog like a lite trailer, but the games pretty short, more like a showcase of learning. Thanks!"}, {"post_id": 55339, "ts": "2026-08-27T02:45:42Z", "hours": 9.8842, "text": "quick stuff, nothing much Finished some updates, but I’m locked so don’t have time to write much"}, {"post_id": 53129, "ts": "2026-08-23T15:40:04Z", "hours": 10.67, "text": "Another devlog about levels. Started work on the second (this takes so long) I can’t say much for fear of spoilers, but just say this involves WAY to much code and sprites (I hate drawing so much)"}, {"post_id": 51334, "ts": "2026-08-20T22:46:55Z", "hours": 10.2436, "text": "quick devlog. I need to do this cause i got 10 hours, Im working on the level system and im so tired please why is htis so hard D: D: D: D: D: D: D: D: D: D: D: D:"}, {"post_id": 49718, "ts": "2026-08-18T17:06:16Z", "hours": 9.2325, "text": "keypads, doors, and beginning of the first level. Im actually making a game! contains spoilers First of many… keypads were really difficult, every button, when clicked, multiplies the correct number by a multiplier, and adds it to a “code” variable. the multiplier is chosen based on what step of the code you’re on, (e.g, 1: 10000, 2: 1000, 3: 100, 4: 10, 5: 1), when you click the green button, it cross checks another variable with the one you typed, and if they’re the same, it sends the function to open the doors, and if not, everything resets. The other terminals and what not just open things when clicked on, so it’s just an easier version of the keypad."}, {"post_id": 47241, "ts": "2026-08-15T01:07:13Z", "hours": 8.0058, "text": "Flying enemy is complete, in record time! wow, 8 hours for an enemy, how quick D: This was a challenge, but also really fun. This enemy is the flying one, which made it a little more difficult than just the copy and paste of old ones but still pretty cool. It works using a Navigation Agent, which is like Godot pathfinding. Fast forward three hours and a whole lot of troubleshooting, but that works. The enemy detects the player in the same fashion as the other enemies and then activates the nav-agent to being movement. It’ll follow the player through vents, passages and really anywhere. The fly has three main detection circles, the first one tells it to move towards the player, if the player enters the second one, it’ll freeze and stop moving, and if the player gets even closer, it’ll try to move away (by reversing the velocity var outputted by the nav-agent, iyc) the enemy’s one hit, acourse, but is really annoying to attack, (ill rework ground pounding to make this easier later). The enemy has a shooting attack, that is on a 6 second timer if it can see the player, otherwise it’s just on hold. its shots are pretty slow, so there easy to avoid, but in a crowded fight ya never know. The main quirk of this enemy is it has a really long forgetfulness timer, so even if it can’t see you, it’ll continue to follow for quite a long time, much longer than other enemies. Next:! -stationary, weird wall tentacle that shoots at you -egg spawner that hatches into 1 of three enemies (mystery ooh) -doors (ikr)"}, {"post_id": 44372, "ts": "2026-08-10T02:47:57Z", "hours": 2.9308, "text": "Enemy is complete: Chomper! Lot of work, but got it done. This is the, please avoid, very dangerous, you will die enemy. I haven’t balanced its health yet, and I’m not going to for a while, so it looks like an easy kill in the video. The weird quirks of this enemy are mostly in its charge attack, that rushes the player. It’s pretty easy to avoid, but once again i haven’t done attack balancing, so it may become harder later. The majority of the enemy works just like the lil guy, so idk read that devlog. But there is two major differences: LIST: gasp 1.!!!1! : idle stuff -really just a randomizer -if enemy is idling, starts a timer, and when it runs out of time, it does one of two things (using a randi() function) -if the outputs a 1, nothing happens, but if its a 2 it flips the enemy, thas all -the main reason for this is that since this enemy is so big, making it a tad more animated than the lil guy felt important to me, and also because the detection areas for the big guy are skewed towards the front, so him turning around makes the player sneaking up on him a little less common, it’s generally just for Q-O-l (slang btw) (only cool people understand) 2.!: dash -dear lord, why was hard so much D: -Wasn’t actually that difficult, I spent a lot of time trying stuff before realizing I just unleash my inner enginneer and do it step by step ’till it works, which it did. -first, theres three detection boxes, one for walking towards the player, one for the chomp, and one for dashing, if the player enters the dash-box, a timer will start -when the timer ends, the charge animation plays, which halfway through, activates a function too add velocity (actual charge part of charge) -If the enemy hits a wall, player, or box, it stops moving, but in the case of the player it plays a second animation (dash_hit) that looks like a chomp and kills the player if it hits them. Theres another If statement that sets velocity back to 0 when this happens also. OTHER CHANGES: -I removed the players health really, I like games that are one shot, because it’s subjectively more fun, I’ll make the player death a little more explosive if I have time. I’ll probably make them have three health but that’ll change when I do attack balancing -made the lil guys attack timer shorter, makes him more dangerous. NEXT TIME PLANS: -hopefully in one day (ima lock in rq) -gonna add a flying enemy, -literally just a tad fly, like 5x5 pixels, it’ll look at the player and fire acid that’ll kill you -i might change the death animation to be more BOOM (IYKWIM) :D -my goal is too complete the flying guy 100% tomorrow, but I got other stuff to do so we shall see -also it’ll be nice to not have to do major animating besides literally 6 pixels splaterring -if extra time, I’ll make a weird egg thing that turns into the fly THANKS FOR READING! as always (not really) go make some interesting, and uh learn something new every day please (P.S I made some changes after I took these videos so it still looks and feels kinda bad but not actually rn) ~Wilfred"}, {"post_id": 44000, "ts": "2026-08-09T14:18:20Z", "hours": 11.6767, "text": "Little enemy beginnings I haven’t actually finished anything yet, but I need to devlog anyways, but I have started to finish the second enemy, which is also the framework for more."}, {"post_id": 41460, "ts": "2026-08-05T17:57:18Z", "hours": 12.2908, "text": "player movement is complete!! went on vacation, so fell behind a bit, but finally got this done. I spent a lot of time thinking on how to make player movement good, and then thought of my BOTW playthroughs, where you can either hold your attack and have a powerful slash, or click fast and hit three in a row. First addition!: Ground pounds were pretty interesting, all it does is forces the player down hard if they attack in the air, decreases stamina, and then hits the ground, I added a dust cloud that explodes when he hits the ground, which just plays the animation and then disappears. I had to do some fenagling with this because the code knows when to start the animation because the player will be ground pounding and on the ground, which starts the poof and then stops ground pounding, which also keeps the animation from playing multiple times. SECOND: Annoying stupid player attacks. Tried to finish this in a day, so I was working till 11:00 at night, but I got the animations done and what not. When the player hits/holds the attack button, it starts a stopwatch that increases, when the player releases the button, depending on the time on this timer, it will either play the first of 3 quick attacks or the big attack, which does more damage. If the quick attacks are chosen, the first one will play, three things happen when thats starts, 2 timers start, and player velocity increases to 500. at the end of the attack, there are three things can happen, the player can wait until the animation ends, they can attack again, or they can walk to reset the attack earlier than waiting, the first timer forces the player to wait to cancel the attack by walking, and the second one stops their velocity so they jolt forward. at the end of the animation, a function is played that: starts the reset timer for the attack A variable increases that sets the next attack to be the second or third in the sequence, instead of the first and a if statement that resets the variable to 0 if it gets to 3. Theres some other details for weird situations, like falling off the edge and ground pounding while attacking, or the variable not resetting weirdly. But all of that was like an hour. Thanks for reading: Play my game when it comes out so I have a reason to finihs Also I need a name for the game (please, I suck at naming) and go play Legend of Zelda (or Just Cause 3) (or research operation Just Cause) #USinvadinglatinamericaAGAINfornoreason P.S (I was gonking on being up till eleven, but I did like 3 hours of animating and coding in like 30 minutes while being food deprived and barely awake because deadlines = lock in, so if you need to lock in just don’t sleep ig ) also, I’m technically not done ‘cause ma boy needs a sawed off before I’m done here Yee Haw"}, {"post_id": 35583, "ts": "2026-07-27T03:37:24Z", "hours": 1.1306, "text": "MOVEMENT PART # (3) les go took me short time, it’s ten o’clock im tired, pretty simple stuff. If player is sprinting and the crouch button is pressed, the normal function is overridden and a slide is activated, this just sets the animation to slide and the X velocity of the player to a high number. There’s some other code for just general quality of life, like stopping if you hit a wall and keeping you from changing directions, but the REALLLY cool part is jumping. Like in real life (trust), while sliding the player will jump further, which permits some cool movement combinations, like vaulting over gaps and climbing 4 block walls. I have to work out stamina changes depending on jump strength and stamina decrease for vaulting, but the movement getting pretty fleshed out. P.S, after I took the video, I changed the sprint stamina decrease to be a consistent decrease instead of being choppy like in the video, it’ll be in the next log, but it was just quality of life. NEXTS STUFFS: -dash -enemy lunge -stamina from hoisting and slide-jump stamina increase Thanks for reading!"}, {"post_id": 34965, "ts": "2026-07-26T03:00:51Z", "hours": 3.8936, "text": "Crouching! #2 in the player movement chronicles! Surprisingly, I also managed to create a whole new 5 animations! slide, crouch idle, crouch walk, and the sledge versions (not slide cause ya can’t sprint with sledge). I implemented all but the slide, which’ll take a long time, so I’m going to keep it off a bit. This was really straight forward to add, and for the first time in a long time, i had like only 1 problem . I really just had a piece of code that asks, “did ya click the crouch button?” and if so, it toggles crouch. IF (and only if!) the crouch is on (or “true”) the idle and walk animations are switched to their respective crouch variants, and the normal player hitbox is replaced by a shorter-er-est one. To bar the player from un-crouching in the midst of a tunnel, I added 2 new raycasts to the front and back of the players head facing up, these casts detect if there is a block above the player, and if either one of them detects anything, the player is unable to un-crouch until they are unshielded. Another quick thing I had to fix a bit was the raycasts detecting the player, which broke EVERYTHING so I just turned good ’ol collision mask/layer 20 into the super-cool (ALL-NEW !!) “player raycast collision!!!” which just only lets them interact with the floor and boxes, so yippee NEXT STEPeths!: -slide ): -enemy lunge -other player attacks (only hard attack right now which is bad)"}, {"post_id": 34347, "ts": "2026-07-24T23:18:41Z", "hours": 13.5214, "text": "Mantling and fixes Hi. I have had a very long week. I spent a lot of time working on sprites, mostly for the game 3rd level (no spoilers, (but that’s pretty boring) so heres the interesting part. I’ve been focusing on revamping player movement to make it feel more interesting and fun, and this is a good start. Mantling! if you don’t know what this is, it’s what you do when you get out of a pool without a ladder or staircase, pretty much just “pulling yourself up” The player does this by using raycasts, I added three, but one is for something else. One of them detects a wall in front of the player, and one detects a wall above. The code uses these casts to detect if the player is up against a wall, and if there is no wall above the player, pretty much checking if there is a mantalable ledge. If there is, the code says “you can mantle” Another line says: if you can mantle, and you are not on the ground, and if the player clicked space (Jump), then mantle. The annoying part was animations. When the player begins mantling, the hitbox and player position is frozen in space, and position is snapped to the nearest block to line up the animation. the only thing that moves during the animation is the player sprite, which means at the end of the animation, when the players position is finally changed, the player sprite needs to snap back at the EXACT same time, or it looks bad, which was hard. The other annoying part was the camera snapping randomly, as it moves with the player and not the sprite. I fixed this by just temporarily turning on the cameras position smoothing while the mantle is happening and then turning it off when the player moves again."}, {"post_id": 31003, "ts": "2026-07-19T01:34:03Z", "hours": 14.4064, "text": "sprites! done some stuff, mostly just game planning (sadly didn’t get time for because notes but I got a lot done, mostly just some serious drawing. I finished some tiles for the first and second levels, and some tiles for the next three."}, {"post_id": 26947, "ts": "2026-07-12T01:17:07Z", "hours": 4.2967, "text": "Quick hurt animations Main thing I added was animations for death and injury. I first added knockback when hit. It just takes the player’s scale.x (what i use for flipping the sprite) and multiplies it by 200 to the player velocity, since the scale is either 1 or -1, it changes the direction the player is thrown (in the future i’d like to make the scale the enemies direction, not the players, as if the player is flipped in the wrong direction, it could have knockback in the wrong direction (very bad) Theres was already a variable to detect if the player was being hit that was used for testing, so I just implemented that to play the injury animations. i also detected if the players health was zero or below after being hit, and if so it would make the player play the death animation instead of the injury. I have currently unimplemented animations for a before-death injured player, so after they are hit for the last time they will stand for a bit before collapsing. NEXT STUFF: (hast beeneth narrowed list) -add enemy knockback (only when injured, lok wierd when die) -fix player knockback thank yoh forth coming to my TED talk"}, {"post_id": 25010, "ts": "2026-07-08T22:32:29Z", "hours": 12.3911, "text": "I’m gonna start this by saying: I HATE animating! Aseprite made this so much easier, but GOD this was difficult… I think I had 5 situations this time around where the problem was the littlest change in the world, and I just needed to go to bed. I made 3 different walk cycles, before giving up and figuring out how to do it for real, it was only a little difficult after that. I have unused hurt, death, and push animations, and need to implement a shorter attack and smooth some things out still (jumping while attacking cough ) Almost all of these 12 hours was fixing stupid little problems and changing little pixels, probably some of the worst time ive spent on this project yet… (but still really interesting) NEXT STEPS::: -fix walk so it looks sensible (drifting) -make jumping illegal hwilst attacking -add short attack -customized tile map ????? Thank you for reading goodbye I want to stop animating"}, {"post_id": 21598, "ts": "2026-07-03T17:09:19Z", "hours": 4.0883, "text": "enemy attacks/better particles. This took some work, but not really… The enemy can now attack and hurt the player the codes really just the same as the player attacking the enemies. Theres a hurtbox in the player that gets hit by an area in the enemy that makes them take damage. The particles took some more difficult work. Godot has CPU and GPU particles, which apparently are different, it just depends on what in your computer renders them. I used GPU particles, because they run better and can collide with things. I whipped up a sprite sheet for the particles in Aseprite, which looked a lot better than the weird purple generic Godot things. The particles only collided with light occluders??, so I added an occlusion layer to the tile map, at some point I hope to create a better system for when they hit the ground, but thats not my priority right now. Next STEPS!!!!! -main thing is that the enemy has a lunge attack that I haven’t implemented yet, so thats next. -starting on the player sprites, this is a LOT of work, so its gonna take me a lot of time, but no time like the present"}, {"post_id": 20225, "ts": "2026-07-01T19:32:16Z", "hours": 5.3086, "text": "Some more enemy development! -first “enemy” in the game, a pretty basic little thing. -designed on Aseprite, took some time to set up with hakatime, but turns out I was using a version only used on Mac OS, so no kidding it was giving me trouble -I created unused animations for a lunge and whip attack animations that I will implement soon (?). NEXT STEPS :D : -stop the player from colliding with the enemy’s hitbox, it’s very annoying, and in the future will we a necessity for having many creatures in the same room -add the enemy attacks, I’ll probably just use a raycasy to see if the players close enough, and then make it hit, pretty simple… Also get Aseprite, it’s like 20 bucks but it’s a really good software, also it’s just really good for game making. gasp :D"}, {"post_id": 18857, "ts": "2026-06-30T01:51:26Z", "hours": 10.155, "text": "Basis of an enemy AI!!! the beginnings… I feel like ten hours is a little much for just this, but there was so much work to do. The main step began with a pretty simple area. It just detects if the player enters. The code uses the player position (or “target” position in the code), and subtracts it from the enemy position, if the numbers greater than 1 it moves one way and if less than -1 other. (The buffer in-between the 2 is just for smoothing) If the player is within the hitbox, the enemy shoots out a ray cast towards the player. If it touches the player, it lets the enemy move, if it hits a box or the ground first it doesn’t, pretty simple, till you realize what can go wrong… For clarification i have NO CLUE why any of what i did helped, but it did so yippee!!! The first problem was that the enemy would only detect the player if they were off the ground. I tried to fix this by forcing the ray cast to not interact with the Tile Map (which wouldn’t have worked anyways, because it still needs to so the objects can block the enemy’s sight). I set a piece of code to print what the enemy was interacting with, and it turns out it was the background? (I know, weird?) I seperated the background and collision ground into 2 tile layers, then turned of collisions for the back layer. After that there was some glitchy stuff which you can see in the video a bit, but I fixed almost all of it with literally one if statement that only lets the player become a target for the code (My code is a modified version from this website) / / / / / Godot 3.0: Visibility with Ray-casting · KCC Blog"}, {"post_id": 14832, "ts": "2026-06-24T02:59:54Z", "hours": 4.9869, "text": "Devlog #4? 3 big things this time, physics blocks, destructive blocks, and stamina upgrades. Physics!: -just a block but it’s a “rigid body”, so Godot gives it physics. -It uses some “borrowed code” to detect if the player is colliding with something and then add the players velocity to it.* -I had to change the hitbox of the floor to be a collision polygon, instead of one per block, which made the pushing kind of shotty.** Destruction!: -Really simple… just an enemy that can’t move or fight back. I added an animation so you can tell it’s getting hit but that’s the most complicated it got. Stamina! (it’s better): -I added 3 major things, though 2 of them are pretty small. First, I added a bar, Godot has a built-in progress bar node, so I just mapped the value from 0 - 10, and used the stamina value from the player as the value input -SECOND! I changed the recharge, instead of a variable that goes up when a timer ends, it now uses a move_toward() function to make the stamina tick up smoothly. -thirdibidily, a pause. Mainly because irl and in games you don’t just start recharging as soon as you stop moving. This uses a float that begins to tick up when the player starts moving, and when it surpasses a certain point, it allows the stamina to recharge. Final stuff!!! -I’ll start focusing on: -more indepth weapons -and maybe ai for enemies… probs something with raycasts……….."}, {"post_id": 13221, "ts": "2026-06-21T17:28:44Z", "hours": 1.7094, "text": "Sprinting! took a bit, but I finally got sprinting to work. Works pretty simply, the characters motion is determined by a speed variable, which just increases if the sprint button (shift) is held down. Here’s the code: if Input.is_action_just_pressed(“sprint”) and stamina >= 1: state_machine.travel(“sprint”) sprinting_timer.start() SPEED = 200 sprinting = true elif Input.is_action_just_released(“sprint”): SPEED = 75 sprinting = false sprinting_timer.stop() I’m using an animation_tree for my animations, instead of just a player, this helps the transitions from animations feel smoother, so thats what the “state_machine” is. The “sprinting” variable is used to force other animations (e.g, for idling and running) to check if the player is sprinting, and thus not override the animation (the sprinting animation currently is identical to running, but when I start designing the character i’ll change that). The timer is just on a .5 sec loop, and makes the stamina decrease when it ends, the second bit of code checks if you stopped sprinting, and returns the SPEED to normal and stops the timer loop. This code doesn’t actually fully work, as another if statement is needed. The extra “and” in the first check makes sure you can’t start sprinting if stamina is below one, but actually only checks once when you start sprinting, not constantly, so the sprinting doesn’t stop if stamina goes below 1 (like it should). if stamina < 1: SPEED = 75 sprinting_timer.stop() sprinting = false This code, unlike the first “if”, checks consistantly if stamina’s below one, and does the same job as if you let go of sprinting. This keeps stamina from going negative D: In the future I plan on adding a gradient to the effect, so the speed up isn’t as jarring, but this is a good start! Thanks to Brackeys for the current assets! (go watch his video on Godot, it’s very informative) ~wil"}, {"post_id": 12762, "ts": "2026-06-20T21:26:41Z", "hours": 13.1589, "text": "Finally started to develop a “game” made 3 things, Attacks, Stamina, and GUI Attacks: ->use hurtboxes detect if an area entered, if that area is_in_group(“attackarea”) the hurtbox takes a damage variable and applies it to the thing it’s attached too (Player, enemy, etc) Stamina: -> A timer slowly makes it tick upwards, starts at 10, and goes down if the player jumps or attacks, uses a Global Variable allow the GUI to display the stamina (there’s probably a better way but I’m lazy ¯ _ (ツ)_/¯) GUI: ->uses a canvas layer being displayed over a sub-viewport, which includes the coins and stamina, just displays text and then the quantities of each integer. next steps: ->destructible blocks ->physics blocks ->stamina bar (not integer) ->sprinting (and smoother movement. Thanks to Brackeys for the assets!"}, {"post_id": 5987, "ts": "2026-06-10T01:24:33Z", "hours": 4.8608, "text": "Finally done learning basic Godot!! My entire time has been dedicated to just learning how to use the software, and I’m glad to say I now have something to work off of. I still need to learn more, like GDscript, pixel art, and game design. Next Steps! -develop weapon (sledgehammer :D) -destructible terrain elements (fancy walls that get destroyed) -physics blocks -begin designing character and aliens"}]...
|
Title: Liable For Damages by @wilson_brunner | Sta Title: Liable For Damages by @wilson_brunner | Stardance
Devlogs:
Finally done learning basic Godot!! My entire time has been dedicated to just learning how to use the software, and I’m glad to say I now have something to work off of. I still need to learn more, like GDscript, pixel art, and game design. Next Steps! -develop weapon (sledgehammer :D) -destructible terrain elements (fancy walls that get destroyed) -physics blocks -begin designing character and aliens
Finally started to develop a “game” made 3 things, Attacks, Stamina, and GUI Attacks: ->use hurtboxes detect if an area entered, if that area is_in_group(“attackarea”) the hurtbox takes a damage variable and applies it to the thing it’s attached too (Player, enemy, etc) Stamina: -> A timer slowly makes it tick upwards, starts at 10, and goes down if the player jumps or attacks, uses a Global Variable allow the GUI to display the stamina (there’s probably a better way but I’m lazy ¯ _ (ツ)_/¯) GUI: ->uses a canvas layer being displayed over a sub-viewport, which includes the coins and stamina, just displays text and then the quantities of each integer. next steps: ->destructible blocks ->physics blocks ->stamina bar (not integer) ->sprinting (and smoother movement. Thanks to Brackeys for the assets!
Sprinting! took a bit, but I finally got sprinting to work. Works pretty simply, the characters motion is determined by a speed variable, which just increases if the sprint button (shift) is held down. Here’s the code: if Input.is_action_just_pressed(“sprint”) and stamina >= 1: state_machine.travel(“sprint”) sprinting_timer.start() SPEED = 200 sprinting = true elif Input.is_action_just_released(“sprint”): SPEED = 75 sprinting = false sprinting_timer.stop() I’m using an animation_tree for my animations, instead of just a player, this helps the transitions from animations feel smoother, so thats what the “state_machine” is. The “sprinting” variable is used to force other animations (e.g, for idling and running) to check if the player is sprinting, and thus not override the animation (the sprinting animation currently is identical to running, but when I start designing the character i’ll change that). The timer is just on a .5 sec loop, and makes the stamina decrease when it ends, the second bit of code checks if you stopped sprinting, and returns the SPEED to normal and stops the timer loop. This code doesn’t actually fully work, as another if statement is needed. The extra “and” in the first check makes sure you can’t start sprinting if stamina is below one, but actually only checks once when you start sprinting, not constantly, so the sprinting doesn’t stop if stamina goes below 1 (like it should). if stamina < 1: SPEED = 75 sprinting_timer.stop() sprinting = false This code, unlike the first “if”, checks consistantly if stamina’s below one, and does the same job as if you let go of sprinting. This keeps stamina from going negative D: In the future I plan on adding a gradient to the effect, so the speed up isn’t as jarring, but this is a good start! Thanks to Brackeys for the current assets! (go watch his video on Godot, it’s very informative) ~wil
Devlog #4? 3 big things this time, physics blocks, destructive blocks, and stamina upgrades. Physics!: -just a block but it’s a “rigid body”, so Godot gives it physics. -It uses some “borrowed code” to detect if the player is colliding with something and then add the players velocity to it.* -I had to change the hitbox of the floor to be a collision polygon, instead of one per block, which made the pushing kind of shotty.** Destruction!: -Really simple… just an enemy that can’t move or fight back. I added an animation so you can tell it’s getting hit but that’s the most complicated it got. Stamina! (it’s better): -I added 3 major things, though 2 of them are pretty small. First, I added a bar, Godot has a built-in progress bar node, so I just mapped the value from 0 - 10, and used the stamina value from the player as the value input -SECOND! I changed the recharge, instead of a variable that goes up when a timer ends, it now uses a move_toward() function to make the stamina tick up smoothly. -thirdibidily, a pause. Mainly because irl and in games you don’t just start recharging as soon as you stop moving. This uses a float that begins to tick up when the player starts moving, and when it surpasses a certain point, it allows the stamina to recharge. Final stuff!!! -I’ll start focusing on: -more indepth weapons -and maybe ai for enemies… probs something with raycasts………..
Basis of an enemy AI!!! the beginnings… I feel like ten hours is a little much for just this, but there was so much work to do. The main step began with a pretty simple area. It just detects if the player enters. The code uses the player position (or “target” position in the code), and subtracts it from the enemy position, if the numbers greater than 1 it moves one way and if less than -1 other. (The buffer in-between the 2 is just for smoothing) If the player is within the hitbox, the enemy shoots out a ray cast towards the player. If it touches the player, it lets the enemy move, if it hits a box or the ground first it doesn’t, pretty simple, till you realize what can go wrong… For clarification i have NO CLUE why any of what i did helped, but it did so yippee!!! The first problem was that the enemy would only detect the player if they were off the ground. I tried to fix this by forcing the ray cast to not interact with the Tile Map (which wouldn’t have worked anyways, because it still needs to so the objects can block the enemy’s sight). I set a piece of code to print what the enemy was interacting with, and it turns out it was the background? (I know, weird?) I seperated the background and collision ground into 2 tile layers, then turned of collisions for the back layer. After that there was some glitchy stuff which you can see in the video a bit, but I fixed almost all of it with literally one if statement that only lets the player become a target for the code (My code is a modified version from this website) / / / / / Godot 3.0: Visibility with Ray-casting · KCC Blog
Some more enemy development! -first “enemy” in the game, a pretty basic little thing. -designed on Aseprite, took some time to set up with hakatime, but turns out I was using a version only used on Mac OS, so no kidding it was giving me trouble -I created unused animations for a lunge and whip attack animations that I will implement soon (?). NEXT STEPS :D : -stop the player from colliding with the enemy’s hitbox, it’s very annoying, and in the future will we a necessity for having many creatures in the same room -add the enemy attacks, I’ll probably just use a raycasy to see if the players close enough, and then make it hit, pretty simple… Also get Aseprite, it’s like 20 bucks but it’s a really good software, also it’s just really good for game making. gasp :D
enemy attacks/better particles. This took some work, but not really… The enemy can now attack and hurt the player the codes really just the same as the player attacking the enemies. Theres a hurtbox in the player that gets hit by an area in the enemy that makes them take damage. The particles took some more difficult work. Godot has CPU and GPU particles, which apparently are different, it just depends on what in your computer renders them. I used GPU particles, because they run better and can collide with things. I whipped up a sprite sheet for the particles in Aseprite, which looked a lot better than the weird purple generic Godot things. The particles only collided with light occluders??, so I added an occlusion layer to the tile map, at some point I hope to create a better system for when they hit the ground, but thats not my priority right now. Next STEPS!!!!! -main thing is that the enemy has a lunge attack that I haven’t implemented yet, so thats next. -starting on the player sprites, this is a LOT of work, so its gonna take me a lot of time, but no time like the present
I’m gonna start this by saying: I HATE animating! Aseprite made this so much easier, but GOD this was difficult… I think I had 5 situations this time around where the problem was the littlest change in the world, and I just needed to go to bed. I made 3 different walk cycles, before giving up and figuring out how to do it for real, it was only a little difficult after that. I have unused hurt, death, and push animations, and need to implement a shorter attack and smooth some things out still (jumping while attacking cough ) Almost all of these 12 hours was fixing stupid little problems and changing little pixels, probably some of the worst time ive spent on this project yet… (but still really interesting) NEXT STEPS::: -fix walk so it looks sensible (drifting) -make jumping illegal hwilst attacking -add short attack -customized tile map ????? Thank you for reading goodbye I want to stop animating
Quick hurt animations Main thing I added was animations for death and injury. I first added knockback when hit. It just takes the player’s scale.x (what i use for flipping the sprite) and multiplies it by 200 to the player velocity, since the scale is either 1 or -1, it changes the direction the player is thrown (in the future i’d like to make the scale the enemies direction, not the players, as if the player is flipped in the wrong direction, it could have knockback in the wrong direction (very bad) Theres was already a variable to detect if the player was being hit that was used for testing, so I just implemented that to play the injury animations. i also detected if the players health was zero or below after being hit, and if so it would make the player play the death animation instead of the injury. I have currently unimplemented animations for a before-death injured player, so after they are hit for the last time they will stand for a bit before collapsing. NEXT STUFF: (hast beeneth narrowed list) -add enemy knockback (only when injured, lok wierd when die) -fix player knockback thank yoh forth coming to my TED talk
sprites! done some stuff, mostly just game planning (sadly didn’t get time for because notes but I got a lot done, mostly just some serious drawing. I finished some tiles for the first and second levels, and some tiles for the next three.
Mantling and fixes Hi. I have had a very long week. I spent a lot of time working on sprites, mostly for the game 3rd level (no spoilers, (but that’s pretty boring) so heres the interesting part. I’ve been focusing on revamping player movement to make it feel more interesting and fun, and this is a good start. Mantling! if you don’t know what this is, it’s what you do when you get out of a pool without a ladder or staircase, pretty much just “pulling yourself up” The player does this by using raycasts, I added three, but one is for something else. One of them detects a wall in front of the player, and one detects a wall above. The code uses these casts to detect if the player is up against a wall, and if there is no wall above the player, pretty much checking if there is a mantalable ledge. If there is, the code says “you can mantle” Another line says: if you can mantle, and you are not on the ground, and if the player clicked space (Jump), then mantle. The annoying part was animations. When the player begins mantling, the hitbox and player position is frozen in space, and position is snapped to the nearest block to line up the animation. the only thing that moves during the animation is the player sprite, which means at the end of the animation, when the players position is finally changed, the player sprite needs to snap back at the EXACT same time, or it looks bad, which was hard. The other annoying part was the camera snapping randomly, as it moves with the player and not the sprite. I fixed this by just temporarily turning on the cameras position smoothing while the mantle is happening and then turning it off when the player moves again.
Crouching! #2 in the player movement chronicles! Surprisingly, I also managed to create a whole new 5 animations! slide, crouch idle, crouch walk, and the sledge versions (not slide cause ya can’t sprint with sledge). I implemented all but the slide, which’ll take a long time, so I’m going to keep it off a bit. This was really straight forward to add, and for the first time in a long time, i had like only 1 problem . I really just had a piece of code that asks, “did ya click the crouch button?” and if so, it toggles crouch. IF (and only if!) the crouch is on (or “true”) the idle and walk animations are switched to their respective crouch variants, and the normal player hitbox is replaced by a shorter-er-est one. To bar the player from un-crouching in the midst of a tunnel, I added 2 new raycasts to the front and back of the players head facing up, these casts detect if there is a block above the player, and if either one of them detects anything, the player is unable to un-crouch until they are unshielded. Another quick thing I had to fix a bit was the raycasts detecting the player, which broke EVERYTHING so I just turned good ’ol collision mask/layer 20 into the super-cool (ALL-NEW !!) “player raycast collision!!!” which just only lets them interact with the floor and boxes, so yippee NEXT STEPeths!: -slide ): -enemy lunge -other player attacks (only hard attack right now which is bad)
MOVEMENT PART # (3) les go took me short time, it’s ten o’clock im tired, pretty simple stuff. If player is sprinting and the crouch button is pressed, the normal function is overridden and a slide is activated, this just sets the animation to slide and the X velocity of the player to a high number. There’s some other code for just general quality of life, like stopping if you hit a wall and keeping you from changing directions, but the REALLLY cool part is jumping. Like in real life (trust), while sliding the player will jump further, which permits some cool movement combinations, like vaulting over gaps and climbing 4 block walls. I have to work out stamina changes depending on jump strength and stamina decrease for vaulting, but the movement getting pretty fleshed out. P.S, after I took the video, I changed the sprint stamina decrease to be a consistent decrease instead of being choppy like in the video, it’ll be in the next log, but it was just quality of life. NEXTS STUFFS: -dash -enemy lunge -stamina from hoisting and slide-jump stamina increase Thanks for reading!
player movement is complete!! went on vacation, so fell behind a bit, but finally got this done. I spent a lot of time thinking on how to make player movement good, and then thought of my BOTW playthroughs, where you can either hold your attack and have a powerful slash, or click fast and hit three in a row. First addition!: Ground pounds were pretty interesting, all it does is forces the player down hard if they attack in the air, decreases stamina, and then hits the ground, I added a dust cloud that explodes when he hits the ground, which just plays the animation and then disappears. I had to do some fenagling with this because the code knows when to start the animation because the player will be ground pounding and on the ground, which starts the poof and then stops ground pounding, which also keeps the animation from playing multiple times. SECOND: Annoying stupid player attacks. Tried to finish this in a day, so I was working till 11:00 at night, but I got the animations done and what not. When the player hits/holds the attack button, it starts a stopwatch that increases, when the player releases the button, depending on the time on this timer, it will either play the first of 3 quick attacks or the big attack, which does more damage. If the quick attacks are chosen, the first one will play, three things happen when thats starts, 2 timers start, and player velocity increases to 500. at the end of the attack, there are three things can happen, the player can wait until the animation ends, they can attack again, or they can walk to reset the attack earlier than waiting, the first timer forces the player to wait to cancel the attack by walking, and the second one stops their velocity so they jolt forward. at the end of the animation, a function is played that: starts the reset timer for the attack A variable increases that sets the next attack to be the second or third in the sequence, instead of the first and a if statement that resets the variable to 0 if it gets to 3. Theres some other details for weird situations, like falling off the edge and ground pounding while attacking, or the variable not resetting weirdly. But all of that was like an hour. Thanks for reading: Play my game when it comes out so I have a reason to finihs Also I need a name for the game (please, I suck at naming) and go play Legend of Zelda (or Just Cause 3) (or research operation Just Cause) #USinvadinglatinamericaAGAINfornoreason P.S (I was gonking on being up till eleven, but I did like 3 hours of animating and coding in like 30 minutes while being food deprived and barely awake because deadlines = lock in, so if you need to lock in just don’t sleep ig ) also, I’m technically not done ‘cause ma boy needs a sawed off before I’m done here Yee Haw
Little enemy beginnings I haven’t actually finished anything yet, but I need to devlog anyways, but I have started to finish the second enemy, which is also the framework for more.
Enemy is complete: Chomper! Lot of work, but got it done. This is the, please avoid, very dangerous, you will die enemy. I haven’t balanced its health yet, and I’m not going to for a while, so it looks like an easy kill in the video. The weird quirks of this enemy are mostly in its charge attack, that rushes the player. It’s pretty easy to avoid, but once again i haven’t done attack balancing, so it may become harder later. The majority of the enemy works just like the lil guy, so idk read that devlog. But there is two major differences: LIST: gasp 1.!!!1! : idle stuff -really just a randomizer -if enemy is idling, starts a timer, and when it runs out of time, it does one of two things (using a randi() function) -if the outputs a 1, nothing happens, but if its a 2 it flips the enemy, thas all -the main reason for this is that since this enemy is so big, making it a tad more animated than the lil guy felt important to me, and also because the detection areas for the big guy are skewed towards the front, so him turning around makes the player sneaking up on him a little less common, it’s generally just for Q-O-l (slang btw) (only cool people understand) 2.!: dash -dear lord, why was hard so much D: -Wasn’t actually that difficult, I spent a lot of time trying stuff before realizing I just unleash my inner enginneer and do it step by step ’till it works, which it did. -first, theres three detection boxes, one for walking towards the player, one for the chomp, and one for dashing, if the player enters the dash-box, a timer will start -when the timer ends, the charge animation plays, which halfway through, activates a function too add velocity (actual charge part of charge) -If the enemy hits a wall, player, or box, it stops moving, but in the case of the player it plays a second animation (dash_hit) that looks like a chomp and kills the player if it hits them. Theres another If statement that sets velocity back to 0 when this happens also. OTHER CHANGES: -I removed the players health really, I like games that are one shot, because it’s subjectively more fun, I’ll make the player death a little more explosive if I have time. I’ll probably make them have three health but that’ll change when I do attack balancing -made the lil guys attack timer shorter, makes him more dangerous. NEXT TIME PLANS: -hopefully in one day (ima lock in rq) -gonna add a flying enemy, -literally just a tad fly, like 5x5 pixels, it’ll look at the player and fire acid that’ll kill you -i might change the death animation to be more BOOM (IYKWIM) :D -my goal is too complete the flying guy 100% tomorrow, but I got other stuff to do so we shall see -also it’ll be nice to not have to do major animating besides literally 6 pixels splaterring -if extra time, I’ll make a weird egg thing that turns into the fly THANKS FOR READING! as always (not really) go make some interesting, and uh learn something new every day please (P.S I made some changes after I took these videos so it still looks and feels kinda bad but not actually rn) ~Wilfred
Flying enemy is complete, in record time! wow, 8 hours for an enemy, how quick D: This was a challenge, but also really fun. This enemy is the flying one, which made it a little more difficult than just the copy and paste of old ones but still pretty cool. It works using a Navigation Agent, which is like Godot pathfinding. Fast forward three hours and a whole lot of troubleshooting, but that works. The enemy detects the player in the same fashion as the other enemies and then activates the nav-agent to being movement. It’ll follow the player through vents, passages and really anywhere. The fly has three main detection circles, the first one tells it to move towards the player, if the player enters the second one, it’ll freeze and stop moving, and if the player gets even closer, it’ll try to move away (by reversing the velocity var outputted by the nav-agent, iyc) the enemy’s one hit, acourse, but is really annoying to attack, (ill rework ground pounding to make this easier later). The enemy has a shooting attack, that is on a 6 second timer if it can see the player, otherwise it’s just on hold. its shots are pretty slow, so there easy to avoid, but in a crowded fight ya never know. The main quirk of this enemy is it has a really long forgetfulness timer, so even if it can’t see you, it’ll continue to follow for quite a long time, much longer than other enemies. Next:! -stationary, weird wall tentacle that shoots at you -egg spawner that hatches into 1 of three enemies (mystery ooh) -doors (ikr)
keypads, doors, and beginning of the first level. Im actually making a game! contains spoilers First of many… keypads were really difficult, every button, when clicked, multiplies the correct number by a multiplier, and adds it to a “code” variable. the multiplier is chosen based on what step of the code you’re on, (e.g, 1: 10000, 2: 1000, 3: 100, 4: 10, 5: 1), when you click the green button, it cross checks another variable with the one you typed, and if they’re the same, it sends the function to open the doors, and if not, everything resets. The other terminals and what not just open things when clicked on, so it’s just an easier version of the keypad.
quick devlog. I need to do this cause i got 10 hours, Im working on the level system and im so tired please why is htis so hard D: D: D: D: D: D: D: D: D: D: D: D:
Another devlog about levels. Started work on the second (this takes so long) I can’t say much for fear of spoilers, but just say this involves WAY to much code and sprites (I hate drawing so much)
quick stuff, nothing much Finished some updates, but I’m locked so don’t have time to write much
WORKING ON MY FINAL STRETCH I’m going to be locked in for the next few days, school starts, so I’ll have less time, but I got a boss fight and then bug fixing and sound effects, hears a sneak peak and one of the many things ive worked on. Also, I came up for a name. Looked up the universal laws for space and saw something about how “Countries of Origin are Liable for Damages caused by their space debris” and said “dang, thas dope” so now i have a name. In my next log ill have a longer devlog like a lite trailer, but the games pretty short, more like a showcase of learning. Thanks!
FINAL STRETCH time to lock in please oh no Im finishing the last level, no time to talk, but got like 4 things to finish THINGS: -level -boss fight -sounds -ending -bugs
SFX stuff, final thing before ending, just finishing sounds, really annoying though ngl. done soon, big update at end
Final Release (or close to it) Game will be out soon, I just gotta ship, but everythings done, I finished sounds, and the ending yesterday, like a 8 hour coding marathon, so i could get this out in time. PLEASE play it, it’s called Liable for Damages, I don’t know where I’ll post it yet, but It’ll probably be on Itch.io or just the game application file. It’s like 150,000 kilabytes, so it shouldn’t be too bad for any computer, hopefully (mines from like 2009 and it ran fine) P.S! Please, (if you do play), comment bugs, especially major things, EXCEPT: -Player dissapearing when opening menu in elevator (don’t try this, im not fixing it it’s funny) -Bugs on top of head, (js kill them) Anything else is bad and needs fix thanks. Also sorry no volume controls, I was crunching down to finish.
devlog for projects i forgot to add, really just time from learning to export godot games, very annoying um, fun fact, if you create a web game, change the file to index.html, or it literally WON’T WORK!!! Play my game (now!)
Started working on Liable for Damages 2.0 Devlog #1 Started working on better settings, mostly just things for volume, fonhts, and scrolling things. Whipped up some basic sprites in aseprite and took a day to implement them and figure out bugs, which were very annoying, mostly just related to button sizing. Had to mess around with Godot’s “containers”, for the first time, and it was quite bad, I’ve got some more work to do before I can get the sliders to work, but I’m close! Next stuff’s: -format sliders -start creating settings related to different busses -create saves for the sliders -implement button to change font -make font-changed labels for all maps -do bum ahh drivers ed instead of W Stardance I’ll hopefully release 2.0 within October, and I’mma try and devlog more! ~Wil
Ships:
I made something! This was my first time coding outside of Arduinos, and one of the biggest learning experiences of my life. There was stress, time crunches, and pain, but it all came down to the wire. The most challenging part was drawing, of course, I’m never going to do this again JUST because of the assets. Thanks for playing...
|
1792856909.6890633
|
1792943309.6890633
|
|
25109
|
Into the cosmos by @tejaswa | Stardance
|
tejaswa
|
3
|
124.31
|
2584
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-16T04:20:51Z", "hours": 54.0, "multiplier": 19.58, "payout": 1259, "blessing": "neutral", "text": "INTO THE COSMOS This is the game i have designed with inspiration from Spaceflight sim and Kerbal Space program, i wanted to capture the total freedom of roaming in space without the stress of designing a space vehicle for hours just for it to crash into a million pieces. I wanted to make a chill relaxing game that people can come back home after a long day of work to, boot it up and have fun just roaming the eternal space without stressing out. Im quiet proud of how im capturing this vision of mine and im very happy with what im making. Heres some information of what i added this ship: I’ve basically been adding a bunch of systems that I’ve wanted in the game for a while, and the game is starting to feel a lot more like an actual sandbox now. First thing, I finally added electricity. This is probably one of the systems I’m most interested in because now I can actually start making more things depend on power instead of everything magically working forever. This also gives me a lot more stuff I can do with spacecraft and bases in the future. I also added scraps and scrap refining. You can now collect scraps while exploring and actually do something with them instead of them just being random useless objects. I’ve also added the material processing system around this, so scraps can be refined into materials that can actually be used to build useful buildings. This is going to become a much bigger system later on. ROVERS ARE FINALLY HERE You can now actually drive around on planets instead of just landing there and leaving. I really wanted this because the planets were starting to feel a little pointless once you landed on them. Now you can actually get out there and explore the surface properly. I’ve also added planet properties. Planets now have their own properties which means I can start making different planets actually matter instead of them just being randomly generated balls you land on. There’s a lot I can do with this later, especially with resources and exploration. I also did a pretty big overhaul on the visuals. The ambiance shaders have been improved and I’ve added a bunch of new stuff to make the planets and space itself look better. black holes now also have a hidden easter egg…. Ive also given every planet a beautiful atmosphere And yes. Mudfish I don’t know why. They’re still stupid. They just walk around on planets doing absolutely nothing useful. But honestly the universe felt too empty without them so I’m keeping them. A lot of this update was also spent doing optimization because some of the newer systems were starting to get pretty heavy. I’ve been going through different parts of the game and trying to make everything run better without completely murdering the visuals. Overall this update is probably one of the biggest changes to the game so far. And I still have a stupid amount of things I want to add. https://www.youtube.com/watch?v=ZZg3blASmgc This is the link to the youtube video if you dont have time to review the game PLEASE check it out and rate the project I read and appreciate every single one of you reviewing this game, please be as informative as you can be as this is one of the biggest games ive worked on till now, thx and have fun playing the game", "repo": "https://github.com/tejaswa4692/IntoTheCosmos", "demo": "https://tejaswa7692.itch.io/into-the-cosmos"}, {"ship_num": 2, "ts": "2026-07-08T12:04:25Z", "hours": 46.0, "multiplier": 19.75, "payout": 1084, "blessing": "neutral", "text": "Into the Cosmos Join Boney on a journey across the endless cosmos, where every horizon hides another world waiting to be discovered. Launch into the unknown, weave between glowing nebulae, drift past impossible black holes, and set foot on planets no one has ever seen before. Build observatories to mark your path through the stars, refuel your rocket, deploy satellites into orbit, and keep pushing farther into the infinite. And when the day is finally over, come relax with Boney and lose yourself among the stars for a while. I’ve always loved games like Kerbal Space Program and Spaceflight Simulator, but I wanted something where you could jump straight into flying without spending hours designing the perfect rocket first. The result is a sandbox space game built around realistic orbital mechanics, exploration, and simply enjoying the journey. The universe is procedurally generated, meaning there is always another unique planet waiting somewhere beyond the next launch. Every expedition can take you somewhere completely new, and every observatory you build becomes another milestone in your adventure. Satellites aren’t just for show either. Launch them into orbit, revisit them later, and use them as your eyes in the sky while you continue expanding your reach across the universe. If you’re new to orbital mechanics, don’t worry. The game includes detailed instructions, an optional on-screen keybind guide, and a full in-game settings menu that lets you tweak graphics and performance to match your hardware. Whether you’re playing on a high-end gaming PC or something much more modest, I spent a lot of time optimizing the project so as many people as possible could enjoy it smoothly. There is one place, however, that lies farther than anywhere you were ever meant to reach. Most people will never find it. Those who do usually don’t come back with an explanation. I call it The Farlands. Whether it’s a bug, a feature, or something else entirely is for you to decide. I built this game in Godot 4.6.2, spending countless hours refining the physics, procedural generation, shaders, rendering, UI, and gameplay systems. Every optimization, every visual effect, and every mechanic was added with one goal in mind: making space feel like a place you can get lost in for hours without realizing where the time went. So fuel up, trust your trajectory, and see just how far Boney can go. If you decide to give the game a try, I’d really appreciate a detailed review afterwards. The feedback I received on my last project genuinely helped shape this game into what it is today, and I’d love to hear what you think could be improved, what you enjoyed, and what you’d like to see added next. If you enjoy the project, consider starring the GitHub repository and liking the YouTube video. It really helps more people discover the game and motivates me to keep building and improving it. So fuel up, trust your trajectory, and see just how far Boney can go.", "repo": "https://github.com/tejaswa4692/IntoTheCosmos", "demo": "https://tejaswa7692.itch.io/into-the-cosmos"}, {"ship_num": 3, "ts": "2026-06-30T14:45:22Z", "hours": 14.0, "multiplier": 17.81, "payout": 241, "blessing": "neutral", "text": "I made Into the Cosmos, a realistic 3D spaceflight sandbox inspired by Kerbal Space Program and Spaceflight Simulator. The game lets players jump straight into the mission and experience realistic orbital rather than spend hours designing the rocket just for it to fail when launching. This is a relaxing and fun game where players can just sit back and enjoy the physics and thrill of sending rockets to space. The biggest challenge was making somewhat realistic physics with enjoyable gameplay. Getting the gravity, RCS controls, and spacecraft handling to feel both snappy and fun to play with without absolutely broken, writing so many lines of code, and deciding on how im gonna be approaching some problems was quiet fun, i have a lot of fun designing it, i used to go to bed thinking what ill be adding to the game tommrow. I’m most proud of achieving the relaxing experience I originally envisioned. Im quiet glad i was able to fianlly have a direction towards my game and have an idea of what i wanted. And the gameplay is quiet fun aswell, i found myself “playtesting” my games just having fun slamming the rocket into planets, doing interplanetary missions. Setting satellite in different planets To test the project, I recommend reading the in-game controls and instructions first. They explain the basics of reaching orbit and make the experience much more enjoyable.", "repo": "https://github.com/tejaswa4692/IntoTheCosmos", "demo": "https://tejaswa7692.itch.io/into-the-cosmos"}]...
|
[{"post_id": 54490, "ts": "202 [{"post_id": 54490, "ts": "2026-08-25T14:44:08Z", "hours": 0.6006, "text": "SHOUT OUT TO @253_Mathilde_IYKYK For starters i made a lil script so that if a rocket is in the SOI of a planet and then it scans near it by pressing F it shows all the necessary details about the planet, currently they are obvious details but i will work on making them useful. I have a few ideas of what i can do with it Now to the important part @253_Mathilde_IYKYK recommended me to add a song they like SO I ADDED IT TO THE GAME Hope yall like it :) (Sorry for not including video idk why stardance was bugging and throwing error when i was tryna upload a video)"}, {"post_id": 53590, "ts": "2026-08-24T06:27:00Z", "hours": 1.7239, "text": "BOOMBOX!!1! , macondo marketing team too good Last night i spent unhealthy amount of time watching ig posts of macondo on hackclub ig, I lowk feel insane amount of fomo and i wanted to go so bad The songs they used in the marketing reels are still stuck in my head So as any reasonable person would, I added a boombox in my game with with my fav songs from the reels they made @zach PLES FLY ME IN NEXT IRL HC EVENT PLES IM BROKE"}, {"post_id": 51670, "ts": "2026-08-21T14:03:35Z", "hours": 1.3228, "text": "IM RICH!!11!! 2080 sd and top 10 in multi I got all positive reviews from yall and i apprciate every single one of u for rating my project. I have finally added scrap mines to the game, i had already made the 3d model for them i just thought they didnt fit in the game but since im adding automation and electricity to the game i think this would be a great addition. Currently they produce 10 scraps, copper, iron per 10 seconds so 1/ sec i will later randomize this and give them weights, im js too lazy cuz of this clg n shi istg Good thing is tho tmr im going home That does mean my work on hardware projects will start again That being said i need you to give me more recommendation for the game, the reviews didn’t give me any ideas or unique views what i could add to my game."}, {"post_id": 49072, "ts": "2026-08-17T17:51:03Z", "hours": 2.0336, "text": "In these 2 hours i have lost all my sanity But finally the factorio like supply/demand electricity mesh finally works First i thought of using recursion to spread the electricity through every single tower But then i ran into a problem where towers interconnected so to fix that i passed a self parameter that didnt seem to help. Then i decided to make towers only connect once (which was a disaster and brought its own set of bugs) and that to tremendously failed So finally i decided upon a global mesh chain architecture where all the nodes in a chain have similar looking list, and whenever an appliance is connected to it the chain just iterates through its connected devices, This in turn brings the time complexity down to O(n) and makes everything a whole lot more efficient. Finally this is done Currently only the tesla charger works with this new logic, later i will add other electric appliances to this mesh network aswell and give them watt draw Few things to keep in mind, Currently 1 generator makes 50kW and one vehicle charger consumes 40W, If the demand isnt satisfied every node in mesh rejects the connection until the demand IS satisfied I know this might feel stupid for some people but this is only done as a feature so you dont overload the electronics in space"}, {"post_id": 48779, "ts": "2026-08-17T09:55:49Z", "hours": 2.4833, "text": "TESLA SUPER CHARGING So for starters i forgot to tell yall that i DIDNT get slimed by senior my clg department helped me and scared tf outta bro and i got to fight bro too And in this update i added set battery capacity to rovers They use supercapacitors to store charge so that means they can be charged and discharged for eternity Then i added charging stations to the game and made them use power grid electricity. I think players might abuse electricity by only placing 1 generator to power an entire city so i will be implementing complex wattage draw logic like they have in factorio to get some supply/demand action rolling. Then i worked on implementing save game in the game and i failed terribly (this will be a hurdle for later) I spent like solid half an hour trying to implement it just for my save file to be completely empty Idk whats going wrong but i will eventually figure it out. For now tho i will be working on factorio like supply/demand logic for electricity wish me luck"}, {"post_id": 48283, "ts": "2026-08-16T16:23:11Z", "hours": 2.1503, "text": "Some really cool additions For starters today i implemented a little list at bottom of the screen that can be used to store the coordinates of player rn Yall might be wondering what tis could be used for, But i have something really cool cooking up in my head lets hope i am able to express it properly. EXPRESSING MY LOVE OF YAGI ANTENNAS I ADDED A YAGI ANTENNA TO THE GAME!1!!! It has a search feature that looks around for strongest signal and then does nothing But in future i will be making a whole mechanic out of this. Then i made a little web release it butchered the visuals i worked hard on. Its okay tho cuz i added a warning label like last time on that release too. Linked the web release as playable link for the game I want YOU to tell me what should i add to this game as im running into a roadblock where i dont know what i could add for the electrical update for the game that would actually be a useful addition, Comment down below to drop your ideas the best one will make it into the game"}, {"post_id": 47469, "ts": "2026-08-15T12:12:27Z", "hours": 4.2428, "text": "YAYAYAYAYAYA 3RD SHIP INCOMING In the first 2 hours i logged i worked on making the 3d models as refined as possible and made them look good by referring to astroneer as someone commented on my game Also made multiple 3d models for the electric pole and finally used the one that sat right with me. Made a new 3d model for generator and upgrade station aswell In the next 2 hours i made minor tweaks and fixed satellite bugs along with updating the help menu with newer control code, also was thinking of implementing a scrap mine but dropped that idea (maybe later ships) Then i added a little keytip marker near the refinery and chest of observatory to aid the player. Added a bunch of sounds to the electronics of the game and now it sounds a whole lot better (also reduced the main music) FINALLY TIME TO SHIP Thnx to all of the support on this proj i wont disappoint yall at all with future ships"}, {"post_id": 46499, "ts": "2026-08-13T19:09:37Z", "hours": 1.13, "text": "I was aiming for 3 hours today but i lowk got in a fight with a senior in my clg and bro is threatening me to slime me tmr it might be wraps for me gng Putting the sliming part aside, today i made the 3D models for a generator concept (or actual thing) i found online of what they use in space. The i did sm audio editing to have a whrrrrrrrrrrrr looped sound effect and it was quiet easy to make a whrrrrrrrrrr loop, easier than i imagined. Then i added another sound and layered both ontop of each other and now it genuinely sounds kinda peak After that i made the electricity spread across all the electric poles, heres the code for that if body.is_in_group(\"tower\"): towers_closest.append(body) create_lines(body.location_to_connect_wire_to) if has_electricity_running: body.has_electricity_running = true elif body.is_in_group(\"electrical_appliance\"): if body.connected == false: towers_closest.append(body) create_lines(body.location_to_connect_wire_to) body.connected = true if body.is_in_group(\"generator\"): has_electricity_running = true for i in towers_closest: if i.is_in_group(\"tower\"): i.has_electricity_running = true I might lowk be taking AI’s job in writing bad code, they should make a me gpt in which i reply with shit code that DOES work. I also visualized the flow of electricity by hiding/showing a random cylindrical mesh that shows if it has elec flowing through it. Tmr ill be redoing ALL the icons cuz currently they look straight dookey, and also fixing the UI, then if i have time give observatory and everything an electric connection and make them so they dont work without it. This was all i worked on today, yall pray for me lets hope i dont get slimed tmr ."}, {"post_id": 45792, "ts": "2026-08-12T14:42:25Z", "hours": 6.0336, "text": "LETS GO IM FINALLY UNBANNED Unban stuff aside, time to explain the devlog even tho being unbanned feels great and i have insane amount of motivation to work on my proj now In past idk however weeks ive been working on 2 major things, first is that ive finally listened to the last ship reviewers and added upgrades for rocket, with custom 3d models for each rocket tier. currently it uses a separate key to open close the menu which is bad but ill fix later Also only the rockets fuel attribute is updated when you upgrade a rocket so ill fix that too. Also after the ban i was working on electronics update for my game, i have implemented electric poles, 50Kv Generators for now, i am going towards direction of factorio im afraid, but i dont wnana make it very grind-y so ill keep that in mind (hopefully) For future i will be adding better UI/UX its currently embarrassingly bad rn (even tho my degree is Computer science and Design) So yeah that will need a massive revamp Also id like to give a shout out to water #Freewater #heaintdonunwrong"}, {"post_id": 40560, "ts": "2026-08-04T06:09:37Z", "hours": 1.4125, "text": "After getting falsely accused for fraud for using the godot wakatime extension and getting a heart attack I have finally added little homes for these skinny dookeys I hate, HATE behavior trees with every cell in my body I hate to admit but i did take help of claude chat to help me set this shi up, it was js the free version tho so we good. I added so like normally it ran away from player if it sensed one near, but now if the player is close by and it has a home near it runs to that and hides in the home, and if player is far enough it emerges back out. Ill move on to adding more entities now rather than polishing these dudes, i think from the final game i wont even keep them in cuz how ugly and weird they are Aye free me bro i aint do nothing wrong, fix the wakatime extension fr"}, {"post_id": 39489, "ts": "2026-08-02T13:55:59Z", "hours": 1.7764, "text": "REALLY NICE ADDITIONS Ive finally added some life to the game. I have added these weird mudfishes inspired by those weird furless cats. These mud fishes aren’t stupid tho, i ___have implemented a proper behavior tree to them, Each one of them has their own set of actions. Normally like minecraft mobs they roam around look around the world, but if a player is near their vicinity, they RUN away from the player protecting them. Currently i have no clue what ill use them for, but one thing is for sure that they have really nice skin I wonder what will happen to it in the near future Really happy by this addition tbh, the world was getting kinda lonely, this was important, in next updates ill be adding colonies of these things mounds and their homes, along with their baby variant."}, {"post_id": 38887, "ts": "2026-08-01T13:38:58Z", "hours": 1.4058, "text": "Man i hate making 3D models Not my best work yet, but refinery is done, After several iterations, getting inspo from pinterest and then ditching it and drawing one in back of the class, im finally set on a design, it looks pretty good as of rn. (its not) I fixed a bug where the text was glitching out when i tried to craft scraps, and now it works as it should. The logic is perfect for how it should act in game and im hoping i dont have to touch it again in future to fix it. That being said ofcourse ill be making the 3D model better, But for now i just wanna focus on programming stuff and making the loop right. We can always make it prettier later . Im unfortunately still not home and i still have to survive in this godforsaken room, but hopefully ill be home soon as ill get my appli signed to go home, And then ill be working on both this and the plane together"}, {"post_id": 37473, "ts": "2026-07-30T07:46:37Z", "hours": 4.0967, "text": "Finally a devlog after several days of straight struggle For starters ill tell yall why it took me so long I lowk changed places and i live alone in a room now, i had to shift and living conditions here are absolute hell I somehow survive without going wild due to all the bs ive been facing recently. My productivity has taken a severe hit, a feature like this took me way too much time to complete than it should’ve. That being said i did wander off in different directions cuz i was lowk clueless which direction i should take this game (i still havent decided ) In this devlog i added advanced material processing and advanced materials to the game, with a minecraft furnace like cooking mechanics, i made the logic quiet efficient and refined, its not my best work but it can always be better later. I js hope this eternal torture ends and i finally get to have better living conditions. istg ive been boiled alive, breathing is a struggle in this place Ill keep serving yall with most banger updates so keep me followed, this game is gonna be the next big thing lowk Now i will be makig the 3d model for refinery, before this i made a failure ahh model in whcih i js made a complete simithing room inside a space bubble 😭 Gotta make something better than that so time to lock in"}, {"post_id": 35113, "ts": "2026-07-26T10:39:31Z", "hours": 2.3589, "text": "OKAYAYAYAYAYA UPDATE TIME I have graves implemented in the game now, after careful consideration about which direction i wanna take my game towards, i think graves would be a nice addition without disrespecting the procedural nature of the game. I want to make this game very lore heavy while being fully open world and giving the remote in players hands. I dont wnana confine them with thick story plot, or tedious tasks. Nor do i wanna make the game absolutely boring and pointless. The “Rot” i talk about is a cosmic disease the players universe is going through, unexplainable things are happening, weird inter dimensional gates are popping up at random places, everything is near extension. Im not sure about the role of player in all this tho, i will figure something out tho, i wont disappoint yall thats my promise. Also i worked a bit more on a weird bug where items were being placed not where the raycast was supposed to hit. Also I will be removing the inventory system entirely and just rely on blueprint building aspect lmk if yall think thats a good idea Also shout out to hackclub for getting me so much stuff i really love every single one of yall ❤️ Also progress on this game will go back to high now as i wont be home to work on my plen."}, {"post_id": 32900, "ts": "2026-07-22T11:12:22Z", "hours": 2.2856, "text": "OKAKAKAYAYAY some more cool additions for exploration aspect for the gam I added an arrow that points towards a set direction, which also changes its with respect to how far the rocket is from that point Also I FINALLY FIXED THE WATER WALKING SOUND ISSUE!!!1!!! Turns out it was quiet easy, i was just too stupid and over complicating it, a simple rewrite fixed everything. For next update i will be adding findable clues, maps, coordinates left out to rot by a “past explorer” that you find across the universe, this is gonna require a bit of time and skill but i can deliver that easy with some time Again progress is a bit slow cuz im actively working on my biggest endurance aircraft but i will keep tis game updated nonetheless, and in future u might even find it on steam who knows"}, {"post_id": 31916, "ts": "2026-07-20T18:18:16Z", "hours": 1.595, "text": "AYEEEYEYYE UPDATE ON THE PEAKEST GAME Made a really smart decision and got rid of the ugly hotbar like menu to place items, now da gam has a nice build menu in which most of the time was spent in making my code more cleaner. But it works now, it looks way more clean and immersive. Instead of relying on hardcoded information for items, i finally made a global that can handle all of that, idk why i didnt do that earlier. About the sound engine, i genuinely hate it a lot, i will be redoing it from scratch and figure out wtf is wrong with it Sorry for slow progress, i dont have much time till im at home so im tryna maximise the time i spend on my rc plen, ples follow it aswell"}, {"post_id": 30554, "ts": "2026-07-18T07:09:50Z", "hours": 1.0953, "text": "Oh i did manage to fix the water walking loop a lil more, its not perfect, but i dont understand whats going on. so ill just work on that later Anyways thats that, big changes i made are that now to place observatories or rovers you need to have a specific amount of scrap on you, i will be turning this into a full fledged build menu so its more appealing, and i will have this menu as a quick hotbar to place blueprints of items. I find this gameloop satisfying as it takes away the management hassle and this game is supposed to be relaxing. And bro how long IS the queue my bambu is STILL not shipped Sorry for slow updates on this project, currently working my ass off irl on the UAV project of mine as i have a deadline to finish it. If i did manage to get a good rep towards this proj, ill be taking the reviewers advice and hosting this game on steam. That developer grant might come in handy ngl"}, {"post_id": 29586, "ts": "2026-07-16T16:53:16Z", "hours": 3.3417, "text": "AYEEEEEE DEVLOG TIME So today i redid the observatory 3d model, gave it some clean nasa textures, its not upto my standards but its getting there, also fixed that stupid atmosphere bug now everything looks insanely better. Added a planet to the launch screen to flex aswell, i think it looks awesome there. Oh and also i tried to add water walking sound but am failing miserably but worry not as i will be reworking the soundengine too later Taking a moment to give a shout out to my followers who motivated me to work on tis more also HM all the reviewers who gave incredibly nice feedback"}, {"post_id": 28757, "ts": "2026-07-15T07:07:48Z", "hours": 3.0931, "text": "HOLEE SHIT, ADDED INSANE STUFF TO MY GAME IT LOOKS SO BEAUTIFUL NOW, I CANT BELIVE IT So, for starters, since yesterday I have been learning shaders. I fixed that shitty atmosphere shader that I translated from someone else’s shader to Godot. I had to make a lot of changes to it to get it working properly for my game. ALSO I MADE A SICK ASS WATER SHADER FOR PLANETS TO HAVE. Then I REWROTE THE PLANET GENERATION SCRIPT. Now each planet has unique properties like: Ambient temperature Water availability Air density, which determines water availability too I also tried adding comets and comet trails to the game, but failed tremendously. Oh, and also, dont go near the black hole. OH AND I GOT MY PAYOUT, AND I GOT THE BAMBULAB A1 MINI. THIS DAY JUST KEEPS GETTING BETTER"}, {"post_id": 27829, "ts": "2026-07-13T18:30:42Z", "hours": 3.1256, "text": "Devlog #idk Didn’t get a ton of new content added today, but I spent most of the time cleaning up annoying bugs and polishing the game. The biggest fix was the rocket explosion system. There was a bug where the rocket would slam into the ground at over 300 m/s … and just refuse to explode. I rewrote the logic, and it’s finally behaving properly. I also started modeling the mothership . It honestly looks like absolute dookey right now, but it’ll do as a placeholder. 3D modeling definitely isn’t my strongest skill, so I’m calling this version “good enough” for now. On the graphics side, I added a proper atmosphere around the planets, which makes them look much better. I also experimented with chromatic aberration , but it didn’t really fit the style of the game, so I ended up removing it. Huge thanks to @aloyak for the inspiration and some really helpful rendering tips. He showed me a much better way to increase the render distance without killing performance, so I’ll be implementing those improvements tomorrow. Also… I earned 1085 Stardust on my second ship. Not bad."}, {"post_id": 27157, "ts": "2026-07-12T13:40:03Z", "hours": 4.2947, "text": "OKAY so really cool changes First of all i fixed major inside stuff, instead of having 350 lines of gd script files in which i had to sift through to find the function i need, and then get overwhelmed later, i made everything modular, All the functions are Nodes in the scene that hold scripts. These scripts hold the functions that were earlier stored in the main .gd file, so now everything is a lot less cluttered and makes my life easier. I also did the same for the rocket scene as it was getting cluttered too. I added chests to the game where you can store items in (dont mind the invisible hotbar), They will be locations to store your items which will be scattered inside of observatories, im also thinking of redoing observatories as this model now looks ugly, and i think this has a lot more potential. Oh and also i have decided upon how im gonna make the player create an observatory, you land on a planet, collect scraps, them build an observatory, and then everything in observatory would cost the player X amount of scraps, also abandoned motherships will also provide the player upgrades for rocket. I got 3 ratings which im thrilled about, but also kinda sad because the reviewers prolly playing the itch release of the game and not the actual one but eh i think its fine, as long as my game is peak. Next ill be working on making an actual 3d model for the mothership"}, {"post_id": 26683, "ts": "2026-07-11T16:52:12Z", "hours": 2.1936, "text": "Designed the actual model for the rover, im pretty happy with how it turned out, i think ill keep it. tweaked the settings for the rover to get it just right, the only problem im facing is that due to the curvature of the planet, rover js flys off n start orbiting at high speed, i gotta add down force to tis i think. I removed the inventory cuz it was too wonky, i think ill have a hotbar and a backpack like peak, i think thatll be more immersive than having a stupid inventory. (this is totally not because i went rabid trying to implement it)"}, {"post_id": 26423, "ts": "2026-07-11T06:30:37Z", "hours": 2.1986, "text": "So i changed the Help UI of the game, made it look a lil better than that roblox ahh UI, Added mother stations to the game where u can get rocket upgrades, im slowly trying to figure out the game loop, itll be that you are a lonely astronaut in eternal void of space, your kind has been extinct, these ships are abandoned u can repair them and get a specific upgrade from each of them. Also i made the web version available too, its been 3 days and ive been sitting at 0 ratings just demotivated the hell out of me, the quality of graphics and gameplay is butchered but i had made that clear in the itch page, lets hope people rate it now"}, {"post_id": 25881, "ts": "2026-07-10T11:24:42Z", "hours": 5.6075, "text": "Working on making the game loop more fun, Im thinking ill be taking the game towards single player base building story mode type of game, I made a web version cuz i had 0 reviews after 2 days, the web version isnt good at all but its make do, I added rovers to the game now too its insanely fun driving them around the planet and having fun, i will be adding more stuff to the game, inventory system turns out is way harder than i expected so ill do that later. Enjoy this clip of the game"}, {"post_id": 25202, "ts": "2026-07-09T09:33:14Z", "hours": 2.2953, "text": "Made major game optimizations, Am adding a proper inventory system with crafting, I have designed inventory with crafting in past for my cooking game shouldn’t be that hard, But doing it in preexisting is a bit of a challenge. I have implemented a simple hotbar and item system in the game, I also used Godots IK nodes to control the bones, and god damm was it useful, this might come in handy in future. Switch to this camera does make it look a lot better"}, {"post_id": 24651, "ts": "2026-07-08T11:38:24Z", "hours": 0.5031, "text": "Okay just fixed another tiny bug, im glad i checked it, when i select the satellite for an observatory, the UI doesn’t open again, so it made it impossible to refuel, i fixed that by giving an option to control satellite now. I think im set for the ship now, i reccomplied the binaries, the readme is ready to, along with the latest youtube video https://youtu.be/RQmEh_rwnzQ"}, {"post_id": 24598, "ts": "2026-07-08T09:44:34Z", "hours": 4.72, "text": "Final devlog before ship. I have polished the UI, remade the boney 3d model, Fixed observatory logic, made other tiny gamebreaking improvements, Also i have fixed animations for boney, added a jump animation. Major change is 3rd Person camera now, which makes the whole experince even more immersive. I have playtested it several times, im kinda nervous and hoping it works perfectly as it is on my machine."}, {"post_id": 24288, "ts": "2026-07-07T19:13:44Z", "hours": 4.7478, "text": "Getting the project production-ready. I’ve finally added local storage for the settings menu, so your graphics and gameplay preferences now persist between sessions instead of resetting every time you launch the game. A lot of people mentioned in the last devlog that they couldn’t figure out the controls, so I added a “Show Keybinds” toggle in the settings menu (press ESC to open it). It displays the controls on-screen whenever you need them. I also found a pretty game-breaking bug, so I’m documenting it here for future me: If you’re mounted in the rocket, enable Show Keybinds, and then hit Apply, the player can no longer unmount from the rocket. I’ll be fixing that later. I spent some time messing around with Godot’s built-in graphics settings and realized I’d completely forgotten to enable anti-aliasing. Turning it on made a huge difference, the game looks so much cleaner now. As you can see, I’ve also added a fuel gauge for the rocket. It helps sell the whole “claiming and exploring planets” vibe. I also changed observatories so each planet can only have one. Another gameplay change is that you now have to visit an observatory to dock a satellite onto your rocket instead of doing it anywhere. Finally, I changed how world persistence works. If your rocket crashes and you reset the game, any observatories you’ve already built will still be there instead of disappearing."}, {"post_id": 24002, "ts": "2026-07-07T08:55:54Z", "hours": 4.1525, "text": "Today i have just started refining the 2/3 stage gameplay i made it so you cant just spam sattelites wherever you want, but instead you have to get them docked on your rocket at the research center. I made the ugly loading screen a little better, i will fix it even more by designing custom graphics for it I revamped the 3d model for the research facility, it has interior and the infamous meme toilet where little boneys take a dookie in unison. (This will be a feature in 3/3 version of the game) Currently i have fixed some more gamebreaking bug where the ui just straight up didnt work, turns out it was due to my own stupidity of forgetting to hide an transparent panel in the scene tree."}, {"post_id": 23577, "ts": "2026-07-06T16:46:05Z", "hours": 4.7711, "text": "SO, Im now starting to add everything people complained about or found annoying in my first ship, Someone pointed out i had made the help but the help i made didnt tell what keybinds to use, so i have designed a dynamically UI screen to add guide for button keypress, it was a bit of a tedious job but its done now. Since i understand that not everyone has a good computer, (I have an RTX4050 with Ryzen 7 AMD Ryzen 7 7435HS CPU with 24 gigs of ram so i cant rely on my laptop to be an average computer) but i know not everyone has these specs so i took the time to code more settings in the settings section, now i can select the major factors of FPS drop in this game. Also i redid the noise the planets used, the noise textures is used before if you see from earlier videos looks very choppy, unrealistic and creative, now it looks a LOT better. Currently i haven’t added keybinds UI for the rocket, which ill add later, I will be making a ship soon after fixing more bugs that i delayed for later."}, {"post_id": 23362, "ts": "2026-07-06T09:04:28Z", "hours": 7.4369, "text": "Finally the biggest change ever yet, this took me HOURS of rewriting debugging fixing weird glitches, tried to even recompile Godot at one point, But its done, A truly frame efficient infinite procedural planet generation with randomness and seed integrated in it, this took so much of my sanity, so many broken hairs, but finally i am able to perfectly get it working at 144fps and around 11ms average frame time. I also optimized the rock generation even more to take advantage of godots multi threading capabilities to take the load off the main thread to generate the chunks for rocks. Current limitations of this architecture are not the architecture but the godot engine itself, as it uses 16 bit floats to keep track of transform, so if you’re like 100,000 units away from your home planet you start facing very weird glitches, I personally think im gonna keep this glitch in the game as i have no idea how these glitches will affect the gameplay, its like minecraft farlands, i want to see how the world generation breaks, and i dont want to stop the player from experiencing that aswell. Its not that idk how to fix this, if i recompile godot to use double instead of float i can extend the range of the farlands way beyond that, but its just the matter of personal preference. I have quiet insane ideas and directions for this project now that ive came so far, its kinda funny how all this became what it is just because i wanted to control a rocket in space."}, {"post_id": 22728, "ts": "2026-07-05T09:44:51Z", "hours": 4.8342, "text": "ABSOLUTELY INSANE ADDITIONS FOR MY GAME THIS TIME. First of all my first ship was finally reviewed so i read all the reviews and made a mental note of all of them, they were all positive and im very happy people resonate with my project so i appreciate everyone who wrote a very thoughtful review for me i thank you all a lot. Now in the technical part of the game: I finally fixed my nebula raymarched shader, now it actually has volume and you can go inside it and it looks absolutely ethereal. Reviews told me that they would love it if the planets had more details, so details i added, i made a VERY efficient chunking pipeline to scatter debries, and whatever i want on the planet mesh, i am being able to have the whole planet populated with no noticeable drop to performance. I made the script in a way that its a module, so in case if i ever want a planet with vegetation or trees, i can just drop the 3d obj file for that mesh and boom ill have a proper chunk based scatter for that mesh. I tested the chunks using debug cubes and it works perfectly as it should. I also added spacewalking to the game, you can genuinely just float in the space and enjoy the view from the outside, this was quiet easy but its an addition that i shouldve added a long time ago. Also ive finally added randomly generated textures for planet surfaces, these dont look AS realistic rn, but im sure after changing a few parameters and adding proper debrie 3d models, it’ll look absolutely astonishing. From the reviews i read that i didn’t add any help for what keys to use and genuinely thats on me im too stupid so in future ship ill 100% fix that Also ive added a feature where you can currently place observatories on planets and use them to control the satellites, This is just for now as for future ill make the player do stuff on the planet first to have their base setup, I dont wanna complicate it too much as this is supposed to be a relaxing game, but i think this much is necessary. Ive also 3d modeled a tiny astronaut along with his animations and im calling the player boney, i have decided on boney’s lore yet but i can assure yall one thing, it will be insanely deep, and there will be clues for it all around the game, you just have to notice it. I also have massively optimised the star spawning shader, i am able to have 10s of thousands stars on the screen without having any frame drops at all, i used GPU instancing for this and this is genuinely black magic, I also used GPU bill boarding to help aid the performance even more. Removed the unnecessary calculations and now the sky is denser than ever. I also herd people wanted me to make a web release for it as the download process was quiet tedious, but i think 2 devlogs ago you can see me in godots compatibility mode, it BUTCHERED the visuals completely so i dont think i can bring myself to do that after spending so much time writing complex shaders. TODO: Add wormholes, infinite planet generation, coordinate system."}, {"post_id": 22073, "ts": "2026-07-04T10:05:33Z", "hours": 5.02, "text": "Okay this devogg im glad to announce i have successfully fixed that bug in last devlog which i told yall about, this devlog i added a lot of visual eye candy changes, and a few more functional changes. For starters i added a settings menu and a homepage so users with low end devices can change the settings accordingly, these settings will obviously be updated as the game updates. Secondly, ive added GPU instanced particles all around the player to give to the eyecandy factor of the game. Thirdly i added black holes and their custom ray marched shader to them, they also have the stretch effect of light when u go near them like how they describe “spaghettification” in encyclopedias. I also added ray marched nebula in aswell, they currently dont serve a specific purpose apart from the eyecandy factor, but to be fair not everything has to have a purpose as this is just a relaxing chill game. I also changed the music to a different royalty free music, i was genuinely so tired of listening to that track on loop it was driving me crazy."}, {"post_id": 21430, "ts": "2026-07-03T11:40:44Z", "hours": 5.1097, "text": "I have genuinely lost hairs, sanity and life, i have this insanely annoying gamebreaking bug. Currently if the world has more than 1 active gravity source, the satellite doesnt perfectly orbit the planet it should be orbiting, after a while it looses velocity and crashes, this is absolutely gamebreaking as the main concept of the game is gravity. I have tried so many fixes, managed to break the game multiple times, but in the end i think i have a clue of whats going on, when i introduced SOI for each planet, the orbit was still terminating with a crash on the planet, i had made it so that if the body is outside the sphere of influence,it sets the gravity influence from that planet to 0, but even if im in my own sphere, i still somehow crash, i initially thought that the other planets might be attracting the satellite, but i think its the floating point calculations that are messing the orbit up, currently i have no clue how ill fix it but ik ill figure something out. If you guys have any idea what it could be please comment i lowk need all the ideas i can get Anyways i fixed the satellite observatory logic, refined it a bit more, ran tests, tried to implement multiplayer but stopped cuz other bugs got overwhelming. I think ill focus more on designing a nice clean UI now rather than bug fix, which ill do later, cuz they do say “make it exist first, make it perfect later”."}, {"post_id": 20673, "ts": "2026-07-02T10:15:08Z", "hours": 4.4403, "text": "Devlog 8 of my epic space game: Following the trend of making a relaxing space sim game with multiplayer, i added quiet a lot of stuff this devlog, i first of all laid a foundation for future, redid all the buggy code, made all the functions future proof, and then i added observatories, proper satellite controller, and made the satellites be able to control with their respective observatory, now the player can spawn satellites, send them to space or go on a mission, come land back and control the sattelite they have sent to the space. In future ill be adding dynamic and unique planets that will be randomly generated eveytime you log into the game."}, {"post_id": 19227, "ts": "2026-06-30T14:21:37Z", "hours": 0.8425, "text": "DEVLOG 7 OF INTO THE COSMOS This devlog i made some really important additions of a help menu for newer players, i find this quiet important as making an orbit around the planet is quiet hard, so i handdrew some quick informative help guide that can help you quickstart. Also finally ready for my ship #1, i have setup the readme, and made a release for this project, Also uploaded a lil youtube video cuz the guide said so."}, {"post_id": 18501, "ts": "2026-06-29T17:48:37Z", "hours": 1.6342, "text": "Devlog 6 of my epic space game: This update i added quiet a bunch of stuff i was excited to add. First of all major addition, A Satellite, you can carry it from your rocket, take it it in your low planetary orbit and release it in there, itll keep orbiting the planet if you made your orbit right. RCS and thrust with VFX for the satellite this was essential as real life satellites also have this feature and im trying to nail reality as much as i can with this project Finally a better camera, now camera can switch between 2 registered entities, and the selected entity will only be controlled by the camera so thats pretty neat. In the video i showcase the rocket, the satellite, satellite boosters and rcs, landing the rocket, rendezvous with the satellite back again (not really but eh lets just call it that) For future im planning to add redocking (its gonna be very hard to do it in game tho), the game is actually quiet hard its not as simple to create orbits, if the user doesnt have the knowledge of how orbits are made then itll be quiet hard for them to understand that, so for the final release ill also be making a little tutorial. The video is 1.5x btw"}, {"post_id": 18150, "ts": "2026-06-29T05:15:37Z", "hours": 2.8544, "text": "Devlog 5 of my epic space travel game: Finally added more stuff i was delaying to add RCS thrusters effects, now rcs thrusters also have a thrust cone like the main booster Really nice explpsion vfx, now the explosion doesnt look like a low effort particle, its multilayered particles now with sound effects Balanced the game a bit as currently landing was quiet hard, so i fixed that Game is coming together really well, personally i spend a lot of time playing it myself so i know its a banger project, Moving forward i will be adding satellites, save states, fuel system, multi stage rockets, production level graphics to the game. (not posting video as they dont do as well)"}, {"post_id": 17045, "ts": "2026-06-27T17:51:18Z", "hours": 2.4083, "text": "Devlog for my awesome space game, so today i remade the 3d model for the rocket which i was dreading to do but finally got it off, the insane part is that i added a really nice vfx trail instead of kiddie looking particle trail for the rocket, this one looks like an actual thruster and the real deal. Also added music this time around, i tried to add thruster sound but that wasnt working so left that for some other day. tommrow i think ill add proper 3d models for planets and make a replica mini solar system (not ours) The vfx look so sick tho i cant have enough of them"}, {"post_id": 16377, "ts": "2026-06-26T17:33:15Z", "hours": 1.7225, "text": "KSP style sandbox game: Okay so a lot happened since last time, firstly i switched to arch linux as my daily os, and in the game i added planets, RCS, realistic gravity. a planet is a datatype that has information of the mass and gravity scale of that planet, and it can attract the rocket object, also the cool part is you can have multiple planets and create really creative orbits around them, its almost like were actually in spacec Added RCS thrusters as landing on planets was impossible without it, rcs uses shift + wasdqe keys to move in all 3 axis, this makes it very playable but not extremely easy, in the video you can see i still haven’t got the total hang of it yet myself, but ik ill do. Ik i was gonna make a playable release today but due to me wiping windows thats gotta wait a while before it actually happens, For future plans i think ill add a proper environment that replicates space, have enhanced 3d models with HD textures, rcs particles and stuff, also an actual level to play around in."}, {"post_id": 15657, "ts": "2026-06-25T13:49:03Z", "hours": 2.7311, "text": "Okay game is coming along quiet awesome, i managed to make a proper 3d model this time, it has textures and an ugly ass nose cone which ill fix later, currently i made more quality of life changes, made the rocket more snappier, and made it so you can revive, added a lil bit of juice by adding explosion particles and revamped thrust particles as well. Somehow managed to break the entire camera script, but that was soon fixed too so the game is coming along quiet good. For the direction aspect, i currently think flying the rocket around the map is quiet fun ngl, watching me maneuver the landscape by trying to not hit anything in process, also added a moon map and made it similar to the moon by downloading the hightmap data and texture data from actual nasa, but i gave up on that cuz the low res one was trash and high res hightmap was like a bajillion gigabytes and aint nobody gonna download this game if its that big. I played around with different gravity settings and realised flying the rocket is quiet easy if youre on moon compared to earth (duh). So IF (big if) i add levels to it, this might be a hint of what theyll be, again i dont like level system as theyre not fun and u get tired of it soon, i might add multiplayer capabilities later with a python webserver running on the server machine so you can battle with your friends too, possibilities are endless, and ill serve yall good with this one. Like this project and follow me, in the next devlog ill release exe file for this project."}, {"post_id": 14983, "ts": "2026-06-24T10:25:23Z", "hours": 1.3406, "text": "Making an awesome godot game in which you control a rocket ship and you can basically do anything with it, currently i havent decided the direction i wanna take this game towards, i might make it into a demolition sandbox type game, a space exploration game, or a movement type game where you have to reach the destination, like that one cool math game. till now ive achieved Rigid body rocket with its yaw and pitch controls An animated rocket 3d model A test scene with kennys prototype textures A particle style thrust system In next devlog i might add sounds, explosions, and gasoline"}]...
|
Title: Into the cosmos by @tejaswa | Stardance
De Title: Into the cosmos by @tejaswa | Stardance
Devlogs:
Making an awesome godot game in which you control a rocket ship and you can basically do anything with it, currently i havent decided the direction i wanna take this game towards, i might make it into a demolition sandbox type game, a space exploration game, or a movement type game where you have to reach the destination, like that one cool math game. till now ive achieved Rigid body rocket with its yaw and pitch controls An animated rocket 3d model A test scene with kennys prototype textures A particle style thrust system In next devlog i might add sounds, explosions, and gasoline
Okay game is coming along quiet awesome, i managed to make a proper 3d model this time, it has textures and an ugly ass nose cone which ill fix later, currently i made more quality of life changes, made the rocket more snappier, and made it so you can revive, added a lil bit of juice by adding explosion particles and revamped thrust particles as well. Somehow managed to break the entire camera script, but that was soon fixed too so the game is coming along quiet good. For the direction aspect, i currently think flying the rocket around the map is quiet fun ngl, watching me maneuver the landscape by trying to not hit anything in process, also added a moon map and made it similar to the moon by downloading the hightmap data and texture data from actual nasa, but i gave up on that cuz the low res one was trash and high res hightmap was like a bajillion gigabytes and aint nobody gonna download this game if its that big. I played around with different gravity settings and realised flying the rocket is quiet easy if youre on moon compared to earth (duh). So IF (big if) i add levels to it, this might be a hint of what theyll be, again i dont like level system as theyre not fun and u get tired of it soon, i might add multiplayer capabilities later with a python webserver running on the server machine so you can battle with your friends too, possibilities are endless, and ill serve yall good with this one. Like this project and follow me, in the next devlog ill release exe file for this project.
KSP style sandbox game: Okay so a lot happened since last time, firstly i switched to arch linux as my daily os, and in the game i added planets, RCS, realistic gravity. a planet is a datatype that has information of the mass and gravity scale of that planet, and it can attract the rocket object, also the cool part is you can have multiple planets and create really creative orbits around them, its almost like were actually in spacec Added RCS thrusters as landing on planets was impossible without it, rcs uses shift + wasdqe keys to move in all 3 axis, this makes it very playable but not extremely easy, in the video you can see i still haven’t got the total hang of it yet myself, but ik ill do. Ik i was gonna make a playable release today but due to me wiping windows thats gotta wait a while before it actually happens, For future plans i think ill add a proper environment that replicates space, have enhanced 3d models with HD textures, rcs particles and stuff, also an actual level to play around in.
Devlog for my awesome space game, so today i remade the 3d model for the rocket which i was dreading to do but finally got it off, the insane part is that i added a really nice vfx trail instead of kiddie looking particle trail for the rocket, this one looks like an actual thruster and the real deal. Also added music this time around, i tried to add thruster sound but that wasnt working so left that for some other day. tommrow i think ill add proper 3d models for planets and make a replica mini solar system (not ours) The vfx look so sick tho i cant have enough of them
Devlog 5 of my epic space travel game: Finally added more stuff i was delaying to add RCS thrusters effects, now rcs thrusters also have a thrust cone like the main booster Really nice explpsion vfx, now the explosion doesnt look like a low effort particle, its multilayered particles now with sound effects Balanced the game a bit as currently landing was quiet hard, so i fixed that Game is coming together really well, personally i spend a lot of time playing it myself so i know its a banger project, Moving forward i will be adding satellites, save states, fuel system, multi stage rockets, production level graphics to the game. (not posting video as they dont do as well)
Devlog 6 of my epic space game: This update i added quiet a bunch of stuff i was excited to add. First of all major addition, A Satellite, you can carry it from your rocket, take it it in your low planetary orbit and release it in there, itll keep orbiting the planet if you made your orbit right. RCS and thrust with VFX for the satellite this was essential as real life satellites also have this feature and im trying to nail reality as much as i can with this project Finally a better camera, now camera can switch between 2 registered entities, and the selected entity will only be controlled by the camera so thats pretty neat. In the video i showcase the rocket, the satellite, satellite boosters and rcs, landing the rocket, rendezvous with the satellite back again (not really but eh lets just call it that) For future im planning to add redocking (its gonna be very hard to do it in game tho), the game is actually quiet hard its not as simple to create orbits, if the user doesnt have the knowledge of how orbits are made then itll be quiet hard for them to understand that, so for the final release ill also be making a little tutorial. The video is 1.5x btw
DEVLOG 7 OF INTO THE COSMOS This devlog i made some really important additions of a help menu for newer players, i find this quiet important as making an orbit around the planet is quiet hard, so i handdrew some quick informative help guide that can help you quickstart. Also finally ready for my ship #1, i have setup the readme, and made a release for this project, Also uploaded a lil youtube video cuz the guide said so.
Devlog 8 of my epic space game: Following the trend of making a relaxing space sim game with multiplayer, i added quiet a lot of stuff this devlog, i first of all laid a foundation for future, redid all the buggy code, made all the functions future proof, and then i added observatories, proper satellite controller, and made the satellites be able to control with their respective observatory, now the player can spawn satellites, send them to space or go on a mission, come land back and control the sattelite they have sent to the space. In future ill be adding dynamic and unique planets that will be randomly generated eveytime you log into the game.
I have genuinely lost hairs, sanity and life, i have this insanely annoying gamebreaking bug. Currently if the world has more than 1 active gravity source, the satellite doesnt perfectly orbit the planet it should be orbiting, after a while it looses velocity and crashes, this is absolutely gamebreaking as the main concept of the game is gravity. I have tried so many fixes, managed to break the game multiple times, but in the end i think i have a clue of whats going on, when i introduced SOI for each planet, the orbit was still terminating with a crash on the planet, i had made it so that if the body is outside the sphere of influence,it sets the gravity influence from that planet to 0, but even if im in my own sphere, i still somehow crash, i initially thought that the other planets might be attracting the satellite, but i think its the floating point calculations that are messing the orbit up, currently i have no clue how ill fix it but ik ill figure something out. If you guys have any idea what it could be please comment i lowk need all the ideas i can get Anyways i fixed the satellite observatory logic, refined it a bit more, ran tests, tried to implement multiplayer but stopped cuz other bugs got overwhelming. I think ill focus more on designing a nice clean UI now rather than bug fix, which ill do later, cuz they do say “make it exist first, make it perfect later”.
Okay this devogg im glad to announce i have successfully fixed that bug in last devlog which i told yall about, this devlog i added a lot of visual eye candy changes, and a few more functional changes. For starters i added a settings menu and a homepage so users with low end devices can change the settings accordingly, these settings will obviously be updated as the game updates. Secondly, ive added GPU instanced particles all around the player to give to the eyecandy factor of the game. Thirdly i added black holes and their custom ray marched shader to them, they also have the stretch effect of light when u go near them like how they describe “spaghettification” in encyclopedias. I also added ray marched nebula in aswell, they currently dont serve a specific purpose apart from the eyecandy factor, but to be fair not everything has to have a purpose as this is just a relaxing chill game. I also changed the music to a different royalty free music, i was genuinely so tired of listening to that track on loop it was driving me crazy.
ABSOLUTELY INSANE ADDITIONS FOR MY GAME THIS TIME. First of all my first ship was finally reviewed so i read all the reviews and made a mental note of all of them, they were all positive and im very happy people resonate with my project so i appreciate everyone who wrote a very thoughtful review for me i thank you all a lot. Now in the technical part of the game: I finally fixed my nebula raymarched shader, now it actually has volume and you can go inside it and it looks absolutely ethereal. Reviews told me that they would love it if the planets had more details, so details i added, i made a VERY efficient chunking pipeline to scatter debries, and whatever i want on the planet mesh, i am being able to have the whole planet populated with no noticeable drop to performance. I made the script in a way that its a module, so in case if i ever want a planet with vegetation or trees, i can just drop the 3d obj file for that mesh and boom ill have a proper chunk based scatter for that mesh. I tested the chunks using debug cubes and it works perfectly as it should. I also added spacewalking to the game, you can genuinely just float in the space and enjoy the view from the outside, this was quiet easy but its an addition that i shouldve added a long time ago. Also ive finally added randomly generated textures for planet surfaces, these dont look AS realistic rn, but im sure after changing a few parameters and adding proper debrie 3d models, it’ll look absolutely astonishing. From the reviews i read that i didn’t add any help for what keys to use and genuinely thats on me im too stupid so in future ship ill 100% fix that Also ive added a feature where you can currently place observatories on planets and use them to control the satellites, This is just for now as for future ill make the player do stuff on the planet first to have their base setup, I dont wanna complicate it too much as this is supposed to be a relaxing game, but i think this much is necessary. Ive also 3d modeled a tiny astronaut along with his animations and im calling the player boney, i have decided on boney’s lore yet but i can assure yall one thing, it will be insanely deep, and there will be clues for it all around the game, you just have to notice it. I also have massively optimised the star spawning shader, i am able to have 10s of thousands stars on the screen without having any frame drops at all, i used GPU instancing for this and this is genuinely black magic, I also used GPU bill boarding to help aid the performance even more. Removed the unnecessary calculations and now the sky is denser than ever. I also herd people wanted me to make a web release for it as the download process was quiet tedious, but i think 2 devlogs ago you can see me in godots compatibility mode, it BUTCHERED the visuals completely so i dont think i can bring myself to do that after spending so much time writing complex shaders. TODO: Add wormholes, infinite planet generation, coordinate system.
Finally the biggest change ever yet, this took me HOURS of rewriting debugging fixing weird glitches, tried to even recompile Godot at one point, But its done, A truly frame efficient infinite procedural planet generation with randomness and seed integrated in it, this took so much of my sanity, so many broken hairs, but finally i am able to perfectly get it working at 144fps and around 11ms average frame time. I also optimized the rock generation even more to take advantage of godots multi threading capabilities to take the load off the main thread to generate the chunks for rocks. Current limitations of this architecture are not the architecture but the godot engine itself, as it uses 16 bit floats to keep track of transform, so if you’re like 100,000 units away from your home planet you start facing very weird glitches, I personally think im gonna keep this glitch in the game as i have no idea how these glitches will affect the gameplay, its like minecraft farlands, i want to see how the world generation breaks, and i dont want to stop the player from experiencing that aswell. Its not that idk how to fix this, if i recompile godot to use double instead of float i can extend the range of the farlands way beyond that, but its just the matter of personal preference. I have quiet insane ideas and directions for this project now that ive came so far, its kinda funny how all this became what it is just because i wanted to control a rocket in space.
SO, Im now starting to add everything people complained about or found annoying in my first ship, Someone pointed out i had made the help but the help i made didnt tell what keybinds to use, so i have designed a dynamically UI screen to add guide for button keypress, it was a bit of a tedious job but its done now. Since i understand that not everyone has a good computer, (I have an RTX4050 with Ryzen 7 AMD Ryzen 7 7435HS CPU with 24 gigs of ram so i cant rely on my laptop to be an average computer) but i know not everyone has these specs so i took the time to code more settings in the settings section, now i can select the major factors of FPS drop in this game. Also i redid the noise the planets used, the noise textures is used before if you see from earlier videos looks very choppy, unrealistic and creative, now it looks a LOT better. Currently i haven’t added keybinds UI for the rocket, which ill add later, I will be making a ship soon after fixing more bugs that i delayed for later.
Today i have just started refining the 2/3 stage gameplay i made it so you cant just spam sattelites wherever you want, but instead you have to get them docked on your rocket at the research center. I made the ugly loading screen a little better, i will fix it even more by designing custom graphics for it I revamped the 3d model for the research facility, it has interior and the infamous meme toilet where little boneys take a dookie in unison. (This will be a feature in 3/3 version of the game) Currently i have fixed some more gamebreaking bug where the ui just straight up didnt work, turns out it was due to my own stupidity of forgetting to hide an transparent panel in the scene tree.
Getting the project production-ready. I’ve finally added local storage for the settings menu, so your graphics and gameplay preferences now persist between sessions instead of resetting every time you launch the game. A lot of people mentioned in the last devlog that they couldn’t figure out the controls, so I added a “Show Keybinds” toggle in the settings menu (press ESC to open it). It displays the controls on-screen whenever you need them. I also found a pretty game-breaking bug, so I’m documenting it here for future me: If you’re mounted in the rocket, enable Show Keybinds, and then hit Apply, the player can no longer unmount from the rocket. I’ll be fixing that later. I spent some time messing around with Godot’s built-in graphics settings and realized I’d completely forgotten to enable anti-aliasing. Turning it on made a huge difference, the game looks so much cleaner now. As you can see, I’ve also added a fuel gauge for the rocket. It helps sell the whole “claiming and exploring planets” vibe. I also changed observatories so each planet can only have one. Another gameplay change is that you now have to visit an observatory to dock a satellite onto your rocket instead of doing it anywhere. Finally, I changed how world persistence works. If your rocket crashes and you reset the game, any observatories you’ve already built will still be there instead of disappearing.
Final devlog before ship. I have polished the UI, remade the boney 3d model, Fixed observatory logic, made other tiny gamebreaking improvements, Also i have fixed animations for boney, added a jump animation. Major change is 3rd Person camera now, which makes the whole experince even more immersive. I have playtested it several times, im kinda nervous and hoping it works perfectly as it is on my machine.
Okay just fixed another tiny bug, im glad i checked it, when i select the satellite for an observatory, the UI doesn’t open again, so it made it impossible to refuel, i fixed that by giving an option to control satellite now. I think im set for the ship now, i reccomplied the binaries, the readme is ready to, along with the latest youtube video https://youtu.be/RQmEh_rwnzQ
Made major game optimizations, Am adding a proper inventory system with crafting, I have designed inventory with crafting in past for my cooking game shouldn’t be that hard, But doing it in preexisting is a bit of a challenge. I have implemented a simple hotbar and item system in the game, I also used Godots IK nodes to control the bones, and god damm was it useful, this might come in handy in future. Switch to this camera does make it look a lot better
Working on making the game loop more fun, Im thinking ill be taking the game towards single player base building story mode type of game, I made a web version cuz i had 0 reviews after 2 days, the web version isnt good at all but its make do, I added rovers to the game now too its insanely fun driving them around the planet and having fun, i will be adding more stuff to the game, inventory system turns out is way harder than i expected so ill do that later. Enjoy this clip of the game
So i changed the Help UI of the game, made it look a lil better than that roblox ahh UI, Added mother stations to the game where u can get rocket upgrades, im slowly trying to figure out the game loop, itll be that you are a lonely astronaut in eternal void of space, your kind has been extinct, these ships are abandoned u can repair them and get a specific upgrade from each of them. Also i made the web version available too, its been 3 days and ive been sitting at 0 ratings just demotivated the hell out of me, the quality of graphics and gameplay is butchered but i had made that clear in the itch page, lets hope people rate it now
Designed the actual model for the rover, im pretty happy with how it turned out, i think ill keep it. tweaked the settings for the rover to get it just right, the only problem im facing is that due to the curvature of the planet, rover js flys off n start orbiting at high speed, i gotta add down force to tis i think. I removed the inventory cuz it was too wonky, i think ill have a hotbar and a backpack like peak, i think thatll be more immersive than having a stupid inventory. (this is totally not because i went rabid trying to implement it)
OKAY so really cool changes First of all i fixed major inside stuff, instead of having 350 lines of gd script files in which i had to sift through to find the function i need, and then get overwhelmed later, i made everything modular, All the functions are Nodes in the scene that hold scripts. These scripts hold the functions that were earlier stored in the main .gd file, so now everything is a lot less cluttered and makes my life easier. I also did the same for the rocket scene as it was getting cluttered too. I added chests to the game where you can store items in (dont mind the invisible hotbar), They will be locations to store your items which will be scattered inside of observatories, im also thinking of redoing observatories as this model now looks ugly, and i think this has a lot more potential. Oh and also i have decided upon how im gonna make the player create an observatory, you land on a planet, collect scraps, them build an observatory, and then everything in observatory would cost the player X amount of scraps, also abandoned motherships will also provide the player upgrades for rocket. I got 3 ratings which im thrilled about, but also kinda sad because the reviewers prolly playing the itch release of the game and not the actual one but eh i think its fine, as long as my game is peak. Next ill be working on making an actual 3d model for the mothership
Devlog #idk Didn’t get a ton of new content added today, but I spent most of the time cleaning up annoying bugs and polishing the game. The biggest fix was the rocket explosion system. There was a bug where the rocket would slam into the ground at over 300 m/s … and just refuse to explode. I rewrote the logic, and it’s finally behaving properly. I also started modeling the mothership . It honestly looks like absolute dookey right now, but it’ll do as a placeholder. 3D modeling definitely isn’t my strongest skill, so I’m calling this version “good enough” for now. On the graphics side, I added a proper atmosphere around the planets, which makes them look much better. I also experimented with chromatic aberration , but it didn’t really fit the style of the game, so I ended up removing it. Huge thanks to @aloyak for the inspiration and some really helpful rendering tips. He showed me a much better way to increase the render distance without killing performance, so I’ll be implementing those improvements tomorrow. Also… I earned 1085 Stardust on my second ship. Not bad.
HOLEE SHIT, ADDED INSANE STUFF TO MY GAME IT LOOKS SO BEAUTIFUL NOW, I CANT BELIVE IT So, for starters, since yesterday I have been learning shaders. I fixed that shitty atmosphere shader that I translated from someone else’s shader to Godot. I had to make a lot of changes to it to get it working properly for my game. ALSO I MADE A SICK ASS WATER SHADER FOR PLANETS TO HAVE. Then I REWROTE THE PLANET GENERATION SCRIPT. Now each planet has unique properties like: Ambient temperature Water availability Air density, which determines water availability too I also tried adding comets and comet trails to the game, but failed tremendously. Oh, and also, dont go near the black hole. OH AND I GOT MY PAYOUT, AND I GOT THE BAMBULAB A1 MINI. THIS DAY JUST KEEPS GETTING BETTER
AYEEEEEE DEVLOG TIME So today i redid the observatory 3d model, gave it some clean nasa textures, its not upto my standards but its getting there, also fixed that stupid atmosphere bug now everything looks insanely better. Added a planet to the launch screen to flex aswell, i think it looks awesome there. Oh and also i tried to add water walking sound but am failing miserably but worry not as i will be reworking the soundengine too later Taking a moment to give a shout out to my followers who motivated me to work on tis more also HM all the reviewers who gave incredibly nice feedback
Oh i did manage to fix the water walking loop a lil more, its not perfect, but i dont understand whats going on. so ill just work on that later Anyways thats that, big changes i made are that now to place observatories or rovers you need to have a specific amount of scrap on you, i will be turning this into a full fledged build menu so its more appealing, and i will have this menu as a quick hotbar to place blueprints of items. I find this gameloop satisfying as it takes away the management hassle and this game is supposed to be relaxing. And bro how long IS the queue my bambu is STILL not shipped Sorry for slow updates on this project, currently working my ass off irl on the UAV project of mine as i have a deadline to finish it. If i did manage to get a good rep towards this proj, ill be taking the reviewers advice and hosting this game on steam. That developer grant might come in handy ngl
AYEEEYEYYE UPDATE ON THE PEAKEST GAME Made a really smart decision and got rid of the ugly hotbar like menu to place items, now da gam has a nice build menu in which most of the time was spent in making my code more cleaner. But it works now, it looks way more clean and immersive. Instead of relying on hardcoded information for items, i finally made a global that can handle all of that, idk why i didnt do that earlier. About the sound engine, i genuinely hate it a lot, i will be redoing it from scratch and figure out wtf is wrong with it Sorry for slow progress, i dont have much time till im at home so im tryna maximise the time i spend on my rc plen, ples follow it aswell
OKAKAKAYAYAY some more cool additions for exploration aspect for the gam I added an arrow that points towards a set direction, which also changes its with respect to how far the rocket is from that point Also I FINALLY FIXED THE WATER WALKING SOUND ISSUE!!!1!!! Turns out it was quiet easy, i was just too stupid and over complicating it, a simple rewrite fixed everything. For next update i will be adding findable clues, maps, coordinates left out to rot by a “past explorer” that you find across the universe, this is gonna require a bit of time and skill but i can deliver that easy with some time Again progress is a bit slow cuz im actively working on my biggest endurance aircraft but i will keep tis game updated nonetheless, and in future u might even find it on steam who knows
OKAYAYAYAYAYA UPDATE TIME I have graves implemented in the game now, after careful consideration about which direction i wanna take my game towards, i think graves would be a nice addition without disrespecting the procedural nature of the game. I want to make this game very lore heavy while being fully open world and giving the remote in players hands. I dont wnana confine them with thick story plot, or tedious tasks. Nor do i wanna make the game absolutely boring and pointless. The “Rot” i talk about is a cosmic disease the players universe is going through, unexplainable things are happening, weird inter dimensional gates are popping up at random places, everything is near extension. Im not sure about the role of player in all this tho, i will figure something out tho, i wont disappoint yall thats my promise. Also i worked a bit more on a weird bug where items were being placed not where the raycast was supposed to hit. Also I will be removing the inventory system entirely and just rely on blueprint building aspect lmk if yall think thats a good idea Also shout out to hackclub for getting me so much stuff i really love every single one of yall ❤️ Also progress on this game will go back to high now as i wont be home to work on my plen.
Finally a devlog after several days of straight struggle For starters ill tell yall why it took me so long I lowk changed places and i live alone in a room now, i had to shift and living conditions here are absolute hell I somehow survive without going wild due to all the bs ive been facing recently. My productivity has taken a severe hit, a feature like this took me way too much time to complete than it should’ve. That being said i did wander off in different directions cuz i was lowk clueless which direction i should take this game (i still havent decided ) In this devlog i added advanced material processing and advanced materials to the game, with a minecraft furnace like cooking mechanics, i made the logic quiet efficient and refined, its not my best work but it can always be better later. I js hope this eternal torture ends and i finally get to have better living conditions. istg ive been boiled alive, breathing is a struggle in this place Ill keep serving yall with most banger updates so keep me followed, this game is gonna be the next big thing lowk Now i will be makig the 3d model for refinery, before this i made a failure ahh model in whcih i js made a complete simithing room inside a space bubble 😭 Gotta make something better than that so time to lock in
Man i hate making 3D models Not my best work yet, but refinery is done, After several iterations, getting inspo from pinterest and then ditching it and drawing one in back of the class, im finally set on a design, it looks pretty good as of rn. (its not) I fixed a bug where the text was glitching out when i tried to craft scraps, and now it works as it should. The logic is perfect for how it should act in game and im hoping i dont have to touch it again in future to fix it. That being said ofcourse ill be making the 3D model better, But for now i just wanna focus on programming stuff and making the loop right. We can always make it prettier later . Im unfortunately still not home and i still have to survive in this godforsaken room, but hopefully ill be home soon as ill get my appli signed to go home, And then ill be working on both this and the plane together
REALLY NICE ADDITIONS Ive finally added some life to the game. I have added these weird mudfishes inspired by those weird furless cats. These mud fishes aren’t stupid tho, i ___have implemented a proper behavior tree to them, Each one of them has their own set of actions. Normally like minecraft mobs they roam around look around the world, but if a player is near their vicinity, they RUN away from the player protecting them. Currently i have no clue what ill use them for, but one thing is for sure that they have really nice skin I wonder what will happen to it in the near future Really happy by this addition tbh, the world was getting kinda lonely, this was important, in next updates ill be adding colonies of these things mounds and their homes, along with their baby variant.
After getting falsely accused for fraud for using the godot wakatime extension and getting a heart attack I have finally added little homes for these skinny dookeys I hate, HATE behavior trees with every cell in my body I hate to admit but i did take help of claude chat to help me set this shi up, it was js the free version tho so we good. I added so like normally it ran away from player if it sensed one near, but now if the player is close by and it has a home near it runs to that and hides in the home, and if player is far enough it emerges back out. Ill move on to adding more entities now rather than polishing these dudes, i think from the final game i wont even keep them in cuz how ugly and weird they are Aye free me bro i aint do nothing wrong, fix the wakatime extension fr
LETS GO IM FINALLY UNBANNED Unban stuff aside, time to explain the devlog even tho being unbanned feels great and i have insane amount of motivation to work on my proj now In past idk however weeks ive been working on 2 major things, first is that ive finally listened to the last ship reviewers and added upgrades for rocket, with custom 3d models for each rocket tier. currently it uses a separate key to open close the menu which is bad but ill fix later Also only the rockets fuel attribute is updated when you upgrade a rocket so ill fix that too. Also after the ban i was working on electronics update for my game, i have implemented electric poles, 50Kv Generators for now, i am going towards direction of factorio im afraid, but i dont wnana make it very grind-y so ill keep that in mind (hopefully) For future i will be adding better UI/UX its currently embarrassingly bad rn (even tho my degree is Computer science and Design) So yeah that will need a massive revamp Also id like to give a shout out to water #Freewater #heaintdonunwrong
I was aiming for 3 hours today but i lowk got in a fight with a senior in my clg and bro is threatening me to slime me tmr it might be wraps for me gng Putting the sliming part aside, today i made the 3D models for a generator concept (or actual thing) i found online of what they use in space. The i did sm audio editing to have a whrrrrrrrrrrrr looped sound effect and it was quiet easy to make a whrrrrrrrrrr loop, easier than i imagined. Then i added another sound and layered both ontop of each other and now it genuinely sounds kinda peak After that i made the electricity spread across all the electric poles, heres the code for that if body.is_in_group("tower"): towers_closest.append(body) create_lines(body.location_to_connect_wire_to) if has_electricity_running: body.has_electricity_running = true elif body.is_in_group("electrical_appliance"): if body.connected == false: towers_closest.append(body) create_lines(body.location_to_connect_wire_to) body.connected = true if body.is_in_group("generator"): has_electricity_running = true for i in towers_closest: if i.is_in_group("tower"): i.has_electricity_running = true I might lowk be taking AI’s job in writing bad code, they should make a me gpt in which i reply with shit code that DOES work. I also visualized the flow of electricity by hiding/showing a random cylindrical mesh that shows if it has elec flowing through it. Tmr ill be redoing ALL the icons cuz currently they look straight dookey, and also fixing the UI, then if i have time give observatory and everything an electric connection and make them so they dont work without it. This was all i worked on today, yall pray for me lets hope i dont get slimed tmr .
YAYAYAYAYAYA 3RD SHIP INCOMING In the first 2 hours i logged i worked on making the 3d models as refined as possible and made them look good by referring to astroneer as someone commented on my game Also made multiple 3d models for the electric pole and finally used the one that sat right with me. Made a new 3d model for generator and upgrade station aswell In the next 2 hours i made minor tweaks and fixed satellite bugs along with updating the help menu with newer control code, also was thinking of implementing a scrap mine but dropped that idea (maybe later ships) Then i added a little keytip marker near the refinery and chest of observatory to aid the player. Added a bunch of sounds to the electronics of the game and now it sounds a whole lot better (also reduced the main music) FINALLY TIME TO SHIP Thnx to all of the support on this proj i wont disappoint yall at all with future ships
Some really cool additions For starters today i implemented a little list at bottom of the screen that can be used to store the coordinates of player rn Yall might be wondering what tis could be used for, But i have something really cool cooking up in my head lets hope i am able to express it properly. EXPRESSING MY LOVE OF YAGI ANTENNAS I ADDED A YAGI ANTENNA TO THE GAME!1!!! It has a search feature that looks around for strongest signal and then does nothing But in future i will be making a whole mechanic out of this. Then i made a little web release it butchered the visuals i worked hard on. Its okay tho cuz i added a warning label like last time on that release too. Linked the web release as playable link for the game I want YOU to tell me what should i add to this game as im running into a roadblock where i dont know what i could add for the electrical update for the game that would actually be a useful addition, Comment down below to drop your ideas the best one will make it into the game
TESLA SUPER CHARGING So for starters i forgot to tell yall that i DIDNT get slimed by senior my clg department helped me and scared tf outta bro and i got to fight bro too And in this update i added set battery capacity to rovers They use supercapacitors to store charge so that means they can be charged and discharged for eternity Then i added charging stations to the game and made them use power grid electricity. I think players might abuse electricity by only placing 1 generator to power an entire city so i will be implementing complex wattage draw logic like they have in factorio to get some supply/demand action rolling. Then i worked on implementing save game in the game and i failed terribly (this will be a hurdle for later) I spent like solid half an hour trying to implement it just for my save file to be completely empty Idk whats going wrong but i will eventually figure it out. For now tho i will be working on factorio like supply/demand logic for electricity wish me luck
In these 2 hours i have lost all my sanity But finally the factorio like supply/demand electricity mesh finally works First i thought of using recursion to spread the electricity through every single tower But then i ran into a problem where towers interconnected so to fix that i passed a self parameter that didnt seem to help. Then i decided to make towers only connect once (which was a disaster and brought its own set of bugs) and that to tremendously failed So finally i decided upon a global mesh chain architecture where all the nodes in a chain have similar looking list, and whenever an appliance is connected to it the chain just iterates through its connected devices, This in turn brings the time complexity down to O(n) and makes everything a whole lot more efficient. Finally this is done Currently only the tesla charger works with this new logic, later i will add other electric appliances to this mesh network aswell and give them watt draw Few things to keep in mind, Currently 1 generator makes 50kW and one vehicle charger consumes 40W, If the demand isnt satisfied every node in mesh rejects the connection until the demand IS satisfied I know this might feel stupid for some people but this is only done as a feature so you dont overload the electronics in space
IM RICH!!11!! 2080 sd and top 10 in multi I got all positive reviews from yall and i apprciate every single one of u for rating my project. I have finally added scrap mines to the game, i had already made the 3d model for them i just thought they didnt fit in the game but since im adding automation and electricity to the game i think this would be a great addition. Currently they produce 10 scraps, copper, iron per 10 seconds so 1/ sec i will later randomize this and give them weights, im js too lazy cuz of this clg n shi istg Good thing is tho tmr im going home That does mean my work on hardware projects will start again That being said i need you to give me more recommendation for the game, the reviews didn’t give me any ideas or unique views what i could add to my game.
BOOMBOX!!1! , macondo marketing team too good Last night i spent unhealthy amount of time watching ig posts of macondo on hackclub ig, I lowk feel insane amount of fomo and i wanted to go so bad The songs they used in the marketing reels are still stuck in my head So as any reasonable person would, I added a boombox in my game with with my fav songs from the reels they made @zach PLES FLY ME IN NEXT IRL HC EVENT PLES IM BROKE
SHOUT OUT TO @253_Mathilde_IYKYK For starters i made a lil script so that if a rocket is in the SOI of a planet and then it scans near it by pressing F it shows all the necessary details about the planet, currently they are obvious details but i will work on making them useful. I have a few ideas of what i can do with it Now to the important part @253_Mathilde_IYKYK recommended me to add a song they like SO I ADDED IT TO THE GAME Hope yall like it :) (Sorry for not including video idk why stardance was bugging and throwing error when i was tryna upload a video)
Ships:
I made Into the Cosmos, a realistic 3D spaceflight sandbox inspired by Kerbal Space Program and Spaceflight Simulator. The game lets players jump straight into the mission and experience realistic orbital rather than spend hours designing the rocket just for it to fail when launching. This is a relaxing and fun game where players can just sit back and enjoy the physics and thrill of sending rockets to space. The biggest challenge was making somewhat realistic physics with enjoyable gameplay. Getting the gravity, RCS controls, and spacecraft handling to feel both snappy and fun to play with without absolutely broken, writing so many lines of code, and deciding on how im gonna be approaching some problems was quiet fun, i have a lot of fun designing it, i used to go to bed thinking what ill be adding to the game tommrow. I’m most proud of achieving the relaxing experience I originally envisioned. Im quiet glad i was able to fianlly have a direction towards my game and have an idea of what i wanted. And the gameplay is quiet fun aswell, i found myself “playtesting” my games just having fun slamming the rocket into planets, doing interplanetary missions. Setting satellite in different planets To test the project, I recommend reading the in-game controls and instructions first. They explain the basics of reaching orbit and make the experience much more enjoyable.
Into the Cosmos Join Boney on a journey across the endless cosmos, where every horizon hides another world waiting to be discovered. Launch into the unknown, weave between glowing nebulae, drift past impossible black holes, and set foot on planets no one has ever seen before. Build observatories to mark your path through the stars, refuel your rocket, deploy satellites into orbit, and keep pushing farther into the infinite. And when the day is finally over, come relax with Boney and lose yourself among the stars for a while. I’ve always loved games like Kerbal Space Program and Spaceflight Simulator, but I wanted something where you could jump straight into flying without spending hours designing the perfect rocket first. The result is a sandbox space game built around realistic orbital mechanics, exploration, and simply enjoying the journey. The universe is procedurally generated, meaning there is always another unique planet waiting somewhere beyond the next launch. Every expedition can take you somewhere completely new, and every observatory you build becomes another milestone in your adventure. Satellites aren’t just for show either. Launch them into orbit, revisit them later, and use them as your eyes in the sky while you continue expanding your reach across the universe. If you’re new to orbital mechanics, don’t worry. The game includes detailed instructions, an optional on-screen keybind guide, and a full in-game settings menu that lets you tweak graphics and performance to match your hardware. Whether you’re playing on a high-end gaming PC or something much more modest, I spent a lot of time optimizing the project so as many people as possible could enjoy it smoothly. There is one place, however, that lies farther than anywhere you were ever meant to reach. Most people will never find it. Those who do usually don’t come back with an explanation. I call it The Farlands. Whether it’s a bug, a feature, or something else entirely is for you to decide. I built this game in Godot 4.6.2, spending countless hours refining the physics, procedural generation, shaders, rendering, UI, and gameplay systems. Every optimization, every visual effect, and every mechanic was added with one goal in mind: making space feel like a place you can get lost in for hours without realizing where the time went. So fuel up, trust your trajectory, and see just how far Boney can go. If you decide to give the game a try, I’d really appreciate a detailed review afterwards. The feedback I received on my last project genuinely helped shape this game into what it is today, and I’d love to hear what you think could be improved, what you enjoyed, and what you’d like to see added next. If you enjoy the project, consider starring the GitHub repository and liking the YouTube video. It really helps more people discover the game and motivates me to keep building and improving it. So fuel up, trust your trajectory, and see just how far Boney can go.
INTO THE COSMOS This is the game i have designed with inspiration from Spaceflight sim and Kerbal Space program, i wanted to capture the total freedom of roaming in space without the stress of designing a space vehicle for hours just for it to crash into a million pieces. I wanted to make a chill relaxing game that people can come back home after a long day of work to, boot it up and have fun just roaming the eternal space without stressing out. Im quiet proud of how im capturing this vision of mine and im very happy with what im making. Heres some information of what i added this ship: I’ve basically been adding a bunch of systems that I’ve wanted in the game for a while, and the game is starting to feel a lot more like an actual sandbox now. First thing, I finally added electricity. This is probably one of the systems I’m most interested in because now I can actually start making more things depend on power instead of everything magically working forever. This also gives me a lot more stuff I can do with spacecraft and bases in the future. I also added scraps and scrap refining. You can now collect scraps while exploring and actually do something with them instead of them just being random useless objects. I’ve also added the material processing system around this, so scraps can be refined into materials that can actually be used to build useful buildings. This is going to become a much bigger system later on. ROVERS ARE FINALLY HERE You can now actually drive around on planets instead of just landing there and leaving. I really wanted this because the planets were starting to feel a little pointless once you landed on them. Now you can actually get out there and explore the surface properly. I’ve also added planet properties. Planets now have their own properties which means I can start making different planets actually matter instead of them just being randomly generated balls you land on. There’s a lot I can do with this later, especially with resources and exploration. I also did a pretty big overhaul on the visuals. The ambiance shaders have been improved and I’ve added a bunch of new stuff to make the planets and space itself look better. black holes now also have a hidden easter egg…. Ive also given every planet a beautiful atmosphere And yes. Mudfish I don’t know why. They’re still stupid. They just walk around on planets doing absolutely nothing useful. But honestly the universe felt too empty without them so I’m keeping them. A lot of this update was also spent doing optimization because some of the newer systems were starting to get pretty heavy. I’ve been going through different parts of the game and trying to make everything run better without completely murdering the visuals. Overall this update is probably one of the biggest changes to the game so far. And I still have a stupid amount of things I want to add. https://www.youtube.com/watch?v=ZZg3blASmgc This is the link to the youtube video if you dont have time to review the game PLEASE check it out and rate the project I read and appreciate every single one of you reviewing this game, please be as informative as you can be as this is one of the biggest games ive worked on till now, thx and have fun playing the game...
|
1792850006.8012064
|
1792936406.8012064
|
|
14070
|
Timetable by @omeriadon | Stardance
|
omeriadon
|
2
|
371.91
|
2591
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-24T09:11:11Z", "hours": 233.0, "multiplier": 18.49, "payout": 2143, "blessing": "neutral", "text": "This ship, I completely remade the app to work around accounts, and all the features that come with that I added a server, because it used to just store your timetable in your local storage and that was quite boring honestly creating a server for this has allowed me to add accounts, notifications, live activities, friends, shared events, multiple devices in the same account, and has made the website much easier to make (still in development, thats why the top devlogs are talking about the website not the app) The app now has all of this: Grades, track the score of all of your subjects notifications for each subject you have and your events etc live activity throughout each school day telling you your subjects etc sharing your location, subjects, and more with friends widgets that show your your subjects, upcoming events, and your friends’ schedules lots of administration options to manage pretty much everything, including who else is admin lol full support for siri, shortcuts, spotlight, and apple intelligence a full apple watch app btw i know 350 hours on a timetable app sounds insane (😭) but its because this project has 4 different aspects: swiftui client for iPhone, iPad, and mac swiftui client for apple watch a website client (still in development) the server that handles everything, and the database i promise it does more than just tell you your subjects 🙏", "repo": "https://github.com/omeriadon/Timetable", "demo": "https://testflight.apple.com/join/DDUXPSq3"}, {"ship_num": 2, "ts": "2026-07-15T13:35:31Z", "hours": 94.0, "multiplier": 9.5, "payout": 448, "blessing": "neutral", "text": "So I made a timetable app for my school, super-specialised and for ios, watchos, and macos. its got live activities and notifications to show you current and next subjects throughout the school day, widgets for your weekly schedule, ability to see your friends’ timetables, and server sync. and apple intelligence support!", "repo": "https://github.com/omeriadon/Timetable", "demo": "https://testflight.apple.com/join/DDUXPSq3"}]...
|
[{"post_id": 65346, "ts": "202 [{"post_id": 65346, "ts": "2026-09-10T13:08:58Z", "hours": 8.2983, "text": "Continuing the assorted improvements to the app: Fixed stacked drawers so nested drawer state updates reactively. Reworked the Friends page into shared List, ListSection, ListRow, and Card components. Preserved friend drag-and-drop ordering within the new layout. Improved timetable UX: i fixed the lesson selection in week view correctly aligned the “now” indicator in today view restricted timetable mode navigation to mobile through CSS, cos desktop already has the sidebar improved planner event styling. made the drawer compenent animate in and out, something i lost from the react -> solid migration I also added a reusable event-tag selection row with symbols and selected-state feedback."}, {"post_id": 62745, "ts": "2026-09-06T08:06:14Z", "hours": 5.9261, "text": "As well as migrating to Tanstack, I wanted even more speed, just for fun at this point honestly, so I decided to move to SolidJS from React. Its decently faster while looking similar to react, and it has some syntax stuff that i much prefer over react. this is basically just adding some margin for me to make bad code The end product looks identical so theres not much to show.. apart from the migration, I’ve also been designing the new landing page, which will also use the 3d model thing. the big question is figuring out how to make the 3d markers for each classroom register correctly, because i need to show a pin for each user at the right place, from swiftui, and somehow embed it into a realitykit 3d model. but im sure this use case has been done many times before so i can find something online!"}, {"post_id": 60821, "ts": "2026-09-03T13:24:26Z", "hours": 7.5314, "text": "Im making a 3d model of the school. this is so that i can show a whole literal map of the campus in the app, and then you can see where each user is, in 3d! i could even reexport it for the website, potentially its going to be interactive and everything"}, {"post_id": 59542, "ts": "2026-09-01T12:52:51Z", "hours": 1.2314, "text": "ok so i think i have optimised it as much as i can lol tanstack clearly was a good idea, it just needed some optimisations!"}, {"post_id": 59501, "ts": "2026-09-01T11:30:41Z", "hours": 8.1464, "text": "I did a few things in this devlog, got quite carried away frankly. So I migrated the codebase from Next.js to Tanstack. The reason was that i was seeing a lot of speed concerns, especially on the landing page. it was just lagging so much. i tried it on all my devices on all the browsers and it was there half the time. after a lot of commenting things out i just couldnt find a bug, so now i moved to tanstack. hopefully taht will remove at least some problems. in any case, i got bored of next.js and tanstack is a different framework to play with and make use of!! also, i continued the landing page by adding cards for each item. i don’t really like it right now, but i have established that i need to add these cards, if not in a different UI. The titles of each card are just image-masks, of Apple wallpapers! i went through some archive and picked out the ones i like, and applied a brightness 200% filter, and they look really nice now. after i finish the landing page im gonna work on rehauling the rest of the ui to be more intuitive and actually usable"}, {"post_id": 57354, "ts": "2026-08-29T14:02:16Z", "hours": 2.4136, "text": "I really wanted the first screen for timetable to look really really interesting and unique and instantly recognisable as Timetable, so i made the text instead of a boring white, it now has 3 really nice effects applied: A grain overlay, or noise, which in this case doesn’t make it look paper but looks nice nonetheless Its not flat white, its white at the top and goes to brown at the bottom, more noticeable when you close up. subtle but also nice The “white” isn’t even white. Its a particular white image i had a lot of difficulty in obtaining. it is the third screenshot, the “white” png. Its an .avif , and it uses some HDR-capable color space format something, which on compatible browsers make the timetable text show considerably brighter than everywhere else on your screen, which makes it really pop! i plan on using this effect in other places as well across the landing page to make it just pop a bit more. (the 4th image shows the white pixel showing as 1.25. anything above 1 is hdr.)"}, {"post_id": 57217, "ts": "2026-08-29T10:04:27Z", "hours": 1.4844, "text": "I added a title to the lading site, but as you can see its not just any title. it uses this package called fitty to make the text size up to the full width of the page, and it does indeed look massive. and it also goes under the rectangles of the logo, so its like an apple depth effect you get on iphone lockscreens i found the website really laggy while scrolling somewhere while finishing of the main interactive icon, and i couldnt figure out why after removing everything that could have been gpu intensive (my gpu was spiking to 80% while just scrolling) so after all that my most likely theory is that the lag is just my computer and not the website (or both 😭😭) also when i made that main art, i made the border radii use px units, which made it look quite deformed on smaller screens, since the rectangle’s size is relative to screen width, whereas border radius is constant… so i went and fixed that too"}, {"post_id": 56944, "ts": "2026-08-28T23:37:12Z", "hours": 1.0728, "text": "After much trying to make glass, yet again, i failed. So now im just using blur and these edge effects, and i think it looks nice! theres even a hover eect, as shown in the second screenshot (class details show and the rectangle rotates a bit randomly)"}, {"post_id": 56543, "ts": "2026-08-28T10:38:02Z", "hours": 8.8014, "text": "I started to make the landing page, and i decided, after very much research from other landing sites I’ve seen, that the main item should be an interactive timetable, a version of the app icon. but interactive and glassy. im trying to recreate everything in css but its not looking as smooth and polished as real liquid glass does so ye. im kinda getting close though! I also added a navbar item that just is the link to actually open timetable, and when you hover it shows options to either open the app in testflight or open the web version which just redirects to /login. and its background switches to black when you start scrolling, which will make more sense later. i haven’t really planned the rest of the landing page, and i might remove this entire component if i find a good liquid glass implementation i can use, especially with bouncy animations etc. but yeah. (worst part is i might even just go change the entire app icon in a week so that kinda wastes all this time 😭😭😭)"}, {"post_id": 53528, "ts": "2026-08-24T03:23:23Z", "hours": 5.4669, "text": "I have started using the shared components around the website, and its actually looking pretty nice! most importantly, these components can be changed once and work everywhere and i removed the drawers i was using everywhere, and i also made said drawers wider while i was rehauling the drawers i also kinda broke their animations and i don’t know how to fix it 😭 the whole website looks really basic now, since its obviously using now the shard unstyled components, and i was thinking about the theme and decided maybe it should be unstyled, and only the user’s own events and content etc can have colours."}, {"post_id": 52138, "ts": "2026-08-22T07:15:18Z", "hours": 9.6475, "text": "I think I have finished making all of the shared components I put everything inside accordions to organise the test components Overlays get the same translucency and outline every other component gets I think im happy with how the lists look, finally the option selectors are really really hot!!! The first page I have remade is the About view, which shows this badge if you are on localhost lol i also had to move the contributors up to the server instead of hardcoding them so that both website and app can see it And a really nice little animated gradient thingy for the about view!!"}, {"post_id": 51517, "ts": "2026-08-21T08:53:31Z", "hours": 3.9036, "text": "I have pretty much finished the components, I’m going to now go and add the other shared components and improve them too. then im gonna go through the css files and clear anything that is unused or overcomplicated, and then i can start remaking the website!"}, {"post_id": 51022, "ts": "2026-08-20T14:43:48Z", "hours": 7.9519, "text": "So the previous UI was really ugly, to be honest, so i decided I am oing to scrap half of the design and completely unstyle the entire app while making everything as standardised as possible, by trying to only use reused components as much as possible. So I spent all today stripping out components I didn’t need, then take the surviving components and adjusting them to my use case and making then look as nice as I can. alert dialogs drawers buttons lists section cards switches I have also decided to stop using tailwind because its quite simply messy and much more confusing than just moduled css, so ye"}, {"post_id": 50337, "ts": "2026-08-19T14:34:49Z", "hours": 5.8117, "text": "I’m still working on making the UI look much better, and I’m still figuring out some website stuff like how i should wire up the sidebar tabs as well as having like a nice homepage to advertise everything the app does, which will be a really fun sub-project. Turns out making nice looking lists in react is much harder than it looks, as shown below 😭 one problem is that each symbol has a different aspect ratio so i dont even know how to fit them nicely And unlike swiftui, its raelly raelly hard to stay consistent in your css and to keep using the ui tokens instead of making custom css everywhere. it looks like the website is gonna be harder than the app to make after all 😔 this classes card though, for example, i think its pretty much almost done. i might need a few more borders to make it look glassy and stuff but it looks exactly like the ios version, which is the end goal! And I added the animations to the classes card, again exactly like the iphone app. i also got a vscode extension that shows you all of your unused css classes, i highly recommend getting one and purging your codebase!"}, {"post_id": 50037, "ts": "2026-08-19T02:03:20Z", "hours": 11.0747, "text": "So I’ve made the first version of the website, it’s really insanely buggy and broken, but the ui is there. so have the html good but no i need to really tweak the css to make it look nice, apple-style. i also need to figure out how to make loading states look nice, since unlike the the swiftui app, i can’t cache anything to not show loading state. in the plus side i dont have to deal with offline state, though. the sidebar and the toolbar are finished, and look really nice. the sidebar has an effect (from ipados) that basically reflects the content in a subtle blurred way, to make it feel like glass while not actually rendering anything expensive. The toolbar is just glass buttons + a black fade effect + progressives blur, also tuned to look like ipados. the icon in the sidebar is pretty ugly honestly so i need to replace that with the non-bordered icon. The other problem i am dealing with is that we are planning a complete redesign of the entire swiftui app, and obviously that has to propagate to the website, so any work i do now is kinda gonna be half wasted, depending on what the redesign actually looks like."}, {"post_id": 47872, "ts": "2026-08-16T03:56:44Z", "hours": 0.5908, "text": "And now it scales up and down and stuff!!! I still can’t believe this is just html and css and js 😭 Theres so many parameters to tweak to make it feel right, its so finicky And depending on the size of the glass, you have to change the numbers, its kinda confusing honestly"}, {"post_id": 47804, "ts": "2026-08-16T00:37:23Z", "hours": 0.8556, "text": "Its nice and squishy now! It uses gsap for this as well gsap is a great framework ngl"}, {"post_id": 47523, "ts": "2026-08-15T14:19:10Z", "hours": 4.8103, "text": "Hehehehe I’ve got a working version of liquid glass It uses gsap, which is nice the second image is an earlier version 😭"}, {"post_id": 47363, "ts": "2026-08-15T08:10:22Z", "hours": 1.1444, "text": "The website is alive! I got a screenshot of an iOS26 sidebar, and i am copying it, as you can see. looks nice i think"}, {"post_id": 47332, "ts": "2026-08-15T06:41:25Z", "hours": 2.6325, "text": "Ok so after a bunch of wrestling with nginx and bun and next.js, i have added the website! its at https://timetable.adonis.pt/ and the current api has been moved to https://timetable.adonis.pt/api Its the usual next.js thing. and it uses bun. my design idea for this is to look like its an ipad app, essentially, and im going to see exactly how far i can take the mimicking, maybe i can even add liquid glass to the web 💀 So yeah no more app building, now its website! It’s gonna be so much easier as well because I aleady have the backend done and tested, so this should be all design which will be really fun."}, {"post_id": 46919, "ts": "2026-08-14T13:55:04Z", "hours": 0.3047, "text": "new icons. the old one that now supports light mode was kinda ugly."}, {"post_id": 46909, "ts": "2026-08-14T13:32:29Z", "hours": 7.6422, "text": "A somewhat interesting devlog this time. I spend a good 2 hours just trying to make live activities work. the miserable part is that they were already working before 😭 I dont even know what I did but it broke. And while i was trying to make a debug button to start a live activity, yeah it just wasn’t working. all kinds of problems with not submitting a good APNs token. and i had to like stop activities before starting new ones and stuff it was just in general really annoying. there was even more problems but its too much to say here 😔 anyway, i have started cleaning up the app. no more big features, to be honest, until i add a website for this thing!! should be really easy since the backend is clearly all done lol events can show weather for them, such as the athletics carnival i removed the ridiculous backgrounds i allowed users to choose, theres no only solid black/white and paper. more reasonable, i think. as part of my optimisation, i removed settings i found useless. haptics are now always on, and highlighting the current day is always on. profile pictures can now have their foreground colour set, like the Monogram can have its colour optimised.you can see the average for when your friends arrive to school per day, instead of in total. developer settings also got reorganised, more settings only show to developers. yet again cleaning up the app experience. the location status was a bit unreliable, if users were offline, etc, so i added multiple ways the app pushes updates to the server, and queued statuses when the device was offline. i also refined the actual radius for what counts as within 5 / 10 minutes, should be a bit better. i havent thought about people who live within 10 minutes, thats an interesting case the subject editors grid also looks nicer (still needs more improvement though the tabview now hides while scrolling, like it collapses into the corner, like apple apps! you can manually turn off sharing your status, for privacy reasons. and some more things i forgot 🥹 im so excited for this thing to actually launch!!!!!"}, {"post_id": 46297, "ts": "2026-08-13T13:01:18Z", "hours": 1.3272, "text": "I spent some time to work on this search button and its animation. idk if the video plays, but it uses apples glass effect transitions! I also made the confirmation dialogs for removing and reporting a friend better, before they just popped up in the middle of the screen, now it comes out of the menu (also found another ios27 beta bug 😐)"}, {"post_id": 46263, "ts": "2026-08-13T11:41:36Z", "hours": 2.4739, "text": "So supporting light mode calls for an icon redesign, at least just for light mode, and here they are! Though to be honest, the entire app is gonna need a redesign, because I need to rename it from Timetable, because it has expanded into doing so much more, and timetable is a bit of a boring name. finding names is so insanely annoying though, but oh well."}, {"post_id": 45744, "ts": "2026-08-12T13:04:58Z", "hours": 2.6161, "text": "I added custom backgrounds! Theres the paper backgrounds i added recently, and then the solid colours, and then also some of the really nice apple ones idk what they are called (i hope apple doesnt copyright me 😭) so yeah it applies to all backgrounds in the app i think it merges really nice with the liquid glass and blur backgrounds different views have it also shows on watch i also added an option to choose how far forward you see events. theres also even more statistics for what app version people are using!"}, {"post_id": 45684, "ts": "2026-08-12T10:26:42Z", "hours": 1.3586, "text": "You can now edit the foreground colours for your profile picture monogram i also completed light mode support for widgets"}, {"post_id": 45645, "ts": "2026-08-12T08:44:01Z", "hours": 2.0167, "text": "I added accessibility improvements, mainly like labels and tags and stuff, for use with voice over etc. this was triggered by me installing a developer process into my app which allowed me to iterate on design faster, and it depended on accessibility elements to discover each element. (the purple thing lets you tap elements and comment on them) i also tried a new background for the cards, as you can see below, its just glass and i think it looks pretty nice"}, {"post_id": 45165, "ts": "2026-08-11T14:09:40Z", "hours": 9.5667, "text": "Big update! Light mode! The app used to be dark mode only, it let me make it look much more pixel-perfect and refine colours and stuff, but its kinda obvious you cant keep the app dark mode only, its just not good. so i went through everything, adding light mode versions of paper, text, glass, etc. took me quite a bit of time because i was trying to maintain consistency while doing it, which included alot of redoing things and creating view modifiers and manually applying each one, etc i also added weatherkit, its just a single line in the today tab, but its nice. while adding light mode support, i found a really nice blur view i could add to lists, so now each lists’s background is nothing other than a blur! i also decided to make all backgrounds made out of paper, and i think it looks nice? theres also now a statistics page for deices and os versions and builds and stuff, itll be more useful later. as well as knowing when your friends arrive to school, i added the ability to know when they are within 5 or 10 mins, and to send notifications for that. average arrival also is split by day now, because people arrive to school at different times per day theres a new tab picker, which you can see int eh controls, its much more glassy than the last one, which is really really playful and stuff! i still have more work to do in terms of ui work, excluding light mode refinements, like notifications and widgets, but yeah."}, {"post_id": 43989, "ts": "2026-08-09T14:04:31Z", "hours": 1.73, "text": "I added a new devices statistics view. or more accurately, i expanded it. before, it just shows device platforms. now, it shows the os version, minor os version, and if it is a beta or not. i also added support for iOS 26 (previous builds only supported OS27 or later). this involved me just making some features not work on os26 😐 and supporting anything before OS26 would probably be legitimately impossible, so yeah not that."}, {"post_id": 43936, "ts": "2026-08-09T11:55:31Z", "hours": 1.5656, "text": "I also made some improvements to the card height for the user’s own item. before, it was just the full width. Halfway while I was working on that, my TabView suddenly froze for a straight 20 seconds every time i changed the tab. this was very weird, and the CPU shows 0% usage, so I was quite surprised. After a large round of commenting things out and seeing what broke, I found it was a single .glassEffect() that I was using for the progress marker. I have no idea how a glass effect can make an entire tabview freeze, but fine. i replaced it with a simple red colour, as shown below, with a stroke and shadow, and i think it looks fine now."}, {"post_id": 43850, "ts": "2026-08-09T08:59:50Z", "hours": 1.6619, "text": "there is a new progress background: its not a background! inspired by the app icon / ios app, the progress view is now this marker thingy which fits into the app’s theme much nicer I’ve also been tweaking the font sizing, image sizing, padding, and gaps between the items here to make sure they look good at all possible subejct names etc. i also had to fight a bit with the safe area of the view, you can see in the image below the name “bob” ends slightly above the text, took me a lot longer than expected to fix that"}, {"post_id": 43782, "ts": "2026-08-09T06:43:26Z", "hours": 7.4142, "text": "I started work on rehauling the watchOS app And I really like how it’s coming out The watch is supposed to distill down the information the user needs, so i picked the current and next period, time, and their location. all these elements are glassy and stuff, so they are clickable, and its in a tabview that scrolls between each card. The first tab is the week view for the user. so I spent a good 2 hours trying to make a ScrollView work, but it didnt. sometimes the views teleported, some lagged, some glitched, and it was overall insanely annoying. so I moved to a tabview, which was considerably more stable, but removed the animations I wanted. it had its own animations which were fine, but yeah. Also, fonts also reflect on the watch! the one in the screenshots below is the expanded style, which to be honest isnt that good on watch since the watch is constrained as is, but yeah. The glass timetable actually looks insane I am still thinking of how to include other content, like grades maybe, and other things, but i dont want to make it too dense and slow"}, {"post_id": 43264, "ts": "2026-08-08T12:54:21Z", "hours": 3.6083, "text": "You can now change the font! this took more work than you would expect, because i did a find on the project and saw there were like 60 references to .monospaced, and each one had to be manually upgraded to dynamically apply font. i also tried to make the rounded font expanded, but after some inspection i found it doesnt even have a .expanded variant 😐 so the options i ended up with were monospaced, rounded, and expanded. no normal font. it just looks boring at this point. below is the same screen with each option! widgets also get the fonts, and they look actually insane ngl"}, {"post_id": 43093, "ts": "2026-08-08T05:35:22Z", "hours": 2.4481, "text": "improving the friend detail view the padding is so much nicer, and the detail view also shows more info and in a better way the week subtab shows a similar timetable to the user’s own, and shows more info. and some more statistics lol"}, {"post_id": 42989, "ts": "2026-08-08T00:22:14Z", "hours": 1.9642, "text": "I decided to remove created timetables. they just don’t work anymore with the Friends concept, which makes it really annoying to adjacently share other timetables alongside having friends. its a shame, i wish it could have worked, maybe ill add it again later. oh well. im still just combing through the app and fixing all the little things i see: grade tracker gets a next item in the top for the top 4 subjects, which is important for atar. improved the friend detail view a bit better, because the old one had not enough information and was displaying badly.added more statistics to administration view cos its fun lol the tag selector view was improved, looks nicer and is a tiny bit more legible nowi changed the grade tracker weighting from semester to year. apparently thats the norm more friend detail view improvements"}, {"post_id": 42669, "ts": "2026-08-07T14:52:24Z", "hours": 2.3131, "text": "Grade tracker!!! I know this is a very cliche topic but I had to implement this because it integrates so seamlessly with the app for example, it already knows your subjects (duh) and when you input the date of your assessment, it also knows which period of the day that is, because it knows your subjects! (duh) I also added ATAR, sthe user can set goals and stuff for what they want to achieve."}, {"post_id": 42589, "ts": "2026-08-07T12:33:01Z", "hours": 1.0975, "text": "some ui improvements (that weird box in the account view is Metal debug overlay, not my app)"}, {"post_id": 42549, "ts": "2026-08-07T11:27:09Z", "hours": 5.165, "text": "lots of little things instead of one big feature: i used to send emails, and i reached limits on the email provider so i had to move to only sending notifications, like device notifications. i still need an alternative, im looking through options now there used to be different settings view between iPhone and iPad, so i consolidated them into one view.you can now see your friend’s status as on or off campus. this uses location to check when you reach school or leave. this also allows some cool statistics like average school arrival time!there is better moderation, it shows in the admins view and lets the admin block or do nothing about the account. it will be expanded later to have more features and actions and stuff you can request to change your friends-since tag, also approved by admin.i deleted all (most) references to #if os(macOS) , since there is no more macOS build, its just iPad running on mac. small ui improvements: added search to some more administration views tapping an existing photo pro allows crop the tabview gets tab transitions, like the ones iOS 26 had (that ios27 removed 😡)year-level tags are separated from other tags expanded statistics!added archived events - events in the past - plus an option to automatically delete old events added a button to reset tips, since the app is getting more and more complicated the onboarding is less condensed, when that permission is first needed, its permission sheet request shows.more stuff gets cached in Defaults, making it more offline-safe.and some toolbar and blur and navigation title stuff."}, {"post_id": 41948, "ts": "2026-08-06T14:06:53Z", "hours": 1.2208, "text": "user account data now has highlighted rows for faster navigation user reports look much better, as well as friends-since requests reporting or sending feedback sends notifications instead of emails, now"}, {"post_id": 41911, "ts": "2026-08-06T12:53:26Z", "hours": 4.0961, "text": "Few things! Adminsitration gets new items for reported users and freinds-since requests sections in adminstration statistics for number of users, etc you can now see your status and other people’s status, like on or off campus new page that asks for location access ofc (ill move it into the onboarding later improved the add a friend sheet admins get emails for reported users, etc"}, {"post_id": 41764, "ts": "2026-08-06T04:50:27Z", "hours": 8.5058, "text": "I finished the refactoring for now, to make the app multi platform. So then i did some more brainstorming and I have consolidated what is the next few features I need to do tips, to tell the user about features the app has they sound easy but each tip needs rules and parameters and all kinds of obscure annoying things, so its going to be harder than it looks my first tip shown below An indicator next to each friend about their status, which is going to take the user’s location, taken in the background, to tell if they are on campus or off campus So from this you can tell when a user arrives at school or if they are sick iOS provides a function that will call my app, from the background, every time the user crosses a specific map polygon (The school). so i dont even need to do any map processing, my app just gets called every time the device goes in or out of school! plus i can add cool related features like the user’s average arrival time to school, which will be pretty cool!"}, {"post_id": 40724, "ts": "2026-08-04T13:16:45Z", "hours": 3.6128, "text": "Still just refactoring and remaking the app. i decided to remove OS 26 compatibility, because there is just too many APIs and stuff the images below are some stuff I’ve been refining: dragging friends around sideays iphone support (same thing as macOS + iPadOS) but I’ve decided now to not work on macOS (which is just iPadOS) and ipad until i perfect iphone and watch. should be fun!"}, {"post_id": 40093, "ts": "2026-08-03T14:09:54Z", "hours": 0.6797, "text": "its getting there! mac catalyst is definitely better than trying to make native macOS work. swiftui isnt really making it any better, its really really restrictive in terms of how i can structure my app. like for example that right column, has so many glitches that i cant really find solutions to because the bugs aren’t in my code, its infuriating."}, {"post_id": 40069, "ts": "2026-08-03T13:17:55Z", "hours": 1.1419, "text": "working with macOS is infuriating me, so i decided im going to make the macos app actually be mac catalyst, so its technically just running an ipad app. which makes sense. still needs alot more work, this refactor is proving very very annoying"}, {"post_id": 40036, "ts": "2026-08-03T11:53:01Z", "hours": 1.3019, "text": "first version of timetable for macos 😭 its really ugly and lwk broken. so im gonna spend the next few hours fixing this incredibly “interesting” UI."}, {"post_id": 39979, "ts": "2026-08-03T10:13:36Z", "hours": 3.41, "text": "So so far up to now, I have completely neglected everything other than iPhone. i needed this so that i could focus on making iphone as seamless and intuitive and possible, and to push features faster. so now i have to go and basically remove all of the non-iPhone code and replace it with iphone code, and then try to make that work multiplatform. so i decided iphone is going to remain as a tabview, for now at least, but ipados, macos, and big iphones can use a navigation split view, shown below. so a sidebar and main view and an inspector on the right sometimes."}, {"post_id": 39467, "ts": "2026-08-02T13:08:27Z", "hours": 0.6319, "text": "I checked the localisation and it went down to 25%, so I went and pushed that back up to 100%. and the friend detail view has been improved a bit more"}, {"post_id": 39451, "ts": "2026-08-02T12:29:09Z", "hours": 0.3811, "text": "before and after some small ui improvements!!"}, {"post_id": 39440, "ts": "2026-08-02T12:06:26Z", "hours": 0.6767, "text": "i just read an article that said @Environment(\\.dismiss) is bad for performance dismiss() is a very simple and fast way to make a sheet or other modal view dismiss , but because its so simple and dynamic, that introduces lots of bugs apparently. so I had to go through all the sheets and this time replace dismiss() with better state management. i hope ill notice the performance improvements!"}, {"post_id": 39417, "ts": "2026-08-02T11:25:42Z", "hours": 1.5344, "text": "some people were saying that it was really annoying that you could drag anywhere in a sheet to dismiss the sheet, you would be halfway through something and then you have to restart. so i went through all the sheets in the app and checked if they needed to remove this swiping. luckily it only needed one modifier per sheet. also, more tester feedback was that i shouldnt have sections for tags, so yeah i did that. also, now that there is a concept known as friends, instead of just shared timetables, i removed the option to allow people to have their timetables searched publicly. i havent figured out what i want for specific created timetables, i might lwk have to just remove that also users now have to fill in what year group they are when onboarding. for tags."}, {"post_id": 39252, "ts": "2026-08-02T03:22:29Z", "hours": 3.0194, "text": "friends detail view shows a bit more content, and is redesigned for more paper you can reorder the badges around now for priority when they show in their overlay event tags editor looks a bit nicer plus, users can edit their year group after signing in."}, {"post_id": 38922, "ts": "2026-08-01T14:51:06Z", "hours": 2.6803, "text": "So the header in settings now reflects with your pfp colours for the profile editor, i made it now scrolling so that you could fit in all of the various options, like animation speed and noise and stuff. when you click on a class in today view, it shows some more details about the class like teacher and location. friends view also looks a bit nicer, both the list view and the detail view."}, {"post_id": 38829, "ts": "2026-08-01T12:04:02Z", "hours": 1.9464, "text": "Given the theme of this app, paper, widgets now get paper too! settings for profiles has been updated too you can now select black → white in the colour selector. friend detail view still kinda looks a bit empty and bland, im not quite sure how to make it feel alive"}, {"post_id": 38704, "ts": "2026-08-01T07:32:35Z", "hours": 4.1875, "text": "you can add special badges to people now, for like early birds or something idk. the profile picutre bakground has been upgraded a bit, but im going to have to fork the repo and adjust it myself, its currently not looking like a gradient but a single noisy colour, im gonna fix that."}, {"post_id": 38184, "ts": "2026-07-31T13:32:47Z", "hours": 0.5325, "text": "The bottom colour grid is concentric to the device!!! although making the white outlines also behave nicely is proving really really hard, as you can see below"}, {"post_id": 38170, "ts": "2026-07-31T13:00:49Z", "hours": 3.5731, "text": "I’ve been busy remaking the profile editor, its coming together really nicely. that profile picture at the top is designed so that lets the other components take up their space, and then the pfp takes up the rest of the space. this allows the same view to not scroll while working on different phones and text sizes etc. and the background is animated!!!"}, {"post_id": 37968, "ts": "2026-07-31T01:17:27Z", "hours": 5.3656, "text": "I made this widget, which is kinda like a summary widget for the user. it requires this large widget size to fit everything, and its goign to be more dynamic than the other widget which always show the same layout. i haven’t thought exactly how i’m going to do it though, below is a rough first version."}, {"post_id": 37025, "ts": "2026-07-29T14:32:52Z", "hours": 1.9747, "text": "i added a section in teh administration to be able to turn off the server for everyone except for me, so that i can maintain the server and test it. and also a section to manage other admins."}, {"post_id": 36962, "ts": "2026-07-29T11:55:40Z", "hours": 7.3492, "text": "so me and my friend did some more brainstorming focussing on the new friends tab, and how friend accounts work, and profiles and pfps etc. we also aggregated a list of bugs and UI glitches in the app that still need fixing. the current first version is (moderately) broken 😭"}, {"post_id": 35775, "ts": "2026-07-27T12:45:52Z", "hours": 1.9714, "text": "Me and my friend did a bit of brainstorming, to get ideas on how to improve the app UI, UX and future features. cos we are planning a future release hopefully. so we gained a good idea of consolidating friends into a more clear friends tab, combingin the currently spread-around-everywhere friends stuff."}, {"post_id": 35475, "ts": "2026-07-26T22:47:13Z", "hours": 2.4061, "text": "I made some UX adjsutments in the settings app, added some images, reordered haptics, etc the planner sub-tab has been rehauled, and shows items chronologically instead of in sections, which i thought was more intuitive. it still needs much more thought though, im not sure how to space them out since some gaps are months long."}, {"post_id": 35175, "ts": "2026-07-26T13:01:49Z", "hours": 2.2025, "text": "Theres now brown and white paper combined. its an interesting ui concept, makes no sense in real life, but i think it looks nonetheless! it definitely creates an app theme, regardless of if this theme looks good or not…"}, {"post_id": 35092, "ts": "2026-07-26T09:28:27Z", "hours": 4.1481, "text": "As usual, I did a very assorted bunch of things: new admin tab so that i can change stuff without having to go onto my mac and hardcode stuff today view looks like paper - reminscient of the app icon! new about view the popover for subject details is smaller, removing bloat and a bunch of server improvements due to all of my users finding bugs and stuff!"}, {"post_id": 34919, "ts": "2026-07-26T00:43:54Z", "hours": 4.7894, "text": "I have expanded the home tab!! Theres three tabs at the top, today, week, and upcoming. week is what it already was upcoming shows term dates, no school days, school events, and also the users own personal events they make. the today view is a bit ugly but its sort of there! there also an admin page now, so that i dont have to hardcode term dates etc, i can just send them as api requests (for admin accounts only lol)"}, {"post_id": 34560, "ts": "2026-07-25T11:50:05Z", "hours": 0.755, "text": "Message extension got improved, it now checks if you have enabled sharing before allowing you to even sahre it, and tells"}, {"post_id": 34551, "ts": "2026-07-25T11:04:40Z", "hours": 0.5589, "text": "I’m adding countdowns everywhere, even when school is out, so that you can count the hours until your next period"}, {"post_id": 34537, "ts": "2026-07-25T10:29:10Z", "hours": 0.6072, "text": "This is currently the message extension ui. kinda ugly. that needs fixing I also updated the created timetables detail view, and (ignore the screenshot) removes the save button cos no one is going to remember to press save when they change details, so this should save some frustration."}, {"post_id": 34523, "ts": "2026-07-25T09:48:04Z", "hours": 1.6383, "text": "I improved the UI for this view, to better show classroom and teacher labels. I also renamed “Authored” to “Created”, apparently its better copy, according to my friend. The settings got cleaned up a bit, and importing from calendar again needs confirmation"}, {"post_id": 34495, "ts": "2026-07-25T08:06:40Z", "hours": 1.9119, "text": "I found an xcode bug, something to do with compilation errors for incorrect architecture, i dont get it but i gave apple feedback."}, {"post_id": 34418, "ts": "2026-07-25T03:27:42Z", "hours": 0.5558, "text": "So I made a few more adjustments like removing the APNs registration page from onboarding to make onboarding even more seamless Not important though. I discovered a really annoying problem: When I try to add iPad support, build fails because its trying to embed the watch app which obviously doesnt work on ipad. and xcode isnt letting me fix that. 😐"}, {"post_id": 34073, "ts": "2026-07-24T15:06:09Z", "hours": 4.9253, "text": "I made some UI rehauls again lol Current day receives theis blur effect which kinda looks like real light bouncing inside a box under the current day The accent colour of the app is now brown, as I am trying to make the app feel more like paper, which will become more obvious as i later add paper elements and views inside the app. My last update released a new account backend, which meant some users were not able to log in, so i decided to nuke the database and reset everything 💀 but anyway it worked and i upgraded the server to be better at handling this The sheet to add a shared timetable is improved, with blur effects and stuff, and that tiemtable preview has gotten much better it was pretty bad before ngl"}, {"post_id": 33492, "ts": "2026-07-23T14:13:01Z", "hours": 6.9467, "text": "I did a bunch of things: current day highlight in ios improve the notification early sending, to allow users to send notifications at multiple offsets remake the ui for share timetable sheet also the ui for the link customisation, tinted mint for whatever reason sharing links is now a URL, which prompts you to open the app but uses decently ugly html, ill fix later. New icon for apple watch that is optimised for the smaller display size (just made the components bigger and removed some duplicate elements added some mroe developer items at the bottom, doesnt serve much purpose just looks cool lol i removed the status badges that show success, cos i thought they would annoy the user with too many success alerts, and success when you are toggling settings doesnt really need alerts, so yeah. i also hit a bug where notifications would send twice, i had to improve the apns token system to not duplicate tokens for a device. on startup the app shows “restoring account…” every time, so i had to cache the profile data to make it stay signed in until explicitly signed out. its kinda hard to see in the screenshot but there is progressivew blur at the bottom and top, looks nice"}, {"post_id": 32346, "ts": "2026-07-21T13:36:10Z", "hours": 3.2925, "text": "I had a bug where the device could receive 2 notifications and live activities for each device, so I had to remake the APNs (apple push notification service) token management. I also added a highlight around the current day, with the setting to disable it. i thought a stroke was better than a fill because its less overwhelming and doesn’t break the ui style."}, {"post_id": 32261, "ts": "2026-07-21T10:07:38Z", "hours": 2.5917, "text": "😍"}, {"post_id": 31757, "ts": "2026-07-20T12:16:31Z", "hours": 0.9472, "text": "As you saw before the onboarding UI was a bit broken, so I went through and fixed it up and also trimmed down how many pgaes it has. Those bottom buttons aren’t concentric for some reason, even though I am using the built-in toolbar API, so I can’t fix it. Oh well. And it’s done to 8 pages, from 13. I still have som non-UI bugs to fix."}, {"post_id": 31728, "ts": "2026-07-20T11:15:51Z", "hours": 3.0553, "text": "Updated splash screen Notificaitons now have threads (each school day is a thread) macos window size animation fixed (the macos window resizes depending on the current state of the app, like currently selected tab etc. fixed some bugs in live activities and server authentication"}, {"post_id": 31613, "ts": "2026-07-20T04:58:28Z", "hours": 2.3833, "text": "Fixed some server bugs, a user reported getting “forbidden” status messages, turns out I forgot to migrate the database 😐 And other UI refinements: Tab bar uses monospace font version and build in settings feedback sheet"}, {"post_id": 31570, "ts": "2026-07-20T02:25:41Z", "hours": 0.5333, "text": "Plus a version for debug builds, I think they came out really nice!!"}, {"post_id": 31548, "ts": "2026-07-20T01:23:34Z", "hours": 0.4489, "text": "I think this is pretty much it."}, {"post_id": 31538, "ts": "2026-07-20T00:55:26Z", "hours": 0.7164, "text": "I think I’m getting there"}, {"post_id": 31518, "ts": "2026-07-20T00:10:10Z", "hours": 0.2719, "text": "I think I’ve locked in to this one. Now I need to figure out what to actually put on the papar, im thinking it has to be a kind of simplifed version of the existing main UI of my app. something kinda like a calendar schedule"}, {"post_id": 31513, "ts": "2026-07-19T23:53:55Z", "hours": 0.6131, "text": "So many variants! and idk which one is best"}, {"post_id": 31504, "ts": "2026-07-19T23:17:08Z", "hours": 2.4258, "text": "Many many iterations later… I’m leaning towards that paper one, it looks really tasteful i think. im not sure what to put on the paper though"}, {"post_id": 31176, "ts": "2026-07-19T11:22:39Z", "hours": 0.635, "text": "I think they are coming along really nicely!!!! The watchOS version has bigger title text and less handwriting rows cos its a smaller display size, i really like this 😃 the refraction effects 👌"}, {"post_id": 31171, "ts": "2026-07-19T10:43:22Z", "hours": 0.2894, "text": "I think it’s looking preetty good so far"}, {"post_id": 31156, "ts": "2026-07-19T10:22:03Z", "hours": 0.3833, "text": "More experiments, cos the previous multicolour outline was kinda ugly, now i’m thinking of adding the fake handwriting instead, it might look nice"}, {"post_id": 31145, "ts": "2026-07-19T09:51:42Z", "hours": 6.1353, "text": "I needed a new design system for my app, currently it was just a font and thats about it. Below are some experimental app icons I’ve been tweaking in sigma, they are made out of “paper” and represent a new theme I could use, which is literal paper as the design language. I think it could merge with Liquid Glass really nicely if done properly. Otherwise, other improvements: New App Intents for Apple Intelligence Allow users to set a custom share link URL, for example timetable.adonis.pt/sharedtimetable/adon’s_timetable More server tests + server improvements due to finding bugs in tests"}, {"post_id": 30567, "ts": "2026-07-18T07:42:48Z", "hours": 0.7647, "text": "I have also decided to remove Apple wallet integration, it just kinda got too messy. so im now going to revert (yes, revert 😭) back to an iMessage extension that lets you share timetables with a link. it fixes some annoying things that wallet integration has, like syncing etc. I can even allow custom link urls for a shared timetable!"}, {"post_id": 30552, "ts": "2026-07-18T06:53:52Z", "hours": 4.8108, "text": "I got carried away, since right now I am just going through and fixing the feedback my beta users gave me, starting with these: improving the onboarding flow to decrease the amount of pages, and condense some other pages, since testers said there were too many. Upgrade the server so that it only allows iOS to make changes to anything, since watchos and ipados and macos can only view, not edit. i added some tests, using codex, on the server. I’m getting tired of manually debugging every single problem I find by hand, I just make tests and its a much easier way of guaranteeing your server works perfectly. the client app is going to be much harder to add tests to, though. and more other random stuff I found and UI fixes etc. The screenshots are some broken UI stuff I found, I can’t really show you server bugs other than these error alerts. Going good so far though, can’t wait to release this as a v3!"}, {"post_id": 30017, "ts": "2026-07-17T08:18:20Z", "hours": 1.2478, "text": "After releasing v2 testflight, my friends pointed out a very large amounts of bugs in the app 😭 so I am now just trying to fix everything they pointed out. I’m pretty sure the server doesn’t have any issues, so at least that’s good. First bug is this bottom bar looks horrendous, This was fine for me cos I set my dynamic text size to small 😭"}, {"post_id": 28834, "ts": "2026-07-15T10:39:28Z", "hours": 2.2433, "text": "I made some final refinements to make sure account management on macOS works, so that my users can actually use the app, and then some other UI refinements, mainly for settings. there are a bunch of weird things i am yet to fix, but im really tired and just want to get this app out, so ill fix them later."}, {"post_id": 26526, "ts": "2026-07-11T11:56:12Z", "hours": 0.4547, "text": "I added some more pages to the onboarding, since that’s the only way I can show users how the app works cos it ngl is kinda obscure. i also added a report feedback or bug button, which needs some ui adjustments bruh"}, {"post_id": 26359, "ts": "2026-07-11T03:14:52Z", "hours": 1.1214, "text": "I can’t really show you haptics but i added haptics to buttons and the status badges. not much to say honestly. theres a toggle in settings to turn that on and off."}, {"post_id": 25978, "ts": "2026-07-10T14:57:41Z", "hours": 0.8503, "text": "I;m nearly read to release version 2 of the app, so i made a list of final tweaks and little improvements to make it as best I can, i think i can release it in a few days."}, {"post_id": 25832, "ts": "2026-07-10T09:47:11Z", "hours": 3.5725, "text": "I improved the friends subjects widgets with concentric corners and stuff."}, {"post_id": 24646, "ts": "2026-07-08T11:25:32Z", "hours": 2.6925, "text": "I think I have built out pretty much all of the projects, but i need to fix the abundance of bugs and problems that i have. the first one was fixing a problem with server syncing, and making watch depend on signing in on the phone, not by itself."}, {"post_id": 23437, "ts": "2026-07-06T12:20:38Z", "hours": 1.6219, "text": "I refined the live activities (that background is for recess and lunch, even though this preview text says before school)"}, {"post_id": 23389, "ts": "2026-07-06T09:53:29Z", "hours": 8.7292, "text": "I added live activities, although they are currently kinda ugly and need much improvement. I also made the watch app independent, because it doesnt need the iphone much really, it can just contact the server. i still have more work in making the server work better and stop giving me random errors, but yeah."}, {"post_id": 22056, "ts": "2026-07-04T09:37:57Z", "hours": 2.8419, "text": "In the onboarding I added pages to teach the user the features of the app, but I havent finished it yet. it needs a few more pages and refinement for smalelr phone screens"}, {"post_id": 21441, "ts": "2026-07-03T12:12:36Z", "hours": 6.5136, "text": "I have added an onboarding view that i really like, its very colourful and stuff. i also improved the server to be able to send notifications to users, to tell them when their next class is."}, {"post_id": 20474, "ts": "2026-07-02T02:23:36Z", "hours": 3.1183, "text": "I added notifications to the app, so that people can receive information in the form of notifications as well as live activities and app intents and widgets. I also improved the share pass button in the prominent tab bar, so that you see this sheet to select what pass you want to share, not just the user’s own timetable."}, {"post_id": 19907, "ts": "2026-07-01T10:45:28Z", "hours": 0.4294, "text": "Much better blur, although the server is taking a full 2.5 seconds to send back the pass, and i need to reduce that as much as possible"}, {"post_id": 19874, "ts": "2026-07-01T09:07:49Z", "hours": 0.5289, "text": "The timetable has some shadow behind it. I wanted to make the card HDR, but after a lot of experimenting i found apple doesn’t let you use hdr in your app like this, so i had to instead do this shadow 😐"}, {"post_id": 19839, "ts": "2026-07-01T07:27:59Z", "hours": 5.4344, "text": "I finished the search view, and i spent a very long time on perfecting some visual animations and stuff. when you click on a search result it separately animates the title in. also, before you search anything, i thought instead of showing most downloaded timetables or something i show this really squishy and fun pokemon-style timetable wallet pass. the settings view has also been improved a bit, to make some settings more clear, but i still need to refine it alot further to get it working really nicely."}, {"post_id": 19231, "ts": "2026-06-30T14:26:57Z", "hours": 3.5647, "text": "I did some debugging and made quite a lot more endpoints, I think I’m ready to move on to making the app."}, {"post_id": 18340, "ts": "2026-06-29T13:38:09Z", "hours": 5.9711, "text": "It took quite some time, but i got some really nice looking status badges! I’m really proud of how they came out, they look very juicy, and i cant show it here but i promise its very touchable and squishy and animated! 🥰"}, {"post_id": 17491, "ts": "2026-06-28T09:18:06Z", "hours": 1.3717, "text": "I’ve built a few endpoints and documented them in rapidapi, ready to import into the client app."}, {"post_id": 17396, "ts": "2026-06-28T04:54:23Z", "hours": 2.2958, "text": "I finally got the server working! took a really long time to get https working though, nginx was impressively difficult"}, {"post_id": 16990, "ts": "2026-06-27T15:55:13Z", "hours": 3.0039, "text": "I have started building the server, using swift vapor. i chose vapor because it is written with swift, like my project, which made it easier to share code between the two files."}, {"post_id": 16274, "ts": "2026-06-26T13:42:03Z", "hours": 4.8597, "text": "Xcode seems to have become extremely broken or something, i spent the last 4 hours trying to make my widget work but Xcode kept erroring out and eating memory swap, and now i have some trouble with making the imported timetables actually show up in the widgets i already made 😡"}, {"post_id": 15592, "ts": "2026-06-25T11:12:59Z", "hours": 0.6642, "text": "I changed the blur effect to this, which i think is much better, because it has less blur, and doesnt add an ugly grey tint, so black background stays black background."}, {"post_id": 15058, "ts": "2026-06-24T13:45:05Z", "hours": 0.5081, "text": "I added this blur effect behind the share sheet, and I think it looks really nice. I had to import a package to get a blur this clear"}, {"post_id": 15044, "ts": "2026-06-24T13:04:35Z", "hours": 1.7442, "text": "I added a share button in the bottom left, which allows the user to share their timetable in one press, using the .prominent Tab style so that it looks seperate from the other tabs while still looking consistent."}, {"post_id": 13120, "ts": "2026-06-21T13:40:22Z", "hours": 1.0011, "text": "So added the ability to share timetables using apple wallet, along with sending them using messages, i think that background will need to get fixed for readability, but otherwise, i like it alot."}, {"post_id": 13066, "ts": "2026-06-21T11:31:59Z", "hours": 3.4256, "text": "I added some App Intents, below is my current subject intent, and also a list of received timetables intent. It took a lot longer than expected because the app intents framework was quite confusing to get working, but i got a nice UI in the end."}, {"post_id": 12370, "ts": "2026-06-20T05:56:30Z", "hours": 1.4289, "text": "I upgraded the watch views, like making the progress rectangle rounded, and this very colourful background for when its recess and lunch"}, {"post_id": 11882, "ts": "2026-06-19T11:15:08Z", "hours": 2.4344, "text": "I updated the background of the window, including in light mode, and I also remade the icon. The settings also looks much better than it was before, and I made a nice window animation for when you click a slot to see what your friends have."}, {"post_id": 9773, "ts": "2026-06-16T06:48:43Z", "hours": 1.3667, "text": "I made some refinements to the watchOS and iOS app, including design and performance."}, {"post_id": 9217, "ts": "2026-06-15T14:09:02Z", "hours": 0.8633, "text": "I made some design adjustments to the macOS app, giving it a blur background. Also, the weekly shedule widget has had its corner radiuses and colours adjusted to be less harsh and look better."}, {"post_id": 9192, "ts": "2026-06-15T13:10:48Z", "hours": 0.2592, "text": "I added some buttons and refined the UI of settings view"}, {"post_id": 9182, "ts": "2026-06-15T12:32:38Z", "hours": 0.5969, "text": "I continued to refine the design of the macOS widget, and I really like it now."}, {"post_id": 9098, "ts": "2026-06-15T06:29:44Z", "hours": 3.9675, "text": "I fixed the widget extension problem by making two widget extensions, one for watch and one for other platforms, and made them use identical code. And then I refined the widget design for macOS and iOS and i think they look really nice now."}, {"post_id": 7893, "ts": "2026-06-13T05:18:30Z", "hours": 0.5119, "text": "I added support for these widgets from only watch to iphone and ipad and macOS, and currently they are ugly and unrefined, so I’m going to fix them now."}, {"post_id": 7438, "ts": "2026-06-12T11:50:09Z", "hours": 3.1881, "text": "I ported the app over to macOS, which was harder than I thought because there was a lot of code throughout every screen that was for connecting iphone to apple watch or some other iOS-only thing, which I had to conditionally compile out for macOS. then I needed to refine the views to work on macOS well, for example the class editor sheet used a sidebar instead of the scrolling tabview on iOS. There’s still more work to do to refine it more and get CloudKit working so that the timetable syncs across devices."}, {"post_id": 6885, "ts": "2026-06-11T15:22:19Z", "hours": 2.7783, "text": "I added these views to the watch, so you can see how much time is left in a session for yourself, and also for others. i also refined the timetable view to not use so much glass because it was lagging the TabView. The main clock uses a liquid glass background against the background progressview, and what class is next."}, {"post_id": 6796, "ts": "2026-06-11T12:06:20Z", "hours": 0.8469, "text": "I fixed the sync button visuals, it now has a blur replace transition effect. the timetable comparison view also blurs in and out when you click around"}, {"post_id": 6781, "ts": "2026-06-11T11:08:53Z", "hours": 2.6286, "text": "I moved the sync button to settings, so that the toolbar in the timetable tab could be removed. this is to make way for this new bottom half of the screen that shows other people’s timetables when you click on the slot in the top half, replacing the previous system of letting you select someone else and see their whole timetable covering your timetable. this system lets you view your own timetable and compare it with everyone else’s at a particular period. It uses a soft scroll edge effect at the bottom, and a hard effect at the top, which i think looks really nice. the second image shows the content scrolling under the timetable, which i really liked."}, {"post_id": 6247, "ts": "2026-06-10T14:30:26Z", "hours": 0.8989, "text": "I’m just refining the software a but before I start adding Siri support and improving Messages import/export flow. I fixed this comparison view, improved the class editor to show the glass nicer, and the settings toolbar has a gradient blur effect instead of hard blur, which was made the new default toolbar background style, which imo is ugly."}, {"post_id": 6208, "ts": "2026-06-10T12:53:06Z", "hours": 4.0678, "text": "I renamed PMS Timetable to Timetable, which took more time than I expected cos it was embedded in like every single file and I even had to go through binary files and just delete all the instances of “pms” . then this managed to corrupt Xcode and make it crash every time I opened it, and i had to delete some stuff to fix that. Now I’m on the OS27 version and I’m going to start fixing some UI."}]...
|
Title: Timetable by @omeriadon | Stardance
Devlog Title: Timetable by @omeriadon | Stardance
Devlogs:
I renamed PMS Timetable to Timetable, which took more time than I expected cos it was embedded in like every single file and I even had to go through binary files and just delete all the instances of “pms” . then this managed to corrupt Xcode and make it crash every time I opened it, and i had to delete some stuff to fix that. Now I’m on the OS27 version and I’m going to start fixing some UI.
I’m just refining the software a but before I start adding Siri support and improving Messages import/export flow. I fixed this comparison view, improved the class editor to show the glass nicer, and the settings toolbar has a gradient blur effect instead of hard blur, which was made the new default toolbar background style, which imo is ugly.
I moved the sync button to settings, so that the toolbar in the timetable tab could be removed. this is to make way for this new bottom half of the screen that shows other people’s timetables when you click on the slot in the top half, replacing the previous system of letting you select someone else and see their whole timetable covering your timetable. this system lets you view your own timetable and compare it with everyone else’s at a particular period. It uses a soft scroll edge effect at the bottom, and a hard effect at the top, which i think looks really nice. the second image shows the content scrolling under the timetable, which i really liked.
I fixed the sync button visuals, it now has a blur replace transition effect. the timetable comparison view also blurs in and out when you click around
I added these views to the watch, so you can see how much time is left in a session for yourself, and also for others. i also refined the timetable view to not use so much glass because it was lagging the TabView. The main clock uses a liquid glass background against the background progressview, and what class is next.
I ported the app over to macOS, which was harder than I thought because there was a lot of code throughout every screen that was for connecting iphone to apple watch or some other iOS-only thing, which I had to conditionally compile out for macOS. then I needed to refine the views to work on macOS well, for example the class editor sheet used a sidebar instead of the scrolling tabview on iOS. There’s still more work to do to refine it more and get CloudKit working so that the timetable syncs across devices.
I added support for these widgets from only watch to iphone and ipad and macOS, and currently they are ugly and unrefined, so I’m going to fix them now.
I fixed the widget extension problem by making two widget extensions, one for watch and one for other platforms, and made them use identical code. And then I refined the widget design for macOS and iOS and i think they look really nice now.
I continued to refine the design of the macOS widget, and I really like it now.
I added some buttons and refined the UI of settings view
I made some design adjustments to the macOS app, giving it a blur background. Also, the weekly shedule widget has had its corner radiuses and colours adjusted to be less harsh and look better.
I made some refinements to the watchOS and iOS app, including design and performance.
I updated the background of the window, including in light mode, and I also remade the icon. The settings also looks much better than it was before, and I made a nice window animation for when you click a slot to see what your friends have.
I upgraded the watch views, like making the progress rectangle rounded, and this very colourful background for when its recess and lunch
I added some App Intents, below is my current subject intent, and also a list of received timetables intent. It took a lot longer than expected because the app intents framework was quite confusing to get working, but i got a nice UI in the end.
So added the ability to share timetables using apple wallet, along with sending them using messages, i think that background will need to get fixed for readability, but otherwise, i like it alot.
I added a share button in the bottom left, which allows the user to share their timetable in one press, using the .prominent Tab style so that it looks seperate from the other tabs while still looking consistent.
I added this blur effect behind the share sheet, and I think it looks really nice. I had to import a package to get a blur this clear
I changed the blur effect to this, which i think is much better, because it has less blur, and doesnt add an ugly grey tint, so black background stays black background.
Xcode seems to have become extremely broken or something, i spent the last 4 hours trying to make my widget work but Xcode kept erroring out and eating memory swap, and now i have some trouble with making the imported timetables actually show up in the widgets i already made 😡
I have started building the server, using swift vapor. i chose vapor because it is written with swift, like my project, which made it easier to share code between the two files.
I finally got the server working! took a really long time to get https working though, nginx was impressively difficult
I’ve built a few endpoints and documented them in rapidapi, ready to import into the client app.
It took quite some time, but i got some really nice looking status badges! I’m really proud of how they came out, they look very juicy, and i cant show it here but i promise its very touchable and squishy and animated! 🥰
I did some debugging and made quite a lot more endpoints, I think I’m ready to move on to making the app.
I finished the search view, and i spent a very long time on perfecting some visual animations and stuff. when you click on a search result it separately animates the title in. also, before you search anything, i thought instead of showing most downloaded timetables or something i show this really squishy and fun pokemon-style timetable wallet pass. the settings view has also been improved a bit, to make some settings more clear, but i still need to refine it alot further to get it working really nicely.
The timetable has some shadow behind it. I wanted to make the card HDR, but after a lot of experimenting i found apple doesn’t let you use hdr in your app like this, so i had to instead do this shadow 😐
Much better blur, although the server is taking a full 2.5 seconds to send back the pass, and i need to reduce that as much as possible
I added notifications to the app, so that people can receive information in the form of notifications as well as live activities and app intents and widgets. I also improved the share pass button in the prominent tab bar, so that you see this sheet to select what pass you want to share, not just the user’s own timetable.
I have added an onboarding view that i really like, its very colourful and stuff. i also improved the server to be able to send notifications to users, to tell them when their next class is.
In the onboarding I added pages to teach the user the features of the app, but I havent finished it yet. it needs a few more pages and refinement for smalelr phone screens
I added live activities, although they are currently kinda ugly and need much improvement. I also made the watch app independent, because it doesnt need the iphone much really, it can just contact the server. i still have more work in making the server work better and stop giving me random errors, but yeah.
I refined the live activities (that background is for recess and lunch, even though this preview text says before school)
I think I have built out pretty much all of the projects, but i need to fix the abundance of bugs and problems that i have. the first one was fixing a problem with server syncing, and making watch depend on signing in on the phone, not by itself.
I improved the friends subjects widgets with concentric corners and stuff.
I;m nearly read to release version 2 of the app, so i made a list of final tweaks and little improvements to make it as best I can, i think i can release it in a few days.
I can’t really show you haptics but i added haptics to buttons and the status badges. not much to say honestly. theres a toggle in settings to turn that on and off.
I added some more pages to the onboarding, since that’s the only way I can show users how the app works cos it ngl is kinda obscure. i also added a report feedback or bug button, which needs some ui adjustments bruh
I made some final refinements to make sure account management on macOS works, so that my users can actually use the app, and then some other UI refinements, mainly for settings. there are a bunch of weird things i am yet to fix, but im really tired and just want to get this app out, so ill fix them later.
After releasing v2 testflight, my friends pointed out a very large amounts of bugs in the app 😭 so I am now just trying to fix everything they pointed out. I’m pretty sure the server doesn’t have any issues, so at least that’s good. First bug is this bottom bar looks horrendous, This was fine for me cos I set my dynamic text size to small 😭
I got carried away, since right now I am just going through and fixing the feedback my beta users gave me, starting with these: improving the onboarding flow to decrease the amount of pages, and condense some other pages, since testers said there were too many. Upgrade the server so that it only allows iOS to make changes to anything, since watchos and ipados and macos can only view, not edit. i added some tests, using codex, on the server. I’m getting tired of manually debugging every single problem I find by hand, I just make tests and its a much easier way of guaranteeing your server works perfectly. the client app is going to be much harder to add tests to, though. and more other random stuff I found and UI fixes etc. The screenshots are some broken UI stuff I found, I can’t really show you server bugs other than these error alerts. Going good so far though, can’t wait to release this as a v3!
I have also decided to remove Apple wallet integration, it just kinda got too messy. so im now going to revert (yes, revert 😭) back to an iMessage extension that lets you share timetables with a link. it fixes some annoying things that wallet integration has, like syncing etc. I can even allow custom link urls for a shared timetable!
I needed a new design system for my app, currently it was just a font and thats about it. Below are some experimental app icons I’ve been tweaking in sigma, they are made out of “paper” and represent a new theme I could use, which is literal paper as the design language. I think it could merge with Liquid Glass really nicely if done properly. Otherwise, other improvements: New App Intents for Apple Intelligence Allow users to set a custom share link URL, for example timetable.adonis.pt/sharedtimetable/adon’s_timetable More server tests + server improvements due to finding bugs in tests
More experiments, cos the previous multicolour outline was kinda ugly, now i’m thinking of adding the fake handwriting instead, it might look nice
I think it’s looking preetty good so far
I think they are coming along really nicely!!!! The watchOS version has bigger title text and less handwriting rows cos its a smaller display size, i really like this 😃 the refraction effects 👌
Many many iterations later… I’m leaning towards that paper one, it looks really tasteful i think. im not sure what to put on the paper though
So many variants! and idk which one is best
I think I’ve locked in to this one. Now I need to figure out what to actually put on the papar, im thinking it has to be a kind of simplifed version of the existing main UI of my app. something kinda like a calendar schedule
I think I’m getting there
I think this is pretty much it.
Plus a version for debug builds, I think they came out really nice!!
Fixed some server bugs, a user reported getting “forbidden” status messages, turns out I forgot to migrate the database 😐 And other UI refinements: Tab bar uses monospace font version and build in settings feedback sheet
Updated splash screen Notificaitons now have threads (each school day is a thread) macos window size animation fixed (the macos window resizes depending on the current state of the app, like currently selected tab etc. fixed some bugs in live activities and server authentication
As you saw before the onboarding UI was a bit broken, so I went through and fixed it up and also trimmed down how many pgaes it has. Those bottom buttons aren’t concentric for some reason, even though I am using the built-in toolbar API, so I can’t fix it. Oh well. And it’s done to 8 pages, from 13. I still have som non-UI bugs to fix.
😍
I had a bug where the device could receive 2 notifications and live activities for each device, so I had to remake the APNs (apple push notification service) token management. I also added a highlight around the current day, with the setting to disable it. i thought a stroke was better than a fill because its less overwhelming and doesn’t break the ui style.
I did a bunch of things: current day highlight in ios improve the notification early sending, to allow users to send notifications at multiple offsets remake the ui for share timetable sheet also the ui for the link customisation, tinted mint for whatever reason sharing links is now a URL, which prompts you to open the app but uses decently ugly html, ill fix later. New icon for apple watch that is optimised for the smaller display size (just made the components bigger and removed some duplicate elements added some mroe developer items at the bottom, doesnt serve much purpose just looks cool lol i removed the status badges that show success, cos i thought they would annoy the user with too many success alerts, and success when you are toggling settings doesnt really need alerts, so yeah. i also hit a bug where notifications would send twice, i had to improve the apns token system to not duplicate tokens for a device. on startup the app shows “restoring account…” every time, so i had to cache the profile data to make it stay signed in until explicitly signed out. its kinda hard to see in the screenshot but there is progressivew blur at the bottom and top, looks nice
I made some UI rehauls again lol Current day receives theis blur effect which kinda looks like real light bouncing inside a box under the current day The accent colour of the app is now brown, as I am trying to make the app feel more like paper, which will become more obvious as i later add paper elements and views inside the app. My last update released a new account backend, which meant some users were not able to log in, so i decided to nuke the database and reset everything 💀 but anyway it worked and i upgraded the server to be better at handling this The sheet to add a shared timetable is improved, with blur effects and stuff, and that tiemtable preview has gotten much better it was pretty bad before ngl
So I made a few more adjustments like removing the APNs registration page from onboarding to make onboarding even more seamless Not important though. I discovered a really annoying problem: When I try to add iPad support, build fails because its trying to embed the watch app which obviously doesnt work on ipad. and xcode isnt letting me fix that. 😐
I found an xcode bug, something to do with compilation errors for incorrect architecture, i dont get it but i gave apple feedback.
I improved the UI for this view, to better show classroom and teacher labels. I also renamed “Authored” to “Created”, apparently its better copy, according to my friend. The settings got cleaned up a bit, and importing from calendar again needs confirmation
This is currently the message extension ui. kinda ugly. that needs fixing I also updated the created timetables detail view, and (ignore the screenshot) removes the save button cos no one is going to remember to press save when they change details, so this should save some frustration.
I’m adding countdowns everywhere, even when school is out, so that you can count the hours until your next period
Message extension got improved, it now checks if you have enabled sharing before allowing you to even sahre it, and tells
I have expanded the home tab!! Theres three tabs at the top, today, week, and upcoming. week is what it already was upcoming shows term dates, no school days, school events, and also the users own personal events they make. the today view is a bit ugly but its sort of there! there also an admin page now, so that i dont have to hardcode term dates etc, i can just send them as api requests (for admin accounts only lol)
As usual, I did a very assorted bunch of things: new admin tab so that i can change stuff without having to go onto my mac and hardcode stuff today view looks like paper - reminscient of the app icon! new about view the popover for subject details is smaller, removing bloat and a bunch of server improvements due to all of my users finding bugs and stuff!
Theres now brown and white paper combined. its an interesting ui concept, makes no sense in real life, but i think it looks nonetheless! it definitely creates an app theme, regardless of if this theme looks good or not…
I made some UX adjsutments in the settings app, added some images, reordered haptics, etc the planner sub-tab has been rehauled, and shows items chronologically instead of in sections, which i thought was more intuitive. it still needs much more thought though, im not sure how to space them out since some gaps are months long.
Me and my friend did a bit of brainstorming, to get ideas on how to improve the app UI, UX and future features. cos we are planning a future release hopefully. so we gained a good idea of consolidating friends into a more clear friends tab, combingin the currently spread-around-everywhere friends stuff.
so me and my friend did some more brainstorming focussing on the new friends tab, and how friend accounts work, and profiles and pfps etc. we also aggregated a list of bugs and UI glitches in the app that still need fixing. the current first version is (moderately) broken 😭
i added a section in teh administration to be able to turn off the server for everyone except for me, so that i can maintain the server and test it. and also a section to manage other admins.
I made this widget, which is kinda like a summary widget for the user. it requires this large widget size to fit everything, and its goign to be more dynamic than the other widget which always show the same layout. i haven’t thought exactly how i’m going to do it though, below is a rough first version.
I’ve been busy remaking the profile editor, its coming together really nicely. that profile picture at the top is designed so that lets the other components take up their space, and then the pfp takes up the rest of the space. this allows the same view to not scroll while working on different phones and text sizes etc. and the background is animated!!!
The bottom colour grid is concentric to the device!!! although making the white outlines also behave nicely is proving really really hard, as you can see below
you can add special badges to people now, for like early birds or something idk. the profile picutre bakground has been upgraded a bit, but im going to have to fork the repo and adjust it myself, its currently not looking like a gradient but a single noisy colour, im gonna fix that.
Given the theme of this app, paper, widgets now get paper too! settings for profiles has been updated too you can now select black → white in the colour selector. friend detail view still kinda looks a bit empty and bland, im not quite sure how to make it feel alive
So the header in settings now reflects with your pfp colours for the profile editor, i made it now scrolling so that you could fit in all of the various options, like animation speed and noise and stuff. when you click on a class in today view, it shows some more details about the class like teacher and location. friends view also looks a bit nicer, both the list view and the detail view.
friends detail view shows a bit more content, and is redesigned for more paper you can reorder the badges around now for priority when they show in their overlay event tags editor looks a bit nicer plus, users can edit their year group after signing in.
some people were saying that it was really annoying that you could drag anywhere in a sheet to dismiss the sheet, you would be halfway through something and then you have to restart. so i went through all the sheets in the app and checked if they needed to remove this swiping. luckily it only needed one modifier per sheet. also, more tester feedback was that i shouldnt have sections for tags, so yeah i did that. also, now that there is a concept known as friends, instead of just shared timetables, i removed the option to allow people to have their timetables searched publicly. i havent figured out what i want for specific created timetables, i might lwk have to just remove that also users now have to fill in what year group they are when onboarding. for tags.
i just read an article that said @Environment(\.dismiss) is bad for performance dismiss() is a very simple and fast way to make a sheet or other modal view dismiss , but because its so simple and dynamic, that introduces lots of bugs apparently. so I had to go through all the sheets and this time replace dismiss() with better state management. i hope ill notice the performance improvements!
before and after some small ui improvements!!
I checked the localisation and it went down to 25%, so I went and pushed that back up to 100%. and the friend detail view has been improved a bit more
So so far up to now, I have completely neglected everything other than iPhone. i needed this so that i could focus on making iphone as seamless and intuitive and possible, and to push features faster. so now i have to go and basically remove all of the non-iPhone code and replace it with iphone code, and then try to make that work multiplatform. so i decided iphone is going to remain as a tabview, for now at least, but ipados, macos, and big iphones can use a navigation split view, shown below. so a sidebar and main view and an inspector on the right sometimes.
first version of timetable for macos 😭 its really ugly and lwk broken. so im gonna spend the next few hours fixing this incredibly “interesting” UI.
working with macOS is infuriating me, so i decided im going to make the macos app actually be mac catalyst, so its technically just running an ipad app. which makes sense. still needs alot more work, this refactor is proving very very annoying
its getting there! mac catalyst is definitely better than trying to make native macOS work. swiftui isnt really making it any better, its really really restrictive in terms of how i can structure my app. like for example that right column, has so many glitches that i cant really find solutions to because the bugs aren’t in my code, its infuriating.
Still just refactoring and remaking the app. i decided to remove OS 26 compatibility, because there is just too many APIs and stuff the images below are some stuff I’ve been refining: dragging friends around sideays iphone support (same thing as macOS + iPadOS) but I’ve decided now to not work on macOS (which is just iPadOS) and ipad until i perfect iphone and watch. should be fun!
I finished the refactoring for now, to make the app multi platform. So then i did some more brainstorming and I have consolidated what is the next few features I need to do tips, to tell the user about features the app has they sound easy but each tip needs rules and parameters and all kinds of obscure annoying things, so its going to be harder than it looks my first tip shown below An indicator next to each friend about their status, which is going to take the user’s location, taken in the background, to tell if they are on campus or off campus So from this you can tell when a user arrives at school or if they are sick iOS provides a function that will call my app, from the background, every time the user crosses a specific map polygon (The school). so i dont even need to do any map processing, my app just gets called every time the device goes in or out of school! plus i can add cool related features like the user’s average arrival time to school, which will be pretty cool!
Few things! Adminsitration gets new items for reported users and freinds-since requests sections in adminstration statistics for number of users, etc you can now see your status and other people’s status, like on or off campus new page that asks for location access ofc (ill move it into the onboarding later improved the add a friend sheet admins get emails for reported users, etc
user account data now has highlighted rows for faster navigation user reports look much better, as well as friends-since requests reporting or sending feedback sends notifications instead of emails, now
lots of little things instead of one big feature: i used to send emails, and i reached limits on the email provider so i had to move to only sending notifications, like device notifications. i still need an alternative, im looking through options now there used to be different settings view between iPhone and iPad, so i consolidated them into one view.you can now see your friend’s status as on or off campus. this uses location to check when you reach school or leave. this also allows some cool statistics like average school arrival time!there is better moderation, it shows in the admins view and lets the admin block or do nothing about the account. it will be expanded later to have more features and actions and stuff you can request to change your friends-since tag, also approved by admin.i deleted all (most) references to #if os(macOS) , since there is no more macOS build, its just iPad running on mac. small ui improvements: added search to some more administration views tapping an existing photo pro allows crop the tabview gets tab transitions, like the ones iOS 26 had (that ios27 removed 😡)year-level tags are separated from other tags expanded statistics!added archived events - events in the past - plus an option to automatically delete old events added a button to reset tips, since the app is getting more and more complicated the onboarding is less condensed, when that permission is first needed, its permission sheet request shows.more stuff gets cached in Defaults, making it more offline-safe.and some toolbar and blur and navigation title stuff.
some ui improvements (that weird box in the account view is Metal debug overlay, not my app)
Grade tracker!!! I know this is a very cliche topic but I had to implement this because it integrates so seamlessly with the app for example, it already knows your subjects (duh) and when you input the date of your assessment, it also knows which period of the day that is, because it knows your subjects! (duh) I also added ATAR, sthe user can set goals and stuff for what they want to achieve.
I decided to remove created timetables. they just don’t work anymore with the Friends concept, which makes it really annoying to adjacently share other timetables alongside having friends. its a shame, i wish it could have worked, maybe ill add it again later. oh well. im still just combing through the app and fixing all the little things i see: grade tracker gets a next item in the top for the top 4 subjects, which is important for atar. improved the friend detail view a bit better, because the old one had not enough information and was displaying badly.added more statistics to administration view cos its fun lol the tag selector view was improved, looks nicer and is a tiny bit more legible nowi changed the grade tracker weighting from semester to year. apparently thats the norm more friend detail view improvements
improving the friend detail view the padding is so much nicer, and the detail view also shows more info and in a better way the week subtab shows a similar timetable to the user’s own, and shows more info. and some more statistics lol
You can now change the font! this took more work than you would expect, because i did a find on the project and saw there were like 60 references to .monospaced, and each one had to be manually upgraded to dynamically apply font. i also tried to make the rounded font expanded, but after some inspection i found it doesnt even have a .expanded variant 😐 so the options i ended up with were monospaced, rounded, and expanded. no normal font. it just looks boring at this point. below is the same screen with each option! widgets also get the fonts, and they look actually insane ngl
I started work on rehauling the watchOS app And I really like how it’s coming out The watch is supposed to distill down the information the user needs, so i picked the current and next period, time, and their location. all these elements are glassy and stuff, so they are clickable, and its in a tabview that scrolls between each card. The first tab is the week view for the user. so I spent a good 2 hours trying to make a ScrollView work, but it didnt. sometimes the views teleported, some lagged, some glitched, and it was overall insanely annoying. so I moved to a tabview, which was considerably more stable, but removed the animations I wanted. it had its own animations which were fine, but yeah. Also, fonts also reflect on the watch! the one in the screenshots below is the expanded style, which to be honest isnt that good on watch since the watch is constrained as is, but yeah. The glass timetable actually looks insane I am still thinking of how to include other content, like grades maybe, and other things, but i dont want to make it too dense and slow
there is a new progress background: its not a background! inspired by the app icon / ios app, the progress view is now this marker thingy which fits into the app’s theme much nicer I’ve also been tweaking the font sizing, image sizing, padding, and gaps between the items here to make sure they look good at all possible subejct names etc. i also had to fight a bit with the safe area of the view, you can see in the image below the name “bob” ends slightly above the text, took me a lot longer than expected to fix that
I also made some improvements to the card height for the user’s own item. before, it was just the full width. Halfway while I was working on that, my TabView suddenly froze for a straight 20 seconds every time i changed the tab. this was very weird, and the CPU shows 0% usage, so I was quite surprised. After a large round of commenting things out and seeing what broke, I found it was a single .glassEffect() that I was using for the progress marker. I have no idea how a glass effect can make an entire tabview freeze, but fine. i replaced it with a simple red colour, as shown below, with a stroke and shadow, and i think it looks fine now.
I added a new devices statistics view. or more accurately, i expanded it. before, it just shows device platforms. now, it shows the os version, minor os version, and if it is a beta or not. i also added support for iOS 26 (previous builds only supported OS27 or later). this involved me just making some features not work on os26 😐 and supporting anything before OS26 would probably be legitimately impossible, so yeah not that.
Big update! Light mode! The app used to be dark mode only, it let me make it look much more pixel-perfect and refine colours and stuff, but its kinda obvious you cant keep the app dark mode only, its just not good. so i went through everything, adding light mode versions of paper, text, glass, etc. took me quite a bit of time because i was trying to maintain consistency while doing it, which included alot of redoing things and creating view modifiers and manually applying each one, etc i also added weatherkit, its just a single line in the today tab, but its nice. while adding light mode support, i found a really nice blur view i could add to lists, so now each lists’s background is nothing other than a blur! i also decided to make all backgrounds made out of paper, and i think it looks nice? theres also now a statistics page for deices and os versions and builds and stuff, itll be more useful later. as well as knowing when your friends arrive to school, i added the ability to know when they are within 5 or 10 mins, and to send notifications for that. average arrival also is split by day now, because people arrive to school at different times per day theres a new tab picker, which you can see int eh controls, its much more glassy than the last one, which is really really playful and stuff! i still have more work to do in terms of ui work, excluding light mode refinements, like notifications and widgets, but yeah.
I added accessibility improvements, mainly like labels and tags and stuff, for use with voice over etc. this was triggered by me installing a developer process into my app which allowed me to iterate on design faster, and it depended on accessibility elements to discover each element. (the purple thing lets you tap elements and comment on them) i also tried a new background for the cards, as you can see below, its just glass and i think it looks pretty nice
You can now edit the foreground colours for your profile picture monogram i also completed light mode support for widgets
I added custom backgrounds! Theres the paper backgrounds i added recently, and then the solid colours, and then also some of the really nice apple ones idk what they are called (i hope apple doesnt copyright me 😭) so yeah it applies to all backgrounds in the app i think it merges really nice with the liquid glass and blur backgrounds different views have it also shows on watch i also added an option to choose how far forward you see events. theres also even more statistics for what app version people are using!
So supporting light mode calls for an icon redesign, at least just for light mode, and here they are! Though to be honest, the entire app is gonna need a redesign, because I need to rename it from Timetable, because it has expanded into doing so much more, and timetable is a bit of a boring name. finding names is so insanely annoying though, but oh well.
I spent some time to work on this search button and its animation. idk if the video plays, but it uses apples glass effect transitions! I also made the confirmation dialogs for removing and reporting a friend better, before they just popped up in the middle of the screen, now it comes out of the menu (also found another ios27 beta bug 😐)
A somewhat interesting devlog this time. I spend a good 2 hours just trying to make live activities work. the miserable part is that they were already working before 😭 I dont even know what I did but it broke. And while i was trying to make a debug button to start a live activity, yeah it just wasn’t working. all kinds of problems with not submitting a good APNs token. and i had to like stop activities before starting new ones and stuff it was just in general really annoying. there was even more problems but its too much to say here 😔 anyway, i have started cleaning up the app. no more big features, to be honest, until i add a website for this thing!! should be really easy since the backend is clearly all done lol events can show weather for them, such as the athletics carnival i removed the ridiculous backgrounds i allowed users to choose, theres no only solid black/white and paper. more reasonable, i think. as part of my optimisation, i removed settings i found useless. haptics are now always on, and highlighting the current day is always on. profile pictures can now have their foreground colour set, like the Monogram can have its colour optimised.you can see the average for when your friends arrive to school per day, instead of in total. developer settings also got reorganised, more settings only show to developers. yet again cleaning up the app experience. the location status was a bit unreliable, if users were offline, etc, so i added multiple ways the app pushes updates to the server, and queued statuses when the device was offline. i also refined the actual radius for what counts as within 5 / 10 minutes, should be a bit better. i havent thought about people who live within 10 minutes, thats an interesting case the subject editors grid also looks nicer (still needs more improvement though the tabview now hides while scrolling, like it collapses into the corner, like apple apps! you can manually turn off sharing your status, for privacy reasons. and some more things i forgot 🥹 im so excited for this thing to actually launch!!!!!
new icons. the old one that now supports light mode was kinda ugly.
Ok so after a bunch of wrestling with nginx and bun and next.js, i have added the website! its at https://timetable.adonis.pt/ and the current api has been moved to https://timetable.adonis.pt/api Its the usual next.js thing. and it uses bun. my design idea for this is to look like its an ipad app, essentially, and im going to see exactly how far i can take the mimicking, maybe i can even add liquid glass to the web 💀 So yeah no more app building, now its website! It’s gonna be so much easier as well because I aleady have the backend done and tested, so this should be all design which will be really fun.
The website is alive! I got a screenshot of an iOS26 sidebar, and i am copying it, as you can see. looks nice i think
Hehehehe I’ve got a working version of liquid glass It uses gsap, which is nice the second image is an earlier version 😭
Its nice and squishy now! It uses gsap for this as well gsap is a great framework ngl
And now it scales up and down and stuff!!! I still can’t believe this is just html and css and js 😭 Theres so many parameters to tweak to make it feel right, its so finicky And depending on the size of the glass, you have to change the numbers, its kinda confusing honestly
So I’ve made the first version of the website, it’s really insanely buggy and broken, but the ui is there. so have the html good but no i need to really tweak the css to make it look nice, apple-style. i also need to figure out how to make loading states look nice, since unlike the the swiftui app, i can’t cache anything to not show loading state. in the plus side i dont have to deal with offline state, though. the sidebar and the toolbar are finished, and look really nice. the sidebar has an effect (from ipados) that basically reflects the content in a subtle blurred way, to make it feel like glass while not actually rendering anything expensive. The toolbar is just glass buttons + a black fade effect + progressives blur, also tuned to look like ipados. the icon in the sidebar is pretty ugly honestly so i need to replace that with the non-bordered icon. The other problem i am dealing with is that we are planning a complete redesign of the entire swiftui app, and obviously that has to propagate to the website, so any work i do now is kinda gonna be half wasted, depending on what the redesign actually looks like.
I’m still working on making the UI look much better, and I’m still figuring out some website stuff like how i should wire up the sidebar tabs as well as having like a nice homepage to advertise everything the app does, which will be a really fun sub-project. Turns out making nice looking lists in react is much harder than it looks, as shown below 😭 one problem is that each symbol has a different aspect ratio so i dont even know how to fit them nicely And unlike swiftui, its raelly raelly hard to stay consistent in your css and to keep using the ui tokens instead of making custom css everywhere. it looks like the website is gonna be harder than the app to make after all 😔 this classes card though, for example, i think its pretty much almost done. i might need a few more borders to make it look glassy and stuff but it looks exactly like the ios version, which is the end goal! And I added the animations to the classes card, again exactly like the iphone app. i also got a vscode extension that shows you all of your unused css classes, i highly recommend getting one and purging your codebase!
So the previous UI was really ugly, to be honest, so i decided I am oing to scrap half of the design and completely unstyle the entire app while making everything as standardised as possible, by trying to only use reused components as much as possible. So I spent all today stripping out components I didn’t need, then take the surviving components and adjusting them to my use case and making then look as nice as I can. alert dialogs drawers buttons lists section cards switches I have also decided to stop using tailwind because its quite simply messy and much more confusing than just moduled css, so ye
I have pretty much finished the components, I’m going to now go and add the other shared components and improve them too. then im gonna go through the css files and clear anything that is unused or overcomplicated, and then i can start remaking the website!
I think I have finished making all of the shared components I put everything inside accordions to organise the test components Overlays get the same translucency and outline every other component gets I think im happy with how the lists look, finally the option selectors are really really hot!!! The first page I have remade is the About view, which shows this badge if you are on localhost lol i also had to move the contributors up to the server instead of hardcoding them so that both website and app can see it And a really nice little animated gradient thingy for the about view!!
I have started using the shared components around the website, and its actually looking pretty nice! most importantly, these components can be changed once and work everywhere and i removed the drawers i was using everywhere, and i also made said drawers wider while i was rehauling the drawers i also kinda broke their animations and i don’t know how to fix it 😭 the whole website looks really basic now, since its obviously using now the shard unstyled components, and i was thinking about the theme and decided maybe it should be unstyled, and only the user’s own events and content etc can have colours.
I started to make the landing page, and i decided, after very much research from other landing sites I’ve seen, that the main item should be an interactive timetable, a version of the app icon. but interactive and glassy. im trying to recreate everything in css but its not looking as smooth and polished as real liquid glass does so ye. im kinda getting close though! I also added a navbar item that just is the link to actually open timetable, and when you hover it shows options to either open the app in testflight or open the web version which just redirects to /login. and its background switches to black when you start scrolling, which will make more sense later. i haven’t really planned the rest of the landing page, and i might remove this entire component if i find a good liquid glass implementation i can use, especially with bouncy animations etc. but yeah. (worst part is i might even just go change the entire app icon in a week so that kinda wastes all this time 😭😭😭)
After much trying to make glass, yet again, i failed. So now im just using blur and these edge effects, and i think it looks nice! theres even a hover eect, as shown in the second screenshot (class details show and the rectangle rotates a bit randomly)
I added a title to the lading site, but as you can see its not just any title. it uses this package called fitty to make the text size up to the full width of the page, and it does indeed look massive. and it also goes under the rectangles of the logo, so its like an apple depth effect you get on iphone lockscreens i found the website really laggy while scrolling somewhere while finishing of the main interactive icon, and i couldnt figure out why after removing everything that could have been gpu intensive (my gpu was spiking to 80% while just scrolling) so after all that my most likely theory is that the lag is just my computer and not the website (or both 😭😭) also when i made that main art, i made the border radii use px units, which made it look quite deformed on smaller screens, since the rectangle’s size is relative to screen width, whereas border radius is constant… so i went and fixed that too
I really wanted the first screen for timetable to look really really interesting and unique and instantly recognisable as Timetable, so i made the text instead of a boring white, it now has 3 really nice effects applied: A grain overlay, or noise, which in this case doesn’t make it look paper but looks nice nonetheless Its not flat white, its white at the top and goes to brown at the bottom, more noticeable when you close up. subtle but also nice The “white” isn’t even white. Its a particular white image i had a lot of difficulty in obtaining. it is the third screenshot, the “white” png. Its an .avif , and it uses some HDR-capable color space format something, which on compatible browsers make the timetable text show considerably brighter than everywhere else on your screen, which makes it really pop! i plan on using this effect in other places as well across the landing page to make it just pop a bit more. (the 4th image shows the white pixel showing as 1.25. anything above 1 is hdr.)
I did a few things in this devlog, got quite carried away frankly. So I migrated the codebase from Next.js to Tanstack. The reason was that i was seeing a lot of speed concerns, especially on the landing page. it was just lagging so much. i tried it on all my devices on all the browsers and it was there half the time. after a lot of commenting things out i just couldnt find a bug, so now i moved to tanstack. hopefully taht will remove at least some problems. in any case, i got bored of next.js and tanstack is a different framework to play with and make use of!! also, i continued the landing page by adding cards for each item. i don’t really like it right now, but i have established that i need to add these cards, if not in a different UI. The titles of each card are just image-masks, of Apple wallpapers! i went through some archive and picked out the ones i like, and applied a brightness 200% filter, and they look really nice now. after i finish the landing page im gonna work on rehauling the rest of the ui to be more intuitive and actually usable
ok so i think i have optimised it as much as i can lol tanstack clearly was a good idea, it just needed some optimisations!
Im making a 3d model of the school. this is so that i can show a whole literal map of the campus in the app, and then you can see where each user is, in 3d! i could even reexport it for the website, potentially its going to be interactive and everything
As well as migrating to Tanstack, I wanted even more speed, just for fun at this point honestly, so I decided to move to SolidJS from React. Its decently faster while looking similar to react, and it has some syntax stuff that i much prefer over react. this is basically just adding some margin for me to make bad code The end product looks identical so theres not much to show.. apart from the migration, I’ve also been designing the new landing page, which will also use the 3d model thing. the big question is figuring out how to make the 3d markers for each classroom register correctly, because i need to show a pin for each user at the right place, from swiftui, and somehow embed it into a realitykit 3d model. but im sure this use case has been done many times before so i can find something online!
Continuing the assorted improvements to the app: Fixed stacked drawers so nested drawer state updates reactively. Reworked the Friends page into shared List, ListSection, ListRow, and Card components. Preserved friend drag-and-drop ordering within the new layout. Improved timetable UX: i fixed the lesson selection in week view correctly aligned the “now” indicator in today view restricted timetable mode navigation to mobile through CSS, cos desktop already has the sidebar improved planner event styling. made the drawer compenent animate in and out, something i lost from the react -> solid migration I also added a reusable event-tag selection row with symbols and selected-state feedback.
Ships:
So I made a timetable app for my school, super-specialised and for ios, watchos, and macos. its got live activities and notifications to show you current and next subjects throughout the school day, widgets for your weekly schedule, ability to see your friends’ timetables, and server sync. and apple intelligence support!
This ship, I completely remade the app to work around accounts, and all the features that come with that I added a server, because it used to just store your timetable in your local storage and that was quite boring honestly creating a server for this has allowed me to add accounts, notifications, live activities, friends, shared events, multiple devices in the same account, and has made the website much easier to make (still in development, thats why the top devlogs are talking about the website not the app) The app now has all of this: Grades, track the score of all of your subjects notifications for each subject you have and your events etc live activity throughout each school day telling you your subjects etc sharing your location, subjects, and more with friends widgets that show your your subjects, upcoming events, and your friends’ schedules lots of administration options to manage pretty much everything, including who else is admin lol full support for siri, shortcuts, spotlight, and apple intelligence a full apple watch app btw i know 350 hours on a timetable app sounds insane (😭) but its because this project has 4 different aspects: swiftui client for iPhone, iPad, and mac swiftui client for apple watch a website client (still in development) the server that handles everything, and the database i promise it does more than just tell you your subjects 🙏...
|
1792878455.271768
|
1793742455.271768
|
|
25644
|
rlbuddy by @kmdw | Stardance
|
kmdw
|
3
|
185.95
|
2643
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-28T00:20:30Z", "hours": 40.0, "multiplier": 18.76, "payout": 740, "blessing": "neutral", "text": "I made rlbuddy, a rocket league companion app! This is the third ship so far. The big features this time are the asset swapper and Linux support, but I think that the feature I’m most proud of this time is the asset swapper! It inserts the appearance of one item into the file of another, meaning by swapping out assets for others you can make your car look however you like! (Client-side only, of course). I learned a lot about byte-level manipulation and working with raw data streams and encryption/decryption in Rust, and I can read hex (relatively) well now! It’s also great because I think this combined with the doorstop experiment from a while ago gives me a nice base to try some reverse-engineering challenges in the future. I also worked a lot on performance this time, such as tuning loop times/ui fps caps and minimizing ram usage (I achieved around an 80% reduction here!) There are a crap ton more features added than that (totaling almost 100 commits), but I’m pretty sure you’re not supposed to have massive feature-dumps on the ship text. So the full list is on the latest github release! In the image, you can see I have a white fennec. In reality, I don’t actually have a tw trim, and the equipped decal isn’t compatible with the fennec either. But, using the power of asset swapping, I can get a beautiful all-white car. Neat!", "repo": "https://github.com/Kalilamodow/rlbuddy", "demo": "https://github.com/Kalilamodow/rlbuddy/releases/latest/"}, {"ship_num": 2, "ts": "2026-09-07T20:33:21Z", "hours": 27.0, "multiplier": 16.74, "payout": 457, "blessing": "neutral", "text": "rlbutddy is a feature-rich companion for Rocket League, and v1.2 is out. There’s been some big architectural changes meaning it’s faster and bug-free-er, as well as big new features! New!!! Avatars! Now you can see people’s profile pictures even when you’re not on their platform. Custom map loader! You can import maps from a ZIP or download them straight from Bakkesplugins! Gamepad overlay! Show your controls while playing, to show off your bindings or get some help with your speedflips. I think I’ve definitely improved at Rust since the last release. Just in terms of the amount of mistakes I make, I feel like it’s way more smooth sailing than before. For example, I was able to (mostly) write not-so-buggy code and “run the borrow checker in my head” without needing to cargo check a million times, and clippy tends to have a lot less suggestions for me. Pretty great!", "repo": "https://github.com/Kalilamodow/rlbuddy", "demo": "https://github.com/Kalilamodow/rlbuddy/releases/latest/"}, {"ship_num": 3, "ts": "2026-08-25T22:08:36Z", "hours": 109.0, "multiplier": 17.59, "payout": 1446, "blessing": "neutral", "text": "rlbuddy is a feature-filled companion for Rocket League! It shows the skill of everyone in your lobby and has tons of toggleable widgets and features to make your life a lot easier, from Discord integration to music control. This is my first non-tiny Rust project, and I think it was really great! I’ve learned a lot such as proper state management and the ins and outs of Rust’s syntax. You can give it a try by heading to the Github releases section. If you play Rocket League, I hope you use it!", "repo": "https://github.com/Kalilamodow/rlbuddy", "demo": "https://github.com/Kalilamodow/rlbuddy/releases/latest/"}]...
|
[{"post_id": 80191, "ts": "202 [{"post_id": 80191, "ts": "2026-10-16T17:13:05Z", "hours": 3.4819, "text": "more small improvements. i gave the session stats widget an actual service as well which speeds things up a lot since its not recalculating statistics every single frame. the swapper also uses the backup file if one is available and it no longer accepts duplicate custom maps"}, {"post_id": 77292, "ts": "2026-10-06T13:38:54Z", "hours": 0.4772, "text": "A few fixes here and there. Some refactors, caching externally loaded playlists in savedata, and fixing a deadlock when clearing the items cache. And for some reason the decal option was missing from the items list picker."}, {"post_id": 75881, "ts": "2026-10-01T13:48:20Z", "hours": 5.9928, "text": "I made a standalone web-based swapper for the people who don’t want to download an entire app. A lot of people had broken packages after the last update but didn’t want to install a dedicated program just for a few swaps. So, I used the asset swapper backend of rlbuddy to make this thingamabob which runs entirely in the browser! First, I had to find out how to actually share rlbuddy’s asset swapper with other projects. Turns out Cargo has a cool thing called workspaces where you can have multiple crates in the same repo! So I moved the dedicated UPK/AES etc. stuff into a new crate and added it as a dependency in regular rlbuddy. Then, I whipped up a small wasm-compatible eframe app with the template, and included the new crate as a dependency. I made a big state machine of the steps meaning it’s impossible to have an invalid state, which is really nice. The only problem was that Rust’s ownership system isn’t smart enough to deal with it, so the code is a bit repetitive in places but it’s definitely worth it. The WASM restrictions were super annoying, mainly do to with filesystem access and requiring async. I ended up using the egui-async crate and spilling Binds all over the place within the state machine. I couldn’t even figure out how to get the actual swap procedure to run in a different thread. I also spent like 30 minutes debugging why in the world asset swapping was just broken. Even when I verified the same binary data were going in to the Upk object in the webapp and rlbuddy, for some reason the output upk was just different. Turns out I used chosen_replacement.name instead of chosen_replacement.package.name() . Isn’t that great? Anyways, it works fine now and I’m planning on posting it on r/RocketLeagueMods and possible r/RocketLeague."}, {"post_id": 74679, "ts": "2026-09-27T23:46:54Z", "hours": 3.0297, "text": "Not much in terms of super-cool stuff this time. Highlights are: make sure dynamic playlist loading uses the latest cache file (and also fix its loading on normal people’s rocket league installs) loading the cache file on another thread so it doesnt freeze the whole app for a second on the first lazy lock access searching for items in the item swapper moved the error handling of the map loader to anyhow So no ultra-exciting things to talk about. anyhow is really cool though, it really simplifies error handling everywhere in the app, and I’m a big fan of its bail! macro. I’m also using Cow a lot more. Moo!"}, {"post_id": 73444, "ts": "2026-09-25T03:22:46Z", "hours": 4.635, "text": "I got licensee version 34 (encrypted payloads too) to swap finally! Okay, so this was awesome. Rocket League’s been having a bunch of updates lately, which breaks the packages of people trying to get free stuff. So, in a Reddit thread, I ended up dishing out a bunch of swapped asset files for people in this situation. There’s a new boost which everybody wanted really bad since it was really rare (but they decided to make it unlockable at rocket pass lv99 so it doesn’t even matter anymore), and it was UNSWAPPABLE for three reasons: it was encrypted specially i hadnt encountered specially encrypted packages meaning their handling was wrong aes keys werent out for it yet (or so I thought) I’ll start with 3. I had written a tool which looks in the games cache for AES keys, and dumped them, and it worked great. What I didn’t expect is the filename to change between versions. So, I was super confused since yesterday since the AES key for the boost was just… missing. Thankfully, the geniuses at the RLMM discord got it and helped me figure out that the file I was reading from was just outdated. Great! Anyways, not too big of a deal, just a big delay. Now it’s time for the real challenge: figuring out how the hell to handle this type of package. First, I did some research. The twelve bytes of padding in files with licensee version >=33 before the summary are actually a nonce/aes iv, not just padding. Then, the header is encrypted with AES-CTR with the twelve first bytes of the iv just being the nonce. And the compressed chunks are encrypted too here: each one is also AES-CTRed with their own nonces in FCompressedChunkInfo. Thing is, I don’t have an implementation to really go off anymore, meaning there’s a lot more trial and error. For the original implementation, there were one or two existing asset swappers (though they were vibecoded meaning more of a puzzle to figure out what they’re even doing), but this time I was mostly relying on emii’s fork of UEViewer. Anyways, after spending a while figuring out what exactly I had to masquerade (payload, key, swap nonces) I finally got it to work!"}, {"post_id": 72491, "ts": "2026-09-23T02:26:44Z", "hours": 1.8381, "text": "rlbuddy now loads additional playlists straight from the game’s cached webconfig, instead of hardcoding them all! This means that the list of playlists will basically never go out of date. There are actually quite a few services which rely on game files (eg. auto stats api setup, custom maps, asset swapper). So, the first thing I did was to refactor it so make all of these load from the same global value. Then, for playlists, I made it read from a specific file in the game’s http cache directory which contains a bunch of configuration. Then, it parses it into a JSON object, grabs all the values with Class PlaylistSettings_TA, and then extracts the title and playlist id! There are still a bunch of built-in Playlists, since those have internal things like going from a casual playlist type to its respective competitive one or having the hard-coded list of singleplayer playlists. But, all the other ones, like ltms are dynamically loaded. Yay!"}, {"post_id": 72027, "ts": "2026-09-22T00:56:20Z", "hours": 3.9097, "text": "I made a ton of improvements to the asset swapper! And fixed a bug with the music player which is cool technically, so I’ll start with that. The player uses the GSMTC api, which is async, but egui doesn’t really like async. So, I made it so that every time you wanted to run some command on the current session, it would start up a new thread. This was less than ideal for a few reasons: terrible performance race conditions could happen just… in Windows itself The main problem was 2: for example, if you skipped a replay too fast, the Play command from the end of the replay might actually reach Windows before the Pause command from the replay start, leaving your music paused. So instead, it starts one dedicated worker thread which has a channel which receives a Box<dyn FnOnce(Session)> , and executes at most one command every 50ms (only one command per loop, fixed loop time of 50ms). It’s really interesting because you actually end up sending a closure through a channel, which feels funny but when you really think about it it’s just ownership semantics. But, that’s working great now! On to swapper improvements! First, I moved most of the swapper module to anyhow handling (it’s heaven!), and I also modernized the upk api a bit since it was basically dragged directly from the proof-of-concept repo, meaning it was not really application-ready. Also, it previously looked at the game’s webcache to decode the AES keys for header decryption, but now it uses the wonderful Toga-Files repository along with a really nice caching layer for it to load items and their associated API keys. Having access to the actual item data is also way better since you don’t have to manually type in a package name which is kinda weird for any normal person. Now, you can select it from a dropdown instead! I love UX."}, {"post_id": 71420, "ts": "2026-09-20T19:51:05Z", "hours": 4.5228, "text": "rlbuddy now has item swapping! Basically, making one item appear like another to use items you don’t actually own. These hours were spent on a few different things. Firstly, I optimized the thing a bunch! There were a few places that were pretty slow since the original repo was mainly for testing. For example instead of decrypting the entire header and rechecking it to find the right key, it only loads the first 4 blocks and attempts to decrypt the first FString. If it fails, that means the AES key isn’t valid. Also, I improved the error handling with anyhow. It actually makes it so much easier to deal with things and was pretty useful when debugging the move over to the actual app. Now I’m just going to work on polishing the panel UI a bit more, since it’s still kind of ugly."}, {"post_id": 70888, "ts": "2026-09-19T23:20:36Z", "hours": 2.1058, "text": "Apparently there are a bunch of different AES keys rocket league uses, not just one. You can get a list of them from the psynet config url, and then do some weird crc stuff to change them from “content keys” to aes keys. I discovered the rocket league mapmaking discord today and I’m blown away by the amount of information on there, and also apparently my whole thing about the unknown bytes when licensee version > 32 was straight up wrong, which is funny. Anyways it works for all items now, which is great. I’m gonna work on actually putting it in rlbuddy now, hopefully that goes well"}, {"post_id": 69896, "ts": "2026-09-18T01:01:05Z", "hours": 0.9667, "text": "IT WORKS WHEN THE HEADER EXPANDS NOW YAYAYYAYAYAYYAYAYYAYAYAY I’m gonna be honest, the problem might just have been that my testing package was corrupted. I was debugging my deserialization logic, which I thought might have some parsing issue near the header extraction, and noticed that once the encrypted region deserializer’s Cursor reached the end of the region, it was actually FARTHER than the package summary’s total_header_size - by 6 bytes! That’s pretty bad, and I don’t know how something like that even happened. Anyways, I repaired the game and brought over the shiny new upk and… it worked. I’m pretty sure that I only accidentally did this while tidying up my workspace a few hours ago, but if this has genuinely been the thing holding me back for the past few days - I also finally made the poc code public, at https://github.com/kalilamodow/rl-upk-testing/"}, {"post_id": 69850, "ts": "2026-09-17T22:15:40Z", "hours": 1.67, "text": "IT SWAPPED IT SWAPPED IT SWAPPED AHAHAHHAHAHAHHAHAHAHAHHA FINALLY Okay now I gotta make it work for other pairs of boosts. If WHEN that works, I’ll actually put it in rlbuddy. I removed all the code relating to changing offsets to try to give myself a minimal workspace to tinker in, with as little side effects as possible. So, all the current code does is 1. open them 2. replace the name table entries and package guid. Surprisingly simple. Once I make it a bit more generic, I can extend it to support more swaps. If I’m really unable to get it to work for more combinations, I’ll probably end up just publishing the poc repo and not adding swapping to rlbuddy at all. This is a great motivation boost, though. I was honestly dreading coming home to work on it today because I was done with failing over and over, and considering giving up."}, {"post_id": 68661, "ts": "2026-09-15T14:25:29Z", "hours": 2.6667, "text": "I got a name swap! It doesn’t work properly, but I’m glad the game didn’t crash. These hours have been by far the most frustrating because the only way to test is against the real game since it’s really picky, but the game takes like 30 seconds to start, and if it crashes, it gives a cryptic error log, and if it freezes, it doesn’t give any log at all. I spent most of the time messing with moving different offset values forward and backwards, and ended up reverting to a simpler version with no overwriting when the header size changes just to test things. So far, I’ve mostly gleaned that name renaming is possible, but only up to a point. If the name grows too much, the game crashes, and if the name shrinks too much, the game freezes. Additionally, for some reason, total_header_size changes by the padded header size instead of the encrypted header size, which I still don’t understand. It’s seriously weird. I serialize each name properly, and yet the game reads it wrong. This game really does need a new codebase. When UE6 comes out, either the game’s gonna be so good it doesn’t need mods, or it’ll be relatively easily moddable. Or neither, which is the most probable based on Epic Games’ track record. Anyways, enjoy the beautiful screenshot."}, {"post_id": 68281, "ts": "2026-09-14T20:49:26Z", "hours": 3.1181, "text": "I figured out what comes after export tables! And it took way too long, since I DISCOVERED IT MYSELF! At least, as far as I know. I couldn’t find any information online about this portion of the header, so it was basically luck that I noticed a pattern. Before, I was just copying everything after the export table and pasting them back in afterwards, but as you can guess, that stopped working if I adjusted anything within the encrypted region. Compressed chunk info is a known part, and I figured out the AES padding pretty easily, so most of the time was spent trying to figure out what in the world those 24 bytes were. The first four bytes in the compressed chunk info are how many chunks they are. Here, in the Bubbles boost package, there are two (little endian), with 24 bytes of ???. And in Flamethrower, there are three, with 36 bytes of ???. I noticed that the ??? was always n chunks * 12 bytes (actually, it’s lucky that I didn’t test any which ended up having 0, otherwise I probably wouldn’t have figured it out). Since this probably had something to do with chunks, I made a guess that each chunk had some extra data stored in this array, 12 bytes of info per chunk. Using HxD’s highlight-bytes-and-get-the-decimal-value feature, I noticed a pattern where the first 8 bytes looked like an i64 offset and the last 4 looked like an i32 size, which the compressed chunk infos were also like for their matching counterparts. So, I deserialized it as [i64; i32] * n chunks and was able to read it better. These additional chunk infos seem to kinda sorta match up to uncompressed header offsets, but I don’t really understand what they are (and they’re marked as such in the code, lol). So, with that working (and some fiddling with broken serialization of TArrays which I’m surprised I didn’t catch earlier), I now understood the ENTIRE package header! Hooray! Let’s look at another example. body_grain_SF, the Fennec, has 4 chunks. Guess how many bytes of ??? it has. That’s right, zero! For some reason, a few packages just don’t have those things. After going through a bunch of them, I found that if licensee version was 32, there was no ???. But if it was 33, there WAS ???. I basically just added an if statement and it was fixed. I’m going to try to work on figuring out the padding in between the package summary and the start of the name table, but if I can’t, I suppose I’ll finally get to actually doing package swapping. Later!"}, {"post_id": 67059, "ts": "2026-09-13T03:19:34Z", "hours": 2.9378, "text": "I JUST DESERIALIZED AND RESERIALIZED A UPK. OMAIGOD IM SO HAPPY. my brain is so tired. Alright so the payload still doesn’t get transferred but that’s pretty simple, it’s just Vec::extend. What a challenge! Deserialization actually ended up being the easy part, which is opposite of what I expected from starting the project. It went (relatively) fast since there are a few existing implementations which I could kinda just “borrow” structure parsing from. But, mine is unique in that it almost completely reserializes the package itself. I might’ve been able to “borrow” reserialization, but the impl I’ve been looking at is STRAIGHT ai slop and it’s more annoying to read that than to just do it myself. It was useful though, so I have to respect it. The first problem: basically, the first byte of an FString determines how many parts it has, NOT how many bytes it has. Which wasn’t a problem for parsing, since I had some word-based helpers which worked so I didn’t think much about it. But, when reserializing, I made two mistakes: 1. forgot to add the null terminator (which shouldn’t even be necessary) and 2. I accidentally put the wrong offset. I have no clue why there’s a null terminator for FStrings. The format is [n chars][the char bytes], meaning it should already be known how long the string is. Pretty stupid, but whatever. Anyways, when reserializing you’re supposed to include the null terminator in the string length marker. So, my logic was that I should offset it by two since unicode characters are two bytes. Bleh! I should’ve only incremented by one, since it’s in terms of utf16 chars rather than bytes. Yay, that worked! I don’t know how to summarize the next problem, so I’ll explain the reasoning. The package header is file summary + tables + something else (we’ll get to that later). Anyways, there’s some mysterious padding in between the summary and tables. Parsing, it’s easy to skip over because the summary includes the tables start offset ( name_offset , the name table is the first one). But when reserializing, you gotta keep those offsets intact. Well, I’m not totally sure if you actually have to keep them, but just for the sake of simplicity I tried to (which ended up adding more complexity, which I’ll see if I can remove now). So, I serialize/push the summary to the big Vec. Then, I make a new Vec and serialize the name table at (name_offset - summary_size), since the new Vec has to be encrypted and then appended to the big Vec. I do the same thing for imports/exports (placing the table at import/export _table_offset - summary_size ). Oh no! Since name_table_offset isn’t equal to summary_size, there’s some padding in between, which is expected. HOWEVER! The previous logic would skip over it in the table Vec creation, meaning the table Vec would have some 0-padding at the start. This padding needs to be in the SUMMARY part instead, and the name_offset should basically be the ZERO of the tables Vec! I doubt I would’ve been able to solve this part without the beautiful tool HxD . It’s really easy to use and is always helpful when I’m figgling around with binary. So, it does some more math, calculates the spacing, adds it to the big vec, and removes it from the tables Vec. Then, it re-encrypts the tables Vec and pushes it onto the big Vec! Okay, now that’s done. NOPE! There’s a mysterious structure for some reason at the end of the real table part? Yep, it’s that something else I said we’ll get to. I actually still have no idea what it is. From some research, I gathered it must be the dependencies table, but it’s really poorly documented. So, I ended up just cutting the bytes out from after the export table to the end of the tables part, and “pasting” it back before re-encryption. I do hope this devlog was readable. Now I’ll get to including the actual package payload and hopefully simplifying reserialization offsets. See you soon!"}, {"post_id": 66867, "ts": "2026-09-12T20:09:08Z", "hours": 2.0211, "text": "I’ve been putting this off for a while, but I’ve finally decided I’m going to add asset swapping. There’re a few existing implementations, so I’m reading those as well as some pdfs about the upk format. So basically credit to this document and this implementation . All it can do for now is parse the file summary. The implementation wasn’t too bad since I had Google as well as the C# implementation I just talked about. I basically have trait Deserializable : Sized { fn deserialize ( reader : & mut impl Read ) -> AnyResult < Self > ; } Then implement that for the various parts (eg. FGuid , a generic TArray ). Then, I use byteorder to read out numbers into each struct. For example, #[derive(Debug)] struct FCompressedChunkInfo { uncompressed_offset : i64 , uncompressed_size : i32 , compressed_offset : i64 , compressed_size : i32 , } impl Deserializable for FCompressedChunkInfo { fn deserialize ( reader : & mut impl Read ) -> AnyResult < Self > { Ok ( Self { uncompressed_offset : reader .read_i64 :: < LittleEndian > () ? , uncompressed_size : reader .read_i32 :: < LittleEndian > () ? , compressed_offset : reader .read_i64 :: < LittleEndian > () ? , compressed_size : reader .read_i32 :: < LittleEndian > () ? , }) } } I originally prototyped it in Python and then moved to Rust once I got tired of python’s byte shenanigans."}, {"post_id": 66219, "ts": "2026-09-11T22:03:11Z", "hours": 2.5883, "text": "I did lots of performance improvements and also IT WORKS ON LINUX NOW!!! Let’s talk about performance first. Anyways, it has been using around 4% and 220MB of ram, which isn’t really what you’d expect from an overlay! So, I used things like DHAT to profile the memory, and noticed that fonts were doing some shenanigans. So I removed egui_system_fonts and loaded directly from C:\\Windows\\Fonts\\segoeui.ttf and RAM usage dropped to 30mb. That was what the previous devlog was about. I then changed the default logic update rate from 10ms (100/s) to 65ms (15/s approx). This reduced idle cpu usage to under 0.2%. But, doing anything with the UI would spike it to 4%, which is still pretty bad. So, I used a method I found in an egui issue thread where I’d count the frametime since the last render, then sleep until the target frametime was finished. For example, if the frame rendered in 2ms but I want 16ms frametime, it would sleep for 14ms. That way, I could limit how often the UI rendered! This made it stay under around 1% CPU forever! Okay, Linux time! Rust is mostly cross-platform, so support was mostly dealing with dumbass design decisions. Since Music relies on GSMTC, I had to feature-gate the entire thing (as well as the windows/windows-future crates) behind cfg(windows) :( I also had to fix Linux font loading (since like I said earlier, it’s hardcoded to segoe ui). So I install fontdb on Linux and search for some popular fonts from there to load instead. Finally, I fixed up the storage paths since it could only load from AppData. I also made it use AppData\\Local vs. AppData\\Roaming instead of putting everything in Roaming. I first got it working through WSL! ! It took some messing with my GPU drivers but I got it to render. Now was the real challenge: getting it to build on an ACTUAL Linux machine. I had an old, basically broken Surface Pro 3 that I had put Debian+GNOME on for shits and giggles a few months ago. The perfect target! The main problem was getting Rocket League to even launch. I set up Legendary (goated launcher btw, check it out ) and tried to run it. I installed Wine, got Wine Mono, and it failed with a weird cryptic error about the CreateWindow function. The obvious solution to a graphical error: disable EAC. Yay, it launched! Then to get it to build. First I had to fix some filepaths since Linux is case-sensitive (nerds) while I don’t care about case on Windows. Then, rust-lld gave some weird error about simd or something which I didn’t care about. I just ran cargo clean and rebuilt it and it worked fine. Then to run, and it actually worked first try! It’s cool because I went into it expecting to debug a million socket errors, but it actuallly connected and ran. Awesome sauce! Now Linux users can use rlbuddy. More minions to contr- I mean cool users! Cya in the next one! ;) If you check out the rl perf overlay in the screenshot, you’ll be able to guess why this is the laptop I decided to put Linux on."}, {"post_id": 65417, "ts": "2026-09-10T15:25:20Z", "hours": 0.8867, "text": "I’ve been debugging high memory for the past month or so. It was egui_system_fonts. Why would fonts take 170mb of ram????????????????????????????????? help!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! I hate external dependencies!!!!!!!!!!!!!!!!!!!!11 I owe my life to DHAT now. go star https://github.com/nnethercote/dhat-rs"}, {"post_id": 65067, "ts": "2026-09-09T22:28:11Z", "hours": 1.5, "text": "More gamepad overlay buttons!!! Yay!!! In not-so-awesomely-exciting news, I also added a table of contents to the readme (as well as a generator for it). The script’s in Python (I’m sorry for not using Rust) meaning the repository is now 0.5% Python. Takeover incoming? I overcomplicated the script a lot, but it’s really easy to read. There are three whole comments, aka 6% of lines in the whole file! It’s not technically interesting in the slightest. I was thinking of building a tree-like structure before outputting the string, but realized I can just use the header level (h1 vs h2 vs h3 etc) as the amount of spaces / 2. I also refactored it not to use magic PanelId s for the default panel list. I kinda rushed that part when I made it, I’ll be honest. But now each Panel can implement fn open_by_default(&self) -> bool (returns false by default) and if it does it keeps it open when savedata doesn’t exist yet. I don’t get how an entire hour n 27 minutes was spent on like 7 not-even-that-big commits. At least it was a good use of my math class. We reviewed limits for some reason (which everyone should already know for one because they took the prereqs?), and the teacher managed to extend her lecture for the ENTIRE class time. rlbuddy development saving the day, I guess (just like it will in your rocket league games btw, so you should download it)"}, {"post_id": 64822, "ts": "2026-09-09T14:32:38Z", "hours": 1.4469, "text": "I’ve mostly been working on smaller features, improvements, and bugfixes. A cool one I did is fixing weird glitchy movement with the gamepad overlay window! Basically, the window needs to persist its position across disabling it/enabling it. And egui is immediate mode. So, every time it rendered the viewport, it would both set and get its position. So, moving it would update the current position, but because of the weird interop between setting the position in a ViewportBuilder and getting it from the viewport info, it would glitch back and forth, especially when my laptop is lagging. I fixed it by only calling the ViewportBuilder ‘s “ with_position ” method when the overlay had just been enabled ( !was_enabled && currently_enabled ). That way, it only sets it once externally, and lets it move freely while it’s open. Then, while it’s moving, it continues to update the saved position. And upon closing and then reopening it, it sets it again (but only once!) Relatively simple fix but it’s kind of funny. I mainly noticed it when I added a feature that would auto-unmaximize the overlay when the user maximizes it, and it would go crazy and fly around the screen. Very fun! I also fixed a pretty old bug where it would incorrectly detect the local player. Basically, the stats api doesn’t actually tell you who the local player is. So, we have to guess based on who the camera is targeting right now. Usually, it’s on the local player, but during goal replays or spectating a bot when joining a casual game, it would be improperly set at the start and then stay like that. So, I made sure that it always updated as long as the match is 1. in progress 2. not in a replay. It also fixes a thing with inconsistent match toasts, since the toasts only fire if the scoring player is the local player (and if it thinks the wrong player is the local player, everything’s messed up). I’m planning on revamping hotkeys next, to allow you to bind to any controller button and even do custom quickchats in-game. Later!"}, {"post_id": 63368, "ts": "2026-09-07T04:36:35Z", "hours": 1.4131, "text": "Time formatting doesn’t suck anymore! I made the implementation way better so I could make it support stuff even past weeks, like months and years. The new implementation added around 60 lines, but it’s for a good cause. The previous implementation used a match statement with duplicated logic that only supported seconds, minutes, and hours, using a pluralize function and inline if-statements everywhere. If it were sent to any rational code-reviewer, they would likely have a heart attack. Now it’s a bit more complex but less complicated. You have TimeUnit s which format the unit themselves and TimePart s which format a value + a unit. Then, just use some math to build a Vec and format it into a string. Boom! Beautiful, well-formed time formatting. To soak in the new beauty, I added days n weeks. I just had to add 14 lines! The previous one would have probably needed a bunch of stupid magic numbers and weird chains everywhere to accomplish the same thing. Okay, I’m done using your time on reading a way-too-long write-up about fixing a crappy implementation that shouldn’t have been there in the first place. I’m gonna ship right after posting this. If you get it, make sure to give it 10 stars in everything 😉. Haha, jk. Well, not really. Cya later."}, {"post_id": 62559, "ts": "2026-09-06T00:29:40Z", "hours": 1.8697, "text": "Had to remove the tracker.gg widget :( unfortunately they don’t allow scraping and what I had wasn’t allowed anyways. Things that used to open the player info widget now just open tracker in a browser."}, {"post_id": 60965, "ts": "2026-09-03T17:23:52Z", "hours": 2.9253, "text": "I finished the big refactor! I pushed around 25 commits to GitHub at once. I’m really gonna enjoy adding the next feature, basking in how much easier it is ;) Apparently, I never made a service for session stats, so it currently can’t persist its one setting. Actually, writing this I realized that the setting isn’t actually used, so I can delete it. That’s great. After finally kicking out all the annoying legacy panel code, I remembered that I never re-implemented the positioning or its related persistence code for the new panel system. The persistence system was reworked too, something that I don’t think really got included in the previous devlog. Each service can implement save , and there are generic helper methods in a common module for saving/loading serde structs to a file in the app data directory. The actual app now uses this method as well instead of doing all the pathing logic itself, so the persistence module is pretty small and could honestly be moved into app.rs. For new positioning, I store a list of open panels. Weirdly enough, it’s actually a lot easier than adding a position/is_open field to every AppPanel. So, I run the name through a Hasher to make a u64 which is easier to clone/copy and stuff and made a newtype around a PanelId. That way I could reuse the code from the previous paneling system to swap/manage open PanelIds, then just use find on the AppPanel vec to find the corresponding widget. Also, I never mentioned it but I’ve been trying RustRover for the past few devlogs. It’s a lot more stable than Zed, but I sorta miss its snappiness and minimalism. If I end up finding an annoying bug in RustRover, I’ll probably switch back. However, it’s been quite a few days and I don’t think I’ve found a single one. JetBrains is truly awesome at tooling. See ya next time. Probably will do my next ship soon :)"}, {"post_id": 60552, "ts": "2026-09-02T23:31:23Z", "hours": 3.3072, "text": "I’m MASSIVELY refactoring rlbuddy! This, I think is the second (and hopefully the final) major refactor to the codebase. So, basically the current architecture is split into services and widgets. Each service has an update method, which does its stuff (draining subscribers, processing commands, etc). Since egui is immediate mode, this architecture works unlike callbacks/event-based which I actually tried to implement but couldn’t. Every widget is just implements egui::Widget, that holds some state handles (Rc) and command senders (Sender), usually just one for its respective service. Services are alive for the lifetime of the app, while widgets are the openable panels you see. Widgets display the data from service state, and talk back to it by mutating shared state or sending commands. I think music control has been the best for me to wrap my head around to decide about changes, so I’ll explain it with that. Music control had a controller, a service, and a widget file. The controller was a thread pool manager (if you can call the questionable implementation that) around Windows’ GSMTC API to give a single-thread api for it (since the app is basically single-threaded). Then, the service is always alive, syncing a state struct between the controller and its own state handle. Finally, the widget is optionally there as a panel, with next/previous/pause buttons which send commands and the ui which reads service state to display. It also has a mutable service state reference for settings (the “pause during anthems” button). The god object RlbuddyApp struct stores all of this stuff. So it has a music_control_service, music_control_widget, stats_api_service, all of those fields, which kinda sucked. On top of that, I had to maintain an enum of every panel, which was enumerated for the “open panel” popup and to render each one if it’s open. you might think “hey… isn’t that a self referential struct? how does music_control_widget store a reference to music_control_service?” Well, music_control_widget internally only has fields for the music_control_service’s state handles which are Rc/Arcs. So it only needs a reference to the service for it’s Widget::new function lifetime, all is well. Although it doesn’t look horrible, it was HELL to do anything. For example, refactoring the gilrs service out of hotkey and adding the gamepad overlay probably involved just as much fiddling around with Rcs in RlbuddyApp as adding the actual feature. So, I decided to move to a new architecture: services + features! And, after thinking about it for around 8 hours (i slept), I decided on something a bit different. Services + panels! Yeah, basically the same as services + widgets, but I was gonna implement it GOOD this time, and make design decisions that wouldn’t bite me in the ass later on. I wrote my first traits - Service, which requires update and optionally save , and Panel , which requires name() -> &'static str and ui (same as egui::Widget: :ui). Then, I’d change how components are registered: instead of keeping every service and widget as a field in RlBuddyApp, I’d make a Vec<Box<dyn Service/Panel» for each, and loop through it. I spent about an hour trying to get Panels to automatically implement ui by requiring egui::Widget as a supertrait, which doesn’t work since widgets are stateful (need &self). So, I tried to require &mut Self to implement egui::Widget, but apparently something to do with type erasure doesn’t let that work with dynamic dispatch which was needed for the Vec<Box> thing. I’ve moved a few features to the new architecture, but I’m still in the process of finishing up. Additionally, it has to work side-by-side with existing crappy monster-Panel-enum architecture, which sucks to maintain. Okay, once again, I had to strip down a ton of detail (and my terrible wording but wtv) cause I hit like 5000 characters b4 realizing. See ya! May the Stardance gods increase devlog limits :)"}, {"post_id": 59926, "ts": "2026-09-01T23:19:29Z", "hours": 2.5164, "text": "rlbuddy has a gamepad overlay now so that you can show off your awesome bindings! Don’t even bother figuring out mine. It’s kinda starting to become hellish to add new widgets/services, but I’m almost done for the next ship so I doubt I’ll refactor just yet [edit: im doing a super refactor now hehe]. I made the overlay with the raw egui::Painter rather than actual controls (since it would be pretty hard to make a controller out of Buttons or something). I also prefer to avoid embedding static assets, otherwise I might have made an actual one in MS Paint or something. I also can’t seem to find a good egui version. I’ve been on 0.34 almost the whole time, which works well but doesn’t support transparency in extra viewports. But, 0.35/0.36 broke external viewports. So, until then, we get an opaque gamepad overlay :( but the main app is still transparent, so it’s not horrible. Rolled an 8 and a 9 on the Stardance rng today! I’m so proud of myself."}, {"post_id": 59228, "ts": "2026-08-31T21:59:04Z", "hours": 0.4561, "text": "I moved the mmr server to alpine linux! Before, it was regular raspberry pi os lite on the Pi. But, it was behaving strangely, randomly rebooting and things, so I decided to try installing Alpine. The lightweight distro has been on my radar for a while now, but this was my first time ever actually trying it. I imaged it normally with the raspberry pi imager, and put it on the pi, did setup-alpine, and all was well. But, I put in the wrong wifi password at first, which broke everything else. I tried changing the wifi config and doing something with wpa_supplicant (thanks google ai overview), but nothing fixed it so I ended up doing a fresh install. This time, I put in the right password and everything went great. I set up ssh, node, pm2, etc. and moved the server files onto the pi through sftp. Then, I got it running over my local network and set up authentication. So, it was time to set up the Cloudflare tunnel again. I followed this neat guide , changing values as needed (for example, my pi is aarch64, but the guide was x64, so I spent a while figuring out why the pi kept giving elf errors). It took a really long time to set up the openrc startup script because 1. cloudflare rotates the setup token relatively frequently and 2. I accidentally put 2 –token arguments. And since I was using vi, I didn’t even notice and kept trying to figure out why cloudflared crashed on startup. But I eventually found out and removed the duplicate and it worked! Then I finished setting up pm2 and put the pi in its home next to the router, and mmr.kmdw.dev is back up exposing your lobby’s skills. See you in the next one! Yes I know part of the token is in the image but it’s used already so it doesn’t matter"}, {"post_id": 56962, "ts": "2026-08-29T00:27:50Z", "hours": 9.075, "text": "rlbuddy can load custom maps now! Either you can download them and then import from a zip, or you can download them from bakkesplugins straight from the app! Importing it from a file is relatively easy. I checked the code for Lethamyr’s custom map loader to see what exactly it did, and for Lethamyr maps it: extracted the zip into a temp dir read info.json, .udk, and preview.jpg copied those into its own saved map directory I knew Rust, being a low-level language would let me not have to extract the zip fully first. Additionally, Bakkesplugins maps don’t contain info.json or preview.jpg, they only contain a udk file, so I had to make sure it would work with that. So, the import code I wrote basically: enumerates files in the zip extracts info.json (if found) into a struct copies *.upk into the target directory copies *.jpg into the target directory/preview.jpg if it exists It worked great. I made a really cool looking widget with stupid manual layouting behind it for map selection. First, it would add the preview image (or a black background if none). Then, it would get the screen rect of the image, and draw a semitransparent black background onto it (for contrast). Finally, it drew the actual contents in that screen rect. So, I got pretty-looking tiles with preview image backgrounds! I also added a progress bar for import status. I benchmarked each main part of the import process and found that decompressing/extracting the upk file took around 2 seconds, for which the ui thread would be totally frozen (big nono)! So, I moved the work onto another thread, and also made it decompress/load in 100 total chunks, updating a progress bar each time. I then moved on to the map downloader. Bakkesplugins doesn’t have an API, so it relies on scraping the website. I didn’t actually use any external crates for gathering information, though. I wrote a parser which takes a list of rules, each with a start and end search string, and looks for each of them in sequence till it fails to find a rule. I tried to make it completely zero-copy, but something it needed was to turn an [Option; N] into a Option<[T; N]> if every element was Some , but the only way I could figure out how to do that was with an iterator. It’s still really fast though. So, it parses search results, including map titles and urls straight out of the html string without needing an HTML parser or regex library. Once it was able to load results from the search page, I went to sleep and came back today. Now I had to get it to actually download the ZIP files and preview images, and import them straight into the app. It first has to download/parse the plugin info page since the ZIP url isn’t available in the search results. Then, it requests the ZIP. I had some trouble with this, since I wanted to show a progress bar for the download status. I first tried a function from this gist , but it didn’t work. So, I made my own which used the same chunking strategy as the import status loader. Turns out, ureq blocks requests once they hit 10MB by default, which was probably why the gist version didn’t work. But, mine was faster anyways, so I kept it. It’s even cooler since I made it myself. Then, I wired up a couple more commands to let it import straight from archive bytes instead of from a file path, and it finally loaded! Once that worked, I made it pass along the map title, author, and description as well. Then, I extended it to parse out the thumbnail image url and download that, then pass that along to the importer as well. Anyways, that was super fun. I would add a lot more detail, but Stardance limits devlogs to 4000 characters and I’m approaching scarily close to that. I’m planning on just polishing the downloader interface a bit more, and then I’ll do some bugfixes for the next release. See ya!"}, {"post_id": 55430, "ts": "2026-08-27T08:04:57Z", "hours": 3.0236, "text": "rlbuddy now can show people’s avatars cross-platform! It uses a web api I put on Cloudflare Workers which uses platform-specific requests to get avatar urls (see the previous devlog), which the app just fetches and renders. The http part was pretty easy, since I already have wrappers for cached HTTP apis, so I just had to define types for that and hook it up. But, once it was time to display, I ran into a weird problem where egui said there was no image loader installed for jpegs! Even using all_loaders + default didn’t work. Turns out, I have to actually include image as a separate crate and enable all the filetype features I want in there. Once I got it to load, it was time to mess with styling again. egui is really annoying with images, so I spent a while trying to get them to size right first. The default avatar used while they’re loading or for Epic/Switch players is from Fandom, like the rank icons. However, even though the icon is 90x90 pixels, the webp is 128x128 pixels, it just has a bunch of transparent padding. So, I initially messed with egui to do some weird ui allocation and calculation to get it to render right. But, turns out I didn’t have to do all of that. All I had to do was allocate a 28x28 space (the target size), scale that up by the 128/90 ratio, then paint the image onto the new size. Worked great. Then, I got to fight with grid layouts again. For some reason, wrapping the avatar and player details in a horizontal totally exploded all the layouting. So, I ended up making avatar and details separate columns. But, since the “player” header text is a bit larger than the icon width, there was too much padding between the avatar and the player details. So, I did more messing around with egui manual layouting, and ended up allocating a 24x(body text height + 2) space for the header, which would give it the default spacing. Then, I’d copy the Rect, shift the left bound over by 12 pixels, then paint the header onto there. That way, the header is left aligned with the avatar and the avatar + details look like they’re in the same column, even though it’s actually a bunch of stupid manual layout magic behind the scenes."}, {"post_id": 55160, "ts": "2026-08-26T17:10:01Z", "hours": 2.6972, "text": "Made an avatars api for Steam, PSN, and Xbox (Epic doesn’t support profile pictures and I have no clue what goes on in Nintendo-land, even Tracker doesn’t show theirs). It’s on Cloudflare Workers instead of my pi since it’s basically just api integration. I totally overcomplicated finding out how to get Steam profile pictures. Like, it’s insane how easy it actually is. A few weeks ago, I got an old version of Steam Rocket League and decompiled it, trying to look for where it fetched avatars from. After some experimentation and debugging, I learned that when Psyonix builds Rocket League, they give it something that implements OnlineSubsystem for whatever the target platform is. So, Steam gets the Steamworks OnlineSubsystem, Epic gets the EOSOnlineSubsystem, and so forth. And the game doesn’t need to know implementation details, just that it implements OnlineSubsystem, I think the term for that is dynamic dispatch in programming languages. Anyways, once I learned that Rocket League doesn’t do any avatar handling itself, I looked at the Steamworks SDK. Basically, it routes the avatar request through the open Steam client. So after some experimentation, I got it to fetch profile pictures with C++ and the Spacewars test game. But, that obviously wouldn’t work on a server, since the Steam client can’t really run on a Worker. So, I tried to use the Steam Web API. I got an API key, but when I tried, it said I was forbidden. According to the documentation, the GetPlayerSummaries endpoint was at partner.steam-api.com, which was only for publishers. About a week later, so yesterday, I had the genius idea to use api.steampowered.com (the public API domain) instead of partner.steam-api.com. Just swapping them out. And it worked. So, I now had a way to get Steam avatar urls. Xbox and PSN were actually really easy. Xbox has an undocumented API at https://peoplehub-public.xboxlive.com/people/gt(GAMERTAG) which returns json containing the avatar uri, and I used the psn-api package with a new PlayStation account to get PSN profile pictures. Then, I just put all of them in a Worker. So, rlbuddy will be able to show avatars soon enough!"}, {"post_id": 54013, "ts": "2026-08-24T19:11:04Z", "hours": 4.6756, "text": "Recently I was going through game archives and came across the BepInEx tool, which is basically a code injection framework for Unity games. I was really curious as to how it actually launched when the game launched, and found that they use a tool called Unity Doorstop, which adds winhttp.dll to the game’s binary directory. So, when the game tries to use things from winhttp, it goes to the new winhttp.dll instead of the system32 winhttp.dll. From there, the custom dll just forwards all the function calls. However, the custom dll is modified so that on its first interaction, it launches whatever Doorstop is configured to launch, and the mods can be loaded. That’s at least as far as I understood, but it made sense, and I thought, “what if I could launch rlbuddy automatically like this?” So, first, I tried to test it with a custom executable and library. I created a basic executable and DLL in C, and got the executable to load and run some code from the DLL. Then, I created another DLL, and got it to “impersonate” the original DLL. So, I’d rename the first dll to something like “mylibrary_original.dll”, rename the faker dll to “mylibrary.dll”, and the original executable would call the original, but it goes through the faker instead. And it worked! I had successfully created an actual doorstop-like faker. Now it was time to actually try this on Rocket League. So, I did a dumpbin /import on RocketLeague.exe, and found a few good targets - IPHLPAPI.dll, a system dll for networking stuff, and xinput1_3.dll, one shipped with the game for talking to controllers. RocketLeague.exe only imported two functions from each of them, meaning my fake interface wouldn’t have to be too big. So, first I tried to spoof IPHLPAPI.dll. The code was pretty simple, just a couple of global objects to hold the function. So, when the game loaded the DLL, it loaded the fake DLL. Then, when it tried to call some function in the DLL, such as GetAdaptersAddresses, the fake DLL would be the actual receiver, it would log something to a file, and then it would call the REAL GetAdaptersAddresses by dynamically loading the system IPHLPAPI.dll and return it. And… it worked! I opened Rocket League and the log file was created and had the log “GetAdaptersAddresses called!” Then, I launched it with anticheat enabled, and EAC immediately shut it down. I guess that was to be expected, but it was pretty annoying. So, I decided to try one more time, this time with xinput1_3.dll. This was more interesting because it was lazy loaded, and functions were imported by ordinals (2 = XInputGetState, 3 = XInputSetState), so I thought something might be different. So, I modified the original faker to be xinput1_3, replacing the function names and definitions. Since Rocket League imported them by ordinal instead of just the function name, I had to create a .def file as well, and define the ordinals there. Then, I did the same surgery on the binary folder, and after a few small mistake fixes, it worked! But, I still hadn’t tried with EAC enabled. So I launched it with anticheat, and it gave me a different error this time - that it couldn’t determine xinput1_3.dll’s file version. That was a different error! I opened the original xinput1_3.dll’s file properties, and it had copyright, file version, product version, and a couple other random things that were missing in my faker DLL. So I made a .rc file and compiled it together with the faker DLL. Then, most of the properties matched up. So, I tried it, and it seemingly worked! And then EAC said that it couldn’t verify the file again. In the end, I didn’t manage to get it working. I should’ve expected EAC to block me from the beginning, but it was pretty fun, and if I ever want to do something similar with a game without anti-cheat, I can do that now! rlbuddy is pretty closed to being released though, I just want to polish a few things and make sure the docs are fleshed out."}, {"post_id": 51407, "ts": "2026-08-21T02:54:11Z", "hours": 1.5947, "text": "rlbuddy doesn’t use the default eframe persistence feature for savedata anymore, which is pretty cool. There were a few reasons for this: It was kind of unnecessary, since eframe uses ron and it was storing a bunch of extra widget data which didn’t really fit with the app model anyway It took up extra dependencies (removing the feature shaved off like 10) There’s a bug where if the app crashed, it would erase all savedata, which, as you can imagine, was quite annoying especially since I actually use the app along with developing it, meaning if the app crashed in development it would delete all my actual match data. It’s easier to externally modify, so if in development I want to mess with some values it’s a lot easier. Anyways, actually getting the data directory was pretty interesting. I’ve basically decided to only support Windows, since the music player relies on Windows APIs anyways and I don’t think the Stats API even works on Linux. Initially, I checked out the source code for the dirs and directories crates, which led me to the dirs-sys crate (which actually isn’t even on crates.io). It used unsafe raw Win32 SHGetKnownFolderPath with the Roaming folder guid. However, since I was already using the windows-rs crate, I tried to find the WinRT equivalent. I ended up enabling the Storage_Search feature to use the API which would let me get it. Of course, this also didn’t work, because of something to do with how Windows apps are supposed to be registered. So, I ended up just grabbing the APPDATA environment variable and using that, then joining rlbuddy\\data.json to it. It’s pretty underwhelming, but it more than gets the job done. Now, whenever the app panics, I won’t lose all of my settings anymore! Pretty nice. Anyways, that’s what mainly got accomplished. I also tried to set up a GitHub Action to build it and make a release, but I kept hitting errors so I gave up and decided to upload a release next time I get the urge to actually update the GitHub repository. There’s also a few fixes, like the window title which has actually had a typo since refactors from around a month ago, and adding a missing ! which broke toasts when in training. Overall, only an hour or so was tracked, but a heck of a lot got done. See you all next time!"}, {"post_id": 49990, "ts": "2026-08-19T00:44:44Z", "hours": 1.4564, "text": "I added a small toast notification that activates when you score in training, like bakkesmod used to add it to text chat. It also activates when you hit the crossbar so you can feel even more remorseful that your beautiful musty didn’t go in :) I actually got the program to segfault while making it. egui’s external viewport api is kinda funky… there are two modes, immediate and deferred, and immediate is supposed to be easier to use. However, when I tried to use immediate mode, it panicked saying that the egui backend was implemented incorrectly. So I switched to deferred, and it gave me the segfault. There were 3 things I had to do: I stored all active toasts in a Vec, and render them in the external viewport every frame. When one should disappear, it uses Vec::retain to remove old ones. However, this doesn’t do any cleanup, meaning the viewport would go bonkers and crash the application. So, I had to close the viewport first. Calling ui.ctx() from the viewport made a segfault, probably my fault but I couldn’t figure out how to resolve it so I ended up just sending Viewport::Close from the main loop. Even if I sent Viewport::Close from the main loop, it still gave the weird error. So, I resolved it by adding a small delay from after it should close, which is when it sends the Viewport::Close command, and when it’s actually removed from the Vec of toasts. Well, I did all that, and it was working, but there was a really weird bug where it would lag the whole system while opening/closing. So, I switched from immediate to deferred viewport mode, and it stopped happening! I hit my first powerful airdribble musty with it on, it was around 105kph, and a total fluke. I wish I had gotten it on recording."}, {"post_id": 49200, "ts": "2026-08-17T21:06:45Z", "hours": 9.2278, "text": "I replaced the Spotify integration with a generic one that uses the Windows GSMTC api, meaning it’s way snappier, since it’s not making network requests every time it wants new data! The only reason it needs data is to fetch playback info, and it’s easy to do that since the windows crate gives a bunch of event listeners, meaning I also don’t need to poll anymore. Unfortunately, the integration from browsers etc. is kind of buggy so thumbnail loading is relatively inconsistent, but by adding some caching and timeouts it works flawlessly :) I also redid the UI since the old one was frankly quite ugly. Since the playback listener doesn’t update that frequently for progressbar changes, I also made it fake progress when music is playing and the ui updates, that way even if the latest data is stale, it still looks like the progress bar is moving. I’m now working on better session stats, I’ll probably end up replacing the all-time stat tracker with more in-depth session-only ones"}, {"post_id": 46652, "ts": "2026-08-14T02:03:01Z", "hours": 4.1664, "text": "rlbuddy finally has an MMR graph! I’m planning on adding more stat displays soon, like W/L, goals for/against, saves, etc. but this is a really big milestone since it’s a feature that a lot of players actually use (I basically only play casual so it’s not really for me 😅). Anyways, this also required me to rearchitect how matches are stored, and now there are two representations: a session match, which contains lots of information about it like detailed player skill information, and a stripped match, which is minimal and stores very little because it actually gets saved to disk! So, match history also gets saved now! This also opens up the doorway to a Deja-Vu-like thing which tells you if you’ve played with someone before and when! It uses the egui_plot library to show the graph. Funnily enough, basically every default option for a displayed plot was the opposite for this, and so the plot builder ended up using almost every method. Also, once again, hackatime is wrong because Zed likes to uninstall extensions randomly :("}, {"post_id": 42417, "ts": "2026-08-07T03:32:05Z", "hours": 2.1161, "text": "The Stats API finally provides the actual playlist id, so rlbuddy isn’t limited to guessing between 1v1/2v2/3v3/4v4 anymore! This brings in some cool extra features like displaying the rank each player is in for the given playlist as well as even better Discord presence! I looked through BakkesMod as well as some psynet endpoints to grab the list of playlist ids to associate with each actual playlist. There isn’t really an image to go with this, so here’s the monster enum of playlists :)"}, {"post_id": 40468, "ts": "2026-08-04T00:47:59Z", "hours": 2.2011, "text": "I rewrote the API admin page with Svelte! Before, it was a quick-and-dirty raw html/css/js solution, but now it should be a lot less annoying to work on. I improved authorization a lot, now instead of adding the pw query parameter for every request you put in a password once and it actually uses the Authorization header. Unfortunately, the browser EventSource doesn’t support headers except for in cookies, meaning I had to use the custom eventsource library for bootstrapping since the bootstrap API uses SSE. There’s basically a whole Vite project in src/webadmin, with its own tsconfig.json and everything. Because of the way it’s set up, development needs Vite running in build watch mode which builds to where the main app serves it out of. It makes deployment a lot easier, though. I didn’t really add any actual features to it, except for a log filter. However, it should be way easier to add more features in the future, like a api tester!"}, {"post_id": 38450, "ts": "2026-07-31T20:22:49Z", "hours": 6.755, "text": "rlbuddy has player lookup now, so you can check for smurfs without needing to boot up a heavy browser while playing. Unfortunately, this has to get its information from TRN because it’s the only source of this information, the rocket league apis don’t provide it. There’s some cool refactors behind the scenes, though. I generalized almost all HTTP requests into its own struct, so it removed like 200 lines of boilerplate code into a single generic module. It automatically handles caching, using new threads, ignoring if there’s already an inflight request, loading states, and automatic serde_json deserialization. The Epic id, uncensorer, ranks, and new TRN apis all use it now! Also, the button to open in TRN from the player list opens the player info dialog instead (though if you need to, you can open in TRN from there)."}, {"post_id": 34762, "ts": "2026-07-25T19:02:58Z", "hours": 1.9536, "text": "Note: I’ve actually had way more hours than it says, but I reinstalled windows and forgot to set up hackatime again so all that’s gone :( mmr-api-v2 finally has an admin page, so I don’t have to ssh into my pi just to check some debug information anymore! It is kind of developer-oriented but I think it looks and works well enough for what it is for. In the actual rlbuddy app, there are some cool new features! Facilitated by lots of refactors, of course (turns out, the matches service was bigger than the actual rocket league service, so I finally separated them). Spotify integration now has a previous button as well as a skip-to-song-in-current-playlist button. Match history was a feature that I’ve kind of ignored, so I gave it a much needed touch-up so its easier to view and browse. A pretty cool thing is that that’s been added a rocket-league-playerid-to-epic-games-id translation endpoint. This means that you can see Switch players’ TRN profiles through their linked Epic account, since TRN doesn’t let you check based on Switch name alone. Finally, there are some small quality of life improvements, like less deadlocks, better anthem pausing, and the open panel list persisting."}, {"post_id": 30390, "ts": "2026-07-17T21:27:26Z", "hours": 3.8292, "text": "Turns out, for spotify integration, I can’t actually let other people use my spotify development mode app. It’s limited to 5 users which I have to invite by email. And to get a quota extension, I need 250,000 existing monthy active users, which I’m slightly short of (by about 249,999). So, I changed the login flow so that each user has to make their own Spotify app, and log in using the client ID from there. I didn’t change the current PKCE flow since that didn’t really need to be changed, but setup unfortunately takes a little more work now. Also, it has transparency now."}, {"post_id": 28659, "ts": "2026-07-15T01:29:51Z", "hours": 13.4597, "text": "It’s been a week since the last devlog, and lots has changed! 1. new architecture! The code was getting pretty messy since I had kept adding new features without really doing major refactors. So, I finally took it upon myself to actually organize everything and come up with a proper architecture. Each feature has its own module, containing services and widgets. Services have all the state, for example the Spotify service stores the current song and settings and the Rocket League module exposes a Matches service for the current match and past matches, which the match and past match widgets actually show. Services all have update functions which get called every 10ms. There are two ways for services to talk to the rest of the app: events and state. State is straightforward, it’s usually just an Rc with a custom generic struct I made to manage whether the widget can read/write to it. Events are enums which the update method returns, and can get passed to other update methods. For example, the Stats API service doesn’t have its own widget, it only connects to the stats api and returns match events which other features can use, like Spotify using replay start/end events to play/pause music. 2. new ui! The dashboard part isn’t as ugly as it was before, and has actual cards for every panel instead of just having horizontal lines in between. Even though it sounds pretty small, it’s actually huge for the prettiness of the app! Along with this, the behaviour of managing panels also changed. There’s an actual close button, and instead of having one button per panel at the bottom, there’s a small picker to open/close them. Also, you can also move them up and down now 3. Automatic stats api setup This is a pretty small feature. It lets you select the path to the rocket league executable, detects whether it’s already enabled, and turns it on if it’s disabled. It does this by just replacing a line in the stats api configuration. 4. mmr api v2 doesnt explode There were a few bugs which would make the API disconnect randomly, but they’ve been ironed out. This also made it so the app doesn’t have to deal with failure behaviour and can just keep asking until the API responds."}, {"post_id": 23975, "ts": "2026-07-07T06:51:05Z", "hours": 8.1119, "text": "rlbuddy now has a little bit of Spotify support! Although it looks like a just few elements and a button, theres a lot going on behind the scenes. I’m not embedding an entire webview to run the web playback SDK this time, so it just uses the Web API to keep resource usage nice and low. Since it’s a native app, it has to jump through some hurdles to authorize, using the PKCE extension version since the client secret can’t be stored securely. It uses the webbrowser crate to open the Spotify auth page, and starts a tiny little oneshot HTTP server on a raw TCPListener. The redirect is set to the HTTP server, and then as soon as it receives the request, it sends a simple HTML page and continues. From there, it receives the authorization code and can continue as normal :) Other than that, it’s just normal REST api interaction. I did learn a ton about thread safety (I hit so many deadlocks), because unlike the stats api, for example, which just sits in a different thread and hurls events over a channel, it actually has to work with the user. It’s also able to pause during goal replays, and that was pretty annoying to structure. Eventually, I decided to just use a channel where the stats api could send replay start/end events through the match widget. Looking back on it, the solution was extremely simple 😅 I am planning to add a bit more, like shuffle/repeat controls as well as a previous track button, but this feature turned out pretty nicely!"}, {"post_id": 22551, "ts": "2026-07-05T02:19:55Z", "hours": 3.7678, "text": "rlbuddy can now show Rich Presence in Discord, so now all your friends can see you destroying your opponents ;)"}, {"post_id": 21165, "ts": "2026-07-02T23:37:22Z", "hours": 12.7792, "text": "rlbuddy has had major ui overhauls to shift it more towards an actual overlay rather than just an app that displays ranks. there are new features like a settings menu as well as major architectural overhauls, with more coming soon!"}, {"post_id": 16053, "ts": "2026-06-26T02:45:17Z", "hours": 2.3483, "text": "Got it working as an actual overlay!! Right now it just displays ranks, though"}, {"post_id": 15855, "ts": "2026-06-25T19:39:34Z", "hours": 30.4556, "text": "I got a stable MMR/ranks api working!! https://github.com/Kalilamodow/mmr-api-v2 Basically, it’s an http server that opens a websocket to the actual rocket league game api in the background and spoofs a real client connection. The socket only stays active for 5 seconds at a time though so I don’t kill psyonix’s servers. That way, rlbuddy can get ranks without getting blocked by tracker network! I originally tried to do it on Cloudflare, but the workers outbound websocket didn’t work since you can’t send custom headers with them. I ended up having to use my old raspberry pi and set up a homeserver behind Cloudflare tunnels, and I’m actually planning on moving the rest of my stuff that used to be on a VPS onto the pi."}]...
|
Title: rlbuddy by @kmdw | Stardance
Devlogs:
I go Title: rlbuddy by @kmdw | Stardance
Devlogs:
I got a stable MMR/ranks api working!! https://github.com/Kalilamodow/mmr-api-v2 Basically, it’s an http server that opens a websocket to the actual rocket league game api in the background and spoofs a real client connection. The socket only stays active for 5 seconds at a time though so I don’t kill psyonix’s servers. That way, rlbuddy can get ranks without getting blocked by tracker network! I originally tried to do it on Cloudflare, but the workers outbound websocket didn’t work since you can’t send custom headers with them. I ended up having to use my old raspberry pi and set up a homeserver behind Cloudflare tunnels, and I’m actually planning on moving the rest of my stuff that used to be on a VPS onto the pi.
Got it working as an actual overlay!! Right now it just displays ranks, though
rlbuddy has had major ui overhauls to shift it more towards an actual overlay rather than just an app that displays ranks. there are new features like a settings menu as well as major architectural overhauls, with more coming soon!
rlbuddy can now show Rich Presence in Discord, so now all your friends can see you destroying your opponents ;)
rlbuddy now has a little bit of Spotify support! Although it looks like a just few elements and a button, theres a lot going on behind the scenes. I’m not embedding an entire webview to run the web playback SDK this time, so it just uses the Web API to keep resource usage nice and low. Since it’s a native app, it has to jump through some hurdles to authorize, using the PKCE extension version since the client secret can’t be stored securely. It uses the webbrowser crate to open the Spotify auth page, and starts a tiny little oneshot HTTP server on a raw TCPListener. The redirect is set to the HTTP server, and then as soon as it receives the request, it sends a simple HTML page and continues. From there, it receives the authorization code and can continue as normal :) Other than that, it’s just normal REST api interaction. I did learn a ton about thread safety (I hit so many deadlocks), because unlike the stats api, for example, which just sits in a different thread and hurls events over a channel, it actually has to work with the user. It’s also able to pause during goal replays, and that was pretty annoying to structure. Eventually, I decided to just use a channel where the stats api could send replay start/end events through the match widget. Looking back on it, the solution was extremely simple 😅 I am planning to add a bit more, like shuffle/repeat controls as well as a previous track button, but this feature turned out pretty nicely!
It’s been a week since the last devlog, and lots has changed! 1. new architecture! The code was getting pretty messy since I had kept adding new features without really doing major refactors. So, I finally took it upon myself to actually organize everything and come up with a proper architecture. Each feature has its own module, containing services and widgets. Services have all the state, for example the Spotify service stores the current song and settings and the Rocket League module exposes a Matches service for the current match and past matches, which the match and past match widgets actually show. Services all have update functions which get called every 10ms. There are two ways for services to talk to the rest of the app: events and state. State is straightforward, it’s usually just an Rc with a custom generic struct I made to manage whether the widget can read/write to it. Events are enums which the update method returns, and can get passed to other update methods. For example, the Stats API service doesn’t have its own widget, it only connects to the stats api and returns match events which other features can use, like Spotify using replay start/end events to play/pause music. 2. new ui! The dashboard part isn’t as ugly as it was before, and has actual cards for every panel instead of just having horizontal lines in between. Even though it sounds pretty small, it’s actually huge for the prettiness of the app! Along with this, the behaviour of managing panels also changed. There’s an actual close button, and instead of having one button per panel at the bottom, there’s a small picker to open/close them. Also, you can also move them up and down now 3. Automatic stats api setup This is a pretty small feature. It lets you select the path to the rocket league executable, detects whether it’s already enabled, and turns it on if it’s disabled. It does this by just replacing a line in the stats api configuration. 4. mmr api v2 doesnt explode There were a few bugs which would make the API disconnect randomly, but they’ve been ironed out. This also made it so the app doesn’t have to deal with failure behaviour and can just keep asking until the API responds.
Turns out, for spotify integration, I can’t actually let other people use my spotify development mode app. It’s limited to 5 users which I have to invite by email. And to get a quota extension, I need 250,000 existing monthy active users, which I’m slightly short of (by about 249,999). So, I changed the login flow so that each user has to make their own Spotify app, and log in using the client ID from there. I didn’t change the current PKCE flow since that didn’t really need to be changed, but setup unfortunately takes a little more work now. Also, it has transparency now.
Note: I’ve actually had way more hours than it says, but I reinstalled windows and forgot to set up hackatime again so all that’s gone :( mmr-api-v2 finally has an admin page, so I don’t have to ssh into my pi just to check some debug information anymore! It is kind of developer-oriented but I think it looks and works well enough for what it is for. In the actual rlbuddy app, there are some cool new features! Facilitated by lots of refactors, of course (turns out, the matches service was bigger than the actual rocket league service, so I finally separated them). Spotify integration now has a previous button as well as a skip-to-song-in-current-playlist button. Match history was a feature that I’ve kind of ignored, so I gave it a much needed touch-up so its easier to view and browse. A pretty cool thing is that that’s been added a rocket-league-playerid-to-epic-games-id translation endpoint. This means that you can see Switch players’ TRN profiles through their linked Epic account, since TRN doesn’t let you check based on Switch name alone. Finally, there are some small quality of life improvements, like less deadlocks, better anthem pausing, and the open panel list persisting.
rlbuddy has player lookup now, so you can check for smurfs without needing to boot up a heavy browser while playing. Unfortunately, this has to get its information from TRN because it’s the only source of this information, the rocket league apis don’t provide it. There’s some cool refactors behind the scenes, though. I generalized almost all HTTP requests into its own struct, so it removed like 200 lines of boilerplate code into a single generic module. It automatically handles caching, using new threads, ignoring if there’s already an inflight request, loading states, and automatic serde_json deserialization. The Epic id, uncensorer, ranks, and new TRN apis all use it now! Also, the button to open in TRN from the player list opens the player info dialog instead (though if you need to, you can open in TRN from there).
I rewrote the API admin page with Svelte! Before, it was a quick-and-dirty raw html/css/js solution, but now it should be a lot less annoying to work on. I improved authorization a lot, now instead of adding the pw query parameter for every request you put in a password once and it actually uses the Authorization header. Unfortunately, the browser EventSource doesn’t support headers except for in cookies, meaning I had to use the custom eventsource library for bootstrapping since the bootstrap API uses SSE. There’s basically a whole Vite project in src/webadmin, with its own tsconfig.json and everything. Because of the way it’s set up, development needs Vite running in build watch mode which builds to where the main app serves it out of. It makes deployment a lot easier, though. I didn’t really add any actual features to it, except for a log filter. However, it should be way easier to add more features in the future, like a api tester!
The Stats API finally provides the actual playlist id, so rlbuddy isn’t limited to guessing between 1v1/2v2/3v3/4v4 anymore! This brings in some cool extra features like displaying the rank each player is in for the given playlist as well as even better Discord presence! I looked through BakkesMod as well as some psynet endpoints to grab the list of playlist ids to associate with each actual playlist. There isn’t really an image to go with this, so here’s the monster enum of playlists :)
rlbuddy finally has an MMR graph! I’m planning on adding more stat displays soon, like W/L, goals for/against, saves, etc. but this is a really big milestone since it’s a feature that a lot of players actually use (I basically only play casual so it’s not really for me 😅). Anyways, this also required me to rearchitect how matches are stored, and now there are two representations: a session match, which contains lots of information about it like detailed player skill information, and a stripped match, which is minimal and stores very little because it actually gets saved to disk! So, match history also gets saved now! This also opens up the doorway to a Deja-Vu-like thing which tells you if you’ve played with someone before and when! It uses the egui_plot library to show the graph. Funnily enough, basically every default option for a displayed plot was the opposite for this, and so the plot builder ended up using almost every method. Also, once again, hackatime is wrong because Zed likes to uninstall extensions randomly :(
I replaced the Spotify integration with a generic one that uses the Windows GSMTC api, meaning it’s way snappier, since it’s not making network requests every time it wants new data! The only reason it needs data is to fetch playback info, and it’s easy to do that since the windows crate gives a bunch of event listeners, meaning I also don’t need to poll anymore. Unfortunately, the integration from browsers etc. is kind of buggy so thumbnail loading is relatively inconsistent, but by adding some caching and timeouts it works flawlessly :) I also redid the UI since the old one was frankly quite ugly. Since the playback listener doesn’t update that frequently for progressbar changes, I also made it fake progress when music is playing and the ui updates, that way even if the latest data is stale, it still looks like the progress bar is moving. I’m now working on better session stats, I’ll probably end up replacing the all-time stat tracker with more in-depth session-only ones
I added a small toast notification that activates when you score in training, like bakkesmod used to add it to text chat. It also activates when you hit the crossbar so you can feel even more remorseful that your beautiful musty didn’t go in :) I actually got the program to segfault while making it. egui’s external viewport api is kinda funky… there are two modes, immediate and deferred, and immediate is supposed to be easier to use. However, when I tried to use immediate mode, it panicked saying that the egui backend was implemented incorrectly. So I switched to deferred, and it gave me the segfault. There were 3 things I had to do: I stored all active toasts in a Vec, and render them in the external viewport every frame. When one should disappear, it uses Vec::retain to remove old ones. However, this doesn’t do any cleanup, meaning the viewport would go bonkers and crash the application. So, I had to close the viewport first. Calling ui.ctx() from the viewport made a segfault, probably my fault but I couldn’t figure out how to resolve it so I ended up just sending Viewport::Close from the main loop. Even if I sent Viewport::Close from the main loop, it still gave the weird error. So, I resolved it by adding a small delay from after it should close, which is when it sends the Viewport::Close command, and when it’s actually removed from the Vec of toasts. Well, I did all that, and it was working, but there was a really weird bug where it would lag the whole system while opening/closing. So, I switched from immediate to deferred viewport mode, and it stopped happening! I hit my first powerful airdribble musty with it on, it was around 105kph, and a total fluke. I wish I had gotten it on recording.
rlbuddy doesn’t use the default eframe persistence feature for savedata anymore, which is pretty cool. There were a few reasons for this: It was kind of unnecessary, since eframe uses ron and it was storing a bunch of extra widget data which didn’t really fit with the app model anyway It took up extra dependencies (removing the feature shaved off like 10) There’s a bug where if the app crashed, it would erase all savedata, which, as you can imagine, was quite annoying especially since I actually use the app along with developing it, meaning if the app crashed in development it would delete all my actual match data. It’s easier to externally modify, so if in development I want to mess with some values it’s a lot easier. Anyways, actually getting the data directory was pretty interesting. I’ve basically decided to only support Windows, since the music player relies on Windows APIs anyways and I don’t think the Stats API even works on Linux. Initially, I checked out the source code for the dirs and directories crates, which led me to the dirs-sys crate (which actually isn’t even on crates.io). It used unsafe raw Win32 SHGetKnownFolderPath with the Roaming folder guid. However, since I was already using the windows-rs crate, I tried to find the WinRT equivalent. I ended up enabling the Storage_Search feature to use the API which would let me get it. Of course, this also didn’t work, because of something to do with how Windows apps are supposed to be registered. So, I ended up just grabbing the APPDATA environment variable and using that, then joining rlbuddy\data.json to it. It’s pretty underwhelming, but it more than gets the job done. Now, whenever the app panics, I won’t lose all of my settings anymore! Pretty nice. Anyways, that’s what mainly got accomplished. I also tried to set up a GitHub Action to build it and make a release, but I kept hitting errors so I gave up and decided to upload a release next time I get the urge to actually update the GitHub repository. There’s also a few fixes, like the window title which has actually had a typo since refactors from around a month ago, and adding a missing ! which broke toasts when in training. Overall, only an hour or so was tracked, but a heck of a lot got done. See you all next time!
Recently I was going through game archives and came across the BepInEx tool, which is basically a code injection framework for Unity games. I was really curious as to how it actually launched when the game launched, and found that they use a tool called Unity Doorstop, which adds winhttp.dll to the game’s binary directory. So, when the game tries to use things from winhttp, it goes to the new winhttp.dll instead of the system32 winhttp.dll. From there, the custom dll just forwards all the function calls. However, the custom dll is modified so that on its first interaction, it launches whatever Doorstop is configured to launch, and the mods can be loaded. That’s at least as far as I understood, but it made sense, and I thought, “what if I could launch rlbuddy automatically like this?” So, first, I tried to test it with a custom executable and library. I created a basic executable and DLL in C, and got the executable to load and run some code from the DLL. Then, I created another DLL, and got it to “impersonate” the original DLL. So, I’d rename the first dll to something like “mylibrary_original.dll”, rename the faker dll to “mylibrary.dll”, and the original executable would call the original, but it goes through the faker instead. And it worked! I had successfully created an actual doorstop-like faker. Now it was time to actually try this on Rocket League. So, I did a dumpbin /import on RocketLeague.exe, and found a few good targets - IPHLPAPI.dll, a system dll for networking stuff, and xinput1_3.dll, one shipped with the game for talking to controllers. RocketLeague.exe only imported two functions from each of them, meaning my fake interface wouldn’t have to be too big. So, first I tried to spoof IPHLPAPI.dll. The code was pretty simple, just a couple of global objects to hold the function. So, when the game loaded the DLL, it loaded the fake DLL. Then, when it tried to call some function in the DLL, such as GetAdaptersAddresses, the fake DLL would be the actual receiver, it would log something to a file, and then it would call the REAL GetAdaptersAddresses by dynamically loading the system IPHLPAPI.dll and return it. And… it worked! I opened Rocket League and the log file was created and had the log “GetAdaptersAddresses called!” Then, I launched it with anticheat enabled, and EAC immediately shut it down. I guess that was to be expected, but it was pretty annoying. So, I decided to try one more time, this time with xinput1_3.dll. This was more interesting because it was lazy loaded, and functions were imported by ordinals (2 = XInputGetState, 3 = XInputSetState), so I thought something might be different. So, I modified the original faker to be xinput1_3, replacing the function names and definitions. Since Rocket League imported them by ordinal instead of just the function name, I had to create a .def file as well, and define the ordinals there. Then, I did the same surgery on the binary folder, and after a few small mistake fixes, it worked! But, I still hadn’t tried with EAC enabled. So I launched it with anticheat, and it gave me a different error this time - that it couldn’t determine xinput1_3.dll’s file version. That was a different error! I opened the original xinput1_3.dll’s file properties, and it had copyright, file version, product version, and a couple other random things that were missing in my faker DLL. So I made a .rc file and compiled it together with the faker DLL. Then, most of the properties matched up. So, I tried it, and it seemingly worked! And then EAC said that it couldn’t verify the file again. In the end, I didn’t manage to get it working. I should’ve expected EAC to block me from the beginning, but it was pretty fun, and if I ever want to do something similar with a game without anti-cheat, I can do that now! rlbuddy is pretty closed to being released though, I just want to polish a few things and make sure the docs are fleshed out.
Made an avatars api for Steam, PSN, and Xbox (Epic doesn’t support profile pictures and I have no clue what goes on in Nintendo-land, even Tracker doesn’t show theirs). It’s on Cloudflare Workers instead of my pi since it’s basically just api integration. I totally overcomplicated finding out how to get Steam profile pictures. Like, it’s insane how easy it actually is. A few weeks ago, I got an old version of Steam Rocket League and decompiled it, trying to look for where it fetched avatars from. After some experimentation and debugging, I learned that when Psyonix builds Rocket League, they give it something that implements OnlineSubsystem for whatever the target platform is. So, Steam gets the Steamworks OnlineSubsystem, Epic gets the EOSOnlineSubsystem, and so forth. And the game doesn’t need to know implementation details, just that it implements OnlineSubsystem, I think the term for that is dynamic dispatch in programming languages. Anyways, once I learned that Rocket League doesn’t do any avatar handling itself, I looked at the Steamworks SDK. Basically, it routes the avatar request through the open Steam client. So after some experimentation, I got it to fetch profile pictures with C++ and the Spacewars test game. But, that obviously wouldn’t work on a server, since the Steam client can’t really run on a Worker. So, I tried to use the Steam Web API. I got an API key, but when I tried, it said I was forbidden. According to the documentation, the GetPlayerSummaries endpoint was at partner.steam-api.com, which was only for publishers. About a week later, so yesterday, I had the genius idea to use api.steampowered.com (the public API domain) instead of partner.steam-api.com. Just swapping them out. And it worked. So, I now had a way to get Steam avatar urls. Xbox and PSN were actually really easy. Xbox has an undocumented API at https://peoplehub-public.xboxlive.com/people/gt(GAMERTAG) which returns json containing the avatar uri, and I used the psn-api package with a new PlayStation account to get PSN profile pictures. Then, I just put all of them in a Worker. So, rlbuddy will be able to show avatars soon enough!
rlbuddy now can show people’s avatars cross-platform! It uses a web api I put on Cloudflare Workers which uses platform-specific requests to get avatar urls (see the previous devlog), which the app just fetches and renders. The http part was pretty easy, since I already have wrappers for cached HTTP apis, so I just had to define types for that and hook it up. But, once it was time to display, I ran into a weird problem where egui said there was no image loader installed for jpegs! Even using all_loaders + default didn’t work. Turns out, I have to actually include image as a separate crate and enable all the filetype features I want in there. Once I got it to load, it was time to mess with styling again. egui is really annoying with images, so I spent a while trying to get them to size right first. The default avatar used while they’re loading or for Epic/Switch players is from Fandom, like the rank icons. However, even though the icon is 90x90 pixels, the webp is 128x128 pixels, it just has a bunch of transparent padding. So, I initially messed with egui to do some weird ui allocation and calculation to get it to render right. But, turns out I didn’t have to do all of that. All I had to do was allocate a 28x28 space (the target size), scale that up by the 128/90 ratio, then paint the image onto the new size. Worked great. Then, I got to fight with grid layouts again. For some reason, wrapping the avatar and player details in a horizontal totally exploded all the layouting. So, I ended up making avatar and details separate columns. But, since the “player” header text is a bit larger than the icon width, there was too much padding between the avatar and the player details. So, I did more messing around with egui manual layouting, and ended up allocating a 24x(body text height + 2) space for the header, which would give it the default spacing. Then, I’d copy the Rect, shift the left bound over by 12 pixels, then paint the header onto there. That way, the header is left aligned with the avatar and the avatar + details look like they’re in the same column, even though it’s actually a bunch of stupid manual layout magic behind the scenes.
rlbuddy can load custom maps now! Either you can download them and then import from a zip, or you can download them from bakkesplugins straight from the app! Importing it from a file is relatively easy. I checked the code for Lethamyr’s custom map loader to see what exactly it did, and for Lethamyr maps it: extracted the zip into a temp dir read info.json, .udk, and preview.jpg copied those into its own saved map directory I knew Rust, being a low-level language would let me not have to extract the zip fully first. Additionally, Bakkesplugins maps don’t contain info.json or preview.jpg, they only contain a udk file, so I had to make sure it would work with that. So, the import code I wrote basically: enumerates files in the zip extracts info.json (if found) into a struct copies *.upk into the target directory copies *.jpg into the target directory/preview.jpg if it exists It worked great. I made a really cool looking widget with stupid manual layouting behind it for map selection. First, it would add the preview image (or a black background if none). Then, it would get the screen rect of the image, and draw a semitransparent black background onto it (for contrast). Finally, it drew the actual contents in that screen rect. So, I got pretty-looking tiles with preview image backgrounds! I also added a progress bar for import status. I benchmarked each main part of the import process and found that decompressing/extracting the upk file took around 2 seconds, for which the ui thread would be totally frozen (big nono)! So, I moved the work onto another thread, and also made it decompress/load in 100 total chunks, updating a progress bar each time. I then moved on to the map downloader. Bakkesplugins doesn’t have an API, so it relies on scraping the website. I didn’t actually use any external crates for gathering information, though. I wrote a parser which takes a list of rules, each with a start and end search string, and looks for each of them in sequence till it fails to find a rule. I tried to make it completely zero-copy, but something it needed was to turn an [Option; N] into a Option<[T; N]> if every element was Some , but the only way I could figure out how to do that was with an iterator. It’s still really fast though. So, it parses search results, including map titles and urls straight out of the html string without needing an HTML parser or regex library. Once it was able to load results from the search page, I went to sleep and came back today. Now I had to get it to actually download the ZIP files and preview images, and import them straight into the app. It first has to download/parse the plugin info page since the ZIP url isn’t available in the search results. Then, it requests the ZIP. I had some trouble with this, since I wanted to show a progress bar for the download status. I first tried a function from this gist , but it didn’t work. So, I made my own which used the same chunking strategy as the import status loader. Turns out, ureq blocks requests once they hit 10MB by default, which was probably why the gist version didn’t work. But, mine was faster anyways, so I kept it. It’s even cooler since I made it myself. Then, I wired up a couple more commands to let it import straight from archive bytes instead of from a file path, and it finally loaded! Once that worked, I made it pass along the map title, author, and description as well. Then, I extended it to parse out the thumbnail image url and download that, then pass that along to the importer as well. Anyways, that was super fun. I would add a lot more detail, but Stardance limits devlogs to 4000 characters and I’m approaching scarily close to that. I’m planning on just polishing the downloader interface a bit more, and then I’ll do some bugfixes for the next release. See ya!
I moved the mmr server to alpine linux! Before, it was regular raspberry pi os lite on the Pi. But, it was behaving strangely, randomly rebooting and things, so I decided to try installing Alpine. The lightweight distro has been on my radar for a while now, but this was my first time ever actually trying it. I imaged it normally with the raspberry pi imager, and put it on the pi, did setup-alpine, and all was well. But, I put in the wrong wifi password at first, which broke everything else. I tried changing the wifi config and doing something with wpa_supplicant (thanks google ai overview), but nothing fixed it so I ended up doing a fresh install. This time, I put in the right password and everything went great. I set up ssh, node, pm2, etc. and moved the server files onto the pi through sftp. Then, I got it running over my local network and set up authentication. So, it was time to set up the Cloudflare tunnel again. I followed this neat guide , changing values as needed (for example, my pi is aarch64, but the guide was x64, so I spent a while figuring out why the pi kept giving elf errors). It took a really long time to set up the openrc startup script because 1. cloudflare rotates the setup token relatively frequently and 2. I accidentally put 2 –token arguments. And since I was using vi, I didn’t even notice and kept trying to figure out why cloudflared crashed on startup. But I eventually found out and removed the duplicate and it worked! Then I finished setting up pm2 and put the pi in its home next to the router, and mmr.kmdw.dev is back up exposing your lobby’s skills. See you in the next one! Yes I know part of the token is in the image but it’s used already so it doesn’t matter
rlbuddy has a gamepad overlay now so that you can show off your awesome bindings! Don’t even bother figuring out mine. It’s kinda starting to become hellish to add new widgets/services, but I’m almost done for the next ship so I doubt I’ll refactor just yet [edit: im doing a super refactor now hehe]. I made the overlay with the raw egui::Painter rather than actual controls (since it would be pretty hard to make a controller out of Buttons or something). I also prefer to avoid embedding static assets, otherwise I might have made an actual one in MS Paint or something. I also can’t seem to find a good egui version. I’ve been on 0.34 almost the whole time, which works well but doesn’t support transparency in extra viewports. But, 0.35/0.36 broke external viewports. So, until then, we get an opaque gamepad overlay :( but the main app is still transparent, so it’s not horrible. Rolled an 8 and a 9 on the Stardance rng today! I’m so proud of myself.
I’m MASSIVELY refactoring rlbuddy! This, I think is the second (and hopefully the final) major refactor to the codebase. So, basically the current architecture is split into services and widgets. Each service has an update method, which does its stuff (draining subscribers, processing commands, etc). Since egui is immediate mode, this architecture works unlike callbacks/event-based which I actually tried to implement but couldn’t. Every widget is just implements egui::Widget, that holds some state handles (Rc) and command senders (Sender), usually just one for its respective service. Services are alive for the lifetime of the app, while widgets are the openable panels you see. Widgets display the data from service state, and talk back to it by mutating shared state or sending commands. I think music control has been the best for me to wrap my head around to decide about changes, so I’ll explain it with that. Music control had a controller, a service, and a widget file. The controller was a thread pool manager (if you can call the questionable implementation that) around Windows’ GSMTC API to give a single-thread api for it (since the app is basically single-threaded). Then, the service is always alive, syncing a state struct between the controller and its own state handle. Finally, the widget is optionally there as a panel, with next/previous/pause buttons which send commands and the ui which reads service state to display. It also has a mutable service state reference for settings (the “pause during anthems” button). The god object RlbuddyApp struct stores all of this stuff. So it has a music_control_service, music_control_widget, stats_api_service, all of those fields, which kinda sucked. On top of that, I had to maintain an enum of every panel, which was enumerated for the “open panel” popup and to render each one if it’s open. you might think “hey… isn’t that a self referential struct? how does music_control_widget store a reference to music_control_service?” Well, music_control_widget internally only has fields for the music_control_service’s state handles which are Rc/Arcs. So it only needs a reference to the service for it’s Widget::new function lifetime, all is well. Although it doesn’t look horrible, it was HELL to do anything. For example, refactoring the gilrs service out of hotkey and adding the gamepad overlay probably involved just as much fiddling around with Rcs in RlbuddyApp as adding the actual feature. So, I decided to move to a new architecture: services + features! And, after thinking about it for around 8 hours (i slept), I decided on something a bit different. Services + panels! Yeah, basically the same as services + widgets, but I was gonna implement it GOOD this time, and make design decisions that wouldn’t bite me in the ass later on. I wrote my first traits - Service, which requires update and optionally save , and Panel , which requires name() -> &'static str and ui (same as egui::Widget: :ui). Then, I’d change how components are registered: instead of keeping every service and widget as a field in RlBuddyApp, I’d make a Vec<Box<dyn Service/Panel» for each, and loop through it. I spent about an hour trying to get Panels to automatically implement ui by requiring egui::Widget as a supertrait, which doesn’t work since widgets are stateful (need &self). So, I tried to require &mut Self to implement egui::Widget, but apparently something to do with type erasure doesn’t let that work with dynamic dispatch which was needed for the Vec<Box> thing. I’ve moved a few features to the new architecture, but I’m still in the process of finishing up. Additionally, it has to work side-by-side with existing crappy monster-Panel-enum architecture, which sucks to maintain. Okay, once again, I had to strip down a ton of detail (and my terrible wording but wtv) cause I hit like 5000 characters b4 realizing. See ya! May the Stardance gods increase devlog limits :)
I finished the big refactor! I pushed around 25 commits to GitHub at once. I’m really gonna enjoy adding the next feature, basking in how much easier it is ;) Apparently, I never made a service for session stats, so it currently can’t persist its one setting. Actually, writing this I realized that the setting isn’t actually used, so I can delete it. That’s great. After finally kicking out all the annoying legacy panel code, I remembered that I never re-implemented the positioning or its related persistence code for the new panel system. The persistence system was reworked too, something that I don’t think really got included in the previous devlog. Each service can implement save , and there are generic helper methods in a common module for saving/loading serde structs to a file in the app data directory. The actual app now uses this method as well instead of doing all the pathing logic itself, so the persistence module is pretty small and could honestly be moved into app.rs. For new positioning, I store a list of open panels. Weirdly enough, it’s actually a lot easier than adding a position/is_open field to every AppPanel. So, I run the name through a Hasher to make a u64 which is easier to clone/copy and stuff and made a newtype around a PanelId. That way I could reuse the code from the previous paneling system to swap/manage open PanelIds, then just use find on the AppPanel vec to find the corresponding widget. Also, I never mentioned it but I’ve been trying RustRover for the past few devlogs. It’s a lot more stable than Zed, but I sorta miss its snappiness and minimalism. If I end up finding an annoying bug in RustRover, I’ll probably switch back. However, it’s been quite a few days and I don’t think I’ve found a single one. JetBrains is truly awesome at tooling. See ya next time. Probably will do my next ship soon :)
Had to remove the tracker.gg widget :( unfortunately they don’t allow scraping and what I had wasn’t allowed anyways. Things that used to open the player info widget now just open tracker in a browser.
Time formatting doesn’t suck anymore! I made the implementation way better so I could make it support stuff even past weeks, like months and years. The new implementation added around 60 lines, but it’s for a good cause. The previous implementation used a match statement with duplicated logic that only supported seconds, minutes, and hours, using a pluralize function and inline if-statements everywhere. If it were sent to any rational code-reviewer, they would likely have a heart attack. Now it’s a bit more complex but less complicated. You have TimeUnit s which format the unit themselves and TimePart s which format a value + a unit. Then, just use some math to build a Vec and format it into a string. Boom! Beautiful, well-formed time formatting. To soak in the new beauty, I added days n weeks. I just had to add 14 lines! The previous one would have probably needed a bunch of stupid magic numbers and weird chains everywhere to accomplish the same thing. Okay, I’m done using your time on reading a way-too-long write-up about fixing a crappy implementation that shouldn’t have been there in the first place. I’m gonna ship right after posting this. If you get it, make sure to give it 10 stars in everything 😉. Haha, jk. Well, not really. Cya later.
I’ve mostly been working on smaller features, improvements, and bugfixes. A cool one I did is fixing weird glitchy movement with the gamepad overlay window! Basically, the window needs to persist its position across disabling it/enabling it. And egui is immediate mode. So, every time it rendered the viewport, it would both set and get its position. So, moving it would update the current position, but because of the weird interop between setting the position in a ViewportBuilder and getting it from the viewport info, it would glitch back and forth, especially when my laptop is lagging. I fixed it by only calling the ViewportBuilder ‘s “ with_position ” method when the overlay had just been enabled ( !was_enabled && currently_enabled ). That way, it only sets it once externally, and lets it move freely while it’s open. Then, while it’s moving, it continues to update the saved position. And upon closing and then reopening it, it sets it again (but only once!) Relatively simple fix but it’s kind of funny. I mainly noticed it when I added a feature that would auto-unmaximize the overlay when the user maximizes it, and it would go crazy and fly around the screen. Very fun! I also fixed a pretty old bug where it would incorrectly detect the local player. Basically, the stats api doesn’t actually tell you who the local player is. So, we have to guess based on who the camera is targeting right now. Usually, it’s on the local player, but during goal replays or spectating a bot when joining a casual game, it would be improperly set at the start and then stay like that. So, I made sure that it always updated as long as the match is 1. in progress 2. not in a replay. It also fixes a thing with inconsistent match toasts, since the toasts only fire if the scoring player is the local player (and if it thinks the wrong player is the local player, everything’s messed up). I’m planning on revamping hotkeys next, to allow you to bind to any controller button and even do custom quickchats in-game. Later!
More gamepad overlay buttons!!! Yay!!! In not-so-awesomely-exciting news, I also added a table of contents to the readme (as well as a generator for it). The script’s in Python (I’m sorry for not using Rust) meaning the repository is now 0.5% Python. Takeover incoming? I overcomplicated the script a lot, but it’s really easy to read. There are three whole comments, aka 6% of lines in the whole file! It’s not technically interesting in the slightest. I was thinking of building a tree-like structure before outputting the string, but realized I can just use the header level (h1 vs h2 vs h3 etc) as the amount of spaces / 2. I also refactored it not to use magic PanelId s for the default panel list. I kinda rushed that part when I made it, I’ll be honest. But now each Panel can implement fn open_by_default(&self) -> bool (returns false by default) and if it does it keeps it open when savedata doesn’t exist yet. I don’t get how an entire hour n 27 minutes was spent on like 7 not-even-that-big commits. At least it was a good use of my math class. We reviewed limits for some reason (which everyone should already know for one because they took the prereqs?), and the teacher managed to extend her lecture for the ENTIRE class time. rlbuddy development saving the day, I guess (just like it will in your rocket league games btw, so you should download it)
I’ve been debugging high memory for the past month or so. It was egui_system_fonts. Why would fonts take 170mb of ram????????????????????????????????? help!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! I hate external dependencies!!!!!!!!!!!!!!!!!!!!11 I owe my life to DHAT now. go star https://github.com/nnethercote/dhat-rs
I did lots of performance improvements and also IT WORKS ON LINUX NOW!!! Let’s talk about performance first. Anyways, it has been using around 4% and 220MB of ram, which isn’t really what you’d expect from an overlay! So, I used things like DHAT to profile the memory, and noticed that fonts were doing some shenanigans. So I removed egui_system_fonts and loaded directly from C:\Windows\Fonts\segoeui.ttf and RAM usage dropped to 30mb. That was what the previous devlog was about. I then changed the default logic update rate from 10ms (100/s) to 65ms (15/s approx). This reduced idle cpu usage to under 0.2%. But, doing anything with the UI would spike it to 4%, which is still pretty bad. So, I used a method I found in an egui issue thread where I’d count the frametime since the last render, then sleep until the target frametime was finished. For example, if the frame rendered in 2ms but I want 16ms frametime, it would sleep for 14ms. That way, I could limit how often the UI rendered! This made it stay under around 1% CPU forever! Okay, Linux time! Rust is mostly cross-platform, so support was mostly dealing with dumbass design decisions. Since Music relies on GSMTC, I had to feature-gate the entire thing (as well as the windows/windows-future crates) behind cfg(windows) :( I also had to fix Linux font loading (since like I said earlier, it’s hardcoded to segoe ui). So I install fontdb on Linux and search for some popular fonts from there to load instead. Finally, I fixed up the storage paths since it could only load from AppData. I also made it use AppData\Local vs. AppData\Roaming instead of putting everything in Roaming. I first got it working through WSL! ! It took some messing with my GPU drivers but I got it to render. Now was the real challenge: getting it to build on an ACTUAL Linux machine. I had an old, basically broken Surface Pro 3 that I had put Debian+GNOME on for shits and giggles a few months ago. The perfect target! The main problem was getting Rocket League to even launch. I set up Legendary (goated launcher btw, check it out ) and tried to run it. I installed Wine, got Wine Mono, and it failed with a weird cryptic error about the CreateWindow function. The obvious solution to a graphical error: disable EAC. Yay, it launched! Then to get it to build. First I had to fix some filepaths since Linux is case-sensitive (nerds) while I don’t care about case on Windows. Then, rust-lld gave some weird error about simd or something which I didn’t care about. I just ran cargo clean and rebuilt it and it worked fine. Then to run, and it actually worked first try! It’s cool because I went into it expecting to debug a million socket errors, but it actuallly connected and ran. Awesome sauce! Now Linux users can use rlbuddy. More minions to contr- I mean cool users! Cya in the next one! ;) If you check out the rl perf overlay in the screenshot, you’ll be able to guess why this is the laptop I decided to put Linux on.
I’ve been putting this off for a while, but I’ve finally decided I’m going to add asset swapping. There’re a few existing implementations, so I’m reading those as well as some pdfs about the upk format. So basically credit to this document and this implementation . All it can do for now is parse the file summary. The implementation wasn’t too bad since I had Google as well as the C# implementation I just talked about. I basically have trait Deserializable : Sized { fn deserialize ( reader : & mut impl Read ) -> AnyResult < Self > ; } Then implement that for the various parts (eg. FGuid , a generic TArray ). Then, I use byteorder to read out numbers into each struct. For example, #[derive(Debug)] struct FCompressedChunkInfo { uncompressed_offset : i64 , uncompressed_size : i32 , compressed_offset : i64 , compressed_size : i32 , } impl Deserializable for FCompressedChunkInfo { fn deserialize ( reader : & mut impl Read ) -> AnyResult < Self > { Ok ( Self { uncompressed_offset : reader .read_i64 :: < LittleEndian > () ? , uncompressed_size : reader .read_i32 :: < LittleEndian > () ? , compressed_offset : reader .read_i64 :: < LittleEndian > () ? , compressed_size : reader .read_i32 :: < LittleEndian > () ? , }) } } I originally prototyped it in Python and then moved to Rust once I got tired of python’s byte shenanigans.
I JUST DESERIALIZED AND RESERIALIZED A UPK. OMAIGOD IM SO HAPPY. my brain is so tired. Alright so the payload still doesn’t get transferred but that’s pretty simple, it’s just Vec::extend. What a challenge! Deserialization actually ended up being the easy part, which is opposite of what I expected from starting the project. It went (relatively) fast since there are a few existing implementations which I could kinda just “borrow” structure parsing from. But, mine is unique in that it almost completely reserializes the package itself. I might’ve been able to “borrow” reserialization, but the impl I’ve been looking at is STRAIGHT ai slop and it’s more annoying to read that than to just do it myself. It was useful though, so I have to respect it. The first problem: basically, the first byte of an FString determines how many parts it has, NOT how many bytes it has. Which wasn’t a problem for parsing, since I had some word-based helpers which worked so I didn’t think much about it. But, when reserializing, I made two mistakes: 1. forgot to add the null terminator (which shouldn’t even be necessary) and 2. I accidentally put the wrong offset. I have no clue why there’s a null terminator for FStrings. The format is [n chars][the char bytes], meaning it should already be known how long the string is. Pretty stupid, but whatever. Anyways, when reserializing you’re supposed to include the null terminator in the string length marker. So, my logic was that I should offset it by two since unicode characters are two bytes. Bleh! I should’ve only incremented by one, since it’s in terms of utf16 chars rather than bytes. Yay, that worked! I don’t know how to summarize the next problem, so I’ll explain the reasoning. The package header is file summary + tables + something else (we’ll get to that later). Anyways, there’s some mysterious padding in between the summary and tables. Parsing, it’s easy to skip over because the summary includes the tables start offset ( name_offset , the name table is the first one). But when reserializing, you gotta keep those offsets intact. Well, I’m not totally sure if you actually have to keep them, but just for the sake of simplicity I tried to (which ended up adding more complexity, which I’ll see if I can remove now). So, I serialize/push the summary to the big Vec. Then, I make a new Vec and serialize the name table at (name_offset - summary_size), since the new Vec has to be encrypted and then appended to the big Vec. I do the same thing for imports/exports (placing the table at import/export _table_offset - summary_size ). Oh no! Since name_table_offset isn’t equal to summary_size, there’s some padding in between, which is expected. HOWEVER! The previous logic would skip over it in the table Vec creation, meaning the table Vec would have some 0-padding at the start. This padding needs to be in the SUMMARY part instead, and the name_offset should basically be the ZERO of the tables Vec! I doubt I would’ve been able to solve this part without the beautiful tool HxD . It’s really easy to use and is always helpful when I’m figgling around with binary. So, it does some more math, calculates the spacing, adds it to the big vec, and removes it from the tables Vec. Then, it re-encrypts the tables Vec and pushes it onto the big Vec! Okay, now that’s done. NOPE! There’s a mysterious structure for some reason at the end of the real table part? Yep, it’s that something else I said we’ll get to. I actually still have no idea what it is. From some research, I gathered it must be the dependencies table, but it’s really poorly documented. So, I ended up just cutting the bytes out from after the export table to the end of the tables part, and “pasting” it back before re-encryption. I do hope this devlog was readable. Now I’ll get to including the actual package payload and hopefully simplifying reserialization offsets. See you soon!
I figured out what comes after export tables! And it took way too long, since I DISCOVERED IT MYSELF! At least, as far as I know. I couldn’t find any information online about this portion of the header, so it was basically luck that I noticed a pattern. Before, I was just copying everything after the export table and pasting them back in afterwards, but as you can guess, that stopped working if I adjusted anything within the encrypted region. Compressed chunk info is a known part, and I figured out the AES padding pretty easily, so most of the time was spent trying to figure out what in the world those 24 bytes were. The first four bytes in the compressed chunk info are how many chunks they are. Here, in the Bubbles boost package, there are two (little endian), with 24 bytes of ???. And in Flamethrower, there are three, with 36 bytes of ???. I noticed that the ??? was always n chunks * 12 bytes (actually, it’s lucky that I didn’t test any which ended up having 0, otherwise I probably wouldn’t have figured it out). Since this probably had something to do with chunks, I made a guess that each chunk had some extra data stored in this array, 12 bytes of info per chunk. Using HxD’s highlight-bytes-and-get-the-decimal-value feature, I noticed a pattern where the first 8 bytes looked like an i64 offset and the last 4 looked like an i32 size, which the compressed chunk infos were also like for their matching counterparts. So, I deserialized it as [i64; i32] * n chunks and was able to read it better. These additional chunk infos seem to kinda sorta match up to uncompressed header offsets, but I don’t really understand what they are (and they’re marked as such in the code, lol). So, with that working (and some fiddling with broken serialization of TArrays which I’m surprised I didn’t catch earlier), I now understood the ENTIRE package header! Hooray! Let’s look at another example. body_grain_SF, the Fennec, has 4 chunks. Guess how many bytes of ??? it has. That’s right, zero! For some reason, a few packages just don’t have those things. After going through a bunch of them, I found that if licensee version was 32, there was no ???. But if it was 33, there WAS ???. I basically just added an if statement and it was fixed. I’m going to try to work on figuring out the padding in between the package summary and the start of the name table, but if I can’t, I suppose I’ll finally get to actually doing package swapping. Later!
I got a name swap! It doesn’t work properly, but I’m glad the game didn’t crash. These hours have been by far the most frustrating because the only way to test is against the real game since it’s really picky, but the game takes like 30 seconds to start, and if it crashes, it gives a cryptic error log, and if it freezes, it doesn’t give any log at all. I spent most of the time messing with moving different offset values forward and backwards, and ended up reverting to a simpler version with no overwriting when the header size changes just to test things. So far, I’ve mostly gleaned that name renaming is possible, but only up to a point. If the name grows too much, the game crashes, and if the name shrinks too much, the game freezes. Additionally, for some reason, total_header_size changes by the padded header size instead of the encrypted header size, which I still don’t understand. It’s seriously weird. I serialize each name properly, and yet the game reads it wrong. This game really does need a new codebase. When UE6 comes out, either the game’s gonna be so good it doesn’t need mods, or it’ll be relatively easily moddable. Or neither, which is the most probable based on Epic Games’ track record. Anyways, enjoy the beautiful screenshot.
IT SWAPPED IT SWAPPED IT SWAPPED AHAHAHHAHAHAHHAHAHAHAHHA FINALLY Okay now I gotta make it work for other pairs of boosts. If WHEN that works, I’ll actually put it in rlbuddy. I removed all the code relating to changing offsets to try to give myself a minimal workspace to tinker in, with as little side effects as possible. So, all the current code does is 1. open them 2. replace the name table entries and package guid. Surprisingly simple. Once I make it a bit more generic, I can extend it to support more swaps. If I’m really unable to get it to work for more combinations, I’ll probably end up just publishing the poc repo and not adding swapping to rlbuddy at all. This is a great motivation boost, though. I was honestly dreading coming home to work on it today because I was done with failing over and over, and considering giving up.
IT WORKS WHEN THE HEADER EXPANDS NOW YAYAYYAYAYAYYAYAYYAYAYAY I’m gonna be honest, the problem might just have been that my testing package was corrupted. I was debugging my deserialization logic, which I thought might have some parsing issue near the header extraction, and noticed that once the encrypted region deserializer’s Cursor reached the end of the region, it was actually FARTHER than the package summary’s total_header_size - by 6 bytes! That’s pretty bad, and I don’t know how something like that even happened. Anyways, I repaired the game and brought over the shiny new upk and… it worked. I’m pretty sure that I only accidentally did this while tidying up my workspace a few hours ago, but if this has genuinely been the thing holding me back for the past few days - I also finally made the poc code public, at https://github.com/kalilamodow/rl-upk-testing/
Apparently there are a bunch of different AES keys rocket league uses, not just one. You can get a list of them from the psynet config url, and then do some weird crc stuff to change them from “content keys” to aes keys. I discovered the rocket league mapmaking discord today and I’m blown away by the amount of information on there, and also apparently my whole thing about the unknown bytes when licensee version > 32 was straight up wrong, which is funny. Anyways it works for all items now, which is great. I’m gonna work on actually putting it in rlbuddy now, hopefully that goes well
rlbuddy now has item swapping! Basically, making one item appear like another to use items you don’t actually own. These hours were spent on a few different things. Firstly, I optimized the thing a bunch! There were a few places that were pretty slow since the original repo was mainly for testing. For example instead of decrypting the entire header and rechecking it to find the right key, it only loads the first 4 blocks and attempts to decrypt the first FString. If it fails, that means the AES key isn’t valid. Also, I improved the error handling with anyhow. It actually makes it so much easier to deal with things and was pretty useful when debugging the move over to the actual app. Now I’m just going to work on polishing the panel UI a bit more, since it’s still kind of ugly.
I made a ton of improvements to the asset swapper! And fixed a bug with the music player which is cool technically, so I’ll start with that. The player uses the GSMTC api, which is async, but egui doesn’t really like async. So, I made it so that every time you wanted to run some command on the current session, it would start up a new thread. This was less than ideal for a few reasons: terrible performance race conditions could happen just… in Windows itself The main problem was 2: for example, if you skipped a replay too fast, the Play command from the end of the replay might actually reach Windows before the Pause command from the replay start, leaving your music paused. So instead, it starts one dedicated worker thread which has a channel which receives a Box<dyn FnOnce(Session)> , and executes at most one command every 50ms (only one command per loop, fixed loop time of 50ms). It’s really interesting because you actually end up sending a closure through a channel, which feels funny but when you really think about it it’s just ownership semantics. But, that’s working great now! On to swapper improvements! First, I moved most of the swapper module to anyhow handling (it’s heaven!), and I also modernized the upk api a bit since it was basically dragged directly from the proof-of-concept repo, meaning it was not really application-ready. Also, it previously looked at the game’s webcache to decode the AES keys for header decryption, but now it uses the wonderful Toga-Files repository along with a really nice caching layer for it to load items and their associated API keys. Having access to the actual item data is also way better since you don’t have to manually type in a package name which is kinda weird for any normal person. Now, you can select it from a dropdown instead! I love UX.
rlbuddy now loads additional playlists straight from the game’s cached webconfig, instead of hardcoding them all! This means that the list of playlists will basically never go out of date. There are actually quite a few services which rely on game files (eg. auto stats api setup, custom maps, asset swapper). So, the first thing I did was to refactor it so make all of these load from the same global value. Then, for playlists, I made it read from a specific file in the game’s http cache directory which contains a bunch of configuration. Then, it parses it into a JSON object, grabs all the values with Class PlaylistSettings_TA, and then extracts the title and playlist id! There are still a bunch of built-in Playlists, since those have internal things like going from a casual playlist type to its respective competitive one or having the hard-coded list of singleplayer playlists. But, all the other ones, like ltms are dynamically loaded. Yay!
I got licensee version 34 (encrypted payloads too) to swap finally! Okay, so this was awesome. Rocket League’s been having a bunch of updates lately, which breaks the packages of people trying to get free stuff. So, in a Reddit thread, I ended up dishing out a bunch of swapped asset files for people in this situation. There’s a new boost which everybody wanted really bad since it was really rare (but they decided to make it unlockable at rocket pass lv99 so it doesn’t even matter anymore), and it was UNSWAPPABLE for three reasons: it was encrypted specially i hadnt encountered specially encrypted packages meaning their handling was wrong aes keys werent out for it yet (or so I thought) I’ll start with 3. I had written a tool which looks in the games cache for AES keys, and dumped them, and it worked great. What I didn’t expect is the filename to change between versions. So, I was super confused since yesterday since the AES key for the boost was just… missing. Thankfully, the geniuses at the RLMM discord got it and helped me figure out that the file I was reading from was just outdated. Great! Anyways, not too big of a deal, just a big delay. Now it’s time for the real challenge: figuring out how the hell to handle this type of package. First, I did some research. The twelve bytes of padding in files with licensee version >=33 before the summary are actually a nonce/aes iv, not just padding. Then, the header is encrypted with AES-CTR with the twelve first bytes of the iv just being the nonce. And the compressed chunks are encrypted too here: each one is also AES-CTRed with their own nonces in FCompressedChunkInfo. Thing is, I don’t have an implementation to really go off anymore, meaning there’s a lot more trial and error. For the original implementation, there were one or two existing asset swappers (though they were vibecoded meaning more of a puzzle to figure out what they’re even doing), but this time I was mostly relying on emii’s fork of UEViewer. Anyways, after spending a while figuring out what exactly I had to masquerade (payload, key, swap nonces) I finally got it to work!
Not much in terms of super-cool stuff this time. Highlights are: make sure dynamic playlist loading uses the latest cache file (and also fix its loading on normal people’s rocket league installs) loading the cache file on another thread so it doesnt freeze the whole app for a second on the first lazy lock access searching for items in the item swapper moved the error handling of the map loader to anyhow So no ultra-exciting things to talk about. anyhow is really cool though, it really simplifies error handling everywhere in the app, and I’m a big fan of its bail! macro. I’m also using Cow a lot more. Moo!
I made a standalone web-based swapper for the people who don’t want to download an entire app. A lot of people had broken packages after the last update but didn’t want to install a dedicated program just for a few swaps. So, I used the asset swapper backend of rlbuddy to make this thingamabob which runs entirely in the browser! First, I had to find out how to actually share rlbuddy’s asset swapper with other projects. Turns out Cargo has a cool thing called workspaces where you can have multiple crates in the same repo! So I moved the dedicated UPK/AES etc. stuff into a new crate and added it as a dependency in regular rlbuddy. Then, I whipped up a small wasm-compatible eframe app with the template, and included the new crate as a dependency. I made a big state machine of the steps meaning it’s impossible to have an invalid state, which is really nice. The only problem was that Rust’s ownership system isn’t smart enough to deal with it, so the code is a bit repetitive in places but it’s definitely worth it. The WASM restrictions were super annoying, mainly do to with filesystem access and requiring async. I ended up using the egui-async crate and spilling Binds all over the place within the state machine. I couldn’t even figure out how to get the actual swap procedure to run in a different thread. I also spent like 30 minutes debugging why in the world asset swapping was just broken. Even when I verified the same binary data were going in to the Upk object in the webapp and rlbuddy, for some reason the output upk was just different. Turns out I used chosen_replacement.name instead of chosen_replacement.package.name() . Isn’t that great? Anyways, it works fine now and I’m planning on posting it on r/RocketLeagueMods and possible r/RocketLeague.
A few fixes here and there. Some refactors, caching externally loaded playlists in savedata, and fixing a deadlock when clearing the items cache. And for some reason the decal option was missing from the items list picker.
more small improvements. i gave the session stats widget an actual service as well which speeds things up a lot since its not recalculating statistics every single frame. the swapper also uses the backup file if one is available and it no longer accepts duplicate custom maps
Ships:
rlbuddy is a feature-filled companion for Rocket League! It shows the skill of everyone in your lobby and has tons of toggleable widgets and features to make your life a lot easier, from Discord integration to music control. This is my first non-tiny Rust project, and I think it was really great! I’ve learned a lot such as proper state management and the ins and outs of Rust’s syntax. You can give it a try by heading to the Github releases section. If you play Rocket League, I hope you use it!
rlbutddy is a feature-rich companion for Rocket League, and v1.2 is out. There’s been some big architectural changes meaning it’s faster and bug-free-er, as well as big new features! New!!! Avatars! Now you can see people’s profile pictures even when you’re not on their platform. Custom map loader! You can import maps from a ZIP or download them straight from Bakkesplugins! Gamepad overlay! Show your controls while playing, to show off your bindings or get some help with your speedflips. I think I’ve definitely improved at Rust since the last release. Just in terms of the amount of mistakes I make, I feel like it’s way more smooth sailing than before. For example, I was able to (mostly) write not-so-buggy code and “run the borrow checker in my head” without needing to cargo check a million times, and clippy tends to have a lot less suggestions for me. Pretty great!
I made rlbuddy, a rocket league companion app! This is the third ship so far. The big features this time are the asset swapper and Linux support, but I think that the feature I’m most proud of this time is the asset swapper! It inserts the appearance of one item into the file of another, meaning by swapping out assets for others you can make your car look however you like! (Client-side only, of course). I learned a lot about byte-level manipulation and working with raw data streams and encryption/decryption in Rust, and I can read hex (relatively) well now! It’s also great because I think this combined with the doorstop experiment from a while ago gives me a nice base to try some reverse-engineering challenges in the future. I also worked a lot on performance this time, such as tuning loop times/ui fps caps and minimizing ram usage (I achieved around an 80% reduction here!) There are a crap ton more features added than that (totaling almost 100 commits), but I’m pretty sure you’re not supposed to have massive feature-dumps on the ship text. So the full list is on the latest github release! In the image, you can see I have a white fennec. In reality, I don’t actually have a tw trim, and the equipped decal isn’t compatible with the fennec either. But, using the power of asset swapping, I can get a beautiful all-white car. Neat!...
|
1792824716.4688025
|
1792911116.4688025
|
|
2129
|
SuperOrbital by @obedot | Stardance
|
obedot
|
1
|
183.0
|
2657
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-23T00:50:05Z", "hours": 183.0, "multiplier": 14.57, "payout": 2657, "blessing": "neutral", "text": "SUPERORBITAL: The Quest of the Anomaly After months of hard work, @orivio and I finally present to you SUPERORBITAL. What on earth is a SUPERORBITAL? SUPERORBITAL is a 2D platformer where you play as Vitri, the only human born without gravity. After years of being ostracized by society, Vitri sets out on a mission to change things for the better. He decides to take a gamble on a popular story that’s been spreading about all planets having tangible gravity cores at their centers, and decides to find one for himself. Accompanied only by his robot assistant, G.R.A.V. (Great Robot Assistant of Vitri), Vitri flies out into deep space and lands on a planet named Zeta-C5, where he uses special abilities, such as turning gravity on and off, to explore and make his way towards the planet’s core. Difficult obstacles and even unexpected foes block his way, but he’s got to get through no matter what. Dev Messages: orivio: SUPERORBITAL has been a really fun introduction to Godot! Though challenging at times, designing the levels around our unique mechanics was pretty fun, and I think overall the game turned out pretty great! Obviously it is only an alpha release, so I plan on working together with Obe Dot to polish it a ton, in terms of artwork, music, story, etc. Expect lots more content to come! Obe Dot: Developing this game has been an amazing experience. This is my first big gamedev project, and I’ve learned so much. I really hope to work more on this project in the future, while also improving my art and programming skills. Much appreciation to Hack Club for creating this event! Try out the game on our itch, or watch the provided gameplay footage and/or trailer! Trailer: https://www.youtube.com/watch?v=5WPKXYqy1FI Gameplay: https://youtu.be/-zq8ps87daI?si=sUK4_9BedT1OdXU8", "repo": "https://github.com/orivio/super_orbital", "demo": "https://obedh.itch.io/superorbital"}]...
|
[{"post_id": 72452, "ts": "202 [{"post_id": 72452, "ts": "2026-09-23T00:34:22Z", "hours": 3.1192, "text": "Finished Up the GitHub Readme, Game Trailer, and Itch.io page! I did all the last remaining steps to finishing the game before shipping. I made a trailer of about 1 minute, and wrote a section of the GitHub Readme about the making of SuperOrbital. I’m going to ship now!"}, {"post_id": 71290, "ts": "2026-09-20T16:09:42Z", "hours": 4.3556, "text": "FINALLY fixed an annoying physics bug, improved the intro cutscene, and made the black holes look better I’m very happy to say that the dash/platform bug I was experiencing previously has now been solved. The player used to clip out of bounds if you dashed into a moving platform, but now, the player will get teleported back to where they were before. I also did some work on the intro cutscene, and while it isn’t yet finalized, I think it looks much better. Also, I made the center of the black hole a perfect circle now."}, {"post_id": 69415, "ts": "2026-09-17T00:28:27Z", "hours": 4.0075, "text": "THE FINISHING TOUCHES Yo yo yo, I am very close to shipping my game. I only have a little bit more to do. I’ve been working on improving the cutscenes, for example, making the colors look better and improving the perspective. I still have more work to do though, of course. Next up, I’m going to polish some of the movement mechanics some more, and then I’ll get some friends to playtest it."}, {"post_id": 65675, "ts": "2026-09-10T23:59:06Z", "hours": 9.0878, "text": "Greatly Improved Sound and Level Design I found it suprisingly easy to make good sound effects for my game. I dropped a rock on the ground and recorded it, and now, that’s the sound that plays when the player lands on rocky terrain after falling. I took a screwdriver and hit it against a bunch of things until I found something that sounded good. It’s a fun process! I also worked more on level design, by balancing everything so that the progression felt natural. I am almost finished with the final level, which I hope will challenging but fun."}, {"post_id": 63535, "ts": "2026-09-07T13:31:33Z", "hours": 1.2772, "text": "Added checkpoints to the levels If you find that the game is too challenging, you can turn on checkpoints in the settings menu. This lets you respawn at the nearest checkpoint after dying, instead of starting the whole level over again. I hope that this option can make my game playable by more people of different skill levels."}, {"post_id": 63220, "ts": "2026-09-06T22:04:35Z", "hours": 5.6608, "text": "Redesigned Old Levels to Work Better With New Player Movement With player movement out of the way, I can get to making even better levels. This one in particular, which you can see below, is a level I’m quite proud of. I took inspiration from Hollow Knight’s Path of Pain a little bit. I don’t have much left to do, but I definitely want to add some better sound effects."}, {"post_id": 62481, "ts": "2026-09-05T21:00:44Z", "hours": 5.6092, "text": "Finishing the Movement and Experimenting with Dynamic Lighting I finally got all the movement mechanics down. I still might refine the black holes a little bit, but first I want to redesign some of the earlier levels. My teammate suggested dynamic lighting for our game, and while it looks cool, it seems to difficult to set up completely for our Stardance release."}, {"post_id": 61134, "ts": "2026-09-03T21:52:29Z", "hours": 2.725, "text": "Greatly improved the Level Select screen by making animated level buttons I used Godot’s Tweens to make the level select buttons rotate and pop when you select them. The effect isn’t perfect yet, but it’s getting there. What do think of the effect?"}, {"post_id": 60806, "ts": "2026-09-03T12:28:16Z", "hours": 0.8911, "text": "Fixed a Tricky Level Transition Bug I was experiencing this frustrating bug where, if you try to run back and forth between levels too fast, you can fall off the map. I expanded the camera boundaries to see what was happening better, and slowed down the game a bit using Godot’s awesome tools. I solved the bug by reordering the level transition code. On the first slide, you can see the original bug, and on the third slide, you can see the fixed version."}, {"post_id": 60543, "ts": "2026-09-02T23:03:33Z", "hours": 1.2192, "text": "Refined the Gravity Switch Shockwave Even More It made the shockwave effect go by faster, and be properly centered on the player. This makes the shockwave feel just right when playing the game, and gives the gravity switch the perfect amount of impact."}, {"post_id": 60497, "ts": "2026-09-02T21:24:04Z", "hours": 7.9831, "text": "Improved Game Juice and Improved Visual Effects Game Juice I started working on adding the little details to the movement that make the game way more fun to play. I added a few freeze frames when starting a dash, which was inspired by Celeste. I also added a bit of camera shake to give the player even more feedback on their movement. Visual Effects This part was really satisfying. I made a shockwave warp effect around the player when they perform a gravity switch, which looks great. Then I made the black holes look better by distorting the background. Frustrating Bugs I’ve been having a lot of movement bugs that are tricky and inconsistent to replicate, and I can’t figure them out yet. Next Steps I still need to get the AnimationTree to work, but that should really be quite easy. I still have to redesign some levels."}, {"post_id": 59189, "ts": "2026-08-31T20:47:27Z", "hours": 4.8492, "text": "Added more to the opening cutscene I don’t want to give away the intro until the game is ready, but I’ll share parts of what I made. This first frame took me the longest, over 2 hours. I planned to animate the guy standing up and walking, but I now realize that that’s probably not feasible. I think it will look great anyway though. I might improve some little parts of the drawing. Creating a cutscene manager in Godot I set up an AnimationPlayer to direct the cutscene, and it’s actually quite easy. I do need to align my crossfades correctly and sync everything with the music."}, {"post_id": 58502, "ts": "2026-08-30T22:41:57Z", "hours": 6.7444, "text": "Created a rough draft of the intro cutscene, and composed music for it The intro cutscene/storyboard I used libresprite to make a basic idea of what the intro cutscene should look like. I still have more to add, and as you can tell, the text is practically illegible. Yeah, libresprite doesn’t have a text tool. But I’ll fix it soon and it’ll look awesome. The intro music I made this song using FamiStudio with the EPSM expansion and FamiStudio’s default instrument pack. This let me use the instruments I wanted while still sounding retro-ish. My brother helped me work on the song, because he’s way better at music than I am. I still need to revise the song more, this is more of a first draft. Any feedback would be appreciated lol"}, {"post_id": 57575, "ts": "2026-08-29T19:17:53Z", "hours": 2.8072, "text": "Redoing the Player Movement I remade the player movement system from scratch, because my previous implementation just wasn’t working. It was buggy, and the movement didn’t feel good to play. My new movement system is not entirely complete, but it already feels much better. For one thing, the variable jump height is much smoother, and stopping a jump midair doesn’t feel as abrupt. I added coyote time, jump buffering, air friction, and faster falling for game juice. I still need to fine tune the settings, and get some more people to playtest the movement. There are more movement mechanics I need to add, such as dashing, but I want to get the basic movement completely down first."}, {"post_id": 56888, "ts": "2026-08-28T21:33:33Z", "hours": 3.1403, "text": "Started refactoring the player movement script. I’m starting from scratch, so I only have basic horizontal movement yet. I added an input sequence recorder to make it easier to replicate bugs, so you can record a sequence of inputs and then play them back again."}, {"post_id": 56307, "ts": "2026-08-28T01:19:58Z", "hours": 3.0025, "text": "Fully refactored the level manager. After a few hours, I have finally cleaned up all the code for level transitions. Now, the code is easier to understand and maintain, and adding new levels takes significantly less time and effort. I added comments on all the related code to make it even easier to read. I also fixed a few bugs in the process. For example, trying to open the menu during a level transition used to put the game in a glitched state, but I fixed that now. I moved towards a cleaner architecture where the scene root (play.tscn) manages the game state, and the pause menu asks the play scene to open the menu, instead of just going ahead and doing it. It’s possible that this refactor may have broken some other aspects of the game, so I’ll have to look over everything later, but right now, it seems to be working fine."}, {"post_id": 54818, "ts": "2026-08-25T23:28:18Z", "hours": 1.6025, "text": "Polished the levels even more, added new art assets, and fixed some minor tile inconsistencies. I also drew this boulder, which currently doesn’t look that great, but I’ll improve it later and add it somewhere where it fits in the game. I showed this game to my grandma, and she was able to figure out the controls pretty quickly, so I see that as a win."}, {"post_id": 54128, "ts": "2026-08-24T23:06:45Z", "hours": 4.1431, "text": "Greatly improved the facility’s tileset by adding details and more background elements."}, {"post_id": 47770, "ts": "2026-08-15T22:44:25Z", "hours": 5.9028, "text": "Well, I tried to refactor the entire world system, but I gave up. It was just taking way too long. I guess I’ll just have to deal with the spaghetti code for now. I did finish the level select screen, and I think it looks pretty good. I just have to rename some of the levels because they are named very generic things."}, {"post_id": 47113, "ts": "2026-08-14T19:20:03Z", "hours": 9.8889, "text": "I’m redoing the level system to clean up the spaghetti code situation. My teammate redesigned one of the characters, and I added it to the game."}, {"post_id": 44826, "ts": "2026-08-10T21:02:18Z", "hours": 9.2131, "text": "I’m bettering my backgrounds, bettering my visuals, bettering my levels!"}, {"post_id": 43535, "ts": "2026-08-08T21:13:55Z", "hours": 5.8183, "text": "Added some more levels to my platformer game, and pretty much done-iffied the player sprite and sound effects"}, {"post_id": 39099, "ts": "2026-08-01T20:07:54Z", "hours": 9.0683, "text": "I’ve added a few more challenging levels. I also almost finished up the sprite work on the protagonist."}, {"post_id": 36431, "ts": "2026-07-28T15:36:26Z", "hours": 3.005, "text": "Made new run, idle, and jump animations and added the final layer"}, {"post_id": 35254, "ts": "2026-07-26T15:39:00Z", "hours": 1.1678, "text": "Added some great audio settings"}, {"post_id": 35153, "ts": "2026-07-26T12:07:00Z", "hours": 9.5392, "text": "Added a save file system"}, {"post_id": 32506, "ts": "2026-07-21T18:48:48Z", "hours": 10.2469, "text": "I added input control remapping for my platformer game. We also added more dialogue."}, {"post_id": 31328, "ts": "2026-07-19T17:03:06Z", "hours": 9.1842, "text": "I tried adding a parallax effect, but it didn’t turn out how I wanted. I fixed a bug with the camera scale not being a whole number ratio. I’m starting to add the last few mechanics to the game, which involve Black Holes."}, {"post_id": 27351, "ts": "2026-07-12T20:49:33Z", "hours": 6.6386, "text": "I just finished a new tileset for my 2d platformer."}, {"post_id": 20330, "ts": "2026-07-01T22:08:11Z", "hours": 6.9336, "text": "I made better running and jumping animations for my 2D platformer."}, {"post_id": 15865, "ts": "2026-06-25T19:51:18Z", "hours": 7.995, "text": "I made this cool background for my game’s menu. I learned about shaders from the book “The Book of Shaders” by Patricio Gonzalez Vivo and Jen Lowe, and some of my shaders were inspired by the content in that book. The star effect was inspired by this very helpful reddit post: https://www.reddit.com/r/godot/comments/1m0czqd/starry_background_in_this_many_lines_of_shader/"}, {"post_id": 12686, "ts": "2026-06-20T18:43:02Z", "hours": 2.7389, "text": "I added another level with a lot of spikes, platforms and timing!"}, {"post_id": 12003, "ts": "2026-06-19T16:14:06Z", "hours": 1.7231, "text": "I added a level that teaches you the jump cutting mechanic in my 2D platformer game. I’m also experimenting with new character sprites."}, {"post_id": 11513, "ts": "2026-06-18T20:06:11Z", "hours": 4.5739, "text": "I added Jump Cutting, Jump Buffering, and Death to my platformer"}, {"post_id": 5261, "ts": "2026-06-08T23:43:38Z", "hours": 6.7183, "text": "Setting up basic movement and levels for my platformer (guys I KNOW the sprites look bad)"}]...
|
Title: SuperOrbital by @obedot | Stardance
Devlog Title: SuperOrbital by @obedot | Stardance
Devlogs:
Setting up basic movement and levels for my platformer (guys I KNOW the sprites look bad)
I added Jump Cutting, Jump Buffering, and Death to my platformer
I added a level that teaches you the jump cutting mechanic in my 2D platformer game. I’m also experimenting with new character sprites.
I added another level with a lot of spikes, platforms and timing!
I made this cool background for my game’s menu. I learned about shaders from the book “The Book of Shaders” by Patricio Gonzalez Vivo and Jen Lowe, and some of my shaders were inspired by the content in that book. The star effect was inspired by this very helpful reddit post: https://www.reddit.com/r/godot/comments/1m0czqd/starry_background_in_this_many_lines_of_shader/
I made better running and jumping animations for my 2D platformer.
I just finished a new tileset for my 2d platformer.
I tried adding a parallax effect, but it didn’t turn out how I wanted. I fixed a bug with the camera scale not being a whole number ratio. I’m starting to add the last few mechanics to the game, which involve Black Holes.
I added input control remapping for my platformer game. We also added more dialogue.
Added a save file system
Added some great audio settings
Made new run, idle, and jump animations and added the final layer
I’ve added a few more challenging levels. I also almost finished up the sprite work on the protagonist.
Added some more levels to my platformer game, and pretty much done-iffied the player sprite and sound effects
I’m bettering my backgrounds, bettering my visuals, bettering my levels!
I’m redoing the level system to clean up the spaghetti code situation. My teammate redesigned one of the characters, and I added it to the game.
Well, I tried to refactor the entire world system, but I gave up. It was just taking way too long. I guess I’ll just have to deal with the spaghetti code for now. I did finish the level select screen, and I think it looks pretty good. I just have to rename some of the levels because they are named very generic things.
Greatly improved the facility’s tileset by adding details and more background elements.
Polished the levels even more, added new art assets, and fixed some minor tile inconsistencies. I also drew this boulder, which currently doesn’t look that great, but I’ll improve it later and add it somewhere where it fits in the game. I showed this game to my grandma, and she was able to figure out the controls pretty quickly, so I see that as a win.
Fully refactored the level manager. After a few hours, I have finally cleaned up all the code for level transitions. Now, the code is easier to understand and maintain, and adding new levels takes significantly less time and effort. I added comments on all the related code to make it even easier to read. I also fixed a few bugs in the process. For example, trying to open the menu during a level transition used to put the game in a glitched state, but I fixed that now. I moved towards a cleaner architecture where the scene root (play.tscn) manages the game state, and the pause menu asks the play scene to open the menu, instead of just going ahead and doing it. It’s possible that this refactor may have broken some other aspects of the game, so I’ll have to look over everything later, but right now, it seems to be working fine.
Started refactoring the player movement script. I’m starting from scratch, so I only have basic horizontal movement yet. I added an input sequence recorder to make it easier to replicate bugs, so you can record a sequence of inputs and then play them back again.
Redoing the Player Movement I remade the player movement system from scratch, because my previous implementation just wasn’t working. It was buggy, and the movement didn’t feel good to play. My new movement system is not entirely complete, but it already feels much better. For one thing, the variable jump height is much smoother, and stopping a jump midair doesn’t feel as abrupt. I added coyote time, jump buffering, air friction, and faster falling for game juice. I still need to fine tune the settings, and get some more people to playtest the movement. There are more movement mechanics I need to add, such as dashing, but I want to get the basic movement completely down first.
Created a rough draft of the intro cutscene, and composed music for it The intro cutscene/storyboard I used libresprite to make a basic idea of what the intro cutscene should look like. I still have more to add, and as you can tell, the text is practically illegible. Yeah, libresprite doesn’t have a text tool. But I’ll fix it soon and it’ll look awesome. The intro music I made this song using FamiStudio with the EPSM expansion and FamiStudio’s default instrument pack. This let me use the instruments I wanted while still sounding retro-ish. My brother helped me work on the song, because he’s way better at music than I am. I still need to revise the song more, this is more of a first draft. Any feedback would be appreciated lol
Added more to the opening cutscene I don’t want to give away the intro until the game is ready, but I’ll share parts of what I made. This first frame took me the longest, over 2 hours. I planned to animate the guy standing up and walking, but I now realize that that’s probably not feasible. I think it will look great anyway though. I might improve some little parts of the drawing. Creating a cutscene manager in Godot I set up an AnimationPlayer to direct the cutscene, and it’s actually quite easy. I do need to align my crossfades correctly and sync everything with the music.
Improved Game Juice and Improved Visual Effects Game Juice I started working on adding the little details to the movement that make the game way more fun to play. I added a few freeze frames when starting a dash, which was inspired by Celeste. I also added a bit of camera shake to give the player even more feedback on their movement. Visual Effects This part was really satisfying. I made a shockwave warp effect around the player when they perform a gravity switch, which looks great. Then I made the black holes look better by distorting the background. Frustrating Bugs I’ve been having a lot of movement bugs that are tricky and inconsistent to replicate, and I can’t figure them out yet. Next Steps I still need to get the AnimationTree to work, but that should really be quite easy. I still have to redesign some levels.
Refined the Gravity Switch Shockwave Even More It made the shockwave effect go by faster, and be properly centered on the player. This makes the shockwave feel just right when playing the game, and gives the gravity switch the perfect amount of impact.
Fixed a Tricky Level Transition Bug I was experiencing this frustrating bug where, if you try to run back and forth between levels too fast, you can fall off the map. I expanded the camera boundaries to see what was happening better, and slowed down the game a bit using Godot’s awesome tools. I solved the bug by reordering the level transition code. On the first slide, you can see the original bug, and on the third slide, you can see the fixed version.
Greatly improved the Level Select screen by making animated level buttons I used Godot’s Tweens to make the level select buttons rotate and pop when you select them. The effect isn’t perfect yet, but it’s getting there. What do think of the effect?
Finishing the Movement and Experimenting with Dynamic Lighting I finally got all the movement mechanics down. I still might refine the black holes a little bit, but first I want to redesign some of the earlier levels. My teammate suggested dynamic lighting for our game, and while it looks cool, it seems to difficult to set up completely for our Stardance release.
Redesigned Old Levels to Work Better With New Player Movement With player movement out of the way, I can get to making even better levels. This one in particular, which you can see below, is a level I’m quite proud of. I took inspiration from Hollow Knight’s Path of Pain a little bit. I don’t have much left to do, but I definitely want to add some better sound effects.
Added checkpoints to the levels If you find that the game is too challenging, you can turn on checkpoints in the settings menu. This lets you respawn at the nearest checkpoint after dying, instead of starting the whole level over again. I hope that this option can make my game playable by more people of different skill levels.
Greatly Improved Sound and Level Design I found it suprisingly easy to make good sound effects for my game. I dropped a rock on the ground and recorded it, and now, that’s the sound that plays when the player lands on rocky terrain after falling. I took a screwdriver and hit it against a bunch of things until I found something that sounded good. It’s a fun process! I also worked more on level design, by balancing everything so that the progression felt natural. I am almost finished with the final level, which I hope will challenging but fun.
THE FINISHING TOUCHES Yo yo yo, I am very close to shipping my game. I only have a little bit more to do. I’ve been working on improving the cutscenes, for example, making the colors look better and improving the perspective. I still have more work to do though, of course. Next up, I’m going to polish some of the movement mechanics some more, and then I’ll get some friends to playtest it.
FINALLY fixed an annoying physics bug, improved the intro cutscene, and made the black holes look better I’m very happy to say that the dash/platform bug I was experiencing previously has now been solved. The player used to clip out of bounds if you dashed into a moving platform, but now, the player will get teleported back to where they were before. I also did some work on the intro cutscene, and while it isn’t yet finalized, I think it looks much better. Also, I made the center of the black hole a perfect circle now.
Finished Up the GitHub Readme, Game Trailer, and Itch.io page! I did all the last remaining steps to finishing the game before shipping. I made a trailer of about 1 minute, and wrote a section of the GitHub Readme about the making of SuperOrbital. I’m going to ship now!
Ships:
SUPERORBITAL: The Quest of the Anomaly After months of hard work, @orivio and I finally present to you SUPERORBITAL. What on earth is a SUPERORBITAL? SUPERORBITAL is a 2D platformer where you play as Vitri, the only human born without gravity. After years of being ostracized by society, Vitri sets out on a mission to change things for the better. He decides to take a gamble on a popular story that’s been spreading about all planets having tangible gravity cores at their centers, and decides to find one for himself. Accompanied only by his robot assistant, G.R.A.V. (Great Robot Assistant of Vitri), Vitri flies out into deep space and lands on a planet named Zeta-C5, where he uses special abilities, such as turning gravity on and off, to explore and make his way towards the planet’s core. Difficult obstacles and even unexpected foes block his way, but he’s got to get through no matter what. Dev Messages: orivio: SUPERORBITAL has been a really fun introduction to Godot! Though challenging at times, designing the levels around our unique mechanics was pretty fun, and I think overall the game turned out pretty great! Obviously it is only an alpha release, so I plan on working together with Obe Dot to polish it a ton, in terms of artwork, music, story, etc. Expect lots more content to come! Obe Dot: Developing this game has been an amazing experience. This is my first big gamedev project, and I’ve learned so much. I really hope to work more on this project in the future, while also improving my art and programming skills. Much appreciation to Hack Club for creating this event! Try out the game on our itch, or watch the provided gameplay footage and/or trailer! Trailer: https://www.youtube.com/watch?v=5WPKXYqy1FI Gameplay: https://youtu.be/-zq8ps87daI?si=sUK4_9BedT1OdXU8...
|
1792853530.485897
|
1792939930.485897
|
|
34953
|
Ultimate Mob Farms by @OffsetMonkey538 | Stardance
|
OffsetMonkey538
|
1
|
139.24
|
2678
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-19T13:59:43Z", "hours": 125.0, "multiplier": 18.99, "payout": 2678, "blessing": "neutral", "text": "This is a Minecraft mod for making mob farms, something similar to for example Mob Grinding Utils. It features item and xp collection, entity movement, spawner relocation and crafting, single block mob farms and some other stuff. Honestly, I’m quite proud just over the fact that I finally did finish this project (or at least got it to the point of being comfortable releasing it publically) and it’s hard to choose any specific features, but here I go… I do really like how the particle effects for the soul fan turned out, they’re quite satisfying imo. This is kind of unrelated to the mod, but I’m also proud of having helped out with the development of RRV, the recipe viewer mod I added compat with. While adding support for it in this mod, I noticed some bugs and crashes and stuff, which I PRed fixes for. It’s a bigger project with many complex things, so coming up with a list of all the things I found hard or took a lot of time and explaining all of them would probably go over whatever character limit this text box has lol. One thing that was a big PITA was the compact mob farm inventory. The original implementation I wrote was just… completely wrong, so I had to rewrite it. Then later I realized I overlooked like the most important part of the item transfer api (transactions, which are used for rolling back changes and stuff) so I had to rewrite it again, and then after that I rewrote quite a bit of it one more time because, after the last rewrite, I had accidentally made it possible for other blocks to insert into the inventory, which isn’t something I wanted as that seems quite OP. Another thing that comes to mind is figuring out the code for the soul fan’s range based on upgrades and strength at a given distance. The problem was that the coordinate you have to increase/decrease depends on the orientation of the block, so as an example, the depth upgrade would need to increase the Y pos when the block is placed pointing up and decrease it when pointing down, the X pos when facing north/south and the Z pos when facing east/west. For pushing the entities, I had to find the coordinates of the middle of the face the block is pointing, and add/subtract the correct coordinate to get the range in the depth direction, and then find the distance between each entity currently in range and the fan in just that plane for calculating the strength. For people testing out the project, I definitely do recommend also installing the Reliable Recipe Viewer (RRV) and Item Description mods", "repo": "https://git.offsetmonkey538.top/OffsetMods538/Ultimate-Mob-Farms", "demo": "https://modrinth.com/mod/ultimate-mob-farms"}]...
|
[{"post_id": 80728, "ts": "202 [{"post_id": 80728, "ts": "2026-10-18T17:03:06Z", "hours": 1.5967, "text": "Started working on setting up a docs page for the mod. Mainly want it for explaining the data driven configuration, but having full pages to give more detailed explanations of the different features is also probably a nice touch. Made a new icon for the mod as well, it’s pretty much the same but higher res because the 256x256 one looked weird on the docs page. The docs are done using Starlight like all my other docs pages (see those here ) and lives at https://ultimate-mob-farms.docs.cursedmods.com/ and on the docs/master branch in the repo Currently it’s just the landing page, but it’ll have more stuff soon enough"}, {"post_id": 79375, "ts": "2026-10-13T18:29:39Z", "hours": 3.9611, "text": "Added an RRV screen showing what items can be acquired from the Compact Mob Farm. Shows the entity, the items it drops and the required tier upgrade level. Hoping this also helps with confusion on how stuff works"}, {"post_id": 76204, "ts": "2026-10-02T17:34:45Z", "hours": 2.1567, "text": "Added a progress bar to the Compact Mob Farm GUI that hopefully makes it much easier to understand when it’ll damage the entity and it doesn’t look like it’s just doing nothing lol, especially with the 30 second default time"}, {"post_id": 75664, "ts": "2026-09-30T17:54:02Z", "hours": 6.5264, "text": "Waow that’s quite a bit of stardust 😅 Quite happy with this project and the ratings it got on the first ship :D (except the one that accused my devlogs of being written by ai… My writing is not that bad, right? ) I noticed in the shipwrights’ review video that how upgrades work is not very obvious, they were trying to put a tier upgrade into a soul fan, which only accepts width, height and depth upgrades. It was mentioned in ratings that stuff is a bit hard to figure out in the beginning as well. So to fix that, I added some silhouettes of the supported upgrades shown in the slots and also a hover tooltip saying what’s supported. Oh and i’ve also added 26.3 support now"}, {"post_id": 70575, "ts": "2026-09-19T11:52:49Z", "hours": 7.4719, "text": "School starting with september really hit my productivity on this mod like a truck I am realizing the deadline for stardance is getting real close, so I think this is probably the point where I’ll have to ship it. There are still some TODOs in the code and bugs that need to be squashed and porting to 26.3 (which released like this week, thanks mojang ) and so I haven’t been comfortable marking the latest release as 1.0.0 yet or making announcements elsewhere, but the mod is now perfectly usable and I like where it is. Changes since last devblog: 26.2 support Injecting some items into vanilla loot chests Advancements 26.2 wasn’t actually as painful as I thought it’d be, which was a nice surprise. Adding advancements was a bit more of a pain with 26.2 support though as I needed custom criteria for some of the advancements (one for putting a soul gem in the compact mob farm and another for using a soul gem on a spawner) and Mojang, in their infinite wisdom, decided to move a bunch of advancement stuff around in 26.2."}, {"post_id": 62252, "ts": "2026-09-05T15:04:19Z", "hours": 6.3956, "text": "Getting closer and closer to the actual release… could this be the last devblog before that? Still not quite 100% about if the required kills for each mob are balanced, but it’s probably good enough. Definitely better than everything being 10 kills tho. Felt very off-balance when withers, which are hard to spawn and hard to kill, and pigs, which are just everywhere, required the same amount of kills to capture. Notable changes: Show soul capturing recipe in rrv when checking usages of spawn eggs Show tooltip with entity name when hovering entity in soul capturing rrv recipe Add item descriptions Fix being able to insert items into the compact mob farm inventory Make amount of kills required for capturing an entity different per entity. Update compact mob farm recipe (now uses soul spikes in the middle instead of stone bricks) Store soul gem colors as hex strings in entity tiers config. Much more understandable and easier to manually change the overrides config or whatever Make built-in packs use the mod icon using a mixin instead of copying the icon into the packs. This shaves like 80kb off the final jar which is quite a bit of unnecessary duplicate crap Remove some log spam that was for debugging"}, {"post_id": 59802, "ts": "2026-09-01T19:04:17Z", "hours": 2.5989, "text": "checking the recipe for a specific soul gem now only shows that specific entity instead of all soul capturing recipes soul capturing recipe now shows up before the duplication recipe soul gems can now be searched by the name of the entity they contain fix compact mob farm gui not rendering vanilla background overlay allow filling soul gem when held in the main hand fix dedicated server crashing Running in a dedicated server would crash because there are quite a few places where I referenced client-only classes in places that the jvm will load on the dedicated server as well. Mostly in the different block entity classes, where I had a clientTick method that had ClientLevel as one of it’s parameters. Even though that method would never get called on the dedicated server, java still wants it to exist when loading the class because it’s part of a method’s definition. My current solution is very very awful… I moved those things into methods in the client initializer and… well… yeah… it just looks and is awful: https://git.offsetmonkey538.top/OffsetMods538/Ultimate-Mob-Farms/src/commit/0.0.7/modded/src/main/java/top/offsetmonkey538/ultimatemobfarms/modded/UltimateMobFarmsModdedClient.java#L65 The real, foolproof solution would be using the split sources feature of loom, which creates a second source set and makes the main source set unable to access client classes. Only problem is that it’d be a bit annoying to fully get set up in my multiloader-version gradle system and would most definitely need many changes on MonkeyLib538 as well and I just am not up for doing that atm."}, {"post_id": 58874, "ts": "2026-08-31T13:27:24Z", "hours": 8.6083, "text": "Fixed compact mob farm inventory not working correctly and being incompatible with other mods’ item movement stuff. The whole point of the transfer API on both fabric and neoforge is the transaction system, where each change must store a snapshot that can be returned to if needed; Turns out ignoring the TransactionContext and not saving any snapshots is a bad idea 😅 I’ve tested and it’s compatible with create fly (see screenshot where a compact mob farm with a blaze is being used to feed a blaze burner for a steam engine) and most probably other mods as well. Added Reliable Recipe Viewer integration that explains soul capturing"}, {"post_id": 54946, "ts": "2026-08-26T11:20:57Z", "hours": 7.2406, "text": "Bunch of refactoring, bug fixes, balancing, etc. Release notes can be seen on the forgejo release or on modrinth, I’m not gonna copy paste em here (this is version 0.0.5 right now) It is now actually reviewed on Modrinth, took two weeks for that to happen (Gosh I remember when review times were like less than 24 hours ). I’m still keeping it unlisted until I get a 1.0.0 release out, but if anyone wants to check it out and share feedback or anything, then it’s right over here: https://modrinth.com/mod/ultimate-mob-farms Before a v1, I still need better rrv and item descriptions integration, some more balancing changes, advancements, quite a few bugfixes and probably some other stuff I’m forgetting at the moment."}, {"post_id": 50153, "ts": "2026-08-19T08:08:41Z", "hours": 2.3531, "text": "Made soul fans placed at different locations use a different starting frame offset, so they don’t all look the same (see before and after videos). The way this is implemented is a bit interesting… There’s no easy “use this model but offset any texture’s animation by 1 frame” as afaik the frame index is global per texture. What Minecraft does allow is each block state variant actually being an array of variants that the game will choose between using afaik a hash derived from the block position. This is used in vanilla for things like stone and deepslate, which have mirrored and rotated variants so caves look less repetitive or whatever. As each texture has a global frame index, I am duplicating the soul fan texture and just changing the order of the frames in the accompanying animation metadata file and creating separate models which point to the different textures and then those models are used as variants in the blockstate. What’s even more fun is I am using datagen for duplicating the texture and creating the animation metadata files, which definitely isn’t concerning at all. This also required me to make a pull request to fabric api because the FabricCodecDataProvider assumes all files it generates are .json files, but animation metadata is .mcmeta. (The PR isn’t yet merged so I resorted to…. injecting a mixin into fabric api, definitely not cursed at all I swear)"}, {"post_id": 49673, "ts": "2026-08-18T15:46:30Z", "hours": 4.43, "text": "Added particle effects for soul fan. Figuring out where to spawn em was quite fun actually, though I did have to add a custom particle (reuses the vanilla “small gust” texture) because turns out most particles won’t obey the velocity you give them and just do their own thing, which was a bit annoying."}, {"post_id": 49138, "ts": "2026-08-17T19:28:11Z", "hours": 3.7422, "text": "Added range upgrades for the fan and collector blocks. It was a bit challenging figuring out actually extending the bounding box in the correct directions based on the block is facing, but I did get it working"}, {"post_id": 48767, "ts": "2026-08-17T09:17:16Z", "hours": 4.6397, "text": "Implemented functionality of the soul fan, getting the strength to scale based on distance was a bit of a pain cause i needed to get the position of the center of the face that the fan’s pointing in and only calculate the distance to the entity based on the correct axis cause otherwise giving it a larger range would make the farther to the side entities get pushed less and uhh yeah, took quite a bit of experimenting with stuff to get it to work correctly"}, {"post_id": 47706, "ts": "2026-08-15T19:55:20Z", "hours": 0.9575, "text": "Spent the last hour and a half faffing about with my loader abstraction in monkeylib (stardance only recorded an hour cause that’s technically a separate project) for creative tabs. All that just cause I really wanted the RRV stack group for the filled soul gems to show up next to the empty soul gem, instead of at the end of the list where it did previously"}, {"post_id": 47530, "ts": "2026-08-15T14:35:38Z", "hours": 3.0928, "text": "Spent a bunch of time on cleaning up some code and abstracting some things out of collector block classes to make it easier to add functionality of the soul fan later on, speaking of which! the soul fan is a block that exists in game now"}, {"post_id": 46880, "ts": "2026-08-14T12:46:12Z", "hours": 0.2881, "text": "Spent some time thinking about what I’m gonna do for the block that moves mobs around. I think I’ve decided on going with a basic “fan” type block and now started working on what it could look like. I’m imagining the souls kinda like escaping from the soul sand and also particles spawning and moving in the direction it’s pushing. As always I’m pretty bad at drawing textures, so the beginning here looks a bit crude, but it’s definitely a start. It’d be really nice if aseprite had a wakatime plugin…"}, {"post_id": 46845, "ts": "2026-08-14T11:27:58Z", "hours": 3.8683, "text": "Added the experience collector block, which obviously picks up xp orbs and turns em into bottles of enchanting. Kind of got so focused I forgot about making more detailed devlogs 😅"}, {"post_id": 46238, "ts": "2026-08-13T10:39:10Z", "hours": 3.695, "text": "Made the soul spikes actually deal extra fall damage when fell on. Current fall damage multiplier is at 5, not sure if that is too much or too little. The damage is done by a FakePlayer, so the mob will also drop loot that only drops from player kills, including experience orbs. (Seems like I need to add an XP Collector block in the future to deal with those). Oh and also did some boilerplate-ish things to soul spikes like adding a recipe, translation, etc Turns out minecraft decides that the block you fall on is the one that’s 0.2 blocks below you…. The model of the soul spikes (which i don’t really wanna change anymore) has the base at 3 pixels high, which makes it… 0.1875 block high 😮💨 Nothing that can’t be solved with a mixin to Entity#getOnPosLegacy that changes the BlockPos it returns if the the block above the “correct” block is soul spikes"}, {"post_id": 45189, "ts": "2026-08-11T14:44:28Z", "hours": 0.2731, "text": "Made an okay-ish texture for the soul spikes block (many of em at once looks kinda noisy but oh well, it’ll do. Hopefully it’ll be locked up in a farm killing chamber room anyway). Had to change the UV mapping again because for whatever reasons, minecraft decides to render a sliver of the neighboring pixel as well which looks super bad with two very contrasty colors next to each other. Solution was to move the blue parts to the bottom of the texture where there was room to have it separated by a row of blank pixels."}, {"post_id": 45107, "ts": "2026-08-11T11:51:36Z", "hours": 0.7186, "text": "Finished UV mapping the spikes…. this literally took like over an hour haha, sadly time spent in blockbench doesn’t count as it doesn’t have a plugin for wakatime or whatever :/ (the 43min this devlog logs was actually setting up oxipng to automatically run on every commit to optimize the png files) Next i guess will be to make an actual texture for it, yay. Here’s the super very interesting texture that currently just has all the different mapped sides in different colors"}, {"post_id": 44754, "ts": "2026-08-10T18:48:32Z", "hours": 2.0067, "text": "Started working on the soul spikes. First made a model for it, not sure if it’ll look good once I make a texture for the actual spikes part of it as well"}, {"post_id": 41521, "ts": "2026-08-05T19:39:30Z", "hours": 1.7181, "text": "Been doing some boring things like writing a description and making an icon and some miscellaneous fixes and whatnot as I actually think I want to get this in a state where I could send it in for review on modrinth. Otherwise if I sent it in once I was actually finished with the project, it probably wouldn’t get reviewed before stardance ends and then i’d have to tell people to download the mod from my git releases and that wouldn’t automatically tell em where to get dependencies and whatnot so yeah, want to get it in the queue asap. Here’s the icon I came up with btw"}, {"post_id": 40668, "ts": "2026-08-04T11:02:42Z", "hours": 2.4575, "text": "Added a texture and recipe to item collector, made it possible to disable it using redstone, made the sample collector only pick up items every 10 ticks."}, {"post_id": 39730, "ts": "2026-08-02T21:36:20Z", "hours": 1.855, "text": "Shift-right-clicking an item collector with an empty hand now shows its range. Drawing lines of particles between the correct corners for the outline took a bit of trial and error, also added a screenshot where it doesn’t look quite correct Also I’m not sure if the video from the previous devlog got uploaded correctly (my browser at least isn’t able to play it) so here it is again"}, {"post_id": 39564, "ts": "2026-08-02T16:40:59Z", "hours": 2.9042, "text": "Made item collector spawn a line of particles when picking up items Oh and also added compatibility to item collector with container blocks from other mods that use the fabric or neoforge transfer api instead of vanilla containers, more loader specific stuff, yay!"}, {"post_id": 38906, "ts": "2026-08-01T14:21:22Z", "hours": 1.0933, "text": "Implemented basic functionality of the item collector. Currently has a range of 2 blocks that it will pick things up from and put em straight into a connected inventory"}, {"post_id": 38761, "ts": "2026-08-01T10:08:52Z", "hours": 3.6756, "text": "Started work on adding the item collector, currently just got done with adding the block itself with some boilerplate stuff and a model. As the name suggests, it’ll be for picking up items in some range of it. Not quite sure if I want it to be a range all around the block, or maybe going outwards from the direction it’s facing? Also not yet quite sure if I want it to just put stuff into an internal inventory and require a hopper or something modded to pull out of it, or if it should act like a hopper pushing things out from the side it’s attached on"}, {"post_id": 37603, "ts": "2026-07-30T13:35:05Z", "hours": 1.1933, "text": "Received new textures and spent some time messing around in the mcmeta file for the animation timing. Looks quite good now. Also made the empty soul gem use the same texture, just with a soul light blue colors."}, {"post_id": 37190, "ts": "2026-07-29T18:31:37Z", "hours": 5.0456, "text": "Past while has been spent on fighting with gradle to extend my overly complicated setup ( monkeylogic, my gradle convention plugin ) and make it even more complicated allow adding dependencies from modrinth to projects. After that I could easily add RRV (Reliable Recipe Viewer) as a dependency and now lastly add integration with it. Currently I’ve got integration to the point of showing the custom duplication recipe, which is great"}, {"post_id": 35160, "ts": "2026-07-26T12:28:59Z", "hours": 2.7197, "text": "Finally fixed the soul gem duplication recipe, which was a bit of a pain to deal with… I initially went down a dumb rabbit hole of overcomplicating the matcher system when turns out having multiple of the same item in the recipe can easily be solved by storing a count for each ingredient instead of having multiple entries for them 😝"}, {"post_id": 34287, "ts": "2026-07-24T21:18:42Z", "hours": 2.5044, "text": "Made spawners craftable, made interacting with spawners using a filled soul gem set the entity in the spawner. Still not quite sure what to call the “filled” soul gem. One idea i had was to call it just a soul gem and call the not filled one an “Empty Soul Gem”, which is honestly a pretty good idea, but I’m not sure what to do when it’s in the process of being filled. Technically at that point it’s not empty , but maybe it’d be fine to call it that"}, {"post_id": 32839, "ts": "2026-07-22T07:47:33Z", "hours": 3.5317, "text": "Lots of fun stuff between this and the last devlog: Creative tab for filled soul gems now only contains supported ones (had to make creative tabs refresh when data is reloaded cause datapacks can change what’s supported) Removed the old SampleTakerItem and FilledSampleTakerItem classes and moved most logic to custom components or mixins. Soul gems can be filled by holding them in the off hand when killing the target entity ( https://imgur.com/a/Lz6PjZs ) Some optimizations"}, {"post_id": 32407, "ts": "2026-07-21T16:00:26Z", "hours": 1.9203, "text": "Optimized the EntityTiers lookup (which I mentioned I messed up last devlog) by using a map instead of a list, and it’s also now storing a reference to the Identifier instead of EntityType, so there’s less work converting between them for the packet codec (has to be sent as an Identifier (or, well, string) over the network) and also when doing some of the lookups (like from the tint provider, which has just the id by itself) Not sure what to put as the screenshot it requires me to add…. I guess have some prototypes of the new soul gem texture a person’s working on (the final shape will probably not be a perfectly round pearl)"}, {"post_id": 32271, "ts": "2026-07-21T10:39:38Z", "hours": 3.1261, "text": "Made “filled” soul gems have colors based on the entity they contain! (and also switched to a different (and probably even worse lmao) texture) The colors are the same as what spawn eggs used to have, thankfully the minecraft wiki has a list of what they all were before that was removed. Sadly I can’t steal the entity colors from vanilla anymore as that was removed in 1.21.5, so I had to add color fields to the entity tiers config and that messed with a lot of stuff and is a bit of a hit on performance when it’s not looping over stuff in weird ways as it’s a list of entries when it really should probably be a map… I’ll fix that i guess Also I know this texture is ass and someone a bit more talented in drawing is cooking up a new one which I’ll probably be able to show off in a few days. Question is… do I want the current one to show up when the vanilla programmer art pack is enabled or is that too embarrassing to show off?"}, {"post_id": 31810, "ts": "2026-07-20T14:25:41Z", "hours": 0.9456, "text": "Added recipes, translations, etc for soul essence and gem, removed spirit bottle, added recipe for spawner, made spawners drop with silk touch. Thanks to neoforge there have to be separate mixins for fabric and neo for disabling the xp drop when a spawner is broken with silk touch (would lead to infinite xp otherwise lol)…. if only neoforge was just fabric"}, {"post_id": 31751, "ts": "2026-07-20T12:04:50Z", "hours": 1.2917, "text": "Made soul essence drop from mobs killed on soul sand/soil. Also spawns fun particles! https://imgur.com/a/Qt5XxUI"}, {"post_id": 31695, "ts": "2026-07-20T09:44:19Z", "hours": 0.3378, "text": "So I’ve been doing some brainstorming and writing things down on paper (like a caveman) and have at least redesigned some of the features that already exist. Instead of a bottle of spirits that you get by right clicking a spawner, there’s going to be Soul Essence that you get by killing a mob while they’re standing on soul sand/soil. Instead of the Sample taker, there’s gonna be a soul gem crafted from a diamond and 4 soul essence that will be filled by holding it in your offhand while killing x amount of the target mob. Also thought of some recipes that I’m not gonna explain here rn. Sadly (or thankfully) I haven’t found a wakatime plugin for Aseprite, so nobody will know just how many hours I spent on the absolute trash textures I made for the soul gem and soul essence (I promise they’ll be better at some point maybe idk if I can do any better 😭 ). Soul essence just looks off somehow, and the soul gem looks like a duck spawn egg 😭 😭 😭 😭"}, {"post_id": 31122, "ts": "2026-07-19T08:32:28Z", "hours": 6.5108, "text": "It is now working on NeoForge as well! Getting the inventory to work with the neoforge transfer api was a bit of a pain, but I managed to get it to work! (Don’t mind the debug upgrades in the screenshot, they make it easier to test but dont have textures) Next up is uhh… some brainstorming and rethinking how the whole mod works and thinking about what’s in scope for this and what’s not: One thing I definitely want to add is a crafting recipe for spawners and making the sample takers (which will probably be renamed to something relating to souls and gems) usable as spawn eggs on spawners. I’m not quite sure if upgradeable spawners should be a part of this though as there’s already apotheosis for neoforge (and a port in the works for fabric) that does that and probably other mods as well. I also really wanted to add things for moving and killing mobs in the world, for which there are also already mods like Dark Utilities (got quite inspired by that) which afaik also is updated to the latest version and is for both fabric and neoforge…. Though it seems to have more random things unrelated to mob farming, and maybe it’d be fine if I really differentiate from it and other similar mods with the theme of this? Yeahhh this’ll need quite a bit more thinking."}, {"post_id": 28545, "ts": "2026-07-14T21:20:48Z", "hours": 2.0633, "text": "Finished getting everything out of :loader:fabric and into :modded that makes sense to move. The fabric subproject now only has 4 files, two of which are just the entrypoints that invoke the common initializer and the other two are using fabric api specific things and can’t be moved out without a lot of headache!"}, {"post_id": 28177, "ts": "2026-07-14T09:44:23Z", "hours": 0.2531, "text": "(the 15m were spent working on getting MenuProvider stuff out from fabric specific code and into the common modded subproject, butttt I’m making a post cause I wanna share…) Some funny screenshots from when I was porting from 1.21.1 to 26.1 (rendering changes here are a pain lol)"}, {"post_id": 28170, "ts": "2026-07-14T09:24:59Z", "hours": 17.9675, "text": "Just realized this is probably something I could submit to stardance as well 😅 Basically the initial idea was to have a mob farm contained in a single block. You craft a sample taker and have to click on 10 separate instances of an entity to get a filled sample of that entity. Then you put that into a Compact Mob Farm, turn it on, maybe give it some upgrades and a sword, and it’ll start farming the drops of the entity you took samples of. Here are some screenshots of what stuff looks like"}]...
|
Title: Ultimate Mob Farms by @OffsetMonkey538 | St Title: Ultimate Mob Farms by @OffsetMonkey538 | Stardance
Devlogs:
Just realized this is probably something I could submit to stardance as well 😅 Basically the initial idea was to have a mob farm contained in a single block. You craft a sample taker and have to click on 10 separate instances of an entity to get a filled sample of that entity. Then you put that into a Compact Mob Farm, turn it on, maybe give it some upgrades and a sword, and it’ll start farming the drops of the entity you took samples of. Here are some screenshots of what stuff looks like
(the 15m were spent working on getting MenuProvider stuff out from fabric specific code and into the common modded subproject, butttt I’m making a post cause I wanna share…) Some funny screenshots from when I was porting from 1.21.1 to 26.1 (rendering changes here are a pain lol)
Finished getting everything out of :loader:fabric and into :modded that makes sense to move. The fabric subproject now only has 4 files, two of which are just the entrypoints that invoke the common initializer and the other two are using fabric api specific things and can’t be moved out without a lot of headache!
It is now working on NeoForge as well! Getting the inventory to work with the neoforge transfer api was a bit of a pain, but I managed to get it to work! (Don’t mind the debug upgrades in the screenshot, they make it easier to test but dont have textures) Next up is uhh… some brainstorming and rethinking how the whole mod works and thinking about what’s in scope for this and what’s not: One thing I definitely want to add is a crafting recipe for spawners and making the sample takers (which will probably be renamed to something relating to souls and gems) usable as spawn eggs on spawners. I’m not quite sure if upgradeable spawners should be a part of this though as there’s already apotheosis for neoforge (and a port in the works for fabric) that does that and probably other mods as well. I also really wanted to add things for moving and killing mobs in the world, for which there are also already mods like Dark Utilities (got quite inspired by that) which afaik also is updated to the latest version and is for both fabric and neoforge…. Though it seems to have more random things unrelated to mob farming, and maybe it’d be fine if I really differentiate from it and other similar mods with the theme of this? Yeahhh this’ll need quite a bit more thinking.
So I’ve been doing some brainstorming and writing things down on paper (like a caveman) and have at least redesigned some of the features that already exist. Instead of a bottle of spirits that you get by right clicking a spawner, there’s going to be Soul Essence that you get by killing a mob while they’re standing on soul sand/soil. Instead of the Sample taker, there’s gonna be a soul gem crafted from a diamond and 4 soul essence that will be filled by holding it in your offhand while killing x amount of the target mob. Also thought of some recipes that I’m not gonna explain here rn. Sadly (or thankfully) I haven’t found a wakatime plugin for Aseprite, so nobody will know just how many hours I spent on the absolute trash textures I made for the soul gem and soul essence (I promise they’ll be better at some point maybe idk if I can do any better 😭 ). Soul essence just looks off somehow, and the soul gem looks like a duck spawn egg 😭 😭 😭 😭
Made soul essence drop from mobs killed on soul sand/soil. Also spawns fun particles! https://imgur.com/a/Qt5XxUI
Added recipes, translations, etc for soul essence and gem, removed spirit bottle, added recipe for spawner, made spawners drop with silk touch. Thanks to neoforge there have to be separate mixins for fabric and neo for disabling the xp drop when a spawner is broken with silk touch (would lead to infinite xp otherwise lol)…. if only neoforge was just fabric
Made “filled” soul gems have colors based on the entity they contain! (and also switched to a different (and probably even worse lmao) texture) The colors are the same as what spawn eggs used to have, thankfully the minecraft wiki has a list of what they all were before that was removed. Sadly I can’t steal the entity colors from vanilla anymore as that was removed in 1.21.5, so I had to add color fields to the entity tiers config and that messed with a lot of stuff and is a bit of a hit on performance when it’s not looping over stuff in weird ways as it’s a list of entries when it really should probably be a map… I’ll fix that i guess Also I know this texture is ass and someone a bit more talented in drawing is cooking up a new one which I’ll probably be able to show off in a few days. Question is… do I want the current one to show up when the vanilla programmer art pack is enabled or is that too embarrassing to show off?
Optimized the EntityTiers lookup (which I mentioned I messed up last devlog) by using a map instead of a list, and it’s also now storing a reference to the Identifier instead of EntityType, so there’s less work converting between them for the packet codec (has to be sent as an Identifier (or, well, string) over the network) and also when doing some of the lookups (like from the tint provider, which has just the id by itself) Not sure what to put as the screenshot it requires me to add…. I guess have some prototypes of the new soul gem texture a person’s working on (the final shape will probably not be a perfectly round pearl)
Lots of fun stuff between this and the last devlog: Creative tab for filled soul gems now only contains supported ones (had to make creative tabs refresh when data is reloaded cause datapacks can change what’s supported) Removed the old SampleTakerItem and FilledSampleTakerItem classes and moved most logic to custom components or mixins. Soul gems can be filled by holding them in the off hand when killing the target entity ( https://imgur.com/a/Lz6PjZs ) Some optimizations
Made spawners craftable, made interacting with spawners using a filled soul gem set the entity in the spawner. Still not quite sure what to call the “filled” soul gem. One idea i had was to call it just a soul gem and call the not filled one an “Empty Soul Gem”, which is honestly a pretty good idea, but I’m not sure what to do when it’s in the process of being filled. Technically at that point it’s not empty , but maybe it’d be fine to call it that
Finally fixed the soul gem duplication recipe, which was a bit of a pain to deal with… I initially went down a dumb rabbit hole of overcomplicating the matcher system when turns out having multiple of the same item in the recipe can easily be solved by storing a count for each ingredient instead of having multiple entries for them 😝
Past while has been spent on fighting with gradle to extend my overly complicated setup ( monkeylogic, my gradle convention plugin ) and make it even more complicated allow adding dependencies from modrinth to projects. After that I could easily add RRV (Reliable Recipe Viewer) as a dependency and now lastly add integration with it. Currently I’ve got integration to the point of showing the custom duplication recipe, which is great
Received new textures and spent some time messing around in the mcmeta file for the animation timing. Looks quite good now. Also made the empty soul gem use the same texture, just with a soul light blue colors.
Started work on adding the item collector, currently just got done with adding the block itself with some boilerplate stuff and a model. As the name suggests, it’ll be for picking up items in some range of it. Not quite sure if I want it to be a range all around the block, or maybe going outwards from the direction it’s facing? Also not yet quite sure if I want it to just put stuff into an internal inventory and require a hopper or something modded to pull out of it, or if it should act like a hopper pushing things out from the side it’s attached on
Implemented basic functionality of the item collector. Currently has a range of 2 blocks that it will pick things up from and put em straight into a connected inventory
Made item collector spawn a line of particles when picking up items Oh and also added compatibility to item collector with container blocks from other mods that use the fabric or neoforge transfer api instead of vanilla containers, more loader specific stuff, yay!
Shift-right-clicking an item collector with an empty hand now shows its range. Drawing lines of particles between the correct corners for the outline took a bit of trial and error, also added a screenshot where it doesn’t look quite correct Also I’m not sure if the video from the previous devlog got uploaded correctly (my browser at least isn’t able to play it) so here it is again
Added a texture and recipe to item collector, made it possible to disable it using redstone, made the sample collector only pick up items every 10 ticks.
Been doing some boring things like writing a description and making an icon and some miscellaneous fixes and whatnot as I actually think I want to get this in a state where I could send it in for review on modrinth. Otherwise if I sent it in once I was actually finished with the project, it probably wouldn’t get reviewed before stardance ends and then i’d have to tell people to download the mod from my git releases and that wouldn’t automatically tell em where to get dependencies and whatnot so yeah, want to get it in the queue asap. Here’s the icon I came up with btw
Started working on the soul spikes. First made a model for it, not sure if it’ll look good once I make a texture for the actual spikes part of it as well
Finished UV mapping the spikes…. this literally took like over an hour haha, sadly time spent in blockbench doesn’t count as it doesn’t have a plugin for wakatime or whatever :/ (the 43min this devlog logs was actually setting up oxipng to automatically run on every commit to optimize the png files) Next i guess will be to make an actual texture for it, yay. Here’s the super very interesting texture that currently just has all the different mapped sides in different colors
Made an okay-ish texture for the soul spikes block (many of em at once looks kinda noisy but oh well, it’ll do. Hopefully it’ll be locked up in a farm killing chamber room anyway). Had to change the UV mapping again because for whatever reasons, minecraft decides to render a sliver of the neighboring pixel as well which looks super bad with two very contrasty colors next to each other. Solution was to move the blue parts to the bottom of the texture where there was room to have it separated by a row of blank pixels.
Made the soul spikes actually deal extra fall damage when fell on. Current fall damage multiplier is at 5, not sure if that is too much or too little. The damage is done by a FakePlayer, so the mob will also drop loot that only drops from player kills, including experience orbs. (Seems like I need to add an XP Collector block in the future to deal with those). Oh and also did some boilerplate-ish things to soul spikes like adding a recipe, translation, etc Turns out minecraft decides that the block you fall on is the one that’s 0.2 blocks below you…. The model of the soul spikes (which i don’t really wanna change anymore) has the base at 3 pixels high, which makes it… 0.1875 block high 😮💨 Nothing that can’t be solved with a mixin to Entity#getOnPosLegacy that changes the BlockPos it returns if the the block above the “correct” block is soul spikes
Added the experience collector block, which obviously picks up xp orbs and turns em into bottles of enchanting. Kind of got so focused I forgot about making more detailed devlogs 😅
Spent some time thinking about what I’m gonna do for the block that moves mobs around. I think I’ve decided on going with a basic “fan” type block and now started working on what it could look like. I’m imagining the souls kinda like escaping from the soul sand and also particles spawning and moving in the direction it’s pushing. As always I’m pretty bad at drawing textures, so the beginning here looks a bit crude, but it’s definitely a start. It’d be really nice if aseprite had a wakatime plugin…
Spent a bunch of time on cleaning up some code and abstracting some things out of collector block classes to make it easier to add functionality of the soul fan later on, speaking of which! the soul fan is a block that exists in game now
Spent the last hour and a half faffing about with my loader abstraction in monkeylib (stardance only recorded an hour cause that’s technically a separate project) for creative tabs. All that just cause I really wanted the RRV stack group for the filled soul gems to show up next to the empty soul gem, instead of at the end of the list where it did previously
Implemented functionality of the soul fan, getting the strength to scale based on distance was a bit of a pain cause i needed to get the position of the center of the face that the fan’s pointing in and only calculate the distance to the entity based on the correct axis cause otherwise giving it a larger range would make the farther to the side entities get pushed less and uhh yeah, took quite a bit of experimenting with stuff to get it to work correctly
Added range upgrades for the fan and collector blocks. It was a bit challenging figuring out actually extending the bounding box in the correct directions based on the block is facing, but I did get it working
Added particle effects for soul fan. Figuring out where to spawn em was quite fun actually, though I did have to add a custom particle (reuses the vanilla “small gust” texture) because turns out most particles won’t obey the velocity you give them and just do their own thing, which was a bit annoying.
Made soul fans placed at different locations use a different starting frame offset, so they don’t all look the same (see before and after videos). The way this is implemented is a bit interesting… There’s no easy “use this model but offset any texture’s animation by 1 frame” as afaik the frame index is global per texture. What Minecraft does allow is each block state variant actually being an array of variants that the game will choose between using afaik a hash derived from the block position. This is used in vanilla for things like stone and deepslate, which have mirrored and rotated variants so caves look less repetitive or whatever. As each texture has a global frame index, I am duplicating the soul fan texture and just changing the order of the frames in the accompanying animation metadata file and creating separate models which point to the different textures and then those models are used as variants in the blockstate. What’s even more fun is I am using datagen for duplicating the texture and creating the animation metadata files, which definitely isn’t concerning at all. This also required me to make a pull request to fabric api because the FabricCodecDataProvider assumes all files it generates are .json files, but animation metadata is .mcmeta. (The PR isn’t yet merged so I resorted to…. injecting a mixin into fabric api, definitely not cursed at all I swear)
Bunch of refactoring, bug fixes, balancing, etc. Release notes can be seen on the forgejo release or on modrinth, I’m not gonna copy paste em here (this is version 0.0.5 right now) It is now actually reviewed on Modrinth, took two weeks for that to happen (Gosh I remember when review times were like less than 24 hours ). I’m still keeping it unlisted until I get a 1.0.0 release out, but if anyone wants to check it out and share feedback or anything, then it’s right over here: https://modrinth.com/mod/ultimate-mob-farms Before a v1, I still need better rrv and item descriptions integration, some more balancing changes, advancements, quite a few bugfixes and probably some other stuff I’m forgetting at the moment.
Fixed compact mob farm inventory not working correctly and being incompatible with other mods’ item movement stuff. The whole point of the transfer API on both fabric and neoforge is the transaction system, where each change must store a snapshot that can be returned to if needed; Turns out ignoring the TransactionContext and not saving any snapshots is a bad idea 😅 I’ve tested and it’s compatible with create fly (see screenshot where a compact mob farm with a blaze is being used to feed a blaze burner for a steam engine) and most probably other mods as well. Added Reliable Recipe Viewer integration that explains soul capturing
checking the recipe for a specific soul gem now only shows that specific entity instead of all soul capturing recipes soul capturing recipe now shows up before the duplication recipe soul gems can now be searched by the name of the entity they contain fix compact mob farm gui not rendering vanilla background overlay allow filling soul gem when held in the main hand fix dedicated server crashing Running in a dedicated server would crash because there are quite a few places where I referenced client-only classes in places that the jvm will load on the dedicated server as well. Mostly in the different block entity classes, where I had a clientTick method that had ClientLevel as one of it’s parameters. Even though that method would never get called on the dedicated server, java still wants it to exist when loading the class because it’s part of a method’s definition. My current solution is very very awful… I moved those things into methods in the client initializer and… well… yeah… it just looks and is awful: https://git.offsetmonkey538.top/OffsetMods538/Ultimate-Mob-Farms/src/commit/0.0.7/modded/src/main/java/top/offsetmonkey538/ultimatemobfarms/modded/UltimateMobFarmsModdedClient.java#L65 The real, foolproof solution would be using the split sources feature of loom, which creates a second source set and makes the main source set unable to access client classes. Only problem is that it’d be a bit annoying to fully get set up in my multiloader-version gradle system and would most definitely need many changes on MonkeyLib538 as well and I just am not up for doing that atm.
Getting closer and closer to the actual release… could this be the last devblog before that? Still not quite 100% about if the required kills for each mob are balanced, but it’s probably good enough. Definitely better than everything being 10 kills tho. Felt very off-balance when withers, which are hard to spawn and hard to kill, and pigs, which are just everywhere, required the same amount of kills to capture. Notable changes: Show soul capturing recipe in rrv when checking usages of spawn eggs Show tooltip with entity name when hovering entity in soul capturing rrv recipe Add item descriptions Fix being able to insert items into the compact mob farm inventory Make amount of kills required for capturing an entity different per entity. Update compact mob farm recipe (now uses soul spikes in the middle instead of stone bricks) Store soul gem colors as hex strings in entity tiers config. Much more understandable and easier to manually change the overrides config or whatever Make built-in packs use the mod icon using a mixin instead of copying the icon into the packs. This shaves like 80kb off the final jar which is quite a bit of unnecessary duplicate crap Remove some log spam that was for debugging
School starting with september really hit my productivity on this mod like a truck I am realizing the deadline for stardance is getting real close, so I think this is probably the point where I’ll have to ship it. There are still some TODOs in the code and bugs that need to be squashed and porting to 26.3 (which released like this week, thanks mojang ) and so I haven’t been comfortable marking the latest release as 1.0.0 yet or making announcements elsewhere, but the mod is now perfectly usable and I like where it is. Changes since last devblog: 26.2 support Injecting some items into vanilla loot chests Advancements 26.2 wasn’t actually as painful as I thought it’d be, which was a nice surprise. Adding advancements was a bit more of a pain with 26.2 support though as I needed custom criteria for some of the advancements (one for putting a soul gem in the compact mob farm and another for using a soul gem on a spawner) and Mojang, in their infinite wisdom, decided to move a bunch of advancement stuff around in 26.2.
Waow that’s quite a bit of stardust 😅 Quite happy with this project and the ratings it got on the first ship :D (except the one that accused my devlogs of being written by ai… My writing is not that bad, right? ) I noticed in the shipwrights’ review video that how upgrades work is not very obvious, they were trying to put a tier upgrade into a soul fan, which only accepts width, height and depth upgrades. It was mentioned in ratings that stuff is a bit hard to figure out in the beginning as well. So to fix that, I added some silhouettes of the supported upgrades shown in the slots and also a hover tooltip saying what’s supported. Oh and i’ve also added 26.3 support now
Added a progress bar to the Compact Mob Farm GUI that hopefully makes it much easier to understand when it’ll damage the entity and it doesn’t look like it’s just doing nothing lol, especially with the 30 second default time
Added an RRV screen showing what items can be acquired from the Compact Mob Farm. Shows the entity, the items it drops and the required tier upgrade level. Hoping this also helps with confusion on how stuff works
Started working on setting up a docs page for the mod. Mainly want it for explaining the data driven configuration, but having full pages to give more detailed explanations of the different features is also probably a nice touch. Made a new icon for the mod as well, it’s pretty much the same but higher res because the 256x256 one looked weird on the docs page. The docs are done using Starlight like all my other docs pages (see those here ) and lives at https://ultimate-mob-farms.docs.cursedmods.com/ and on the docs/master branch in the repo Currently it’s just the landing page, but it’ll have more stuff soon enough
Ships:
This is a Minecraft mod for making mob farms, something similar to for example Mob Grinding Utils. It features item and xp collection, entity movement, spawner relocation and crafting, single block mob farms and some other stuff. Honestly, I’m quite proud just over the fact that I finally did finish this project (or at least got it to the point of being comfortable releasing it publically) and it’s hard to choose any specific features, but here I go… I do really like how the particle effects for the soul fan turned out, they’re quite satisfying imo. This is kind of unrelated to the mod, but I’m also proud of having helped out with the development of RRV, the recipe viewer mod I added compat with. While adding support for it in this mod, I noticed some bugs and crashes and stuff, which I PRed fixes for. It’s a bigger project with many complex things, so coming up with a list of all the things I found hard or took a lot of time and explaining all of them would probably go over whatever character limit this text box has lol. One thing that was a big PITA was the compact mob farm inventory. The original implementation I wrote was just… completely wrong, so I had to rewrite it. Then later I realized I overlooked like the most important part of the item transfer api (transactions, which are used for rolling back changes and stuff) so I had to rewrite it again, and then after that I rewrote quite a bit of it one more time because, after the last rewrite, I had accidentally made it possible for other blocks to insert into the inventory, which isn’t something I wanted as that seems quite OP. Another thing that comes to mind is figuring out the code for the soul fan’s range based on upgrades and strength at a given distance. The problem was that the coordinate you have to increase/decrease depends on the orientation of the block, so as an example, the depth upgrade would need to increase the Y pos when the block is placed pointing up and decrease it when pointing down, the X pos when facing north/south and the Z pos when facing east/west. For pushing the entities, I had to find the coordinates of the middle of the face the block is pointing, and add/subtract the correct coordinate to get the range in the depth direction, and then find the distance between each entity currently in range and the fan in just that plane for calculating the strength. For people testing out the project, I definitely do recommend also installing the Reliable Recipe Viewer (RRV) and Item Description mods...
|
1792853443.0379903
|
1792939843.0379903
|
|
901
|
Kern by @AntKru | Stardance
|
AntKru
|
3
|
153.98
|
2739
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-20T16:46:53Z", "hours": 65.0, "multiplier": 19.56, "payout": 1269, "blessing": "neutral", "text": "I have released the next version of my own kernel! The biggest feature I added is multitasking. While it doesn’t look that special, it was actually very difficult to make my kernel switch between different tasks! Here are some notes on how to try the project: If you don’t want/can’t run it, you can look at the video in the readme. If you want to run it on macOS with UTM, you have to force a PS/2 controller: https://docs.getutm.app/settings-qemu/qemu/#force-ps2-controller", "repo": "https://gitlab.com/AntKru/kern", "demo": "https://gitlab.com/AntKru/kern/-/releases/"}, {"ship_num": 2, "ts": "2026-07-24T06:30:43Z", "hours": 48.0, "multiplier": 19.83, "payout": 961, "blessing": "neutral", "text": "I added a CLI the kernel, which was possible, because I finally have a keyboard driver! It only took so long, because it was actually difficult to write it: I thought I have to program the PIC, but it was already disabled so I had to learn the more complicated APIC. There is a demo video in the README if you don’t want to run the kernel. If you want to run it on macOS with UTM, you have to force a PS/2 controller: https://docs.getutm.app/settings-qemu/qemu/#force-ps2-controller", "repo": "https://gitlab.com/AntKru/kern", "demo": "https://gitlab.com/AntKru/kern/-/releases/"}, {"ship_num": 3, "ts": "2026-06-20T14:34:14Z", "hours": 30.0, "multiplier": 17.21, "payout": 509, "blessing": "neutral", "text": "I made an x86_64 kernel using the limine boot protocol. I don’t know what the most difficult thing was, as even most basic things are very complicated for me as a beginner in osdev. I still have to learn much and the kernel will be improved, but I thing it kind of works now. I have a video demo in the readme, if you don’t have qemu . When building, remember to clone the submodules ( git submodule init && git submodule update ). You need xorriso to build the ISO. Sorry for mixing meson and make , but in the README is a guide. Please use clang, gcc is very complicated.", "repo": "https://gitlab.com/AntKru/kern", "demo": "https://gitlab.com/AntKru/kern/-/releases/"}]...
|
[{"post_id": 79283, "ts": "202 [{"post_id": 79283, "ts": "2026-10-13T09:56:47Z", "hours": 4.6628, "text": "Memory management problems… It seems like there was a critical bug sleeping inside my memory manager. It appeared since I started using the PMM in my AHCI driver, but I think the problem is in the virtual memory manager. For this reason I am working currently on the memory manager instead of the AHCI driver. Roadmap As soon as I fix the MM, I will continue on the AHCI driver. It probably won’t be finished until the end of stardance."}, {"post_id": 76791, "ts": "2026-10-04T16:08:54Z", "hours": 2.6242, "text": "AHCI! (SATA) I am jumping a little bit fast form PCI to AHCI, but I think the PCI driver is as good as I need it right now, and if I learn that it isn’t, I will fix it. Anyway, I am starting to work on AHCI! This is really cool, as this allows me to communicate to storage devices! At the moment the kernel just lists connected devices, but that’s just the beginning! Roadmap The AHCI driver is in a very early stage, and it will take me a lot of time to finish, as AHCI is relatively complicated and the documentation isn’t written for beginners like me ;-)"}, {"post_id": 74920, "ts": "2026-09-28T16:27:51Z", "hours": 3.6928, "text": "PCI! I am starting to write a PCI driver, which opens a new world to me! As you can see, the kernel is already able to print some information on boot about connected PCI devices. I also added a function that can search for a specific PCI device by it’s class, which will help me to implement drivers for specific PCI devices. Roadmap The real reason I am implementing PCI is that I need it to find the AHCI controller. The AHCI controller can be used to access connected storage devices, which is my long-term goal."}, {"post_id": 71311, "ts": "2026-09-20T16:38:40Z", "hours": 1.3486, "text": "Release 0.3.0 I finished the release, including the new borders command! The visible bugs that I found are also fixed, please report them if you find some! Roadmap The kernel isn’t finished yet, I will continue to improve it and see how far I will get."}, {"post_id": 70750, "ts": "2026-09-19T18:15:14Z", "hours": 4.075, "text": "Final improvements before the next release Status bar I moved the status bar from the bottom to the top and removed the borders, in my opinion it looks better this way. Framebuffer borders I am already working on a new command which will make it possible to see the borders of the framebuffer in QEMU. This will be useful for debugging while keeping the UI simple. Bugs There are still some obvious bugs: My printf() implementation seems to break with invalid format strings and I have a bug in my memory manager which prevents me from merging the command showing the screen borders into main. Roadmap I will try to fix the bugs, but the features are now complete. I want to release the new version tomorrow."}, {"post_id": 68765, "ts": "2026-09-15T18:23:31Z", "hours": 7.8061, "text": "printf compatability I improved the printf() compatability, so that I can pad numbers with or 0 . This is very useful, for example I now can use it to display time and date properly. Roadmap I don’t know yet what’s the next thing to do, maybe I will ship soon."}, {"post_id": 63678, "ts": "2026-09-07T16:41:58Z", "hours": 4.1103, "text": "Status bar! I added a status bar which show the current time. It is very basic, but makes the OS look way more friendlier in my opinion. Sorry for the weird messages in the main window, I am currently debugging my printf implementation. Roadmap I still have a problem with printing dates: The year 2006 would be printed as 206 , because the RTC has seperate registers for year and century, so if century is 20 and year is 6 it prints 206."}, {"post_id": 58325, "ts": "2026-08-30T18:21:09Z", "hours": 2.6081, "text": "“Windows” I am making it possible to split the framebuffer into multiple views. This should make it more easy to have a more advanced UI than a CLI already inside the kernel. Hopefully there will be user processes at some point, but I want to have a nice looking OS before that. Roadmap I still have to fix some things (as visible on the screenshot). After that, I can try to make use of it and add a status bar or a separate command window."}, {"post_id": 55470, "ts": "2026-08-27T10:27:14Z", "hours": 4.5317, "text": "RTC The kernel can now read the current time from the Computer’s RTC! At the moment, you can’t select the time zone, so the time is probably in UTC, depending on how the computer is configured. Roadmap I am planning to improve the use experience, for example by using multiple “windows”, to maybe even have a status bar."}, {"post_id": 52423, "ts": "2026-08-22T15:29:50Z", "hours": 4.2389, "text": "GCC support I added GCC support, which should (hopefully) make debugging easier for me. I can’t show it really on the screenshot, trust me, it is compiled with gcc! Roadmap I have still bugs in my multitasking system. Currently I get a page fault when compiling with optimization > -O2 with clang, the next step is to test it with GCC."}, {"post_id": 47914, "ts": "2026-08-16T05:50:20Z", "hours": 2.6892, "text": "Mutexes I implemented a simple mutex (which isn’t perfect yet, but it works). As visible on the screenshot, I used it to make it impossible for the test tasks to print at the same time. One problem with it is that it currently runs hlt after releasing a mutex so that a different task has a chance to acquire it, which doesn’t seem like the best solution to me. Roadmap I am making the terminal position atomic, so that I don’t need mutexes for output, which I can not use in interrupt handlers"}, {"post_id": 46418, "ts": "2026-08-13T16:41:17Z", "hours": 5.8897, "text": "Multitasking! I fixed the last bug (that I could find) and multitasking works now! On the screenshot you can see two tasks trying to print the numbers 0-19 at the same time. The CLI even waits until the tasks are finished! Road map The output is still a little bit broken, so I want to implement output buffering and mutexes, so that multiple threads can’t print at the same time."}, {"post_id": 44770, "ts": "2026-08-10T19:26:17Z", "hours": 6.2656, "text": "Multitasking… I am still working on multitasking, but I am stuck currently. I am trying to modify the stack frame so that asm_switch_task is called after iretq , but it doesn’t work. As you can see on the screenshot, I get a page fault as soon as it tries to switch tasks (in the debugging process I had it switch 2-3 times before it crashes, which is not really better) Road map My highest priority is to get task switching to work consistently. After that, I will see what I can polish."}, {"post_id": 43900, "ts": "2026-08-09T10:50:40Z", "hours": 2.4128, "text": "SSE register state switching! The kernel will now switch the SSE register state lazily, but I still have two problems: The Part for the registers in the TCB must be 16 byte aligned, which it currently not guaranteed The interrupt handlers are not allowed to use SSE instructions, but I have no way of verifying this Road map I think it is time to write a version of malloc() which can guarantee a specified alignment. After that, I can try to actually switch tasks automatically with a simple scheduler! I will probably use the PIT interrupt to switch to the next task in a list."}, {"post_id": 42570, "ts": "2026-08-07T11:56:52Z", "hours": 4.5606, "text": "It probably doesn’t sound special, but it is as important as everything else: SSE support SSE is an extension of the CPU which has 16 128-bit registers, but is rarely used. This means, that saving all of these registers every time a task switch occurs would cost some performance. For this reason, the CPU has a bit that can be set to indicate that a task switch occurred. In most cases, nothing happens and the registers are kept in their original state. But if a task needs to use SSE instructions, the CPU generates an interrupt, which manually saves the SSE registers. This is what I am working on currently. Custom ISR wrapper All interrupt handlers use now my custom wrappers, which made possible that I can work on SSE support."}, {"post_id": 40940, "ts": "2026-08-04T19:52:16Z", "hours": 5.0347, "text": "Array optimization (Screenshot 1) I now actually optimized the dynamic array type, which means that it allocates memory in bigger chunks instead of every time an element is added / removed. In the process I added some debug logging, so typing is now very difficult if you don’t know how it works with log level LOG_DEBUG . Custom ISR wrapper (Screenshot 2) I finally decided to implement my own wrapper for ISRs instead of relying on __attribute__((interrupt)) . This should allow me to use floating point math with the FPU in the future. Also, I can now read more registers on interrupt (screenshot). Road map I am currently working on making all ISRs compatible with my wrapper. Then I will continue trying to get multitasking to work."}, {"post_id": 38897, "ts": "2026-08-01T14:03:43Z", "hours": 6.4275, "text": "Multitasking (Screenshot 1) I decided to try to implement multitasking! The kernel can now switch tasks, but only one time. This is the first step in direction of real multitasking, but I still have much to do. It is interesting to see, How I realize how bad my implementations I did earlier are, because I don’t fully understand them. But now I can improve them! Dynamic arrays (Screenshot 2) I made a quick implementation of dynamic arrays for the keyboard driver, but as I realized that I need them to store a list of tasks, I decided to implement one optimized implementation I can use everywhere. I have implemented a very simple version and use it in the keyboard driver, but it isn’t optimized yet. In fact, it’s even worse than the one I had earlier in the keyboard driver, because every modification now requires a reallocation. Road map I am going to optimize dynamic arrays, and then continue with multitasking."}, {"post_id": 36558, "ts": "2026-07-28T19:08:32Z", "hours": 2.8569, "text": "PIT I quickly wrote a simple PIT (Programmable Interval Timer) driver, so that I have a basic sleep function. It isn’t really useful at the moment and not thread safe, but as it was very simple I thought why not? APIC I realized that MADT I/O APIC overrides also override the flags of entries, so I am using these now unless it’s overridden by the user. Road map As I have now a simple keyboard driver, I want to work on something new. Some things I am considering: Multitasking Filesystems ELF loading PCI USB All of this topics are completely new to me, so I will pick the one that looks the most simple and probably fail anyway."}, {"post_id": 33535, "ts": "2026-07-23T15:58:35Z", "hours": 2.3419, "text": "I am shipping soon! Some little improvements in messages I improved some messages, so that the kernel looks more polished to new users. v0.2.0 I released a new version, which is what I am shipping soon (if nothing goes wrong). It includes an interactive CLI, which was made possible with the new keyboard driver. I improved the scrolling performance a lot, which I personally really enjoy! Finally, I fixed a bug when printing numbers, so the printed memory map now has (mostly) correct addresses."}, {"post_id": 32511, "ts": "2026-07-21T18:56:41Z", "hours": 3.1614, "text": "The kernel is now interactive! Demo CLI I added a demo CLI (you can see it on the screenshot) where you can exit properly, run tests or view the old demo! Keyboard driver I had to fix some bugs with the keyboard driver, but now I think it works okay enough that the CLI is stable (previously, it kept parts from the old buffer when reading it again) Road map I want to add more features to the CLI, such as setting the log level. As you can see on the screenshot, the debug output disturbs the CLI."}, {"post_id": 31826, "ts": "2026-07-20T14:47:46Z", "hours": 5.0328, "text": "I FINALLY get interrupts from the keyboard! PS/2 Keyboard driver The problem was, that I mistook the IRQ number for the interrupt vector when calling my own function! Now I can start expanding my keyboard driver. Currently, it already prints the pressed keys to the screen, as you can see on the screen shot. Performance improvements when scrolling After I finished the interrupt stuff, I can focus on improving the TTY in other areas, like the performance. I am using now memset() and memcpy() functions when scrolling the frame buffer, which itself is not an improvement: I optimized the two functions to use copy 8-byte blocks ad uint64_t instead of each byte individually, which made a significant difference. Scrolling with KVM acceleration is now almost instant on my PC, and without it is as fast as it was before with acceleration. Road map I want to improve the TTY with things like buffering, which should improve the performance even more. When I have a solid TTY, I can rework the demo and ship again."}, {"post_id": 30816, "ts": "2026-07-18T19:00:05Z", "hours": 6.3653, "text": "I am still far away from getting interrupts from the keyboard, but I am still learning much and making progress on other parts of the kernel! PMM I added support for mapping pages manually, which means that I can program now the APICs! While debugging this, I also improved my Page Fault handler, which you can see on the screenshot. APIC driver The APIC driver should now be able to configure IRQs on the I/O APIC to get delivered to the local APIC, but I can’t test it as I still don’t know why I can’t get interrupts from the keyboard :-( Road Map I am still working on getting interrupts from the keyboard, which is my main goal before the next ship. I currently suspect that my PS/2 driver is broken."}, {"post_id": 29069, "ts": "2026-07-15T18:32:01Z", "hours": 7.5669, "text": "I prefer this devlog format, so I will stick to it. I/O APIC As I explained earlier, I need to configure the APIC to get interrupts. I think I only need the I/O APIC and not the local APIC, if I understand the limine documentation correctly. But when trying to access it’s registers, I got a page fault. It seems like I need to manually map the registers to virtual memory, which brings me to… Physical Memory Manager I need to do what I already feared when starting to write the PMM, manually editing page tables. I am working on a function which will map pages (Including the I/O APIC registers) to virtual addresses. For this, I need to walk the complete paging structure: PML4 (from cr3) -> PDPT -> PD -> PT I can already parse it until I have the PT’s address, but when accessing the PT I get a page fault, as you can see on the screenshot. Road map I just wanted to post this update so that the next devlog is not too long. I will continue to work on the PMM, until I can access the I/O APIC’s registers."}, {"post_id": 24628, "ts": "2026-07-08T10:52:11Z", "hours": 8.3475, "text": "I did not post for some time, so this devlog will be relatively long. PS/2 driver (Screenshot 1) I wanted to get the PIC to work, but as I had no idea why it didn’t work I thought that the PS/2 Controller might not be in a functioning state. So, I wrote a PS/2 driver which initializes the Controller, and also detects connected devices! PIC -> APIC After that, I finally found out that limine already sets up the APIC, which means that the PIC is no longer functional. So I decided that my next big goal is to learn how ACPI and APIC work… ACPI (Screenshot 2) As you can see on the screenshots, I started working on an ACPI driver, which is already able to find tables like the MADT, which I need to find the APICs UEFI This does not have anything to do with the progress of my project, but I learned how to use UEFI in QEMU, so that I can debug my ACPI driver better. Road map I will have to learn now how APICs work, so that I can get interrupts from the keyboard. Then, I can improve the keyboard driver, which should make the kernel way more fun to use!"}, {"post_id": 20746, "ts": "2026-07-02T13:20:11Z", "hours": 6.0672, "text": "I have finished implementing the memory manager! free() will now call pmm_free() to free unused pages. At the moment it does not make any difference, but if I want to extend the PMM it will have saved me the work. Also, I split the demo from the main function so that it is more maintainable. Log messages with the log level DEBUG will now only appear in debug builds. This made the output much more readable, as you can see in the screenshots."}, {"post_id": 19208, "ts": "2026-06-30T14:00:38Z", "hours": 9.6128, "text": "I have added a simple memory manager to my kernel! It was only possible with the help from kmos , a project I found while voting. I didn’t know how to start writing a physical memory manager, but in that kernel I found that I have to use the limine HHDM request to have simple access to physical addresses. Then I could implement the rest completely myself. The last thing left to do until I’m satisfied with my memory manager, is to free pages in the PMM after using free()"}, {"post_id": 12539, "ts": "2026-06-20T14:12:50Z", "hours": 0.8414, "text": "Now I am actually shipping! I had a bug that occured only when compiling with optimization level 2 or higher (which I used in the release CI). As I am working now on a Debian machine, I made it also compile on Debian stable by not requiring a new objcopy version. On the screenshot you can see the bug."}, {"post_id": 11482, "ts": "2026-06-18T19:17:02Z", "hours": 4.0292, "text": "I will ship the kernel now for the first time! I added a libk (like a libc but for the kernel) and implemented some cool functions like printf(), which I could use for cool error messages with hex numbers like the one on the screenshot."}, {"post_id": 9395, "ts": "2026-06-15T18:55:28Z", "hours": 2.4939, "text": "I sadly don’t have much to say, because I did make almost no progress. I am trying to use the PIC to get interrupts from the keyboard, but it doesn’t work for some reason. Maybe I will try to use APIC instead, but it’s more complicated."}, {"post_id": 8627, "ts": "2026-06-14T10:44:21Z", "hours": 2.2619, "text": "I finally figured out how I can integrate the external library! Now I can skip instructions when an interrupt is executed and continue execution"}, {"post_id": 7621, "ts": "2026-06-12T19:00:11Z", "hours": 1.0647, "text": "I just wanted to implement an interrupt handler specific to divide error, but it turned out to be way more difficult than I thought! To continue execution after the interrupt, I have to manually increment the instruction pointer manually. But to know by which amount, I need to now the size of the whole instruction. To find it I wanted to use a library called Zydis, but I could not get it to compile, because clang generates calls to memset() and memcpy() . As I can not link with the standard library, I will have to find a solution tomorrow."}, {"post_id": 5837, "ts": "2026-06-09T19:37:29Z", "hours": 3.1153, "text": "I added a demo to show the features of my kernel. The kernel is almost ready for the first ship!"}, {"post_id": 4373, "ts": "2026-06-07T18:00:51Z", "hours": 3.2469, "text": "After giving up on the memory manager, I added logging and very basic interrupt handling. I will ship the project when I have a demo of all the features and published ISOs."}, {"post_id": 3530, "ts": "2026-06-06T14:47:32Z", "hours": 2.2575, "text": "As I have now a very basic way to interact with the kernel, I will try to move on to more complex topics. At the moment I try to understand how memory management exactly works (specifically, how to write a physical memory manager), but it’s difficult to find information about it. Until now, I have requested a memory map from limine and can display it in a table."}, {"post_id": 3364, "ts": "2026-06-06T07:57:08Z", "hours": 1.7286, "text": "I implemented enter key press detection before doing anything else, so that I can interact somehow with the kernel. I did it with IO Ports instead of interrupts for now (because I don’t know how to set up interrupts), which means it only works with PS/2 Keyboards. Luckily, qemu shows the keyboard as a PS/2 Keyboard."}, {"post_id": 2308, "ts": "2026-06-04T18:38:28Z", "hours": 2.5331, "text": "I have added a normal font which makes things way simpler. I also improved the general tty: scrolling, new lines and tabs work now!"}, {"post_id": 1458, "ts": "2026-06-03T14:42:11Z", "hours": 1.7617, "text": "I spend so much time to fix a stupid bug (taking the address of a pointer instead of the address stored in the pointer), but know I can display characters from my ugly psf2 font! At least I learned more about gdb."}, {"post_id": 957, "ts": "2026-06-02T18:43:29Z", "hours": 3.0825, "text": "I implemented a set_pixel function, so that I can set specific pixels on the framebuffer. The next step will probably be to display text, maybe with a font made with psfedit, my project for flavortown. I also published my code on GitLab, which means I will try to build ISOs with gitlab CI at some point."}, {"post_id": 294, "ts": "2026-06-01T15:23:58Z", "hours": 1.1658, "text": "I have started to work on my kernel! I just set up my project structure but it does not work as you can see on the screenshot. I will look at it tomorrow. I have already tried to write a kernel earlier this week, but it was an i686 kernel with multiboot 2. Also, I had to copy much code from the limine template, but I will go beyond that when the kernel runs. This means, that I have a weird mix of makefile and meson, as the example uses make but I prefer meson. As I do not want to set up long mode myself, my new kernel uses limine instead of multiboot. My current plan is to get it to run and then publish the source code. Later, I might try to remove make completely and only rely on meson for building the iso."}]...
|
Title: Kern by @AntKru | Stardance
Devlogs:
I hav Title: Kern by @AntKru | Stardance
Devlogs:
I have started to work on my kernel! I just set up my project structure but it does not work as you can see on the screenshot. I will look at it tomorrow. I have already tried to write a kernel earlier this week, but it was an i686 kernel with multiboot 2. Also, I had to copy much code from the limine template, but I will go beyond that when the kernel runs. This means, that I have a weird mix of makefile and meson, as the example uses make but I prefer meson. As I do not want to set up long mode myself, my new kernel uses limine instead of multiboot. My current plan is to get it to run and then publish the source code. Later, I might try to remove make completely and only rely on meson for building the iso.
I implemented a set_pixel function, so that I can set specific pixels on the framebuffer. The next step will probably be to display text, maybe with a font made with psfedit, my project for flavortown. I also published my code on GitLab, which means I will try to build ISOs with gitlab CI at some point.
I spend so much time to fix a stupid bug (taking the address of a pointer instead of the address stored in the pointer), but know I can display characters from my ugly psf2 font! At least I learned more about gdb.
I have added a normal font which makes things way simpler. I also improved the general tty: scrolling, new lines and tabs work now!
I implemented enter key press detection before doing anything else, so that I can interact somehow with the kernel. I did it with IO Ports instead of interrupts for now (because I don’t know how to set up interrupts), which means it only works with PS/2 Keyboards. Luckily, qemu shows the keyboard as a PS/2 Keyboard.
As I have now a very basic way to interact with the kernel, I will try to move on to more complex topics. At the moment I try to understand how memory management exactly works (specifically, how to write a physical memory manager), but it’s difficult to find information about it. Until now, I have requested a memory map from limine and can display it in a table.
After giving up on the memory manager, I added logging and very basic interrupt handling. I will ship the project when I have a demo of all the features and published ISOs.
I added a demo to show the features of my kernel. The kernel is almost ready for the first ship!
I just wanted to implement an interrupt handler specific to divide error, but it turned out to be way more difficult than I thought! To continue execution after the interrupt, I have to manually increment the instruction pointer manually. But to know by which amount, I need to now the size of the whole instruction. To find it I wanted to use a library called Zydis, but I could not get it to compile, because clang generates calls to memset() and memcpy() . As I can not link with the standard library, I will have to find a solution tomorrow.
I finally figured out how I can integrate the external library! Now I can skip instructions when an interrupt is executed and continue execution
I sadly don’t have much to say, because I did make almost no progress. I am trying to use the PIC to get interrupts from the keyboard, but it doesn’t work for some reason. Maybe I will try to use APIC instead, but it’s more complicated.
I will ship the kernel now for the first time! I added a libk (like a libc but for the kernel) and implemented some cool functions like printf(), which I could use for cool error messages with hex numbers like the one on the screenshot.
Now I am actually shipping! I had a bug that occured only when compiling with optimization level 2 or higher (which I used in the release CI). As I am working now on a Debian machine, I made it also compile on Debian stable by not requiring a new objcopy version. On the screenshot you can see the bug.
I have added a simple memory manager to my kernel! It was only possible with the help from kmos , a project I found while voting. I didn’t know how to start writing a physical memory manager, but in that kernel I found that I have to use the limine HHDM request to have simple access to physical addresses. Then I could implement the rest completely myself. The last thing left to do until I’m satisfied with my memory manager, is to free pages in the PMM after using free()
I have finished implementing the memory manager! free() will now call pmm_free() to free unused pages. At the moment it does not make any difference, but if I want to extend the PMM it will have saved me the work. Also, I split the demo from the main function so that it is more maintainable. Log messages with the log level DEBUG will now only appear in debug builds. This made the output much more readable, as you can see in the screenshots.
I did not post for some time, so this devlog will be relatively long. PS/2 driver (Screenshot 1) I wanted to get the PIC to work, but as I had no idea why it didn’t work I thought that the PS/2 Controller might not be in a functioning state. So, I wrote a PS/2 driver which initializes the Controller, and also detects connected devices! PIC -> APIC After that, I finally found out that limine already sets up the APIC, which means that the PIC is no longer functional. So I decided that my next big goal is to learn how ACPI and APIC work… ACPI (Screenshot 2) As you can see on the screenshots, I started working on an ACPI driver, which is already able to find tables like the MADT, which I need to find the APICs UEFI This does not have anything to do with the progress of my project, but I learned how to use UEFI in QEMU, so that I can debug my ACPI driver better. Road map I will have to learn now how APICs work, so that I can get interrupts from the keyboard. Then, I can improve the keyboard driver, which should make the kernel way more fun to use!
I prefer this devlog format, so I will stick to it. I/O APIC As I explained earlier, I need to configure the APIC to get interrupts. I think I only need the I/O APIC and not the local APIC, if I understand the limine documentation correctly. But when trying to access it’s registers, I got a page fault. It seems like I need to manually map the registers to virtual memory, which brings me to… Physical Memory Manager I need to do what I already feared when starting to write the PMM, manually editing page tables. I am working on a function which will map pages (Including the I/O APIC registers) to virtual addresses. For this, I need to walk the complete paging structure: PML4 (from cr3) -> PDPT -> PD -> PT I can already parse it until I have the PT’s address, but when accessing the PT I get a page fault, as you can see on the screenshot. Road map I just wanted to post this update so that the next devlog is not too long. I will continue to work on the PMM, until I can access the I/O APIC’s registers.
I am still far away from getting interrupts from the keyboard, but I am still learning much and making progress on other parts of the kernel! PMM I added support for mapping pages manually, which means that I can program now the APICs! While debugging this, I also improved my Page Fault handler, which you can see on the screenshot. APIC driver The APIC driver should now be able to configure IRQs on the I/O APIC to get delivered to the local APIC, but I can’t test it as I still don’t know why I can’t get interrupts from the keyboard :-( Road Map I am still working on getting interrupts from the keyboard, which is my main goal before the next ship. I currently suspect that my PS/2 driver is broken.
I FINALLY get interrupts from the keyboard! PS/2 Keyboard driver The problem was, that I mistook the IRQ number for the interrupt vector when calling my own function! Now I can start expanding my keyboard driver. Currently, it already prints the pressed keys to the screen, as you can see on the screen shot. Performance improvements when scrolling After I finished the interrupt stuff, I can focus on improving the TTY in other areas, like the performance. I am using now memset() and memcpy() functions when scrolling the frame buffer, which itself is not an improvement: I optimized the two functions to use copy 8-byte blocks ad uint64_t instead of each byte individually, which made a significant difference. Scrolling with KVM acceleration is now almost instant on my PC, and without it is as fast as it was before with acceleration. Road map I want to improve the TTY with things like buffering, which should improve the performance even more. When I have a solid TTY, I can rework the demo and ship again.
The kernel is now interactive! Demo CLI I added a demo CLI (you can see it on the screenshot) where you can exit properly, run tests or view the old demo! Keyboard driver I had to fix some bugs with the keyboard driver, but now I think it works okay enough that the CLI is stable (previously, it kept parts from the old buffer when reading it again) Road map I want to add more features to the CLI, such as setting the log level. As you can see on the screenshot, the debug output disturbs the CLI.
I am shipping soon! Some little improvements in messages I improved some messages, so that the kernel looks more polished to new users. v0.2.0 I released a new version, which is what I am shipping soon (if nothing goes wrong). It includes an interactive CLI, which was made possible with the new keyboard driver. I improved the scrolling performance a lot, which I personally really enjoy! Finally, I fixed a bug when printing numbers, so the printed memory map now has (mostly) correct addresses.
PIT I quickly wrote a simple PIT (Programmable Interval Timer) driver, so that I have a basic sleep function. It isn’t really useful at the moment and not thread safe, but as it was very simple I thought why not? APIC I realized that MADT I/O APIC overrides also override the flags of entries, so I am using these now unless it’s overridden by the user. Road map As I have now a simple keyboard driver, I want to work on something new. Some things I am considering: Multitasking Filesystems ELF loading PCI USB All of this topics are completely new to me, so I will pick the one that looks the most simple and probably fail anyway.
Multitasking (Screenshot 1) I decided to try to implement multitasking! The kernel can now switch tasks, but only one time. This is the first step in direction of real multitasking, but I still have much to do. It is interesting to see, How I realize how bad my implementations I did earlier are, because I don’t fully understand them. But now I can improve them! Dynamic arrays (Screenshot 2) I made a quick implementation of dynamic arrays for the keyboard driver, but as I realized that I need them to store a list of tasks, I decided to implement one optimized implementation I can use everywhere. I have implemented a very simple version and use it in the keyboard driver, but it isn’t optimized yet. In fact, it’s even worse than the one I had earlier in the keyboard driver, because every modification now requires a reallocation. Road map I am going to optimize dynamic arrays, and then continue with multitasking.
Array optimization (Screenshot 1) I now actually optimized the dynamic array type, which means that it allocates memory in bigger chunks instead of every time an element is added / removed. In the process I added some debug logging, so typing is now very difficult if you don’t know how it works with log level LOG_DEBUG . Custom ISR wrapper (Screenshot 2) I finally decided to implement my own wrapper for ISRs instead of relying on __attribute__((interrupt)) . This should allow me to use floating point math with the FPU in the future. Also, I can now read more registers on interrupt (screenshot). Road map I am currently working on making all ISRs compatible with my wrapper. Then I will continue trying to get multitasking to work.
It probably doesn’t sound special, but it is as important as everything else: SSE support SSE is an extension of the CPU which has 16 128-bit registers, but is rarely used. This means, that saving all of these registers every time a task switch occurs would cost some performance. For this reason, the CPU has a bit that can be set to indicate that a task switch occurred. In most cases, nothing happens and the registers are kept in their original state. But if a task needs to use SSE instructions, the CPU generates an interrupt, which manually saves the SSE registers. This is what I am working on currently. Custom ISR wrapper All interrupt handlers use now my custom wrappers, which made possible that I can work on SSE support.
SSE register state switching! The kernel will now switch the SSE register state lazily, but I still have two problems: The Part for the registers in the TCB must be 16 byte aligned, which it currently not guaranteed The interrupt handlers are not allowed to use SSE instructions, but I have no way of verifying this Road map I think it is time to write a version of malloc() which can guarantee a specified alignment. After that, I can try to actually switch tasks automatically with a simple scheduler! I will probably use the PIT interrupt to switch to the next task in a list.
Multitasking… I am still working on multitasking, but I am stuck currently. I am trying to modify the stack frame so that asm_switch_task is called after iretq , but it doesn’t work. As you can see on the screenshot, I get a page fault as soon as it tries to switch tasks (in the debugging process I had it switch 2-3 times before it crashes, which is not really better) Road map My highest priority is to get task switching to work consistently. After that, I will see what I can polish.
Multitasking! I fixed the last bug (that I could find) and multitasking works now! On the screenshot you can see two tasks trying to print the numbers 0-19 at the same time. The CLI even waits until the tasks are finished! Road map The output is still a little bit broken, so I want to implement output buffering and mutexes, so that multiple threads can’t print at the same time.
Mutexes I implemented a simple mutex (which isn’t perfect yet, but it works). As visible on the screenshot, I used it to make it impossible for the test tasks to print at the same time. One problem with it is that it currently runs hlt after releasing a mutex so that a different task has a chance to acquire it, which doesn’t seem like the best solution to me. Roadmap I am making the terminal position atomic, so that I don’t need mutexes for output, which I can not use in interrupt handlers
GCC support I added GCC support, which should (hopefully) make debugging easier for me. I can’t show it really on the screenshot, trust me, it is compiled with gcc! Roadmap I have still bugs in my multitasking system. Currently I get a page fault when compiling with optimization > -O2 with clang, the next step is to test it with GCC.
RTC The kernel can now read the current time from the Computer’s RTC! At the moment, you can’t select the time zone, so the time is probably in UTC, depending on how the computer is configured. Roadmap I am planning to improve the use experience, for example by using multiple “windows”, to maybe even have a status bar.
“Windows” I am making it possible to split the framebuffer into multiple views. This should make it more easy to have a more advanced UI than a CLI already inside the kernel. Hopefully there will be user processes at some point, but I want to have a nice looking OS before that. Roadmap I still have to fix some things (as visible on the screenshot). After that, I can try to make use of it and add a status bar or a separate command window.
Status bar! I added a status bar which show the current time. It is very basic, but makes the OS look way more friendlier in my opinion. Sorry for the weird messages in the main window, I am currently debugging my printf implementation. Roadmap I still have a problem with printing dates: The year 2006 would be printed as 206 , because the RTC has seperate registers for year and century, so if century is 20 and year is 6 it prints 206.
printf compatability I improved the printf() compatability, so that I can pad numbers with or 0 . This is very useful, for example I now can use it to display time and date properly. Roadmap I don’t know yet what’s the next thing to do, maybe I will ship soon.
Final improvements before the next release Status bar I moved the status bar from the bottom to the top and removed the borders, in my opinion it looks better this way. Framebuffer borders I am already working on a new command which will make it possible to see the borders of the framebuffer in QEMU. This will be useful for debugging while keeping the UI simple. Bugs There are still some obvious bugs: My printf() implementation seems to break with invalid format strings and I have a bug in my memory manager which prevents me from merging the command showing the screen borders into main. Roadmap I will try to fix the bugs, but the features are now complete. I want to release the new version tomorrow.
Release 0.3.0 I finished the release, including the new borders command! The visible bugs that I found are also fixed, please report them if you find some! Roadmap The kernel isn’t finished yet, I will continue to improve it and see how far I will get.
PCI! I am starting to write a PCI driver, which opens a new world to me! As you can see, the kernel is already able to print some information on boot about connected PCI devices. I also added a function that can search for a specific PCI device by it’s class, which will help me to implement drivers for specific PCI devices. Roadmap The real reason I am implementing PCI is that I need it to find the AHCI controller. The AHCI controller can be used to access connected storage devices, which is my long-term goal.
AHCI! (SATA) I am jumping a little bit fast form PCI to AHCI, but I think the PCI driver is as good as I need it right now, and if I learn that it isn’t, I will fix it. Anyway, I am starting to work on AHCI! This is really cool, as this allows me to communicate to storage devices! At the moment the kernel just lists connected devices, but that’s just the beginning! Roadmap The AHCI driver is in a very early stage, and it will take me a lot of time to finish, as AHCI is relatively complicated and the documentation isn’t written for beginners like me ;-)
Memory management problems… It seems like there was a critical bug sleeping inside my memory manager. It appeared since I started using the PMM in my AHCI driver, but I think the problem is in the virtual memory manager. For this reason I am working currently on the memory manager instead of the AHCI driver. Roadmap As soon as I fix the MM, I will continue on the AHCI driver. It probably won’t be finished until the end of stardance.
Ships:
I made an x86_64 kernel using the limine boot protocol. I don’t know what the most difficult thing was, as even most basic things are very complicated for me as a beginner in osdev. I still have to learn much and the kernel will be improved, but I thing it kind of works now. I have a video demo in the readme, if you don’t have qemu . When building, remember to clone the submodules ( git submodule init && git submodule update ). You need xorriso to build the ISO. Sorry for mixing meson and make , but in the README is a guide. Please use clang, gcc is very complicated.
I added a CLI the kernel, which was possible, because I finally have a keyboard driver! It only took so long, because it was actually difficult to write it: I thought I have to program the PIC, but it was already disabled so I had to learn the more complicated APIC. There is a demo video in the README if you don’t want to run the kernel. If you want to run it on macOS with UTM, you have to force a PS/2 controller: https://docs.getutm.app/settings-qemu/qemu/#force-ps2-controller
I have released the next version of my own kernel! The biggest feature I added is multitasking. While it doesn’t look that special, it was actually very difficult to make my kernel switch between different tasks! Here are some notes on how to try the project: If you don’t want/can’t run it, you can look at the video in the readme. If you want to run it on macOS with UTM, you have to force a PS/2 controller: https://docs.getutm.app/settings-qemu/qemu/#force-ps2-controller...
|
1792842658.7836795
|
1792929058.7836795
|
|
15129
|
Tempname: Engine by @pkncoder | Stardance
|
pkncoder
|
1
|
165.0
|
2930
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-24T12:06:16Z", "hours": 165.0, "multiplier": 19.97, "payout": 2930, "blessing": "neutral", "text": "—————– Ship #1 —————– - - Welcome - To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). 💚 The current state 💫 There is still no UI, all render control is based in a JSON file. The current only renderer is a custom Deferred Renderer. Note: As this is built for 3d rendering, a modern computer, with a GPU is recommended. Modern Macbooks will run it, however it will be slower as it is basically magic that it works on them. Thank you so much! I’ve spent a lot of time on this. It may not seem like that, however when building this, I decided to do it right (as this is my 3rd attempt). I split the development into phases: Get a window Get something rendering + a camera Get object/material/texture loaders + basic scene managers + basic concept of working Create full scale (professional) renderers/scene managers/resource managers/etc. Get a UI Currently, I’m in getting everything polished in the backend. I didn’t want to move on to the UI, as I didn’t want to rush that. Rushing a UI meant missing other things. So thank you, and I really hope you enjoy. If there are any issues, please report them to the issues page on the github, and message me on slack ( @pkncoder ). Github releases: https://github.com/pkncoder/Engine/releases Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine", "repo": "https://github.com/pkncoder/Engine/", "demo": "https://pkncoder.github.io/Engine/index.html"}]...
|
[{"post_id": 72971, "ts": "202 [{"post_id": 72971, "ts": "2026-09-24T04:20:28Z", "hours": 2.5239, "text": "—————– Devlog XXVII —————– - - Release is out testing time – To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ Not too much has happened, mostly: Updated README (resources, gallery, installation & use) Updated the landing page (added a tech-stack) Created my first release under the 1.3.x alpha title That big 1.3.x “alpha” release is the big one, as I need some help. If you could just take a bit of time, and you aren’t on linux-arm or apple-intel, could you check out the github releases and try it out, that would be great! I plan to ship tmwr, but I want some testing done first. Thank You for Reading So close!! Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine"}, {"post_id": 72516, "ts": "2026-09-23T03:30:31Z", "hours": 9.9433, "text": "—————– Devlog XXVI —————– - - Almost… there – To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ In order to show the capabilites, I’ve been setting up scenes for my engine to show off, and here are some of the results! It would be great to get your favorite render of these! For the full 9 renders , check out the scrapbook in the slack , as they will be there w/ a thread. Thank You for Reading Hopefully will actually ship tmwr! I’m actually getting kind of sad, I won’t be stopping development by any means, but this has been my summer (although I might not be able to get any stardance tokens, but that’s ok ig…). If you have any questions, feel free to DM me either here, or at @pkncoder on discord if that’s easier for you! Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine"}, {"post_id": 71565, "ts": "2026-09-21T02:05:45Z", "hours": 2.1433, "text": "—————– Devlog XXV —————– – New JSON scene file 📁 - SHIP TIMEEEEE – To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ Not that much has happened tbh. All that has really happened… Updated the README a bit more Added a new json parser to spawn the scene from that Added hot reloading of the scene So yea, next should be the ship. When updating the README on the github, I was going through the Usage section, and added a new promise for how people could add their own meshes. In this I created the idea of activeScene.json , a JSON file that listed the scene data (crazy, right?). And so, after I updated the README , I added the new loader, and made the scene reload by pressing the “ r ” key. That’s kinda it… Thank You for Reading Before shipping, I need to… Do another update of the README Create the base Releases for Mac, Windows, and Linux And test these Do a pass through TODO.md Update the landing page Shouldn’t take too long Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine"}, {"post_id": 69952, "ts": "2026-09-18T03:52:09Z", "hours": 8.6456, "text": "—————– Devlog XXIV —————– – i HATE shadow maps!!! - Renderer? I hardly know her? – To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ WOAH A lot has happened. Previously, I had just implemented a new entity system & a new camera system. So what’s new? I present: The Deferred Renderer !!! Basically, it’s just another way of rendering. HOWEVER , it has some funzies: Mostly together render graph, just a little smthin Shadow Pass G-Buffer Pass Lighting Pass New point lights (replacing the emmissive texture searching before) Looking to add SSAO (hemisphere sampling) in the future!! Now, along with this, I just tested creating a build for windows and testing it on a friends machine, and it worked (his laptop is crap, so it ran slow, but surprisingly fast) . Along with that, I also tried the current build on mac, and it also worked, so that’s also great (I’m supprised)!! However, the real prize, is the trypophobia horrors made along the way!! That’s right! When trying to get textures to work, I ran into a ton of problems (mostly related to the alpha map & image formats) that caused major headaches. Images and videos, where they are a bit compressed, can be found below. Thank You for Reading Almost there, I still need to change up the landing page, rewrite the readme, and merge the main branch, plus try to get a way to change the 3d models for users, but I’m getting there. Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine"}, {"post_id": 67656, "ts": "2026-09-13T20:09:19Z", "hours": 7.9958, "text": "—————– Devlog XXIII —————– – I NEED TO HURRY UP AAAA - EnTT - Table – To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ In my previous devlog, I stated how I was working on the new RenderGraph . I’ve now realized, that I have like until the end of the week for when I need to ship. So instead , my goal is to get this looking impressive . To start, here is what I’ve done so far : Cleaned up system inits Changed how the UUID service works (now you just access it and call generate ) Implemented a new library, EnTT Did some cleanning up Added a PointLightComponent for future use (no dev. yet) Added and implemented the CameraComponent Here are the big things: EnTT EnTT is an open-source library that handles objects within games, editors, etc. It’s creator is: Michele Caini (skypjack on github) . EnTT is a library that exposes something called an Entity Component System (ECS). Basically, instead of saving a bunch of data directly inside of one struct or class, you define an entity (a unique id) and assign that entity components. The components are what actually gives the entity meaning. New Camera If you have ever ued Blender for a bit, you would know that your camera is on the same list as your meshes. This is since, to Blender, they are inherantly the same thing (don’t quote me on that) . Previously, my camera was seperate to all of the rest of the objects. This caused the data to be split, and handling the differences made my architecture a bit weird. Now that I’ve implemented EnTT , I’ve added a CameraComponent that defines things like rotation, FoV, etc - completely erasing the need for a separate camera, and opening the doors to more flexibility. Thank You for Reading New book is great! I won’t get to use too much of it for stardance, but I’m checking out this snowglobe thing that seems like it would be the next area!! Wish me luck on the ship. I want to get it out by the end of the week so I can hopefully still cache in some stardust. Probally won’t get the computer though (high hopes for a living or smthin idk) Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine ❓ What’s next? 🛑 Change my Rasterizer to be a Defered Renderer & implement multiple point lights UI??"}, {"post_id": 61084, "ts": "2026-09-03T20:05:33Z", "hours": 3.7325, "text": "—————– Devlog XXII —————– – BrEaKiNg ChaNGeS - 📖 NEW BOOOKKKK – To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ Sadly, I’ve done much coding Base list This is what I have done since the last devlog: Planned out a bit more on the inner workings from no Renderer->Rendered Image Created the new Shader & Program classes Updated the workings on RendererManager Started work on the new Renderer / IRenderer class Current commit is now broken (compiles, doesn’t run Overview In my new obsidian vault , I’ve been working on creating the new database on how it all works. Through this, I’ve been using excalidraw (Obsidian) to plan out pipelines & create visuals. Currently, I have 2 main drawings: Shader & Program pipeline Renderer Pipeline The Shader & Program pipeline explains the lifetime and usage of both the Shader and Program (OpenGL program) classes. A program gets created, has shaders attached to it (deleting the shader in the process) , and then the program gets linked & binded. The Renderer Pipeline explains the lifetime and usage of a renderer. Starting from the RendererManager, go through normal rendering stuff, and will end at shutting down the RendererManager. For the inner workings of the new renderer setup, I’ll leave that for (hopefully next devlog) when I get everything working start to finish of the RendererPipeline . Thank You for Reading As for the “ New Book I got, I have just purchased “ Game Engine Architecture Vol. I ” (Jason Gregory) to specialize the program more (most likely after Stardance ends). Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine ❓ What’s next? 🛑 Plan out the RenderGraph Create the base RenderGraph class Create the BlitList Create the INodeInput & INodeOutput"}, {"post_id": 58866, "ts": "2026-08-31T13:21:49Z", "hours": 3.4211, "text": "—————– Devlog XXI —————– – My brain hurts 🧠 - Sharp like glass – To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ Sadly, I haven’t done much coding Instead, I’ve been trying to figure out how I want my Render Graph to work. To start, what is a render graph? What I am interpreting the render graph as, issss: An API meant to simplify and provide structure to a final renderer. In the final application, the render graph will be an option for a more advanced final render editor. What I am working on now, is how it will be put together so I don’t have a mess in the future. Recently, I’ve been using Obsidian to mark everything down. This also starts a little docs. Using a mix of Obsidian and the excalidraw plugin, I’m able to write everything down and create visuals. Currently, I have a mix of nodes that are the main important ones. These nodes are just the interfaces , so they aren’t specified. They act as a blueprint for any of the full nodes. IRenderOutput - Add textures to a list of blitables IShaderInput - Base input interface IShaderOutput - Base output interface IShaderNode - Node representation of shaders IShaderPassNode - Base shader interface Thank You for Reading I haven’t been home enough to create the “big brain wall” which is sad, but at least my stuff is digital. Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine ❓ What’s next? 🛑 Setup current program for Render Graph implementation Implement IShader, IGPUTexture, etc. Create IRenderGraph for the renderers"}, {"post_id": 53552, "ts": "2026-08-24T04:42:42Z", "hours": 3.7022, "text": "—————– Devlog XX —————– – 🌟I have the best one liners 🗿– 🥀 Now I have to be smart ??? 🧠 – To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ For the quick overview: Fixed the shadow map issue ( so angry about this, see below ) Fixed an issue with textures not caching Got the very base implementation of Uniform Buffers To start off, in the previous devlog I mentioned I was re-writing the shadow mapping . Shadow Mapping - Rendering a 3d model with the light being the eye. Everything that it can see is not in shadow, everything else is. quick explanation I was having issues with getting the shadows to work correctly. I had ideas for issues, including: (the model matrix , the renderPackets being in a bad order , the far plane ). IT TURNS OUT It was none of these. Whenever I made the code to compile a geometry shader along the vertex & fragment shader, I just copied my old one and spliced in the code. Turns out I forgot to swap some variables, and I was putting code in places it should NOT be at. No idea why it didn’t crash, but it fixed my shadow issues very quick . As for UBOs, I’ll talk about them in a future devlog, when I have everything planned out. Thank You for Reading As I said with “Planning out” everything, I’m going to set up a whiteboard - I’ll have to move my 🏳️🌈 pride flags 🏳️⚧️ :( - Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine ❓ What’s next? 🛑 Refactor Build the big brain wall Do some thinking 🥀 Git Commits🗿 Weird position issue Saving now, I am so angry about this. I was compiling and overwrigting the wrong code :( Made the testing for shadows a bit better, and changed the rendering a bit Fixed issue with textures and full models not actually caching Removed anoying debug line for shadow transform matricies Working on getting the ubos working’ Got it to push First test ubos"}, {"post_id": 52406, "ts": "2026-08-22T15:11:34Z", "hours": 4.0344, "text": "—————– Devlog XIX —————– - 🌲 Textuers 🧚♀️ - 👩💻 Shadoowwsss 💀- To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ To recap on what I did: Got the program to launch to black screen I needed to inject the Asset Manager to a class Got objects loading correctly without shadows Got textures to load Started work on fixing the shadow map Nothing too crazy has been changed, the texture issues were about some compatibility problems and not uploading to the same index. The shadow values are uploaded to a 3d texture, where to calculate if an object is in sight or not, we commit triangles based on their position. The problem now is about the far plane, and hitting triangles that weren’t in shadow. I’m not sure what the problem is, but I’m going to do a bit more looking into it. Thank You for Reading :3-blahaj-spinning I still have to fix the shadows issue (obviuosly) but then I can move onto formatting the data (putting it into buffers, creating wrappers, etc).!! Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine ❓ What’s next? 🛑 Write the shadow cubemap geometry shader & ad it to the OpaquePass (temp main pass) Make and debug UBOs replacing base uniforms Refactor / clean Create the real Render Graph? 🥀 Git Commits (shortened)🗿 Commits: https://github.com/pkncoder/Engine/commits/Phase-IV/ Most Recent: Temporary Save"}, {"post_id": 50519, "ts": "2026-08-19T18:20:39Z", "hours": 5.6344, "text": "—————– Devlog XVIII —————– - 🌲 Trees 🧚♀️ - 👩💻 SO MUCH REWRITING 💀- To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ These last few days, I’ve been working on getting my Rasterizer (drawing triangles of a model on screen and coloring them) working. The big changes that I did include: Fixing an issue with textures not loading Updated the Interface for every Renderer. Implemented the extract / prepare / dispatch pipeline into the Rasterizer for real now. Started working on the base ideas of a “Shader Graph” The issue with textures was just moving a line like 3 lines lower . I was freeing the image data before saving it (oops) . The updated interface is the IRenderer class. Each Renderer bases off of the class, supplying it with a framework so each Renderer can be talked to the same way. Here are some of those functions: beginFrame - Clear previous frame data and prepare for a new frame extract - Take raw scene data ( camera , renderables ) and convert it into packets for the next step. prepare - Take each packet from extract and turn them into draw commands for dispatch. dispatch - Take each draw command and send a draw call, along the way binding any textures & uniforms. postProcess - Take the frame and post-process it. This may be removed. present - Take the rendered frame and show it to the screen ( blit it ). To do a quick review on what the Shader Graph is - it is a collection of “nodes,” each with their own inputs and outputs that connect together to render out a frame. I’m still a bit confused, but I’ve been watching presentations on the topic from companies like Unity & Activision . Thank You for Reading Yea, I know it’s been a while since my last devlog. I’ve been making some posts in slack about my Path Tracer, since I spent a little time on that. I’m looking at the timing for everything , the hope is to ship this at the end of Phase-IV and hope that I can get a UI working before too late. I’m hoping I can get enough stardust to pay for a new laptop, but idk that’s a long shot. I still have about 25 more hours if I get a 16x mult (which I can only hope for) before I would hit the mark for the FW 12, which isn’t crazy (the mult is tho). Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine ❓ What’s next? 🛑 Stop the program from crashing to reach a black screen Rewrite shaders to allow for correct models wo/ shadows Write the shadow cubemap geometry shader & ad it to the OpaquePass (temp main pass) Make and debug UBOs replacing base uniforms 🥀 Git Commits (shortened)🗿 https://github.com/pkncoder/Engine/commits/Phase-IV/"}, {"post_id": 45347, "ts": "2026-08-11T18:54:11Z", "hours": 2.9381, "text": "—————– Devlog XVII —————– - Strange Hours - To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ To start off, I did not work directly on my application, but the online demo . It’s like working on the website, but through another editor sometimes. The goal of the Path Tracer is to eventaully get it clean & quick enough to be real-time. This is the first of the 5 renderers that I will be making. I was working on my online shadertoy DEMO for the Path Tracer, specifically the denoiser. The name of the denoiser I am using is the “Edge-Avoiding Á Trous Wavelet Transform” . As a quick overview: It applies a blur “ with holes ” to allow for less to no image distortion Fast enough for realtime Includes “ weights ” based on (in my code): Normal , Depth , and Color . The larger the difference between the center pixel and the scanned pixel * (kernel), the more weight is applied, lessening the amount of blur. This is amazing, however when the camera moves , the denoiser assumes that the current and previous pixel are in the same world postion (when it isn’t). This causes errors when trying to overlay the image and gather data. This is why we track the motion of the camera, creating a vector to get the same world position pixel. I got this wrong on one of the first attempts, the last attachment (videos are compressed) shows that fun video (warning for those who get motion sick). With this, I am able to blur the image, and with some more techniques, I can get rid of “ghosting.” Thank You for Reading In the videos, I rendered them in fullscreen 4k on my better laptop+GPU, don’t worry about your system being too slow, just don’t fullscreen it <3 (the development was done on my lower end mac). The hours logged are from refactoring the project after the last devlog, and editing the code when I didn’t do it in shadertoy’s editor. Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine 🥀 Git Commits 🗿 BREAKING CHANGE - Refactored Buffer & GPUResource managers + IRenderer - Code has been broken for a bit but womp womp Shadertoy shaders path tracer https://www.shadertoy.com/view/7fBSzR"}, {"post_id": 44514, "ts": "2026-08-10T10:13:23Z", "hours": 4.0428, "text": "—————– Devlog XVI —————– So long , gay Bowser ⭐️ – IRenderer, hardly know her? - To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ⭐️ BEFORE ANYTHING - Thanks so much to @AVD for the super star, wasn’t expecting it and I really appreciate it 👏 👏. Now, for what I did: Dealt with an issue in Obsidian, as apparently there was “minor rendering performance improvements.” This is FALSE :( - I just downgraded the version Created the new BufferManager to handle UBOs, SSBOs, VBOs, EBOs, etc. + Dynamic, Static, and Stream buffers. Integrated the RenderTarget & ShaderPass system from PathTracer straight into IRenderer + added base utilities to it. Did some formatting Overall the two big things that I did was the new Buffer system & the updated IRenderer interface. For the new Buffers, previously I had UBOs (dynamic values) & SSBOs (big mostly static information blocks) set up in seperate files, that BufferManager returned. Now, every buffer is a single struct called GPUBuffer , and GPUBuffer has a type, and a usage (see attached photo). Now everything is centralized on that. For the new IRenderer interface, now there are RenderTargets - textures that shaders write to as output - and ShaderPasses - A pass of a shader. These can be added to a registry, keyed by a UUID (big number, in this case). Thanks for reading Again, thanks so much to AVD for the super star! I’m excited for when I can finally start writing my shaders, it’s getting closer & closer!! The fancy Path Tracer will be cool and all, but I have big plans for the Ray Marcher!! Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine 🥀 Git Commits 🗿 Fixed an obsidian issue I ran into, “Minor rendering performance improvements.” was NOT true, broke almost the entire canvas. Fixed it though + new png Created the new buffer managegr system, I need to go through and make changes. Also, on launch there was more blacked out sections, different every launch :( New IRenderer setup for the render targets & render handles Refactor 1-6 Refactor 7-9 for BufferManager"}, {"post_id": 42396, "ts": "2026-08-07T02:46:23Z", "hours": 5.3317, "text": "—————– Devlog XV —————– – Temp code go brrrrr 🔋 - New term : “Far Landing” – To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ I tried getting this out before 4 hours, but it just –wouldn’t__ happen. Weird errors kept popping up ( mostly being my fault) . Here’s a list of what I did: Figured out generally how I was going to deal with uploading and caching meshes + textures Put the new GPUResourceManager class into place to do the previously mentioned job Started reworking the renderer pipeline (NOT THE RENDER PIPELINE) on CPU side, and set up the interface class with that Patched together the old Rasterizer renderer to work with the new IRenderer pipeline Fixed errors throughout Split up normal & bump textures Planned out how I will deal with all the different textures on the shader side, cutting the checks out at shader compile time Yea, I know, it’s a lot . It just felt wrong to create a devlog in the middle of everything, since up until after fixing errors I had nothing to show for it. :( I ran into this errors when fixing those errors, where the entire model (I was using the Sponza scene, check the attached video ) was banded, where parts “didn’t exist” and the other bands did . This reminded me a lot of the “Minecraft Farlands” specifically the pocket edition ones. 🔥 What didn’t I do? 💥 To keep this brief: Fully split up the SSBO system in the BufferManager Reimplement good use cases of UBOs (although I did put in place double buffering) Add the more sophicticated data handling in the PathTracer (as I commented it’s existance out so I could complile). Figure out how shadow mapping is going to be cleaned up in the Rasterizer. ❤️ Thanks for reading! These devlogs have been getting more attention, and I’m getting closer to doing a rebrand to finally get my point and final ideas across! :3 Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine 🥀 Git commits 🗿 Patched in the “new” buffer system - Really just to get it to compile before I do anything big. Attempting to run the app to test resources & scene Well it compiles, runs, and renders. I still need to go through all the models, HOWEVER, I am having an issue with like 3 models in sponza and bump UGH Well, I checked Phase-III, and the issue with those models are there too, probally some texture coord issue or the bump map is messed up (I’ll check in blender), BUT THEN ON FIRST LOAD THE MODEL FRA LANDED????"}, {"post_id": 40154, "ts": "2026-08-03T15:39:36Z", "hours": 3.0697, "text": "—————– Devlog XIV —————– The Planning - The possible NEW NAME??? - The New Project!! To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ So What Happened? 📸 I haven’t done much pure coding, HOWEVER , I am getting ready for some large-scale rewrites and additions to the code. For what has happened: Fully sectioned the resource - disk - and scene - cpu/logic - directories (folders) so there wasn’t any GPU actions taken place. Refactored resource and scene directories Re-implemented Application into CMakeLists so I can compile and link that file. Did some planning for the huge renderer rewrite that is coming up. Along with all of that, I came up with a possible name for the application (since, surprisingly, Tempname: Engine is a temp name) I had it when when gazing at the sun through some clouds over a feild. Although it is super basic, so I’m going to have to play with it. ❤️ Thanks for Reading!!! I might have to take a bit of a break from progress on this project, as I have a website that I’m making for my local fire dept. (look out for a new stardance project)! I’m also planning on doing some re-marketing / re-branding (idk what to call it) to change the descriptions of the project (ex. the “To recap section on my devlogs, and the landing page). I’ve been getting more questions on it, and my current explanations are a bit too much. Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine 🗿 Commits 🥀 (top-oldest : bottom-newest) No more mention of buffer manager or any uploading to gpu in scene & assets. Meshes are now split up from models in the cache, models hold refrences to asset handles to meshes. Refactored and fixed errors in scene and resources. The program won’t work, as only scene and resources are being compiled & linked Added application back into the mix & fixed the scene loading section. Did some planning on how a model will go from spawn to render"}, {"post_id": 38683, "ts": "2026-08-01T06:03:47Z", "hours": 3.0264, "text": "—————– Devlog XIII —————– Spent some time off from working on this project, started the beginnings of another one. Finally ended up getting the interest to come back to this one To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). 💡 Overview Commit message for this devlog: BREAKING CHANGE - New asset system, new scene system, renamed SceneLoader to PrefabSpawner, still need to update rest of code with temp fix until reworking for new system. ✨ What did I do? Previously, the asset manager did still handle caching already loaded assets (models, materials, textures), however the implementation was not professional and temporary: Caching based on a string key (slow) Broke the “single responsibility principal” many times by uploading to the GPU & constructing Scene objects Now, I am using AssetHandles (UUIDs) for caching, and I no longer uploading to the GPU in AssetManager. ❌ What didn’t I do? This new system is a good start for realigning and separating the different parts of the program, but is only about a third of the work. For what I still need to do, this is what follows: Stop uploading to the GPU in the PrefabSpawner (scene) Fix the renderer and find where I will upload the mesh & texture data. Check for compilation and working across the whole project. Change every instance of AssetManager to using AssetHandles. Once I have these, I can move onto redoing the renderers and FINALLY start working on the “fun stuff” ❤️ Thanks for reading Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine"}, {"post_id": 36073, "ts": "2026-07-27T22:33:56Z", "hours": 1.5831, "text": "—————– Devlog XII —————– I haven’t done as much programing recently, but yesterday I wanted to finish what I needed to do quickly, as it wouldn’t take that long. To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). 🎯 UUIDs For a quick explanation of what a UUID is: UUID stands for Universally Unique Identifier. In practice it is a random alphanumeric (a-z,0-9) ID between 64-128 bits. For my project, I used an unsigned 64 bit integer (no negative numbers). It isn’t exactly what the standard for a UUID is, as it isn’t alphanumeric, but I think for now 18.4 quintillion ids are just fine. ⬆️ What Next?? Now that I’ve finished this, the next step is to gut & rewrite the entire asset managing system. I need to redo how files are found, how data is stored, how they are retrieved. Basically the CRUD (create, read, update, delete) line and more. ❤️ Thanks for reading Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine"}, {"post_id": 32890, "ts": "2026-07-22T10:48:43Z", "hours": 6.8567, "text": "—————– Devlog XI —————– I haven’t been programming as much, as marching band 🎺 has started, so I’ve had less time. But now I can do the really exiting stuff! To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). What did I Do? As I mentioned in the last devlog, I have been working on doing a full passthrough of the entire project to get ready for major rewrites. I have completed by refactor checklist, so I have gone through ever cpp file to: Fix warnings Check object method & attribute visibility Check const, static, and inline declarations Change the placement and formatting of method Going through every line of code to do minor logic changes & change formatting Rename methods, attributes, functions, and variables to better names & names w/ personal conventions. Add comments everywhere Change the placement of the #include statements (main header file, object interfaces, project files, project packages, extra C++ headers) Run a full clean, compile, and test of the application The LIE Technically I didn’t go through every file, as I left AssetManager & Rasterizer . Since these will be completely rewrote soon I felt like it was a waste. What next? Now that I have finished cleaning up the code base, the next projects are to: Move to using UUIDs instead of an entity index in scene Gut AssetManager and rewrite it Change to using metafiles instead of a preditermined path to assets Rework the scene class Extend IRenderer and get ready for the fun part! Thanks for reading! I tried to keep this one shorter for y’all. I don’t normally get too much attention to my devlogs, but I would be more than happy to answer any questions, as there is so much more to this project that even the landing page doesn’t cover (WIP). If you’re curious, feel free to reach out on slack (pkncoder), and here are some extra links about the project: Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine"}, {"post_id": 29073, "ts": "2026-07-15T18:41:40Z", "hours": 4.3689, "text": "—————– Devlog X —————– I’ve been working on refactoring my project for the last few hours. Part of how I code includes: Comments throughout to explain the code, strict formatting throughout, and trying to help the compiler with “const” and “inline” keywords. To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). The process My process of refactoring usually happens once I finish a new addition, however I haven’t been adding new things for a while. Now that I’ve added a new addition to the project (Event system & LayerStack), I want to go through the entire codebase under the src/ directory (not the glsl shaders). Project code stats (src/ directory) Running the command line utility “cloc” on my src/ directory to count code stats, I get these counts: ------------------------------------------------------------------------------- Language files blank comment code ------------------------------------------------------------------------------- C++ 23 646 464 1930 C/C++ Header 47 506 205 1302 ------------------------------------------------------------------------------- SUM: 70 1152 669 3232 ------------------------------------------------------------------------------- Not very big yet, although that will be increased once I get to redoing the entire rendering engine. What I have done Now, back to my refactoring. I got through the basics: removing warnings, double checking the public/private attribute declarations on classes & structs, setting const on functions & params, setting inline on functions. The checklist This is my entire checklist for refactors, this is my first project using it, so it is still being worked on: ### Refactor Checklist (src/) 1. [x] Fix warnings 2. [x] Fix public vs. private 3. [x] Make functions const when needed 4. [x] Make function params const when needed 5. [x] Make functions inline when needed 6. [ ] Fix placement of functions 7. [ ] Refactor step by step in code 8. [ ] Rename things 9. [ ] Add comments 10. [ ] Place the \\#includes in the right spots 11. [ ] Fix file tree 12. [ ] Run ```./fullTest``` 13. [ ] Update the obsidian canvas & png 14. [ ] Update the website Eventually I will also need to make one for the shaders too, as they are sometimes more technical on the code side. Conclusion That’s all that I’ve been doing, thanks for reading. Here is my Github repo & landing page for this application: Source Code: https://github.com/pkncoder/Engine Landing Page: https://pkncoder.github.io/Engine"}, {"post_id": 27729, "ts": "2026-07-13T15:23:24Z", "hours": 8.2792, "text": "Devlog IX I have been working the past week to get the Event system working & trying to fix pointer / referance issues (there are still a few I haven’t figured out). But now I have a working event system. To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). LayerStack recap In my previous devlog, I explained the Layer Stack 🥞, a top-down structure for controlling object ownership and main loop execution. Every frame, the layer stack runs the first layer to poll camera movement inputs (temp), and then next layer is ran to render out the frame through the RendererManager. Events This is great, but where the layer stack really shines is the event system . Events are reactions to when anything happens, keys being pressed / released, the window resizing, etc. When an event is dispatched, the layerstack stops, loops through each layer running it’s “onEvent” function to let that layer react (ex. the final render needing it’s texture resized). If a layer doesn’t want below layers to react to the event, it can consume it, stopping the event dispatching and continuing execution. Struggle and Pointer Nonsense I struggled a ton with the event state not updating correctly, and the camera not giving the right values to render the triangles. It turned out to be objects/classes duplicating, and not being able to update. There is so many debug messages in the terminal 😭 Ends This was all front-end changes (no change in the render), but now there is a better system put in place (back end changes). Github repo: https://github.com/pkncoder/Engine/tree/Phase-IV Landing page / Website: https://pkncoder.github.io/Engine/"}, {"post_id": 23348, "ts": "2026-07-06T07:48:30Z", "hours": 11.7481, "text": "Tempname: Engine update. I am so tired To keep it all contained, since the last devlog I have: Merged Phase-III into main & created a Phase-IV branch Changed the landing page’s color palette Modified the target architecture 4 times (3 committed) Created a rudimentary SceneManager class Implemented an EngineContext class to distribute ownership & to help with data flow+containment Implemented a layer system to help cut down on application & to contain/host the events system. Finally put in the system directory (folder) in the architecture that will host any simulations, computations, and animations. Currently it is the planned details for the camera system. The biggest thing that I have done so far is the layer system & state/context creation. The context of the engine lets managers talk to each other so everything can work together, while keeping everything contained. The state is split up into two parts, state & settings (or state & configuration). The state is meant for information that is meant to change throughout runtime, and the engine depends on it to render the right final result (ex. camera state & position). The settings part is meant for variables that won’t change too much, but if they do it is something that is a large modification to the runtime (ex. window title, rendering engine). The layer system is like a regenerating stack of pancakes 🥞. Before you cast your pancake regeneration spell we all have, you have to prep the pancakes with butter and syrup. Each time you finish the pancakes, a new round starts and you eat them again. Then, once you are done, you have to disable the regeneration spell. The layer system acts the same, but computationally & layers instead of pancakes. Each layer goes through the lifecycle of onAttach -> onUpdate -> onDetach. By far the biggest reason for the layer system is the event system, but I’ll leave that for the next devlog. Here is the github page: https://github.com/pkncoder/Engine/tree/Phase-IV Here is the landing page: https://pkncoder.github.io/Engine/ I still have soooo much to do, especially with & after the event system. I’ve completed most of the easy stuff for Phase-IV. Here is the current architecture & a site screenshot."}, {"post_id": 19362, "ts": "2026-06-30T17:15:23Z", "hours": 5.5031, "text": "Changed my mind on shipping, however I do now have a landing page! I still have to do things like changing the color palette (it’s alright now, but I want something different I think), adding little details to really sell the “Rendering” aspect of Tempname: Engine, etc. etc. Here’s the landing page, please check it out & give any feedback! https://pkncoder.github.io/Engine/index.html Since I changed my mind on shipping, here are those images that I was going to use!"}, {"post_id": 18091, "ts": "2026-06-29T02:57:38Z", "hours": 8.6825, "text": "Just got done with some renders on the engine, been working all day on implementing the things needed. Along with the images, I added: Shadow Mapping for the Rasterizer (only 1 emitter) Tone mapping to the Rasterizer Fog to the Rasterizer A vignette effect to the Rasterizer Transparency maps to the Rasterizer Settings & presets for the renders A new “Queer Room” modeled by me in blender for the Path Tracer (going to post it on ship). I honestly have had so much fun with this. Currently working on a landing page to go in place of my “Online Demo” on stardance (since this isn’t that kind of application D: ). Here’s the github: https://github.com/pkncoder/Engine/tree/Phase-III ! At some point I’ll be redoing the README as well for more info. Also, these images aren’t even the best ones, I’ll leave that for the ship :3"}, {"post_id": 16960, "ts": "2026-06-27T15:16:34Z", "hours": 1.2764, "text": "I’ve done a bunch more Todos in my code, getting ready for shipping Phase-III. However, I realized I forgot in my planned Architechture about Acceleration structures (which are very important). So I planned that out! Currently just: BVH (Bounding Volume Heirarchy) for Ray & Path Tracing SVO (Sparse Voxel Octree) for Ray Marching (Hypothetically) These acceleration structures make rendering methods like Ray & Path Tracing, Ray Marching, Ray Casting, etc. feasible for real-time by “cutting out” data (objects) similar to how a Binary Tree works. Next is more clean up, then creating models for some renders I can use in the banner of this + the github Readme, and finally creating a landing page to put in place of the online demo! Then I can finally ship!!!! Here’s the github (ignore main branch): https://github.com/pkncoder/Engine/tree/Phase-III ."}, {"post_id": 16713, "ts": "2026-06-27T04:43:42Z", "hours": 17.5281, "text": "Working on finishing the current development phase, of my project, which also means finally shipping Tempname Engine: Phase-III. I wanted to plan out Phase IV a little bit more, which will focus on: Getting a structured scene management system Improving the Renderer (ability & architecture) + adding 2 new Renderers Adding scene loading & serialization (and “asset serialization” which is weird name) Here is the current & planned architectures of Phase III & Phase IV, at some point I need to redo Phase-III’s to match the style, but I’m tired of working in obsidian to not even get the hours logged."}, {"post_id": 11788, "ts": "2026-06-19T05:50:41Z", "hours": 7.56, "text": "I have finished getting albedo (basic color) textures loading! To get this working I had to redo how meshes were loaded completely, but I finally finished that. The backrooms model was an issue, as I needed to find one that would work, and then fix it in blender, but I’m glad it’s rendering! As for the promised model of the oiiaioooooiai cat 🐈 (Ethel), I did get the model & textures, but I will have to mess with it more, as the model & texture do not line up yet. If you would like to try for yourself, the github repo is here: https://github.com/pkncoder/Engine/tree/Phase-III . The repo is large currently, as I still need to compress the files, or remove them (gitignore). The path tracer is currently disabled , as I need to swap the textures to handles, and then modify the path tracer to work with the textures. It will look really good once I get that working though!"}, {"post_id": 10063, "ts": "2026-06-16T17:20:32Z", "hours": 2.4, "text": "I haven’t done much work on getting textures or anything, however I was able to re-do the shaders. Just some framework stuff like abstracting the shader models so each renderer can implement them to their need. I also spent some more time getting some generic formatting stuff like naming conventions (mostly naming conventions) I also made an “architecture” diagram, as I was requested for one (plus I needed one anyways). Anything purple (besides the background) is a temporary connection/file. Anything green needs re-worked The “Services” group contains files that are completely static in use, and are accessible globally. It’s still a bit messy, but that’s partly due to the temporary/need re-worked files. There’s a still some spaghetti code due to that. The shader files do look a lot like spaghetti as well, but that is mostly do to positioning. It’s pretty basic, as the ui/ and system/ dirs aren’t in there either (system/ is simulations + any computations that would need to be done (ex. translating data for one renderer to another)). I made the image in Obsidian’s canvas, sadly the wakatime add-on wasn’t working for me, so that time didn’t get counted, but oh well. And if the image is cut-off for you, the Services block has Input.cpp, Timer.cpp, and Logger.cpp. I still have a lot of shader work to redo, but I might try to get textures working soon for the Rasterizer, as I’m wanting them more & more."}, {"post_id": 9647, "ts": "2026-06-16T01:45:44Z", "hours": 19.2833, "text": "Hey everyone, I’m Kia! 👋 I’m currently building a custom 3D Engine from the ground up. While it’s definitely a fun passion project, it’s designed to be a genuinely powerful and useful tool. The scope of this project is pretty massive, but here are the main goals I’m chasing right now: 🎨 Multi-Style Rendering: I want this engine to render scenes in highly stylized ways using a variety of techniques. Currently planning support for: Rasterization Path Tracing Ray Marching Ray Casting (Voxels) Simple and easy: No one likes being thrown to the wolves. The engine will feature a clean, simple UI that scales in complexity as you learn how to use it, rather than overwhelming you right at the start. Accessible Animation: Built-in tools for animations and simulations that are actually easy to understand and use. 🛠️ Latest Update: Path Tracer Rewrite I recently did a complete rewrite of the Path Tracer! This was a massive step to future-proof the engine. It now supports multiple shader passes, debug textures, and is fully prepped for texture mapping. Why am I so excited about getting textures working? Because the second they drop, I am immediately rendering 1) The Backrooms 🟨 and 2) the spinning “Oiiaioooooiai” cat 🐈. Texture support should be ready very soon! Want to check it out (please do)? 💻 GitHub: Check out the code and the todo.md to see what I’m working on next: https://github.com/pkncoder/Engine/tree/Phase-III 🎮 Live Demo: Try out my almost real-time Path Tracer right in your browser (click and drag to look around): Shadertoy Path Tracer Demo: https://www.shadertoy.com/view/7fBSzR"}]...
|
Title: Tempname: Engine by @pkncoder | Stardance
Title: Tempname: Engine by @pkncoder | Stardance
Devlogs:
Hey everyone, I’m Kia! 👋 I’m currently building a custom 3D Engine from the ground up. While it’s definitely a fun passion project, it’s designed to be a genuinely powerful and useful tool. The scope of this project is pretty massive, but here are the main goals I’m chasing right now: 🎨 Multi-Style Rendering: I want this engine to render scenes in highly stylized ways using a variety of techniques. Currently planning support for: Rasterization Path Tracing Ray Marching Ray Casting (Voxels) Simple and easy: No one likes being thrown to the wolves. The engine will feature a clean, simple UI that scales in complexity as you learn how to use it, rather than overwhelming you right at the start. Accessible Animation: Built-in tools for animations and simulations that are actually easy to understand and use. 🛠️ Latest Update: Path Tracer Rewrite I recently did a complete rewrite of the Path Tracer! This was a massive step to future-proof the engine. It now supports multiple shader passes, debug textures, and is fully prepped for texture mapping. Why am I so excited about getting textures working? Because the second they drop, I am immediately rendering 1) The Backrooms 🟨 and 2) the spinning “Oiiaioooooiai” cat 🐈. Texture support should be ready very soon! Want to check it out (please do)? 💻 GitHub: Check out the code and the todo.md to see what I’m working on next: https://github.com/pkncoder/Engine/tree/Phase-III 🎮 Live Demo: Try out my almost real-time Path Tracer right in your browser (click and drag to look around): Shadertoy Path Tracer Demo: https://www.shadertoy.com/view/7fBSzR
I haven’t done much work on getting textures or anything, however I was able to re-do the shaders. Just some framework stuff like abstracting the shader models so each renderer can implement them to their need. I also spent some more time getting some generic formatting stuff like naming conventions (mostly naming conventions) I also made an “architecture” diagram, as I was requested for one (plus I needed one anyways). Anything purple (besides the background) is a temporary connection/file. Anything green needs re-worked The “Services” group contains files that are completely static in use, and are accessible globally. It’s still a bit messy, but that’s partly due to the temporary/need re-worked files. There’s a still some spaghetti code due to that. The shader files do look a lot like spaghetti as well, but that is mostly do to positioning. It’s pretty basic, as the ui/ and system/ dirs aren’t in there either (system/ is simulations + any computations that would need to be done (ex. translating data for one renderer to another)). I made the image in Obsidian’s canvas, sadly the wakatime add-on wasn’t working for me, so that time didn’t get counted, but oh well. And if the image is cut-off for you, the Services block has Input.cpp, Timer.cpp, and Logger.cpp. I still have a lot of shader work to redo, but I might try to get textures working soon for the Rasterizer, as I’m wanting them more & more.
I have finished getting albedo (basic color) textures loading! To get this working I had to redo how meshes were loaded completely, but I finally finished that. The backrooms model was an issue, as I needed to find one that would work, and then fix it in blender, but I’m glad it’s rendering! As for the promised model of the oiiaioooooiai cat 🐈 (Ethel), I did get the model & textures, but I will have to mess with it more, as the model & texture do not line up yet. If you would like to try for yourself, the github repo is here: https://github.com/pkncoder/Engine/tree/Phase-III . The repo is large currently, as I still need to compress the files, or remove them (gitignore). The path tracer is currently disabled , as I need to swap the textures to handles, and then modify the path tracer to work with the textures. It will look really good once I get that working though!
Working on finishing the current development phase, of my project, which also means finally shipping Tempname Engine: Phase-III. I wanted to plan out Phase IV a little bit more, which will focus on: Getting a structured scene management system Improving the Renderer (ability & architecture) + adding 2 new Renderers Adding scene loading & serialization (and “asset serialization” which is weird name) Here is the current & planned architectures of Phase III & Phase IV, at some point I need to redo Phase-III’s to match the style, but I’m tired of working in obsidian to not even get the hours logged.
I’ve done a bunch more Todos in my code, getting ready for shipping Phase-III. However, I realized I forgot in my planned Architechture about Acceleration structures (which are very important). So I planned that out! Currently just: BVH (Bounding Volume Heirarchy) for Ray & Path Tracing SVO (Sparse Voxel Octree) for Ray Marching (Hypothetically) These acceleration structures make rendering methods like Ray & Path Tracing, Ray Marching, Ray Casting, etc. feasible for real-time by “cutting out” data (objects) similar to how a Binary Tree works. Next is more clean up, then creating models for some renders I can use in the banner of this + the github Readme, and finally creating a landing page to put in place of the online demo! Then I can finally ship!!!! Here’s the github (ignore main branch): https://github.com/pkncoder/Engine/tree/Phase-III .
Just got done with some renders on the engine, been working all day on implementing the things needed. Along with the images, I added: Shadow Mapping for the Rasterizer (only 1 emitter) Tone mapping to the Rasterizer Fog to the Rasterizer A vignette effect to the Rasterizer Transparency maps to the Rasterizer Settings & presets for the renders A new “Queer Room” modeled by me in blender for the Path Tracer (going to post it on ship). I honestly have had so much fun with this. Currently working on a landing page to go in place of my “Online Demo” on stardance (since this isn’t that kind of application D: ). Here’s the github: https://github.com/pkncoder/Engine/tree/Phase-III ! At some point I’ll be redoing the README as well for more info. Also, these images aren’t even the best ones, I’ll leave that for the ship :3
Changed my mind on shipping, however I do now have a landing page! I still have to do things like changing the color palette (it’s alright now, but I want something different I think), adding little details to really sell the “Rendering” aspect of Tempname: Engine, etc. etc. Here’s the landing page, please check it out & give any feedback! https://pkncoder.github.io/Engine/index.html Since I changed my mind on shipping, here are those images that I was going to use!
Tempname: Engine update. I am so tired To keep it all contained, since the last devlog I have: Merged Phase-III into main & created a Phase-IV branch Changed the landing page’s color palette Modified the target architecture 4 times (3 committed) Created a rudimentary SceneManager class Implemented an EngineContext class to distribute ownership & to help with data flow+containment Implemented a layer system to help cut down on application & to contain/host the events system. Finally put in the system directory (folder) in the architecture that will host any simulations, computations, and animations. Currently it is the planned details for the camera system. The biggest thing that I have done so far is the layer system & state/context creation. The context of the engine lets managers talk to each other so everything can work together, while keeping everything contained. The state is split up into two parts, state & settings (or state & configuration). The state is meant for information that is meant to change throughout runtime, and the engine depends on it to render the right final result (ex. camera state & position). The settings part is meant for variables that won’t change too much, but if they do it is something that is a large modification to the runtime (ex. window title, rendering engine). The layer system is like a regenerating stack of pancakes 🥞. Before you cast your pancake regeneration spell we all have, you have to prep the pancakes with butter and syrup. Each time you finish the pancakes, a new round starts and you eat them again. Then, once you are done, you have to disable the regeneration spell. The layer system acts the same, but computationally & layers instead of pancakes. Each layer goes through the lifecycle of onAttach -> onUpdate -> onDetach. By far the biggest reason for the layer system is the event system, but I’ll leave that for the next devlog. Here is the github page: https://github.com/pkncoder/Engine/tree/Phase-IV Here is the landing page: https://pkncoder.github.io/Engine/ I still have soooo much to do, especially with & after the event system. I’ve completed most of the easy stuff for Phase-IV. Here is the current architecture & a site screenshot.
Devlog IX I have been working the past week to get the Event system working & trying to fix pointer / referance issues (there are still a few I haven’t figured out). But now I have a working event system. To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). LayerStack recap In my previous devlog, I explained the Layer Stack 🥞, a top-down structure for controlling object ownership and main loop execution. Every frame, the layer stack runs the first layer to poll camera movement inputs (temp), and then next layer is ran to render out the frame through the RendererManager. Events This is great, but where the layer stack really shines is the event system . Events are reactions to when anything happens, keys being pressed / released, the window resizing, etc. When an event is dispatched, the layerstack stops, loops through each layer running it’s “onEvent” function to let that layer react (ex. the final render needing it’s texture resized). If a layer doesn’t want below layers to react to the event, it can consume it, stopping the event dispatching and continuing execution. Struggle and Pointer Nonsense I struggled a ton with the event state not updating correctly, and the camera not giving the right values to render the triangles. It turned out to be objects/classes duplicating, and not being able to update. There is so many debug messages in the terminal 😭 Ends This was all front-end changes (no change in the render), but now there is a better system put in place (back end changes). Github repo: https://github.com/pkncoder/Engine/tree/Phase-IV Landing page / Website: https://pkncoder.github.io/Engine/
—————– Devlog X —————– I’ve been working on refactoring my project for the last few hours. Part of how I code includes: Comments throughout to explain the code, strict formatting throughout, and trying to help the compiler with “const” and “inline” keywords. To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). The process My process of refactoring usually happens once I finish a new addition, however I haven’t been adding new things for a while. Now that I’ve added a new addition to the project (Event system & LayerStack), I want to go through the entire codebase under the src/ directory (not the glsl shaders). Project code stats (src/ directory) Running the command line utility “cloc” on my src/ directory to count code stats, I get these counts: ------------------------------------------------------------------------------- Language files blank comment code ------------------------------------------------------------------------------- C++ 23 646 464 1930 C/C++ Header 47 506 205 1302 ------------------------------------------------------------------------------- SUM: 70 1152 669 3232 ------------------------------------------------------------------------------- Not very big yet, although that will be increased once I get to redoing the entire rendering engine. What I have done Now, back to my refactoring. I got through the basics: removing warnings, double checking the public/private attribute declarations on classes & structs, setting const on functions & params, setting inline on functions. The checklist This is my entire checklist for refactors, this is my first project using it, so it is still being worked on: ### Refactor Checklist (src/) 1. [x] Fix warnings 2. [x] Fix public vs. private 3. [x] Make functions const when needed 4. [x] Make function params const when needed 5. [x] Make functions inline when needed 6. [ ] Fix placement of functions 7. [ ] Refactor step by step in code 8. [ ] Rename things 9. [ ] Add comments 10. [ ] Place the \#includes in the right spots 11. [ ] Fix file tree 12. [ ] Run ```./fullTest``` 13. [ ] Update the obsidian canvas & png 14. [ ] Update the website Eventually I will also need to make one for the shaders too, as they are sometimes more technical on the code side. Conclusion That’s all that I’ve been doing, thanks for reading. Here is my Github repo & landing page for this application: Source Code: https://github.com/pkncoder/Engine Landing Page: https://pkncoder.github.io/Engine
—————– Devlog XI —————– I haven’t been programming as much, as marching band 🎺 has started, so I’ve had less time. But now I can do the really exiting stuff! To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). What did I Do? As I mentioned in the last devlog, I have been working on doing a full passthrough of the entire project to get ready for major rewrites. I have completed by refactor checklist, so I have gone through ever cpp file to: Fix warnings Check object method & attribute visibility Check const, static, and inline declarations Change the placement and formatting of method Going through every line of code to do minor logic changes & change formatting Rename methods, attributes, functions, and variables to better names & names w/ personal conventions. Add comments everywhere Change the placement of the #include statements (main header file, object interfaces, project files, project packages, extra C++ headers) Run a full clean, compile, and test of the application The LIE Technically I didn’t go through every file, as I left AssetManager & Rasterizer . Since these will be completely rewrote soon I felt like it was a waste. What next? Now that I have finished cleaning up the code base, the next projects are to: Move to using UUIDs instead of an entity index in scene Gut AssetManager and rewrite it Change to using metafiles instead of a preditermined path to assets Rework the scene class Extend IRenderer and get ready for the fun part! Thanks for reading! I tried to keep this one shorter for y’all. I don’t normally get too much attention to my devlogs, but I would be more than happy to answer any questions, as there is so much more to this project that even the landing page doesn’t cover (WIP). If you’re curious, feel free to reach out on slack (pkncoder), and here are some extra links about the project: Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine
—————– Devlog XII —————– I haven’t done as much programing recently, but yesterday I wanted to finish what I needed to do quickly, as it wouldn’t take that long. To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). 🎯 UUIDs For a quick explanation of what a UUID is: UUID stands for Universally Unique Identifier. In practice it is a random alphanumeric (a-z,0-9) ID between 64-128 bits. For my project, I used an unsigned 64 bit integer (no negative numbers). It isn’t exactly what the standard for a UUID is, as it isn’t alphanumeric, but I think for now 18.4 quintillion ids are just fine. ⬆️ What Next?? Now that I’ve finished this, the next step is to gut & rewrite the entire asset managing system. I need to redo how files are found, how data is stored, how they are retrieved. Basically the CRUD (create, read, update, delete) line and more. ❤️ Thanks for reading Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine
—————– Devlog XIII —————– Spent some time off from working on this project, started the beginnings of another one. Finally ended up getting the interest to come back to this one To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). 💡 Overview Commit message for this devlog: BREAKING CHANGE - New asset system, new scene system, renamed SceneLoader to PrefabSpawner, still need to update rest of code with temp fix until reworking for new system. ✨ What did I do? Previously, the asset manager did still handle caching already loaded assets (models, materials, textures), however the implementation was not professional and temporary: Caching based on a string key (slow) Broke the “single responsibility principal” many times by uploading to the GPU & constructing Scene objects Now, I am using AssetHandles (UUIDs) for caching, and I no longer uploading to the GPU in AssetManager. ❌ What didn’t I do? This new system is a good start for realigning and separating the different parts of the program, but is only about a third of the work. For what I still need to do, this is what follows: Stop uploading to the GPU in the PrefabSpawner (scene) Fix the renderer and find where I will upload the mesh & texture data. Check for compilation and working across the whole project. Change every instance of AssetManager to using AssetHandles. Once I have these, I can move onto redoing the renderers and FINALLY start working on the “fun stuff” ❤️ Thanks for reading Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine
—————– Devlog XIV —————– The Planning - The possible NEW NAME??? - The New Project!! To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ So What Happened? 📸 I haven’t done much pure coding, HOWEVER , I am getting ready for some large-scale rewrites and additions to the code. For what has happened: Fully sectioned the resource - disk - and scene - cpu/logic - directories (folders) so there wasn’t any GPU actions taken place. Refactored resource and scene directories Re-implemented Application into CMakeLists so I can compile and link that file. Did some planning for the huge renderer rewrite that is coming up. Along with all of that, I came up with a possible name for the application (since, surprisingly, Tempname: Engine is a temp name) I had it when when gazing at the sun through some clouds over a feild. Although it is super basic, so I’m going to have to play with it. ❤️ Thanks for Reading!!! I might have to take a bit of a break from progress on this project, as I have a website that I’m making for my local fire dept. (look out for a new stardance project)! I’m also planning on doing some re-marketing / re-branding (idk what to call it) to change the descriptions of the project (ex. the “To recap section on my devlogs, and the landing page). I’ve been getting more questions on it, and my current explanations are a bit too much. Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine 🗿 Commits 🥀 (top-oldest : bottom-newest) No more mention of buffer manager or any uploading to gpu in scene & assets. Meshes are now split up from models in the cache, models hold refrences to asset handles to meshes. Refactored and fixed errors in scene and resources. The program won’t work, as only scene and resources are being compiled & linked Added application back into the mix & fixed the scene loading section. Did some planning on how a model will go from spawn to render
—————– Devlog XV —————– – Temp code go brrrrr 🔋 - New term : “Far Landing” – To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ I tried getting this out before 4 hours, but it just –wouldn’t__ happen. Weird errors kept popping up ( mostly being my fault) . Here’s a list of what I did: Figured out generally how I was going to deal with uploading and caching meshes + textures Put the new GPUResourceManager class into place to do the previously mentioned job Started reworking the renderer pipeline (NOT THE RENDER PIPELINE) on CPU side, and set up the interface class with that Patched together the old Rasterizer renderer to work with the new IRenderer pipeline Fixed errors throughout Split up normal & bump textures Planned out how I will deal with all the different textures on the shader side, cutting the checks out at shader compile time Yea, I know, it’s a lot . It just felt wrong to create a devlog in the middle of everything, since up until after fixing errors I had nothing to show for it. :( I ran into this errors when fixing those errors, where the entire model (I was using the Sponza scene, check the attached video ) was banded, where parts “didn’t exist” and the other bands did . This reminded me a lot of the “Minecraft Farlands” specifically the pocket edition ones. 🔥 What didn’t I do? 💥 To keep this brief: Fully split up the SSBO system in the BufferManager Reimplement good use cases of UBOs (although I did put in place double buffering) Add the more sophicticated data handling in the PathTracer (as I commented it’s existance out so I could complile). Figure out how shadow mapping is going to be cleaned up in the Rasterizer. ❤️ Thanks for reading! These devlogs have been getting more attention, and I’m getting closer to doing a rebrand to finally get my point and final ideas across! :3 Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine 🥀 Git commits 🗿 Patched in the “new” buffer system - Really just to get it to compile before I do anything big. Attempting to run the app to test resources & scene Well it compiles, runs, and renders. I still need to go through all the models, HOWEVER, I am having an issue with like 3 models in sponza and bump UGH Well, I checked Phase-III, and the issue with those models are there too, probally some texture coord issue or the bump map is messed up (I’ll check in blender), BUT THEN ON FIRST LOAD THE MODEL FRA LANDED????
—————– Devlog XVI —————– So long , gay Bowser ⭐️ – IRenderer, hardly know her? - To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ⭐️ BEFORE ANYTHING - Thanks so much to @AVD for the super star, wasn’t expecting it and I really appreciate it 👏 👏. Now, for what I did: Dealt with an issue in Obsidian, as apparently there was “minor rendering performance improvements.” This is FALSE :( - I just downgraded the version Created the new BufferManager to handle UBOs, SSBOs, VBOs, EBOs, etc. + Dynamic, Static, and Stream buffers. Integrated the RenderTarget & ShaderPass system from PathTracer straight into IRenderer + added base utilities to it. Did some formatting Overall the two big things that I did was the new Buffer system & the updated IRenderer interface. For the new Buffers, previously I had UBOs (dynamic values) & SSBOs (big mostly static information blocks) set up in seperate files, that BufferManager returned. Now, every buffer is a single struct called GPUBuffer , and GPUBuffer has a type, and a usage (see attached photo). Now everything is centralized on that. For the new IRenderer interface, now there are RenderTargets - textures that shaders write to as output - and ShaderPasses - A pass of a shader. These can be added to a registry, keyed by a UUID (big number, in this case). Thanks for reading Again, thanks so much to AVD for the super star! I’m excited for when I can finally start writing my shaders, it’s getting closer & closer!! The fancy Path Tracer will be cool and all, but I have big plans for the Ray Marcher!! Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine 🥀 Git Commits 🗿 Fixed an obsidian issue I ran into, “Minor rendering performance improvements.” was NOT true, broke almost the entire canvas. Fixed it though + new png Created the new buffer managegr system, I need to go through and make changes. Also, on launch there was more blacked out sections, different every launch :( New IRenderer setup for the render targets & render handles Refactor 1-6 Refactor 7-9 for BufferManager
—————– Devlog XVII —————– - Strange Hours - To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ To start off, I did not work directly on my application, but the online demo . It’s like working on the website, but through another editor sometimes. The goal of the Path Tracer is to eventaully get it clean & quick enough to be real-time. This is the first of the 5 renderers that I will be making. I was working on my online shadertoy DEMO for the Path Tracer, specifically the denoiser. The name of the denoiser I am using is the “Edge-Avoiding Á Trous Wavelet Transform” . As a quick overview: It applies a blur “ with holes ” to allow for less to no image distortion Fast enough for realtime Includes “ weights ” based on (in my code): Normal , Depth , and Color . The larger the difference between the center pixel and the scanned pixel * (kernel), the more weight is applied, lessening the amount of blur. This is amazing, however when the camera moves , the denoiser assumes that the current and previous pixel are in the same world postion (when it isn’t). This causes errors when trying to overlay the image and gather data. This is why we track the motion of the camera, creating a vector to get the same world position pixel. I got this wrong on one of the first attempts, the last attachment (videos are compressed) shows that fun video (warning for those who get motion sick). With this, I am able to blur the image, and with some more techniques, I can get rid of “ghosting.” Thank You for Reading In the videos, I rendered them in fullscreen 4k on my better laptop+GPU, don’t worry about your system being too slow, just don’t fullscreen it <3 (the development was done on my lower end mac). The hours logged are from refactoring the project after the last devlog, and editing the code when I didn’t do it in shadertoy’s editor. Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine 🥀 Git Commits 🗿 BREAKING CHANGE - Refactored Buffer & GPUResource managers + IRenderer - Code has been broken for a bit but womp womp Shadertoy shaders path tracer https://www.shadertoy.com/view/7fBSzR
—————– Devlog XVIII —————– - 🌲 Trees 🧚♀️ - 👩💻 SO MUCH REWRITING 💀- To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ These last few days, I’ve been working on getting my Rasterizer (drawing triangles of a model on screen and coloring them) working. The big changes that I did include: Fixing an issue with textures not loading Updated the Interface for every Renderer. Implemented the extract / prepare / dispatch pipeline into the Rasterizer for real now. Started working on the base ideas of a “Shader Graph” The issue with textures was just moving a line like 3 lines lower . I was freeing the image data before saving it (oops) . The updated interface is the IRenderer class. Each Renderer bases off of the class, supplying it with a framework so each Renderer can be talked to the same way. Here are some of those functions: beginFrame - Clear previous frame data and prepare for a new frame extract - Take raw scene data ( camera , renderables ) and convert it into packets for the next step. prepare - Take each packet from extract and turn them into draw commands for dispatch. dispatch - Take each draw command and send a draw call, along the way binding any textures & uniforms. postProcess - Take the frame and post-process it. This may be removed. present - Take the rendered frame and show it to the screen ( blit it ). To do a quick review on what the Shader Graph is - it is a collection of “nodes,” each with their own inputs and outputs that connect together to render out a frame. I’m still a bit confused, but I’ve been watching presentations on the topic from companies like Unity & Activision . Thank You for Reading Yea, I know it’s been a while since my last devlog. I’ve been making some posts in slack about my Path Tracer, since I spent a little time on that. I’m looking at the timing for everything , the hope is to ship this at the end of Phase-IV and hope that I can get a UI working before too late. I’m hoping I can get enough stardust to pay for a new laptop, but idk that’s a long shot. I still have about 25 more hours if I get a 16x mult (which I can only hope for) before I would hit the mark for the FW 12, which isn’t crazy (the mult is tho). Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine ❓ What’s next? 🛑 Stop the program from crashing to reach a black screen Rewrite shaders to allow for correct models wo/ shadows Write the shadow cubemap geometry shader & ad it to the OpaquePass (temp main pass) Make and debug UBOs replacing base uniforms 🥀 Git Commits (shortened)🗿 https://github.com/pkncoder/Engine/commits/Phase-IV/
—————– Devlog XIX —————– - 🌲 Textuers 🧚♀️ - 👩💻 Shadoowwsss 💀- To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ To recap on what I did: Got the program to launch to black screen I needed to inject the Asset Manager to a class Got objects loading correctly without shadows Got textures to load Started work on fixing the shadow map Nothing too crazy has been changed, the texture issues were about some compatibility problems and not uploading to the same index. The shadow values are uploaded to a 3d texture, where to calculate if an object is in sight or not, we commit triangles based on their position. The problem now is about the far plane, and hitting triangles that weren’t in shadow. I’m not sure what the problem is, but I’m going to do a bit more looking into it. Thank You for Reading :3-blahaj-spinning I still have to fix the shadows issue (obviuosly) but then I can move onto formatting the data (putting it into buffers, creating wrappers, etc).!! Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine ❓ What’s next? 🛑 Write the shadow cubemap geometry shader & ad it to the OpaquePass (temp main pass) Make and debug UBOs replacing base uniforms Refactor / clean Create the real Render Graph? 🥀 Git Commits (shortened)🗿 Commits: https://github.com/pkncoder/Engine/commits/Phase-IV/ Most Recent: Temporary Save
—————– Devlog XX —————– – 🌟I have the best one liners 🗿– 🥀 Now I have to be smart ??? 🧠 – To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ For the quick overview: Fixed the shadow map issue ( so angry about this, see below ) Fixed an issue with textures not caching Got the very base implementation of Uniform Buffers To start off, in the previous devlog I mentioned I was re-writing the shadow mapping . Shadow Mapping - Rendering a 3d model with the light being the eye. Everything that it can see is not in shadow, everything else is. quick explanation I was having issues with getting the shadows to work correctly. I had ideas for issues, including: (the model matrix , the renderPackets being in a bad order , the far plane ). IT TURNS OUT It was none of these. Whenever I made the code to compile a geometry shader along the vertex & fragment shader, I just copied my old one and spliced in the code. Turns out I forgot to swap some variables, and I was putting code in places it should NOT be at. No idea why it didn’t crash, but it fixed my shadow issues very quick . As for UBOs, I’ll talk about them in a future devlog, when I have everything planned out. Thank You for Reading As I said with “Planning out” everything, I’m going to set up a whiteboard - I’ll have to move my 🏳️🌈 pride flags 🏳️⚧️ :( - Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine ❓ What’s next? 🛑 Refactor Build the big brain wall Do some thinking 🥀 Git Commits🗿 Weird position issue Saving now, I am so angry about this. I was compiling and overwrigting the wrong code :( Made the testing for shadows a bit better, and changed the rendering a bit Fixed issue with textures and full models not actually caching Removed anoying debug line for shadow transform matricies Working on getting the ubos working’ Got it to push First test ubos
—————– Devlog XXI —————– – My brain hurts 🧠 - Sharp like glass – To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ Sadly, I haven’t done much coding Instead, I’ve been trying to figure out how I want my Render Graph to work. To start, what is a render graph? What I am interpreting the render graph as, issss: An API meant to simplify and provide structure to a final renderer. In the final application, the render graph will be an option for a more advanced final render editor. What I am working on now, is how it will be put together so I don’t have a mess in the future. Recently, I’ve been using Obsidian to mark everything down. This also starts a little docs. Using a mix of Obsidian and the excalidraw plugin, I’m able to write everything down and create visuals. Currently, I have a mix of nodes that are the main important ones. These nodes are just the interfaces , so they aren’t specified. They act as a blueprint for any of the full nodes. IRenderOutput - Add textures to a list of blitables IShaderInput - Base input interface IShaderOutput - Base output interface IShaderNode - Node representation of shaders IShaderPassNode - Base shader interface Thank You for Reading I haven’t been home enough to create the “big brain wall” which is sad, but at least my stuff is digital. Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine ❓ What’s next? 🛑 Setup current program for Render Graph implementation Implement IShader, IGPUTexture, etc. Create IRenderGraph for the renderers
—————– Devlog XXII —————– – BrEaKiNg ChaNGeS - 📖 NEW BOOOKKKK – To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ Sadly, I’ve done much coding Base list This is what I have done since the last devlog: Planned out a bit more on the inner workings from no Renderer->Rendered Image Created the new Shader & Program classes Updated the workings on RendererManager Started work on the new Renderer / IRenderer class Current commit is now broken (compiles, doesn’t run Overview In my new obsidian vault , I’ve been working on creating the new database on how it all works. Through this, I’ve been using excalidraw (Obsidian) to plan out pipelines & create visuals. Currently, I have 2 main drawings: Shader & Program pipeline Renderer Pipeline The Shader & Program pipeline explains the lifetime and usage of both the Shader and Program (OpenGL program) classes. A program gets created, has shaders attached to it (deleting the shader in the process) , and then the program gets linked & binded. The Renderer Pipeline explains the lifetime and usage of a renderer. Starting from the RendererManager, go through normal rendering stuff, and will end at shutting down the RendererManager. For the inner workings of the new renderer setup, I’ll leave that for (hopefully next devlog) when I get everything working start to finish of the RendererPipeline . Thank You for Reading As for the “ New Book I got, I have just purchased “ Game Engine Architecture Vol. I ” (Jason Gregory) to specialize the program more (most likely after Stardance ends). Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine ❓ What’s next? 🛑 Plan out the RenderGraph Create the base RenderGraph class Create the BlitList Create the INodeInput & INodeOutput
—————– Devlog XXIII —————– – I NEED TO HURRY UP AAAA - EnTT - Table – To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ In my previous devlog, I stated how I was working on the new RenderGraph . I’ve now realized, that I have like until the end of the week for when I need to ship. So instead , my goal is to get this looking impressive . To start, here is what I’ve done so far : Cleaned up system inits Changed how the UUID service works (now you just access it and call generate ) Implemented a new library, EnTT Did some cleanning up Added a PointLightComponent for future use (no dev. yet) Added and implemented the CameraComponent Here are the big things: EnTT EnTT is an open-source library that handles objects within games, editors, etc. It’s creator is: Michele Caini (skypjack on github) . EnTT is a library that exposes something called an Entity Component System (ECS). Basically, instead of saving a bunch of data directly inside of one struct or class, you define an entity (a unique id) and assign that entity components. The components are what actually gives the entity meaning. New Camera If you have ever ued Blender for a bit, you would know that your camera is on the same list as your meshes. This is since, to Blender, they are inherantly the same thing (don’t quote me on that) . Previously, my camera was seperate to all of the rest of the objects. This caused the data to be split, and handling the differences made my architecture a bit weird. Now that I’ve implemented EnTT , I’ve added a CameraComponent that defines things like rotation, FoV, etc - completely erasing the need for a separate camera, and opening the doors to more flexibility. Thank You for Reading New book is great! I won’t get to use too much of it for stardance, but I’m checking out this snowglobe thing that seems like it would be the next area!! Wish me luck on the ship. I want to get it out by the end of the week so I can hopefully still cache in some stardust. Probally won’t get the computer though (high hopes for a living or smthin idk) Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine ❓ What’s next? 🛑 Change my Rasterizer to be a Defered Renderer & implement multiple point lights UI??
—————– Devlog XXIV —————– – i HATE shadow maps!!! - Renderer? I hardly know her? – To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ WOAH A lot has happened. Previously, I had just implemented a new entity system & a new camera system. So what’s new? I present: The Deferred Renderer !!! Basically, it’s just another way of rendering. HOWEVER , it has some funzies: Mostly together render graph, just a little smthin Shadow Pass G-Buffer Pass Lighting Pass New point lights (replacing the emmissive texture searching before) Looking to add SSAO (hemisphere sampling) in the future!! Now, along with this, I just tested creating a build for windows and testing it on a friends machine, and it worked (his laptop is crap, so it ran slow, but surprisingly fast) . Along with that, I also tried the current build on mac, and it also worked, so that’s also great (I’m supprised)!! However, the real prize, is the trypophobia horrors made along the way!! That’s right! When trying to get textures to work, I ran into a ton of problems (mostly related to the alpha map & image formats) that caused major headaches. Images and videos, where they are a bit compressed, can be found below. Thank You for Reading Almost there, I still need to change up the landing page, rewrite the readme, and merge the main branch, plus try to get a way to change the 3d models for users, but I’m getting there. Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine
—————– Devlog XXV —————– – New JSON scene file 📁 - SHIP TIMEEEEE – To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ Not that much has happened tbh. All that has really happened… Updated the README a bit more Added a new json parser to spawn the scene from that Added hot reloading of the scene So yea, next should be the ship. When updating the README on the github, I was going through the Usage section, and added a new promise for how people could add their own meshes. In this I created the idea of activeScene.json , a JSON file that listed the scene data (crazy, right?). And so, after I updated the README , I added the new loader, and made the scene reload by pressing the “ r ” key. That’s kinda it… Thank You for Reading Before shipping, I need to… Do another update of the README Create the base Releases for Mac, Windows, and Linux And test these Do a pass through TODO.md Update the landing page Shouldn’t take too long Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine
—————– Devlog XXVI —————– - - Almost… there – To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ In order to show the capabilites, I’ve been setting up scenes for my engine to show off, and here are some of the results! It would be great to get your favorite render of these! For the full 9 renders , check out the scrapbook in the slack , as they will be there w/ a thread. Thank You for Reading Hopefully will actually ship tmwr! I’m actually getting kind of sad, I won’t be stopping development by any means, but this has been my summer (although I might not be able to get any stardance tokens, but that’s ok ig…). If you have any questions, feel free to DM me either here, or at @pkncoder on discord if that’s easier for you! Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine
—————– Devlog XXVII —————– - - Release is out testing time – To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). ✨ What did I do? ☀️ Not too much has happened, mostly: Updated README (resources, gallery, installation & use) Updated the landing page (added a tech-stack) Created my first release under the 1.3.x alpha title That big 1.3.x “alpha” release is the big one, as I need some help. If you could just take a bit of time, and you aren’t on linux-arm or apple-intel, could you check out the github releases and try it out, that would be great! I plan to ship tmwr, but I want some testing done first. Thank You for Reading So close!! Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine
Ships:
—————– Ship #1 —————– - - Welcome - To recap, my project is a custom made rendering engine that focuses on diverse rendering options along with high stylistic control (very high-level explanation). 💚 The current state 💫 There is still no UI, all render control is based in a JSON file. The current only renderer is a custom Deferred Renderer. Note: As this is built for 3d rendering, a modern computer, with a GPU is recommended. Modern Macbooks will run it, however it will be slower as it is basically magic that it works on them. Thank you so much! I’ve spent a lot of time on this. It may not seem like that, however when building this, I decided to do it right (as this is my 3rd attempt). I split the development into phases: Get a window Get something rendering + a camera Get object/material/texture loaders + basic scene managers + basic concept of working Create full scale (professional) renderers/scene managers/resource managers/etc. Get a UI Currently, I’m in getting everything polished in the backend. I didn’t want to move on to the UI, as I didn’t want to rush that. Rushing a UI meant missing other things. So thank you, and I really hope you enjoy. If there are any issues, please report them to the issues page on the github, and message me on slack ( @pkncoder ). Github releases: https://github.com/pkncoder/Engine/releases Github repo: https://github.com/pkncoder/Engine Project landing page: https://pkncoder.github.io/Engine...
|
1792853732.3869977
|
1792940132.3869977
|
|
10673
|
DimeTrack by @d3monas | Stardance
|
d3monas
|
3
|
325.0
|
2960
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-18T21:44:49Z", "hours": 123.0, "multiplier": 16.88, "payout": 1039, "blessing": "neutral", "text": "DimeTrack is an open-source personal finance manager that helps people manage their money entirely in a browser. There are no accounts or subscriptions required and your data is stored locally on your device, with an OPTIONAL cloud sync if you want to access it across devices. Since my second shipment, the project has grown even further. I read every single review and Implemented all the suggestions that were provided. Made an optional cloud syncing feature that allows users to access and use the app across multiple devices. Made a small tutorial/guide that provides a bit more information on how to use DimeTrack. Replaced the Calendar tab with a new Timeline, that shows all your recurring transactions in your selected time interval, your projected balance and an ability to add a safety net and see if your projected balance falls below it in the coming months. Added an ability to manually track your Investments. Even more customization options and many other things. Similar to my previous shipments, the biggest challenge was to keep everything synced. One feature depends on another, so adding new functionality means that I have to update existing systems to ensure that everything stays working. I’ve somehow spent 325 hrs on this project and this will probably be my final shipment. I’ve had a lot of fun working on it and hope to maybe sometime later. For the v3 you should try to: Complete the tutorial (If you have used DimeTrack previously, go to settings -> data -> clear all data or just use incognito window) Add some recurring transactions and test out the Timeline to see your projected balance Explore the new subscriptions tab Set up cloud sync Add some Investments, update their price so see how your portfolio value goes up or down Check out the new financial insights in the Overview tab Use the Command Bar at top middle, you can find some quick actions there, search for any transaction or even create a quick transaction by typing in the search bar - Amount, Description, Existing Category (for example: 5 Coffee Food (must have a category called Food)) Explore the keyboard shortcuts Do a few achievements Create a few transactions and test out the bulk editing options", "repo": "https://github.com/d3monas/DimeTrack", "demo": "https://dime-track.vercel.app/"}, {"ship_num": 2, "ts": "2026-07-24T18:06:38Z", "hours": 174.0, "multiplier": 18.83, "payout": 1539, "blessing": "neutral", "text": "DimeTrack is an open-source personal finance manager that helps people manage their money entirely in a browser. There are no accounts, subscriptions, servers - everything is stored locally on device. Since my first shipment, the project has grown significantly. It now supports accounts, transfers between them, split purchases, multiple savings goals with contribution history and target dates, budget limits, auto-categorization rules, cash flow calendar with forecasting, monthly spending reports, net worth tracking, customizable categories and accounts, JSON backups, CSV import & export and many other quality of life improvements were made during the many hours spent on this project. The biggest challenge was keeping every feature synced as the project grew. Transactions can affect accounts, budgets, savings goals, recurring payments, reports, charts and basically everything. Adding new functionality means that I have to update existing systems to ensure that everything stays working as intended. But I’m proud to see how much my project has evolved and grown. You should try to: Create multiple accounts and transfer money between them Add income & expense transactions, try the split transaction function Set up a few savings goals with target dates and see how the contribution suggestion feature works Customize categories & accounts with icons and colors Configure budget limits and see the warnings that It gives you when nearing the limits Create an auto-categorization rule Explore the cash flow calendar Try exporting your data to JSON", "repo": "https://github.com/d3monas/DimeTrack", "demo": "https://dime-track.vercel.app/"}, {"ship_num": 3, "ts": "2026-06-18T11:37:29Z", "hours": 28.0, "multiplier": 13.41, "payout": 382, "blessing": "neutral", "text": "I built DimeTrack, a personal finance & budgeting web app that helps users to track their income, expenses, manage custom spending categories, create budgets & save toward their set goals. The application store data locally, allowing users to use it without creating an account. One of the biggest challenges was managing the app as it grew. Features such as recurring transactions, savings goal contributions, budget tracking & categories all interact with each other. Ensuring that data remained synced required lots of testing. I’m proud that I built DimeTrack to have so many features, I’ve never built anything quite like this. To test DimeTrack: Try to create some categories through the settings menu Add income & expenses Create a savings goal and try to contribute to it Set budget limits Try recurring transactions Search & filter your transactions (transcations can be searched by description, amount or category) Export your transaction data using the CSV export feature (if you only want data from let’s say todays transactions, apply a filter) Refresh the page with all the data, to confirm that everything is saved. No accounts needed!", "repo": "https://github.com/d3monas/DimeTrack", "demo": "https://dime-track.vercel.app/"}]...
|
[{"post_id": 49906, "ts": "202 [{"post_id": 49906, "ts": "2026-08-18T21:22:02Z", "hours": 5.8847, "text": "Worked on a custom date picker for the Timeline, so now instead of being locked into 7-day, 1 or 3 month views, users can now view any custom date they want. Created a financial safety net, where users can set a minimum balance and if your projected balance drops below it, a warning banner appears. Updated the auto-sync feature and made it truly auto, all users now need to do, is just enter a password once. Finally, did a final test of the app, fixed bugs, updated the landing page and the GitHub readme"}, {"post_id": 48713, "ts": "2026-08-17T07:13:40Z", "hours": 5.0786, "text": "Today, I worked on more Quality of Life features for my app, first of all - Introduced Keyboard Shortcuts, you can open the Command Bar with CTRL + K, add new transactions with ALT + N and switch tabs with ALT + 1 through 6. Created a small dialog that shows all the keyboard shortcuts available. Another feature - Transaction Presets. You can now create a preset for your most used transactions, just fill out the add transaction form as usual and instead of pressing “Save Transaction” just press the new Bookmark icon, then at the top your preset will appear, next time just press on the preset and everything will be filled out for you. Fixed a few tiny UI details, optimized mobile design, fixed a bug where the quick-add suggestion bar hardcoded a $ sign regardless of your selected currency. Finally, when creating a new transaction through the quick-add feature, you must now include a valid category otherwise the app won’t recognize that you are trying to add a transaction."}, {"post_id": 48036, "ts": "2026-08-16T10:16:00Z", "hours": 7.9572, "text": "Today, I Improved the “Smart Stats” feature with a new “Insights” tab. I didn’t want to create a new tab just for the Insights, so I decided to Implement the new feature in to an already existing one. Insights display your spending pace, give budget warnings, alerts you If your Net Worth & Savings are trending up or down and gives your Goal Projections without you having to navigate to the Goals tab. Also, replaced the default browser confirmation dialogs with custom ones, updated the tabs list design to a bit more modern one and made the tabs list stick so when you are scrolling down, your tabs list will always be accessible. Finally, fixed a few small bugs and a major budget rollover bug that would instantly roll over your budget without checking, if you even had a budget limit previously."}, {"post_id": 46940, "ts": "2026-08-14T14:40:05Z", "hours": 7.0375, "text": "Today, I’ve updated the command bar navigation to include the new Timeline and Investment tabs and with that also created a quicker way to add transactions - To create a transaction quicker, In the command bar all you need to do is type the amount, description and optionally category and account (for example: 9 Breakfast Food Checking). Also, reworked the transaction list and added abilities to select multiple or all transactions and bulk change account, categories, type or bulk delete transactions. Added ability to restore your transaction, if deleted accidentally. Finally, added an ability to duplicate transactions If needed."}, {"post_id": 45842, "ts": "2026-08-12T15:51:41Z", "hours": 9.6678, "text": "Today, I created a fun new achievement system which currently features 12 achievements. In the achievements page you can see all of them + progress tracker towards them. Upon unlocking an achievement, you will receive a notification in the bottom right corner of your screen. All achievements are saved locally, included in JSON backups and sync seamlessly. Also, fixed some localstorage and JSON backup issues and fixed a bug that when clearing your data, your investments would not clear."}, {"post_id": 45096, "ts": "2026-08-11T11:17:58Z", "hours": 6.7625, "text": "For todays update, I’ve worked on customization more. In settings, added an ability to turn off selected widgets that you do not care about. Turned off widgets will not be shown in the Overview tab. Also, I’ve done some more work to the Timeline tab, after each recurring transaction - your projected balance will show now, added an overdraft warning, so if your projected balance dips below 0 on a specific day, the chart will show a red zero-line and a warning banner will appear. Made the 3-month view sorted into groups by month, so Its easier to differentiate by month. Finally, I updated the exporting/importing and cloud syncing to make sure that everything is properly synced and no errors occur."}, {"post_id": 44522, "ts": "2026-08-10T10:42:39Z", "hours": 6.9944, "text": "Made some small improvements to the Investments tab and added a “Portfolio Performance” chart, which tracks how much you invested vs how much your portfolio is worth currently. Other than that, I completely reworked the Calendar, which is now called - Timeline. Instead of a Calendar it now shows your 7 day, 30 day and 3 month timeline with a projected balance, a projected balance chart and upcoming recurring transactions. It it somewhat similar to the calendar, however the whole UX is much more simpler and cleaner. Finally, I fixed some math calculations."}, {"post_id": 43894, "ts": "2026-08-09T10:37:55Z", "hours": 6.7469, "text": "Reworked the Investments Tab. Now you can properly buy/sell/update your investments to keep track of your Profit & Loss. When creating a new Investment, first of all, you will be able to select what kind of asset this is (It can be Stock, Crypto, ETF or Other). After creating an asset, you can buy/sell/update your asset. When buying, enter the quantity, price per date and set a date when bought. After buying you will instantly see your new updated portfolio value & how much you have invested. If you want to see your Total Profit & Loss, update your asset prices."}, {"post_id": 42550, "ts": "2026-08-07T11:27:13Z", "hours": 7.3378, "text": "Another requested feature was cloud syncing or login so It was easier to use DimeTrack between multiple devices. I built a cloud syncing feature with Upstash. Basically, your data is still encryped and nobody except you can see it. Also built an auto-sync feature so any time you add a transaction, update a budget, create a goal or do anything, the application waits 3 seconds and pushes your updated data to the cloud. Finally, did some minor settings UI changes to the tabs are less cluttered, especially on mobile screens. How to set up syncing? Open Settings and navigate to the new Sync tab Under “Start New Sync” create your password and enable syncing The app will generate a unique Sync ID, save this ID On your secondary device: Open Settings and navigate to the Sync tab Under “Connect to Existing Sync”, paste your Sync ID and enter your password Click Pull Data & Connect and your data will be downloaded. Auto-Sync is now active on both. Auto-Sync is only active until you refresh your browser. After you refresh your browser, you will see a banner saying that Auto-sync is paused. To unpause - enter your password again. *This sync feature is completely optional"}, {"post_id": 41530, "ts": "2026-08-05T19:59:50Z", "hours": 9.8156, "text": "Since the last devlog, I created a new Investments tab, where users can manually log their assets, mark them as Recurring Investments and update their values. Also, the total asset value is automatically added to the user’s Net Worth. For now, this investment tracker is very simple and I will be expanding on this feature a bit later. Most of my time during these few days was spent, trying to figure out how to connect Upstash to my app, so users can sync their data between devices, while I still keep DimeTrack fully serverless."}, {"post_id": 40251, "ts": "2026-08-03T17:32:22Z", "hours": 9.4694, "text": "I’ve read the reviews of my previous ship and a few users suggested that I create a tutorial. So that’s what I have done. When a brand new user opens the app (or an existing user clears their data), they will receive this welcome popup and will be given 2 choices - “Start Fresh” or “Start Demo Tour”. If the user chooses the Demo Tour, the app will instantly fill with realistic sample data (transactions, categories, accounts, recurring transactions, savings goals & more). On top of that, a quick 12 step tutorial will appear. During the tutorial, users will create a transaction, a new category, setup an auto categorization rule & create a savings goal. Once the tutorial is finished, the sample data will be wiped and the user will be able to use the app with their own data."}, {"post_id": 39370, "ts": "2026-08-02T09:43:02Z", "hours": 8.1022, "text": "Upgraded the budgeting side and added support for category rollover. So basically, If you underspend your limit this month, the remainder rolls over to the next month. But If you overspend, it will carry over as debt and your limit next month will be lower. Also worked on some smaller features, such as: added a clear filters button in transaction list whenever active filters are applied. Added small colored dots next to category names in the transaction list, the color of the dot matches your category color. If no recurring expenses are present, you will see a button, that will help you to create one. Finally, started working on a proper tutorial which is probably going to be in the next devlog."}, {"post_id": 38100, "ts": "2026-07-31T09:53:36Z", "hours": 6.8269, "text": "Added a new chart to the overview tab that projects your accounts balance 12 months in to the future based on your active recurring income & expenses. It features a red line at 0$ to warn you of potential overdrafts. Other than that, I’ve made a few code refactors, extracted formatting logic into a shared component and worked on mobile UI for this chart."}, {"post_id": 36954, "ts": "2026-07-29T11:29:37Z", "hours": 6.8278, "text": "Since the last update, I’ve made some small QOL improvements. Created ability to edit assigned accounts when editing a transaction. Also, you can now sort transactions by date (newest/oldest) or amount (highest/lowest). Added ability to filter and search transactions by tags. Reorganized the filter & search toolbar to fit everything smoothly, especially for mobiles. Lastly, upgraded empty states, so if you have no transactions, you’ll see not only the empty state but also an “Add Transaction” button. The change applies to Savings Goals"}, {"post_id": 35845, "ts": "2026-07-27T15:23:08Z", "hours": 9.1947, "text": "Today I spent a lot of time making a command menu, basically you can press Ctrl+K anywhere or click the new search bar in the header to open the Command Menu. It allows you to instantly search all transactions, jump to any tab, or trigger actions like adding a transaction or goal. Also, I created a new tags feature, you can add tags when creating or editing transactions for cross-category tracking. Finally, slightly redesigned the header so It now fully functions and fits on mobile."}, {"post_id": 35147, "ts": "2026-07-26T11:57:54Z", "hours": 9.3906, "text": "Continuing to work on DimeTrack, I made a dedicated “Subscriptions” tab, where It scans your recurring expenses, displays how much you spend on subscriptions monthly & annually and allows to toggle subscriptions between “Active” and “Cancelled” without deleting past transaction history. Also upgraded the main dashboard tabs to support 5 categories, added Icons to the tabs and on mobile tabs switch to icon-only layout to prevent text squishing. Finally, added a native browser confirmation prompts to all delete actions (deleting goals, accounts, categories & recurring transactions)"}, {"post_id": 34160, "ts": "2026-07-24T17:48:20Z", "hours": 7.9261, "text": "Created a “Monthly Report” dialog that generates a breakdown of the current months total income & expenses, net savings & savings rate, daily average spending, top spending category, largest single purchase & a trend comparison of expenses versus the previous month. Also fixed chart tool tip clipping om mobile screens, optimized the main header layout by hiding button text on small screens, preventing the “Settings” & “View Monthly Report” buttons from going out of bounds. Updated the landing page with new features and screenshots & updated the github readme."}, {"post_id": 33454, "ts": "2026-07-23T13:04:07Z", "hours": 9.5942, "text": "Added a new Net Worth History chart to the overview tab, which tracks your all-time balance over the last 6 months. Also upgraded the 6-month Income vs Expenses visualization from a Bar chart to a Line chart to match the Net Worth History chart design. Both charts now feature a smart Y-axis formatting for large numbers, shared tooltip styles."}, {"post_id": 32937, "ts": "2026-07-22T12:42:22Z", "hours": 7.5039, "text": "Today I made a guided setup checklist to help new users configure their dashboard with ease. Instead of an empty app, now a “Get Started” button appears at the top right corner, which opens a 5 step tutorial (Create Account, Category, Set a budget limit, a savings goal & Add a transaction). The checklist automatically detects completed steps and also allows users to skip the guide. Onboarding is fully linked with localStorage and JSON backups, so It doesn’t appear to users who already have everything setup."}, {"post_id": 31958, "ts": "2026-07-20T19:40:38Z", "hours": 9.7931, "text": "Created 2 new features: Net Worth - replaced the “current balance” card on the overview tab which a dynamic Net Worth widget which calculates your all-time balance and compares it to your balance at the end of last month, displaying a green or red trend arrow to show how much your net worth has grown or shrunk this month. Custom color theming - created a new settings tab called “appearance” & custom color picker which allows users to instantly re-theme buttons, active tabs, calendar selections, focused inputs. The color picker here is powered by react-colorful and color change is being handled by colord. Also implemented a localColor state so the app only commits the CSS when the user releases the color picker drag."}, {"post_id": 31210, "ts": "2026-07-19T12:56:00Z", "hours": 9.5264, "text": "Created a new Smart Stats widget to Overview tab that calculates your Daily Average spending and projects your End Of Month spending based on your current Daily Average spending. Then after that, I looked through every file and did some refactors, bug fixes & UI polishing (especially on mobile). Bug fixes: Excluded “Starting Balance” transactions from calculateIncome & getMonthlyTrends so adding an account with starting balance doesn’t inflate income stats or trend charts. Fixed deleteCategory to clean up everything (including transaction splits, auto-categorization rules and category customization). Added a transfer account validation to Add Transaction dialog to prevent saving a transfer with empty “From/To” accounts or transferring money to the same account. Fixed the “Will exceed budget” warning showing when adding Income. Added defaultAccountId to JSON export/import handlers so the user’s default account setting survives JSON backups. Refactors: Extracted the duplicated color/icon Popover UI from settingsUI & accountManager in to a single colorIconPicker component. Extracted duplicated Recharts tooltip styling into a shared chartStyles.ts constant. UI Polish: Made the calendar mobile-friendly by showing colored dots on small screens and full text & balances on larger ones. Hid the default calendar navigation arrows that appeared at the top of the screen and adjusted button heights to match. Adjusted TabsList to use text-xs on mobile to prevent text overlapping on small screens. Added offset, z-index & allowEscapeViewBox to chart styles to prevent hover tooltips from being hidden behind chart graphics. Removed dead props, fixed a few typos and replaced hardcoded values with consts."}, {"post_id": 30620, "ts": "2026-07-18T10:38:01Z", "hours": 9.6939, "text": "Final part of the Accounts update: Worked on visual customization for the accounts system. Users can now edit account names without losing their transaction history. Also introduced a color and icon picker for accounts (just like with categories), so It’s easier for users to differentiate between accounts. Created a new “Total Balance” card that quickly shows your balance between all accounts. Finally, added a new filter for the transaction list - “Transfer”, colored transfers in a gray color so they don’t look like expenses, hidden the “Starting Balance” system transactions to reduce the visual clutter of the transaction list & updated the default account badge design."}, {"post_id": 29478, "ts": "2026-07-16T13:32:53Z", "hours": 10.1997, "text": "Part 2 of the Accounts update: Created a new ‘account balance’ widget that displays all your accounts & their balances. The transaction list now features a badge with the account name that the transaction was assigned to. Spent a lot of time fixing CSV exports/imports to properly support accounts & transfers between accounts. Finally, introduced a ‘starting balance’ feature for users can instantly input their balance when creating a new account without typing months of history and a ‘default account’ setting that auto selects their primary account when creating a new transaction"}, {"post_id": 28548, "ts": "2026-07-14T21:22:16Z", "hours": 9.845, "text": "Part 1 of the Accounts update: I finally built the whole architecture for multi-account management. Users can now create accounts (like checking or savings) and assign transactions to them. Also Introduced “transfers” which allow users to move money between accounts without adding fake data to income or expenses. The add and edit transaction dialogs now feature a dynamic UI that swaps out categories & split transaction functionalities for “From/to” account selectors. Finally, updated localStorage & JSON data exports to make sure that accounts are included."}, {"post_id": 27124, "ts": "2026-07-12T12:16:03Z", "hours": 7.7758, "text": "Improved the spending pie chart by adding a legend below the chart, displaying currency symbols when hovering & vastly improving tooltip readability on hover. Also expanded the Recent Transactions page with even more filters. Now you can filter transactions by income, expenses and categories. Finally, fixed some design inconsistencies."}, {"post_id": 26471, "ts": "2026-07-11T09:01:46Z", "hours": 9.3356, "text": "Added category customization, allowing users to personalize categories with custom icons & colors. Updated the spending chart and budget overview to use the new customization system, so select icons and colors are consistent throughout the whole application. Refactored the application to use default icon & color when none are selected."}, {"post_id": 25000, "ts": "2026-07-08T22:05:19Z", "hours": 11.4794, "text": "Added auto-categorization rules, which allows transactions to be automatically assigned to categories based on custom keywords. When you type the set keyword in description, a category will be auto chosen based on the rule. Built a rules manager in the Settings page to manage auto-categorization rules. Also expanded CSV & JSON import/export functionality to include notes & auto-categorization rules. Fixed several issues with CSV importing, when imported descriptions, notes were missing & incorrect amounts were assigned. Finally, redesigned the Settings UI and assigned each category to its own tab & cleaned up various design inconsistencies."}, {"post_id": 24022, "ts": "2026-07-07T09:34:59Z", "hours": 13.2997, "text": "Introduced the ability to split a single transaction across multiple categories. Also improved the transaction list to clearly display split categories and their amounts. Now, creating new categories is much easier, as they can be added directly when creating a transaction. Finally, I added warnings that notify users when a savings goal contribution would exceed its target or when a new expense would push a category over Its budget limit."}, {"post_id": 21802, "ts": "2026-07-03T22:35:42Z", "hours": 11.8697, "text": "I spent 12 hours on this 😭😭😭. It’s a cash flow calendar which uses historical and current transactions & puts them in a calendar. This feature projects your upcoming recurring transactions & income, automatically calculating your daily running balance. It highlights your balance red, if there is a potential overdraft. It’s pretty easy to navigate through past & future months to analyze your spending."}, {"post_id": 19107, "ts": "2026-06-30T10:41:35Z", "hours": 12.7331, "text": "Created an optional selection when creating a savings goal - Target Date. If Target Date is selected, when contributing to a goal, you will get a suggested amount based on your goal & target date. Created a notification system and replaced all alert() functions with notifications. When creating & editing transactions, users can now enter additional notes that they may have about the transaction. Also fixed CSV importing bugs & a few small UI inconsistencies."}, {"post_id": 17223, "ts": "2026-06-27T22:43:14Z", "hours": 8.6589, "text": "Today most of my time was dedicated to a UI rearrangement. I split the whole dashboard into 3 main tabs. Also created a section that shows your upcoming recurring transactions in the next 7 days. Finally, made a setting that allows users to wipe all their data."}, {"post_id": 15987, "ts": "2026-06-25T23:18:41Z", "hours": 10.7472, "text": "Mostly worked on the new Import CSV, Export & Import backups features. With Import CSV, you can import your existing transactions & categories while with Import backup you can import everything that your app has, this is great if user is switching browsers or devices. The other feature is a 6 month expenses vs income TrendChart that allows you to visually see how much you are making, spending & compare."}, {"post_id": 14707, "ts": "2026-06-23T22:10:13Z", "hours": 8.1892, "text": "DEV #7 Well first of all, It took me an hour to find a simple shadow class that needed to be removed so the landing page picture looks better. The rest of the time was spent figuring out how to & actually making the ability to create multiple goals at once."}, {"post_id": 13351, "ts": "2026-06-21T21:23:45Z", "hours": 5.655, "text": "DEV #6 Since shipping I worked on a small landing page which presents the core features of dimetrack. Fixed some issues with recurring transactions & implemented the ability to use custom values for recurring transactions instead of using the preset ones. Lastly, created loading skeletons & worked on some small design improvements (inconsistent gaps, settings dialog not being scrollable when too many elements are present, added small animations to progress bars.)"}, {"post_id": 11219, "ts": "2026-06-18T11:22:15Z", "hours": 5.0586, "text": "DEV #5 Polished the application more (especially mobile design) and finished the remaining features that I had planned. Users can now search their transactions by description, category or amount Added a separate goal contribution history for easier tracking Added budget limit warnings at: 50%, 80% & 100% Users can export their data in a .csv file"}, {"post_id": 10249, "ts": "2026-06-16T21:45:47Z", "hours": 6.6958, "text": "DEV #4 Added recurring transactions support. Users can select recurring transactions every day, week, month or year. Users can see all their recurring transactions & delete them in settings Added transaction filtering, same as recurring transactions, users can filter their recent transactions by day, week, month, year or lifetime Created field errors Many bug fixes"}, {"post_id": 8385, "ts": "2026-06-13T22:57:24Z", "hours": 8.8989, "text": "DEV #3 New features: Currency selector New settings page Ability to contribute to goal Ability to delete categories Ability to edit budget limits Lots of bug fixes Huge code cleanup, refactors & +99 more bugs to fix"}, {"post_id": 5190, "ts": "2026-06-08T21:42:35Z", "hours": 4.8833, "text": "Day 2 Created: Categories Spending by category & spending breakdown pie-chart Ability to edit goals Mostly worked on optimization today, moved most components into separate files. Fixed some bugs (hopefully). Designed a quick (was not quick) logo & favicon."}, {"post_id": 4518, "ts": "2026-06-07T21:11:11Z", "hours": 2.9533, "text": "Created the first working version of the transaction system. Income and expenses are now accepted, and actual data rather than hardcoded amounts are used to update balance, income, and spending in real time. Also created transaction saving to localStorage. Discovered a bug early on where an invalid input broke all calculations, so I added a better validation in the form to (hopefully) prevent these types of errors in the future. For now, I’ll keep working on the UX part and create more features and then move on to UI."}]...
|
Title: DimeTrack by @d3monas | Stardance
Devlogs: Title: DimeTrack by @d3monas | Stardance
Devlogs:
Created the first working version of the transaction system. Income and expenses are now accepted, and actual data rather than hardcoded amounts are used to update balance, income, and spending in real time. Also created transaction saving to localStorage. Discovered a bug early on where an invalid input broke all calculations, so I added a better validation in the form to (hopefully) prevent these types of errors in the future. For now, I’ll keep working on the UX part and create more features and then move on to UI.
Day 2 Created: Categories Spending by category & spending breakdown pie-chart Ability to edit goals Mostly worked on optimization today, moved most components into separate files. Fixed some bugs (hopefully). Designed a quick (was not quick) logo & favicon.
DEV #3 New features: Currency selector New settings page Ability to contribute to goal Ability to delete categories Ability to edit budget limits Lots of bug fixes Huge code cleanup, refactors & +99 more bugs to fix
DEV #4 Added recurring transactions support. Users can select recurring transactions every day, week, month or year. Users can see all their recurring transactions & delete them in settings Added transaction filtering, same as recurring transactions, users can filter their recent transactions by day, week, month, year or lifetime Created field errors Many bug fixes
DEV #5 Polished the application more (especially mobile design) and finished the remaining features that I had planned. Users can now search their transactions by description, category or amount Added a separate goal contribution history for easier tracking Added budget limit warnings at: 50%, 80% & 100% Users can export their data in a .csv file
DEV #6 Since shipping I worked on a small landing page which presents the core features of dimetrack. Fixed some issues with recurring transactions & implemented the ability to use custom values for recurring transactions instead of using the preset ones. Lastly, created loading skeletons & worked on some small design improvements (inconsistent gaps, settings dialog not being scrollable when too many elements are present, added small animations to progress bars.)
DEV #7 Well first of all, It took me an hour to find a simple shadow class that needed to be removed so the landing page picture looks better. The rest of the time was spent figuring out how to & actually making the ability to create multiple goals at once.
Mostly worked on the new Import CSV, Export & Import backups features. With Import CSV, you can import your existing transactions & categories while with Import backup you can import everything that your app has, this is great if user is switching browsers or devices. The other feature is a 6 month expenses vs income TrendChart that allows you to visually see how much you are making, spending & compare.
Today most of my time was dedicated to a UI rearrangement. I split the whole dashboard into 3 main tabs. Also created a section that shows your upcoming recurring transactions in the next 7 days. Finally, made a setting that allows users to wipe all their data.
Created an optional selection when creating a savings goal - Target Date. If Target Date is selected, when contributing to a goal, you will get a suggested amount based on your goal & target date. Created a notification system and replaced all alert() functions with notifications. When creating & editing transactions, users can now enter additional notes that they may have about the transaction. Also fixed CSV importing bugs & a few small UI inconsistencies.
I spent 12 hours on this 😭😭😭. It’s a cash flow calendar which uses historical and current transactions & puts them in a calendar. This feature projects your upcoming recurring transactions & income, automatically calculating your daily running balance. It highlights your balance red, if there is a potential overdraft. It’s pretty easy to navigate through past & future months to analyze your spending.
Introduced the ability to split a single transaction across multiple categories. Also improved the transaction list to clearly display split categories and their amounts. Now, creating new categories is much easier, as they can be added directly when creating a transaction. Finally, I added warnings that notify users when a savings goal contribution would exceed its target or when a new expense would push a category over Its budget limit.
Added auto-categorization rules, which allows transactions to be automatically assigned to categories based on custom keywords. When you type the set keyword in description, a category will be auto chosen based on the rule. Built a rules manager in the Settings page to manage auto-categorization rules. Also expanded CSV & JSON import/export functionality to include notes & auto-categorization rules. Fixed several issues with CSV importing, when imported descriptions, notes were missing & incorrect amounts were assigned. Finally, redesigned the Settings UI and assigned each category to its own tab & cleaned up various design inconsistencies.
Added category customization, allowing users to personalize categories with custom icons & colors. Updated the spending chart and budget overview to use the new customization system, so select icons and colors are consistent throughout the whole application. Refactored the application to use default icon & color when none are selected.
Improved the spending pie chart by adding a legend below the chart, displaying currency symbols when hovering & vastly improving tooltip readability on hover. Also expanded the Recent Transactions page with even more filters. Now you can filter transactions by income, expenses and categories. Finally, fixed some design inconsistencies.
Part 1 of the Accounts update: I finally built the whole architecture for multi-account management. Users can now create accounts (like checking or savings) and assign transactions to them. Also Introduced “transfers” which allow users to move money between accounts without adding fake data to income or expenses. The add and edit transaction dialogs now feature a dynamic UI that swaps out categories & split transaction functionalities for “From/to” account selectors. Finally, updated localStorage & JSON data exports to make sure that accounts are included.
Part 2 of the Accounts update: Created a new ‘account balance’ widget that displays all your accounts & their balances. The transaction list now features a badge with the account name that the transaction was assigned to. Spent a lot of time fixing CSV exports/imports to properly support accounts & transfers between accounts. Finally, introduced a ‘starting balance’ feature for users can instantly input their balance when creating a new account without typing months of history and a ‘default account’ setting that auto selects their primary account when creating a new transaction
Final part of the Accounts update: Worked on visual customization for the accounts system. Users can now edit account names without losing their transaction history. Also introduced a color and icon picker for accounts (just like with categories), so It’s easier for users to differentiate between accounts. Created a new “Total Balance” card that quickly shows your balance between all accounts. Finally, added a new filter for the transaction list - “Transfer”, colored transfers in a gray color so they don’t look like expenses, hidden the “Starting Balance” system transactions to reduce the visual clutter of the transaction list & updated the default account badge design.
Created a new Smart Stats widget to Overview tab that calculates your Daily Average spending and projects your End Of Month spending based on your current Daily Average spending. Then after that, I looked through every file and did some refactors, bug fixes & UI polishing (especially on mobile). Bug fixes: Excluded “Starting Balance” transactions from calculateIncome & getMonthlyTrends so adding an account with starting balance doesn’t inflate income stats or trend charts. Fixed deleteCategory to clean up everything (including transaction splits, auto-categorization rules and category customization). Added a transfer account validation to Add Transaction dialog to prevent saving a transfer with empty “From/To” accounts or transferring money to the same account. Fixed the “Will exceed budget” warning showing when adding Income. Added defaultAccountId to JSON export/import handlers so the user’s default account setting survives JSON backups. Refactors: Extracted the duplicated color/icon Popover UI from settingsUI & accountManager in to a single colorIconPicker component. Extracted duplicated Recharts tooltip styling into a shared chartStyles.ts constant. UI Polish: Made the calendar mobile-friendly by showing colored dots on small screens and full text & balances on larger ones. Hid the default calendar navigation arrows that appeared at the top of the screen and adjusted button heights to match. Adjusted TabsList to use text-xs on mobile to prevent text overlapping on small screens. Added offset, z-index & allowEscapeViewBox to chart styles to prevent hover tooltips from being hidden behind chart graphics. Removed dead props, fixed a few typos and replaced hardcoded values with consts.
Created 2 new features: Net Worth - replaced the “current balance” card on the overview tab which a dynamic Net Worth widget which calculates your all-time balance and compares it to your balance at the end of last month, displaying a green or red trend arrow to show how much your net worth has grown or shrunk this month. Custom color theming - created a new settings tab called “appearance” & custom color picker which allows users to instantly re-theme buttons, active tabs, calendar selections, focused inputs. The color picker here is powered by react-colorful and color change is being handled by colord. Also implemented a localColor state so the app only commits the CSS when the user releases the color picker drag.
Today I made a guided setup checklist to help new users configure their dashboard with ease. Instead of an empty app, now a “Get Started” button appears at the top right corner, which opens a 5 step tutorial (Create Account, Category, Set a budget limit, a savings goal & Add a transaction). The checklist automatically detects completed steps and also allows users to skip the guide. Onboarding is fully linked with localStorage and JSON backups, so It doesn’t appear to users who already have everything setup.
Added a new Net Worth History chart to the overview tab, which tracks your all-time balance over the last 6 months. Also upgraded the 6-month Income vs Expenses visualization from a Bar chart to a Line chart to match the Net Worth History chart design. Both charts now feature a smart Y-axis formatting for large numbers, shared tooltip styles.
Created a “Monthly Report” dialog that generates a breakdown of the current months total income & expenses, net savings & savings rate, daily average spending, top spending category, largest single purchase & a trend comparison of expenses versus the previous month. Also fixed chart tool tip clipping om mobile screens, optimized the main header layout by hiding button text on small screens, preventing the “Settings” & “View Monthly Report” buttons from going out of bounds. Updated the landing page with new features and screenshots & updated the github readme.
Continuing to work on DimeTrack, I made a dedicated “Subscriptions” tab, where It scans your recurring expenses, displays how much you spend on subscriptions monthly & annually and allows to toggle subscriptions between “Active” and “Cancelled” without deleting past transaction history. Also upgraded the main dashboard tabs to support 5 categories, added Icons to the tabs and on mobile tabs switch to icon-only layout to prevent text squishing. Finally, added a native browser confirmation prompts to all delete actions (deleting goals, accounts, categories & recurring transactions)
Today I spent a lot of time making a command menu, basically you can press Ctrl+K anywhere or click the new search bar in the header to open the Command Menu. It allows you to instantly search all transactions, jump to any tab, or trigger actions like adding a transaction or goal. Also, I created a new tags feature, you can add tags when creating or editing transactions for cross-category tracking. Finally, slightly redesigned the header so It now fully functions and fits on mobile.
Since the last update, I’ve made some small QOL improvements. Created ability to edit assigned accounts when editing a transaction. Also, you can now sort transactions by date (newest/oldest) or amount (highest/lowest). Added ability to filter and search transactions by tags. Reorganized the filter & search toolbar to fit everything smoothly, especially for mobiles. Lastly, upgraded empty states, so if you have no transactions, you’ll see not only the empty state but also an “Add Transaction” button. The change applies to Savings Goals
Added a new chart to the overview tab that projects your accounts balance 12 months in to the future based on your active recurring income & expenses. It features a red line at 0$ to warn you of potential overdrafts. Other than that, I’ve made a few code refactors, extracted formatting logic into a shared component and worked on mobile UI for this chart.
Upgraded the budgeting side and added support for category rollover. So basically, If you underspend your limit this month, the remainder rolls over to the next month. But If you overspend, it will carry over as debt and your limit next month will be lower. Also worked on some smaller features, such as: added a clear filters button in transaction list whenever active filters are applied. Added small colored dots next to category names in the transaction list, the color of the dot matches your category color. If no recurring expenses are present, you will see a button, that will help you to create one. Finally, started working on a proper tutorial which is probably going to be in the next devlog.
I’ve read the reviews of my previous ship and a few users suggested that I create a tutorial. So that’s what I have done. When a brand new user opens the app (or an existing user clears their data), they will receive this welcome popup and will be given 2 choices - “Start Fresh” or “Start Demo Tour”. If the user chooses the Demo Tour, the app will instantly fill with realistic sample data (transactions, categories, accounts, recurring transactions, savings goals & more). On top of that, a quick 12 step tutorial will appear. During the tutorial, users will create a transaction, a new category, setup an auto categorization rule & create a savings goal. Once the tutorial is finished, the sample data will be wiped and the user will be able to use the app with their own data.
Since the last devlog, I created a new Investments tab, where users can manually log their assets, mark them as Recurring Investments and update their values. Also, the total asset value is automatically added to the user’s Net Worth. For now, this investment tracker is very simple and I will be expanding on this feature a bit later. Most of my time during these few days was spent, trying to figure out how to connect Upstash to my app, so users can sync their data between devices, while I still keep DimeTrack fully serverless.
Another requested feature was cloud syncing or login so It was easier to use DimeTrack between multiple devices. I built a cloud syncing feature with Upstash. Basically, your data is still encryped and nobody except you can see it. Also built an auto-sync feature so any time you add a transaction, update a budget, create a goal or do anything, the application waits 3 seconds and pushes your updated data to the cloud. Finally, did some minor settings UI changes to the tabs are less cluttered, especially on mobile screens. How to set up syncing? Open Settings and navigate to the new Sync tab Under “Start New Sync” create your password and enable syncing The app will generate a unique Sync ID, save this ID On your secondary device: Open Settings and navigate to the Sync tab Under “Connect to Existing Sync”, paste your Sync ID and enter your password Click Pull Data & Connect and your data will be downloaded. Auto-Sync is now active on both. Auto-Sync is only active until you refresh your browser. After you refresh your browser, you will see a banner saying that Auto-sync is paused. To unpause - enter your password again. *This sync feature is completely optional
Reworked the Investments Tab. Now you can properly buy/sell/update your investments to keep track of your Profit & Loss. When creating a new Investment, first of all, you will be able to select what kind of asset this is (It can be Stock, Crypto, ETF or Other). After creating an asset, you can buy/sell/update your asset. When buying, enter the quantity, price per date and set a date when bought. After buying you will instantly see your new updated portfolio value & how much you have invested. If you want to see your Total Profit & Loss, update your asset prices.
Made some small improvements to the Investments tab and added a “Portfolio Performance” chart, which tracks how much you invested vs how much your portfolio is worth currently. Other than that, I completely reworked the Calendar, which is now called - Timeline. Instead of a Calendar it now shows your 7 day, 30 day and 3 month timeline with a projected balance, a projected balance chart and upcoming recurring transactions. It it somewhat similar to the calendar, however the whole UX is much more simpler and cleaner. Finally, I fixed some math calculations.
For todays update, I’ve worked on customization more. In settings, added an ability to turn off selected widgets that you do not care about. Turned off widgets will not be shown in the Overview tab. Also, I’ve done some more work to the Timeline tab, after each recurring transaction - your projected balance will show now, added an overdraft warning, so if your projected balance dips below 0 on a specific day, the chart will show a red zero-line and a warning banner will appear. Made the 3-month view sorted into groups by month, so Its easier to differentiate by month. Finally, I updated the exporting/importing and cloud syncing to make sure that everything is properly synced and no errors occur.
Today, I created a fun new achievement system which currently features 12 achievements. In the achievements page you can see all of them + progress tracker towards them. Upon unlocking an achievement, you will receive a notification in the bottom right corner of your screen. All achievements are saved locally, included in JSON backups and sync seamlessly. Also, fixed some localstorage and JSON backup issues and fixed a bug that when clearing your data, your investments would not clear.
Today, I’ve updated the command bar navigation to include the new Timeline and Investment tabs and with that also created a quicker way to add transactions - To create a transaction quicker, In the command bar all you need to do is type the amount, description and optionally category and account (for example: 9 Breakfast Food Checking). Also, reworked the transaction list and added abilities to select multiple or all transactions and bulk change account, categories, type or bulk delete transactions. Added ability to restore your transaction, if deleted accidentally. Finally, added an ability to duplicate transactions If needed.
Today, I Improved the “Smart Stats” feature with a new “Insights” tab. I didn’t want to create a new tab just for the Insights, so I decided to Implement the new feature in to an already existing one. Insights display your spending pace, give budget warnings, alerts you If your Net Worth & Savings are trending up or down and gives your Goal Projections without you having to navigate to the Goals tab. Also, replaced the default browser confirmation dialogs with custom ones, updated the tabs list design to a bit more modern one and made the tabs list stick so when you are scrolling down, your tabs list will always be accessible. Finally, fixed a few small bugs and a major budget rollover bug that would instantly roll over your budget without checking, if you even had a budget limit previously.
Today, I worked on more Quality of Life features for my app, first of all - Introduced Keyboard Shortcuts, you can open the Command Bar with CTRL + K, add new transactions with ALT + N and switch tabs with ALT + 1 through 6. Created a small dialog that shows all the keyboard shortcuts available. Another feature - Transaction Presets. You can now create a preset for your most used transactions, just fill out the add transaction form as usual and instead of pressing “Save Transaction” just press the new Bookmark icon, then at the top your preset will appear, next time just press on the preset and everything will be filled out for you. Fixed a few tiny UI details, optimized mobile design, fixed a bug where the quick-add suggestion bar hardcoded a $ sign regardless of your selected currency. Finally, when creating a new transaction through the quick-add feature, you must now include a valid category otherwise the app won’t recognize that you are trying to add a transaction.
Worked on a custom date picker for the Timeline, so now instead of being locked into 7-day, 1 or 3 month views, users can now view any custom date they want. Created a financial safety net, where users can set a minimum balance and if your projected balance drops below it, a warning banner appears. Updated the auto-sync feature and made it truly auto, all users now need to do, is just enter a password once. Finally, did a final test of the app, fixed bugs, updated the landing page and the GitHub readme
Ships:
I built DimeTrack, a personal finance & budgeting web app that helps users to track their income, expenses, manage custom spending categories, create budgets & save toward their set goals. The application store data locally, allowing users to use it without creating an account. One of the biggest challenges was managing the app as it grew. Features such as recurring transactions, savings goal contributions, budget tracking & categories all interact with each other. Ensuring that data remained synced required lots of testing. I’m proud that I built DimeTrack to have so many features, I’ve never built anything quite like this. To test DimeTrack: Try to create some categories through the settings menu Add income & expenses Create a savings goal and try to contribute to it Set budget limits Try recurring transactions Search & filter your transactions (transcations can be searched by description, amount or category) Export your transaction data using the CSV export feature (if you only want data from let’s say todays transactions, apply a filter) Refresh the page with all the data, to confirm that everything is saved. No accounts needed!
DimeTrack is an open-source personal finance manager that helps people manage their money entirely in a browser. There are no accounts, subscriptions, servers - everything is stored locally on device. Since my first shipment, the project has grown significantly. It now supports accounts, transfers between them, split purchases, multiple savings goals with contribution history and target dates, budget limits, auto-categorization rules, cash flow calendar with forecasting, monthly spending reports, net worth tracking, customizable categories and accounts, JSON backups, CSV import & export and many other quality of life improvements were made during the many hours spent on this project. The biggest challenge was keeping every feature synced as the project grew. Transactions can affect accounts, budgets, savings goals, recurring payments, reports, charts and basically everything. Adding new functionality means that I have to update existing systems to ensure that everything stays working as intended. But I’m proud to see how much my project has evolved and grown. You should try to: Create multiple accounts and transfer money between them Add income & expense transactions, try the split transaction function Set up a few savings goals with target dates and see how the contribution suggestion feature works Customize categories & accounts with icons and colors Configure budget limits and see the warnings that It gives you when nearing the limits Create an auto-categorization rule Explore the cash flow calendar Try exporting your data to JSON
DimeTrack is an open-source personal finance manager that helps people manage their money entirely in a browser. There are no accounts or subscriptions required and your data is stored locally on your device, with an OPTIONAL cloud sync if you want to access it across devices. Since my second shipment, the project has grown even further. I read every single review and Implemented all the suggestions that were provided. Made an optional cloud syncing feature that allows users to access and use the app across multiple devices. Made a small tutorial/guide that provides a bit more information on how to use DimeTrack. Replaced the Calendar tab with a new Timeline, that shows all your recurring transactions in your selected time interval, your projected balance and an ability to add a safety net and see if your projected balance falls below it in the coming months. Added an ability to manually track your Investments. Even more customization options and many other things. Similar to my previous shipments, the biggest challenge was to keep everything synced. One feature depends on another, so adding new functionality means that I have to update existing systems to ensure that everything stays working. I’ve somehow spent 325 hrs on this project and this will probably be my final shipment. I’ve had a lot of fun working on it and hope to maybe sometime later. For the v3 you should try to: Complete the tutorial (If you have used DimeTrack previously, go to settings -> data -> clear all data or just use incognito window) Add some recurring transactions and test out the Timeline to see your projected balance Explore the new subscriptions tab Set up cloud sync Add some Investments, update their price so see how your portfolio value goes up or down Check out the new financial insights in the Overview tab Use the Command Bar at top middle, you can find some quick actions there, search for any transaction or even create a quick transaction by typing in the search bar - Amount, Description, Existing Category (for example: 5 Coffee Food (must have a category called Food)) Explore the keyboard shortcuts Do a few achievements Create a few transactions and test out the bulk editing options...
|
1792860521.7037585
|
1793724521.7037585
|
|
14066
|
Janitor Space Program (J.S.P.) by @aloyak | Starda Janitor Space Program (J.S.P.) by @aloyak | Stardance...
|
aloyak
|
2
|
160.0
|
3078
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-17T13:40:57Z", "hours": 55.0, "multiplier": 18.95, "payout": 1041, "blessing": "neutral", "text": "This is my 3D exploration-sandbox game that I built with my custom game engine! I’ve added quite a lot of stuff like a simple exploration game mode that allows you to move around a hand-crafted solar system i called “Halcyon”. there are also a lot of other game modes you can try and have fun with before I finally add the campaign game mode for the final version! In the picture you can see an in-game screenshot of the player walking around the surface of the earth-like planet “Gaia”, hope you like my game! With <3, 4loyak!", "repo": "https://github.com/aloyak/jsp", "demo": "https://aloyak.itch.io/jsp"}, {"ship_num": 2, "ts": "2026-07-16T13:34:38Z", "hours": 105.0, "multiplier": 19.52, "payout": 2037, "blessing": "neutral", "text": "This is my 3D game about space exploration and kessler cascades, it has a campaign mode coming up but i havent finished that yet, for now enjoy the 3 game modes! i built this on top of my custom engine so its been a lot of hard work, please try it out!!!!", "repo": "https://github.com/aloyak/jsp", "demo": "https://aloyak.itch.io/jsp"}]...
|
[{"post_id": 48889, "ts": "202 [{"post_id": 48889, "ts": "2026-08-17T13:35:52Z", "hours": 3.9133, "text": "JSP! I’m back! and I finally have a new decent version that im probably gonna ship shortly after I publish this devlog. Its been so long since the last devlog because a number of factors, I had some vacations, my main pc is now just a steam deck connected to a monitor and also I’m kind of struggling to continue this project, I hope this isnt the last version but working on the project and adding or fixing things is very complicated and requires a lot of research to do it right, and it is exhausting What was added?? Included the new planet models to the halcyon system, you can now correctly explore them by using the new terrain system I added to the engine! Added some small help windows/hints for the new stuff before shipping! Fixed some audio bugs and added a sound effect for when you close a window Fixed the in-helmet HUD UI, the input vectors now correctly show the direction the thrust is being applied to, kinda like in Outer Wilds!! I’m most likely to be focusing on continuing the engine for a little bit, it really really does require some refactoring and I also need to clean some likely dead code or at least re-understand the code i wrote as it has lines from almost a 10 months ago! Hopefully someone could help and contribute to the project maybe or make something new out of it too! Im still planing on continuing to develop it but not at this pace considering im about to start college :))"}, {"post_id": 41224, "ts": "2026-08-05T09:35:20Z", "hours": 6.8169, "text": "J.S.P. Very exciting changes to the exploration mode yay !! I’ve been working on precisely TWO (2) things but one of them is way too early for me to be able to show you anything, more on that in the end Whats new? I’ve create a custom blender addon that lets me create procedural noise-based planets! It is really powerful and it gets you really good results for how simple it is really. In a way, its nothing but a vertex shader but coded in python lol It generates 3D spherical noise and applies it into an icosphere with a variety of parameters. Some of them arent precisely working but they are fine for now (specially the “ridged” option) You can try it yourself, its open source too! https://github.com/aloyak/JSP/blob/main/assets_src/blender/addons/planet_generator.py Terrain System I’m developing a way for the player to correctly collide with the geometry of these planets, but this is mostly engine-sided changes and I’m not very deep into it yet. I’m currently researching how to handle multi-threading async functions… more information about this in my latest engine’s devlog: https://stardance.hackclub.com/projects/1029/devlogs/34738 Known issues These are not really important right now, but for some reason I’ve realized that the splash screen takes different amounts of time depending on where you run the game?? what? A steam deck is around 3 seconds, my computer (the intended duration) is 4 seconds and in a friend’s laptop it is ~0.5 seconds"}, {"post_id": 39548, "ts": "2026-08-02T15:55:39Z", "hours": 7.1231, "text": "JSP We are SO back! I thought it would take me weeks to solve this issue but it wasnt that hard, thanks claude lol for helping. It’s not perfect just yet but its honestly crazy how my own engine managed to handle what im about to explain What took soo long The game now handles a transition from a global physics world to a new extra physics world that lives locally when the player enters a new planet (the origin of the new physics world would be the planet’s center), this means that you can perfectly walk on the surface of all the planets while they move around in the orbits without any weird behaviors This took a good amount of engine refactoring and a few changes to some systems (specially the floating origin) I need to fix a couple things like the drag when you are entering a planet, but that should be handled later on when you actually use a spaceship to enter and not just yourself with your spacesuit Other stuff that is cool Added a helmet overlay! (very inspired by outer wilds, id like some suggestions to make it more original honestly, but right now it decent). It is currently work in progress tho, and theres a lot of information missing… Small UI improvements: rounded borders, removed window’s transparency, added window close sound effects (need to find a better one tho), little better controller support… I just this idea to have vehicles but that will take super long, its added to the ideas file but thats certainty not being considered for short term, Any suggestions are welcome tho PD: video is very bad res bc i had to compress it unfortunately"}, {"post_id": 35908, "ts": "2026-07-27T17:18:56Z", "hours": 5.9792, "text": "JSP! I’ve finished porting the game to the new action based input system, its not great yet, theres a lot to polish but at least you can play 80% of the game just as good as with a keyboard/mouse (even better sometimes!) What’s the new input system? The game now asks for “actions” callbacks instead of directly asking for raw input. This new layer in the middle allows to make different devices have their own way to control each actions, so it now supports all the gamepads you probably have: xbox, playstation, steam, nintendo, generic ones too It is almost steam deck ready! Ive been playing this game on my steam deck and it works great! (you can get around 900 fps when unrestricted) Playing the game with a controller plus a little help from the little mouse trackpad really makes this game fun to play (100% coverage with this setup) Now i will finally start doing the boring physics stuff that will hopefully not take so long but idk, we’ll have to see Other stuff that was added Improved a bit the gravity based movement mode, it now adds the atmosphere’s drag gradually depending on its density, being the density higher the closer you are to the surface, this makes entering planets feel better Fixed some messed up formatting style in my code I dont know if start a new project for no more than 2 weeks and then go back, ive been having some cool new ideas but for now ill stick to this project PD: the picture is an old version (0.12.1), latest version with good controller support is 0.14.0"}, {"post_id": 34767, "ts": "2026-07-25T19:07:39Z", "hours": 8.6764, "text": "JSP Omg i need a break! just one more change bro and i will start doing the hard and boring stuff, just one more i swear! This sums up everything ive done for the past few hours, although the new improvements are actually quite important, i feel like im somewhat rushing them instead of focusing on the exploration mode New things!! Simple LOD system for planets, there wasnt a big performance change, but the model swap is very unnoticeable and nice so thats great! Added a simple spoiler warning to the exploration mode, the original idea was that you should unlock it after playing the campaign but i guess its fine lol I FIXED THE DEPTH BUFFER PRECISION ISSUE!!!! it was such a small change omg, i just dynamically changed the near plane of the camera based on how far you are to a planet, pretty nice WIP Work in progress: I’m porting the whole game to the new action-based input system so that the game supports controllers natively without any kind of steam layer on top, this is till very early and i still dont know how to make some stuff be fun to use with a controller…. I finish this, finish the two major things on the exploration mode that are 100% gonna be quick, make some decent amount of content for it, add the custom spaceship controller and launch system, make the first ~5 minutes of the campaign mode, and then SHIP THIS PROJECT (this will surely go as planned) PD: the video u see is completely controlled with my gamepad, not the best controls yet but its better than nothing!"}, {"post_id": 33389, "ts": "2026-07-23T09:24:10Z", "hours": 5.8975, "text": "JSP Worked on so many things before getting started with the complicated stuff, ill tell more about that in the bottom section, but for now, im pretty happy with what ive just added, even tho progress is pretty slow!!! What have i added? Full/complete atmospheric effect , it now not only looks good from outside, now from the inside too!!! Its a small trick but when the camera gets close enough to a planet, its atmosphere’s density scales up making the sky blue like here on earth or greatly improving the sunrises and sunsets , they do look beatiful Added floating origin: double precision was not enough so ive added a system that teleports all the entities in the scene when the player gets too far from the origin, this works surprisingly good and it was very simple to do, hopefully it wont break physics later on, but so far its great! This allows the solar system to go from ~10000 units wide to over ~3000000!! that is great! This was a engine-level change mostly tho You can finally use the planets you discover in the campaign mode in the sandbox mode Dynamic settings!!! I made it so that when you first load into the game, the UI scales to your resolution and your target fps are set to your monitor’s refresh rate, might not look like something important but this is actually HUGE Whats cooking up currently! Need a system to allow the player to be placed on top of moving planets (it currently works but breaks sometimes), and also to allow those planets to rotate. This will be achieved with a completely new physics world that will live localy on the closest planet the player is to Chunked mesh collider system i really dont know how to this, because of the terrain of my planets (TODO), collisions will be complicated to calculate, if you know about anything that could help, please send it!!! PD: I wish i could spend more time actually coding than thinking, if that were to be the case id have 300 hours+ in this project already"}, {"post_id": 32263, "ts": "2026-07-21T10:11:59Z", "hours": 8.1467, "text": "JSP This is one of the most exiting devlogs so far!! I’ve managed to get a very basic “solar system working, not all the time and of course it isnt perfect but it is really cool, heres its lore: (note that planets are placeholders right now, and distances/scale should be a lot bigger in the future) The “Halcyon” System Somewhere very very far from our current home, humanity has managed to establish a multi-planetary life in a new system after traveling for generations in their own space station The Halcyon system is composed of 5 planets (maybe more in the future) that orbit around a massive black hole (it doesnt have a name yet) “Gaia” is the earth-like planet whose own satellite, “Vesta”, is a red dwarf star that provides just enough light and heat in order to live (seen in the demo video) “Ying” and “Yan” (names will probably change), are two tiny planets that follow exact opposite orbits around the black hole, when one of them is at the perihelion, the other ones at the aphelion “Kepler” is a huge rocky planet at the outskirts of the system where small human colonies currently live Note that the campaign will be linear and happen entirely inside this place, but you will also have a “exploration” game mode that will allow you to find and see new secrets hidden… :)) Technical stuff (i.e. what was added) Created the base for the Halcyon System, planets follow a predetermined elliptical orbit in real-time. Note that for debugging, scale is around 10 to 100 times less! Added a simple physics based player controller, this took a lot of engine refactoring too. The player is affected by the gravity of the near planets and, when close enough to a planet’s surface, it is automatically aligned with the gravity vector and its also affected by the atmosphere’s drag (if theres any), this was by far the most difficult thing to do Added a little Free Camera controller as well What will be added in the future This is only the start . Theres still a few complicated things to do: Add double precision and floating origin to solve the problems that will appear when distances become as big as id like them to be Add a chunked collision mesh system for planets with complex geometry, like mountains or things like that. Right now they are all controlled by a simple kinematic sphere collider This system currently breaks the player movement when planets are moving, this is why i set “time scale” to 0. To fix this ive been thinking of creating a local physics world that sets the planet you are on to be the origin of the physics, making it look like if the planet was static, this will by by far what will take the most amount of work probably i also wanna update the atmospheric shader as it is by far the thing worsening the game’s performance, and id like to make the sky fully tint when your inside it PD: Thank you so much for all the people that support/follow this project, it already has 21 followers . thank you, really!"}, {"post_id": 30589, "ts": "2026-07-18T09:11:03Z", "hours": 8.3614, "text": "JSP I want to dedicate this devlog to @Rupnil as he always says that devlogs need to be 3-4 hours max, so i can explain why thats not always possible. Out of the 8 hours i devlog today, around 7.5 of them were spent ONLY debugging ONE SINGLE BUG for 2 whole days. I started losing my mind lmfao the bug: All the built-in and embedded textures became completely broken and ONLY on super specific conditions on certain parts and game modes. But the worst part was that rolling back to a version from days ago DID NOT solve the issue at all . I even considered that my GPU gave up on my and it was just showing gpu artifact slop in my screen the fix: Apparently there was a small bug with gpu memory allocation in the backend of dear imgui (apparently ONLY in the SDL2-OpenGL backend lmfao) and only for the docking branch of the repo. Rolling back to an old dear imgui version from the main branch solved the issue but damn. Ive also reported the issue as much as i could in the official repo. Pretty much, updating the engine to the latest version automatically updated its dependencies and thus leaked the bug to my game Appart from that I’ve spent a little bit on starting to develop the open-universe system where you can travel around planets! More on that in the next devlog probably. I already have though about the planet’s names, positions and stuff! pretty exiting!! PD: In the mean time ive also being updating the engine at the same time to improve the physics system, which is a lot better right now!"}, {"post_id": 29477, "ts": "2026-07-16T13:30:28Z", "hours": 4.3869, "text": "JSP Pre-ship checklist is complete! I’m so ready to ship the first version and start developing the campaign, which is the main thing of this game. I’ve actually started it a little bit, it now has an interior level system completely different to the gamemode system i had for the rest of the game, this is pretty exiting! stuff that ive done before shipping Built the game for windows, took a little bit but performance is 1:1 and everything works perfectly, the only thing was that i had to change the backend of the audio engine to use something else but that was fairly quick! Reduced the size of the game MASSIVELY , it went from around 350MB to ~35MB , thats literally 10 times less!! managed to do this by compressing the audio files, although the change is almost unnoticeable, and also making the engine bake some textures on build time, just like real fancy engines do! Changed a bit the main menu/ campaing mode but for now it is all a placeholder Created a new itch.io banner Made the HELP menu show up by default, i dont really like this but i think its probably the best for people to rate it nicely, wont be in the final version… Added a input mode (another one) to the spaceship building mode that allows you to hover the attachment points and it will tell you with a little popup what category of part can go there If you are rating my project, please ishowspeed i need this now in all fairness i hope people like my game! im not even close to finishing it lol Right after this first ship i will work on updating the engine to support new features that the campaign mode will certainty need 100%, like a working physics engine, ive thought of porting what i currently have to use a new one i found and that is getting very popular called “Box3D”, we’ll see, byeeeeeee"}, {"post_id": 27751, "ts": "2026-07-13T16:07:37Z", "hours": 7.2142, "text": "JSP https://github.com/aloyak/JSP https://aloyak.itch.io/jsp?secret=nkYXIEVo8woJvblBQRYMIrWSFc I feel like im getting very close to a first ever release and finally start with the campaign mode! I finished some polishing stuff and fixed a bit, i dont think the spacecraft builder mode is ready 100% but ill use it in the campaing mode either way so ill have to update it regardless I’ve officially published the github repository where you can check out the huge amount of code this project already has lol. I’ve also created a new itchio page, this is the secret link (for feedback): https://aloyak.itch.io/jsp?secret=nkYXIEVo8woJvblBQRYMIrWSFc added things: Published the github repo and the itchio page! With a lot of new screenshots and art. I’ve also added the source files of the textures (.xfc gimp files, including the itchio banners) as well as the 3D models I’ve made (in blender) which can all be found in the assets_src/ folder Added a way to delete different parts in the spaceship building mode Added a few new parts to the spaceship building mode, refactored the whole system to make it “easier” (not really) to add new parts and things Added a full README + LICENSE to the repo Added a new shader , it is the small fog that you see in the vide when building a spaceship in order to hide the lack of detail in the exterior, the shader fades out the more you look up so you can see the beautiful skybox Added load/saving to the spacecraft building game mode, you can now save your ship’s to load them later just like with planets and sandboxes Fix some memory management problems where i forgot to delete some pointers => no memory leaks or crashes! I dont think this will be the last devlog before the first ship, but maybe, who knows right? Looking forward to you all trying my game! (the part that is done) PD: 100 hours"}, {"post_id": 25218, "ts": "2026-07-09T10:34:55Z", "hours": 3.7989, "text": "JSP Can’t really express enough how much I enjoy making shaders, the look really good. i might make a video about it with the new hackclub video challenge, we might see, I’m kinda shy for these sort of things :)) Today’s devlog is pretty much to show only one thing. I’ve been doing some really small changes to UI, a few bug fixes but the important thing is the new Central Body system for the sandbox mode (the code is pretty rough right now but hopefully ill improve it), this now allows you to choose the central body that your planets will orbit around So now, instead of having only the sun in the middle you can now select a BLACK HOLE instead, which i think its a lot cooler. Note that the whole black hole is completely done by a single glsl fragment shader, how cool is that? I’ve reused a small amount of code from the atmosphere shader and then researched a bit on similar projects Apart from this I’ve also added a new “extra” option to allow the player to change the tint of the skybox, so you can create even weirder solar systems, any new suggestions on what else to add are welcome! After this im gonna do a small refactoring change that is really stupid and needs to be changed in the entire code base, its just a small thing with the new language system"}, {"post_id": 24594, "ts": "2026-07-08T09:29:46Z", "hours": 8.8931, "text": "JSP Worked on polishing and improving a few quality of life features and overall stability, also I took my time to translate every single text in the game to spanish, although the new dynamic language system should work for adding any new language fairly quickly. this is a very important change because doing this after the campaign would be a nightmare. language is also saved to settings new stuff Added a dynamic language system and support for playing the game in spanish, if you want any new languages or help translate and thus be added to the credits please reach out Added a full credits panel where it shows all the licenses and 3rd party code/art used, AI disclosure and other stuff Fixed some weird seg faults when going back to main menu from the blueprint view Updated all icons, all of them were used in the sandbox game mode Added some new settings to the blueprint view inside the spaceship building game mode What I wanna do now is to finally finish the spaceship sandbox finally but its taking longer than expected and it requires a lot of brainpower that many times is less appealing to do compared to playing persona 5 royal lmao. Note: once the source code is published, sending feedback, playtesting or translating would maybe mean that i put you in the credits! fr i might need some help tho"}, {"post_id": 22329, "ts": "2026-07-04T19:06:08Z", "hours": 7.0856, "text": "JSP I really enjoy creating and coding shaders and so i started adding some cool effects to the spacecraft editor, didnt really add any new parts but i think that what i added was pretty interesting. I’ve also been working on improving a bit the user experience and making things obvious to use without explaining anything, this is probably the most fun i had doing this project in a while :) what was added Added “Blueprint” view for your spaceship, watch the video to see what it is! currently very early version tho Added a help window that changes based on the gamemode Added geometry center (blue) and center of mass (yellow) to the spaceship Small fixes to transition between movesets Added a border shader to mark the bounds of the building workspace Added a few icons that really need some improvement The idea of the blueprint mode is to edit different things from the spaceship, and also to see the different stages of your little ship! more on this later, im not specially creative enough to write a lot today lol Ill also probably add a dynamic cursor system but idk"}, {"post_id": 20638, "ts": "2026-07-02T08:56:03Z", "hours": 6.5689, "text": "JSP Been working on the spaceship builder gamemode and its pretty fun! right now the system is very simple but solid. i had to model a couple test things and fix many bugs but it is going quite fast. The current system is a simple attachment-part system where each attachment holds up information about allowed part’s categories to attach and the normal vector of the attachment. Unfortunately removing parts is not really an option yet cuz i need to see how i will make that possible later on summary on new features: started the actual spaceship building gamemode, currently it features just basic part placement logic small changes to sound effects and music (not shown in the video) Apart from obvious structural changes, id also want to add some sort of customization to your spaceships, with different colors, flags, sigils idk. I dont want to make building a spaceship something hard but just a simple thing you do to have your own individual experience, obviously you wont be able to make some cursed stuff as it wont just fly into space without an engine, but the idea is that everything with enough parts should work"}, {"post_id": 18642, "ts": "2026-06-29T20:39:49Z", "hours": 3.7319, "text": "JSP Unfortunately hackatime doesnt support blender so the ~2.5 hours i spent modeling the assembly building for the spacecraft editor sandbox will not count but its fine. I’ve also done some deep debugging to the engine as it now supports embedded materials even when they dont have any texture, before this change everything looked like a wierd artifact in black/purple colors (check out the second image if ud like to see it, its pretty in a way) what was added/changed Created a not-final but decent model for the assembly building you will be creating your custom spaceship in Added first person camera control, that is used by this gamemode to get a different “perspective” on your awesome creation. you can toggle between the normal orbital view and the fp view some engine-level optimizations This now means im FREE… to actually start developing the spacecraft building sandbox, so we are back to it lol. im hoping it doesnt take me that much but i still need to finish to understand how exactly i want this to be as this is probably the only shared code that the campaign game mode will use, so i better make it good as it “counts” double PD: already said this, but the second screenshot is just so you comprehend what ive been struggling with for the past 48 hours :("}, {"post_id": 17110, "ts": "2026-06-27T19:42:28Z", "hours": 9.6172, "text": "JSP Huge progress!! (yes, really) I’ve made some cool stuff an this game now looks a lot more professional, these last changes we’re surprisingly fast and fun to do (finally for once lmao), although the following changes, most of them, are still work in progress. I’ve officially decided that I’m not gonna be updating the engine’s repository solely for this project as im a bit more focused on making my game work rather than making the engine reliable and well-structured for any usecase, even tho the engine will still recieve updates any way cuz i really need them for the game, but the main focus is to not suffocate the engine with specific jsp stuff. new stuff audio system: custom imgui wrapper that lets me make sound effects for buttons on hover and press + background music system that lets me control simple fade out and transition to other songs, currently only in the main menu user settings: instead of making the same json slop ive made for the rest of the load/saving stuff, i made a fancy system that lives in the engine’s core and that lets you save any kind of settings a lot easier. user settings are now correctly saved when changed on user/settings.json created a simple intro text for the first run that explains a some information made the settings window accessible from anywhere, not tied to the main menu anymore FANCY TRANSITIONS between gamemodes, it now fades in/out to black with a little loading icon in the bottom right corner, this took longer than id like to explain unfortunately added a color history for the paint tool in the planet sandbox improved atmosphere UI controls in the planet sandbox fix water shader sometimes rendering on top of an atmosphere As you might be able to guess, some of these changes weren’t really necessary but im sort of procrastinating so that i dont have to model the assembly building for the next game mode cuz i really suck at it and will be painful most likely I’ve though of adding a “first person view” move mode to the spacecraft sandbox as it would be cool to see your creation from an engineer’s point of view and also because that way i already will have coded the controls for the campaign :))"}, {"post_id": 15575, "ts": "2026-06-25T10:26:14Z", "hours": 5.6989, "text": "JSP Currently finishing the gravity sandbox gamemode! I still need to make quite a big change as im thinking of unifying the “gravity body” struct i use in the sandbox with the “planet component” i use in the rest of the game, so this will probably take a while but, for now, the sandbox game mode seems to be the next thing to be finished! new stuff! the gravity sandbox now has gravity!!!! note that it is not super realistic nasa-level simulation, i was thinking of something a lot more arcade. this is very well reflected in the fictional scale (its around 1:100000), because games must be fun first, then realistic if possible separated the gravity sandbox file to hold the built-in planet’s registry in a different file (its around ~1300 lines of code rn lol, after the simplification…) added a nice destroy animation for the planets, improved the velocity tool and made the selection tool follow the planets the intro animation now locks into the sun, which is now the origin of the scene + changes to the style of the sun added trails to the planets in the simulation (that you can toggle, of course) small UI improvements Whats next u say? applying the same load/save system that i used in the planet builder sandbox, only that now i wont have to create a vertex data to file system (yay) Im also starting to 3d model in blender the “assembly building” where you will be able to build your spaceships in the other game mode, but im really bad at it so ill leave it for later, once the spacecraft builder game mode is finished i will probably ship the first version"}, {"post_id": 13151, "ts": "2026-06-21T14:56:42Z", "hours": 10.1961, "text": "JSP I’ve officially finished the planet builder sandbox gamemode finally, probably will tweak a lot of things but the main stuff is done. i spent quite a lot trying to fix a problem with the depth texture that isnt even fixed right now lmao, quick explanation: distances are huge and so the depth texture loses a lot of precision, to combat this i decide to add reverse-z to the engine’s renderer but this didnt really solve the issue as it probably needs even more work adding an inifinite “far” plane or logarithmic depth but i think its fine for now, ill explain this more in depth with the next devlog on the origin engine. new features added oceans to the planet builder, very simple for now but as a first version i think it works just fine, i spent at least 8 hours with this already lol, added basic controls to the ui to modify the shader’s uniforms and hopefully its good enough added loading/saving to the planet builder and to the sandbox, you can now save your projects using json serialization, a geometry-to-file algorithm and a texture-to file algorithm. note that the planets you create in the planet builder can also be used in the gravity sandbox added the terrain tool so you can now modify the geometry of your planet as you like, creating mountains, valleys or oceans Next up is to finish the gravity sandbox gamemode, hopefully that should be a lot quicker as most of it is already done, but you know how this usually goes HELP: if you have any ideas on how to make the depth texture more precise given the huge distances please let me know, theres not a lot of information out there"}, {"post_id": 11875, "ts": "2026-06-19T10:45:42Z", "hours": 5.4583, "text": "JSP I’ve been stuck with a super upsetting bug with the engine’s render class and the ownership of the output buffer that made the engine’s sandbox editor be completely unusable for however long this “postprocessing pipeline update” lasted. it is now fixed and i could continue developing this game finally. As the engine now supports adding many layers of postprocessing on top of the main render pipeline, i started cooking up atmospheric and star shaders, although only the first one is finished. i ported the atmosphere shader from a tutorial posted by nvidia on atmospheric scattering from a many years ago but the end result is honestly amazing, way better than what i had in mind. This is supposed to give the same feeling as the atmospheres from outer wilds, which is part of my inspiration for this project (and also my fav game in general) new features add “Has atmosphere” option to the planet builder mode, with a lot of options and parameters to control and make your own planets, showcased in the video… made all entities with the planet component now have an option to show an atmosphere, although it is disabled by default. this results on the earth shown in the main menu to now also have a atmosphere I will be focusing on finishing the planet builder game mode first, as it is ~60% done (probably less), i just need to add the entire terrain tool and save the planet settings to a file to be able to use it later or use it in the gravity sandbox PD: i know it seems like im focusing too much into the small/extra gamemodes but this is supposed to function as a base for the campaign mode, which i dont think will be released in the first public version unfortunately"}, {"post_id": 10582, "ts": "2026-06-17T12:03:21Z", "hours": 4.9575, "text": "JSP Good but slow progress (im not finishing this game before stardance ends probably) I want to focus on having the 4 main gamemodes ready to have a good base for the camping, which is gonna be epic! new features/changes: wrote the story for the campaign mode, yet to be showcased, but it is pretty cool, more on that later removed the explore mode, this was a thing i had in mind at the very beginning of the development but it doesnt really fit my view right now, will make a comeback at some point, but the previous implementation was just a bunch of dead code created a simple spaceship building scene, wip as you can see in the video added a very simple splash screen improved the planet creation sandbox, now with a paint tool (a bit buggy, for now) that lets you generate a real-time texture and save it to a png file, biggest progress here was made in the engine itself actually. This took so much time fighting with translation of screen-space coords to world-space coords to UV coords, im actually impressed it even works lmao. this was almost gonna get scrapped till i realized the UV unwrapping of the sphere was a cubic projection and that was messing everything up I am struggling so much with blender and my sandbox, it looks like they hate each other, also WHY DOES BLENDER USE Z+ UP, anyway, stay tuned! Its hard to make devlogs when progress is so slow but i hope you like it PD: I just fixed the colors looking like confetti (look at the color of the blue paint brush), apparently i was multiplying the alpha channel by 255 in the texture class because of a previous implementation and that was causing some sort of overflow in the shaders, thus the weird colors, so paint tool is officially finished, hopefully"}, {"post_id": 9425, "ts": "2026-06-15T19:45:20Z", "hours": 8.1431, "text": "J.S.P. I’ve been making some progress in every direction while i find out exactly what i want this game to be. ive started writing the story for the campaign mode that i hope is about 3 to 4 hours. Overall the main progress of this devlog is summarized in a finished early version of the sandbox, although theres a lot to fix in it, the main stuff is done. Ive also started with the planet creation sandbox and focused on working into instancing even though it is not quite there yet (im thinking of removing the explore mode entirely or do it completely different) new features: improved sandbox mode with actual simulation (very early), a new intro animation, different tools to select, move and change the starting velocity of each planet set a base for both the planet and spacecraft creation sandboxes as these mechanics will make the development of the campaign a bit easier, hopefully created a simple logo, probably to be changed, i dont really like it but id appreciate feedback refactored the scale system to make working with different distances and planet’s radius a lot easier, this new system is so clean i actually love it As you can see progress is extremely slow, i want to make this right and also make sure that the project is well structured enough to hold up. Also did a simple check on performance and after a couple tweaks, average fps sit around 3000, fr, on my little rtx 3060 so thats great"}, {"post_id": 7522, "ts": "2026-06-12T15:45:45Z", "hours": 5.6847, "text": "JSP Today’s devlog is not so much focus into the progress but into some design decisions that made me had to restructure the project a quite a lot, ive got a new view of the project that i think will make it a lot more fun gamemodes: campaign: top secret for now explore: you can explore, find, filter and search up real-life satellites at their real position, this is mostly done already but i need to work on adding instancing to the engine because rendering ~14000 satellites is not something my little tiny engine can really handle right now, performance drops from ~1700 fps to 9 fps lol sandbox: no more real life stuff, distances are too big and not fun to play with, this is the main change. this means that the idea is to now not only allow to play around with 3d gravity and make solar systems, but also to create and design custom planets and spacecrafts (and save/load them to a custom json file that you can share or reuse) new features I want to showcase how the current sandbox mode is like right now, this is only a part of the final sandbox mode tho (read the previous paragraph for more info). I added this cool animation from the main menu, simple movement that scales with distance, and a placing-editing system that took way too long (i had to do matrix calculations lol, math does be useful sometimes), right now the only object you can place is the Earth, but you will be able to place pretty much anything and modify their mass, velocity or anything really I will now start with making instancing something real and not just a dead branch in the engine’s repo, but this means im gonna have to read some opengl documentation :( PD: the visual bug in the video is completely intentional"}, {"post_id": 6769, "ts": "2026-06-11T10:36:15Z", "hours": 7.2383, "text": "JSP I’ve been working on a lot of things and the project is taking a really nice shape! ive organized the game into different game modes that independently manage their needs in an organized way. Also ive made some progress with the real life satellites and made some nice main menu! new features: WIP: explore real time satellites and see them move as they are in real life, with custom orbit calculations, still in the works, getting fetched directly from the internet and cached every 24 hours Added a main menu, as the engine doesnt have any in-house UI system, Im using a modified dear imgui version that is holding up nicely, also added some placeholders for settings etc… Started a new gamemode: gravity sandbox, where you can play around with custom objects and real life planets and their gravitational interactions I also had to update the engine a bit to make it be able to handle quads and their operations. the idea is to finalize a working sandbox gamemode as that would set the base for many more complex features incoming"}, {"post_id": 6120, "ts": "2026-06-10T09:09:05Z", "hours": 6.2383, "text": "JSP A 3D pixelart videogame about space exploration where you have to save humanity from the Kessler effect, currently working on the “exploration” mode where you can find and explore all the satellites of earth (and later on the solar system) at their real time location. Current Features! I’ve made a simple system that gets the real life data of these satellites from CelesTrak’s Public TLE Text Files, which than caches them and are refreshed every 24 hours, so you can see the real-life position of, for example, the ISS Built using my own custom engine, actually been updating the engine while creating this because, lets say the engine isnt very “mature” yet, but its holding up nicely! Check out the ORIGIN engine at: https://origin.aloyak.dev The game will feature this little 3d pixel art style that i really like honestly. The hardest thing to do so far was to setup a fork of the engine so that i could work on the game without actually contributing to the engine itself at all. All these models used currently are from NASA themselves, so they should be pretty accurate! I’m thinking of maybe adding a web build but the more i try to make it work the more it breaks lol :( 🚀🚀"}]...
|
Title: Janitor Space Program (J.S.P.) by @aloyak | Title: Janitor Space Program (J.S.P.) by @aloyak | Stardance
Devlogs:
JSP A 3D pixelart videogame about space exploration where you have to save humanity from the Kessler effect, currently working on the “exploration” mode where you can find and explore all the satellites of earth (and later on the solar system) at their real time location. Current Features! I’ve made a simple system that gets the real life data of these satellites from CelesTrak’s Public TLE Text Files, which than caches them and are refreshed every 24 hours, so you can see the real-life position of, for example, the ISS Built using my own custom engine, actually been updating the engine while creating this because, lets say the engine isnt very “mature” yet, but its holding up nicely! Check out the ORIGIN engine at: https://origin.aloyak.dev The game will feature this little 3d pixel art style that i really like honestly. The hardest thing to do so far was to setup a fork of the engine so that i could work on the game without actually contributing to the engine itself at all. All these models used currently are from NASA themselves, so they should be pretty accurate! I’m thinking of maybe adding a web build but the more i try to make it work the more it breaks lol :( 🚀🚀
JSP I’ve been working on a lot of things and the project is taking a really nice shape! ive organized the game into different game modes that independently manage their needs in an organized way. Also ive made some progress with the real life satellites and made some nice main menu! new features: WIP: explore real time satellites and see them move as they are in real life, with custom orbit calculations, still in the works, getting fetched directly from the internet and cached every 24 hours Added a main menu, as the engine doesnt have any in-house UI system, Im using a modified dear imgui version that is holding up nicely, also added some placeholders for settings etc… Started a new gamemode: gravity sandbox, where you can play around with custom objects and real life planets and their gravitational interactions I also had to update the engine a bit to make it be able to handle quads and their operations. the idea is to finalize a working sandbox gamemode as that would set the base for many more complex features incoming
JSP Today’s devlog is not so much focus into the progress but into some design decisions that made me had to restructure the project a quite a lot, ive got a new view of the project that i think will make it a lot more fun gamemodes: campaign: top secret for now explore: you can explore, find, filter and search up real-life satellites at their real position, this is mostly done already but i need to work on adding instancing to the engine because rendering ~14000 satellites is not something my little tiny engine can really handle right now, performance drops from ~1700 fps to 9 fps lol sandbox: no more real life stuff, distances are too big and not fun to play with, this is the main change. this means that the idea is to now not only allow to play around with 3d gravity and make solar systems, but also to create and design custom planets and spacecrafts (and save/load them to a custom json file that you can share or reuse) new features I want to showcase how the current sandbox mode is like right now, this is only a part of the final sandbox mode tho (read the previous paragraph for more info). I added this cool animation from the main menu, simple movement that scales with distance, and a placing-editing system that took way too long (i had to do matrix calculations lol, math does be useful sometimes), right now the only object you can place is the Earth, but you will be able to place pretty much anything and modify their mass, velocity or anything really I will now start with making instancing something real and not just a dead branch in the engine’s repo, but this means im gonna have to read some opengl documentation :( PD: the visual bug in the video is completely intentional
J.S.P. I’ve been making some progress in every direction while i find out exactly what i want this game to be. ive started writing the story for the campaign mode that i hope is about 3 to 4 hours. Overall the main progress of this devlog is summarized in a finished early version of the sandbox, although theres a lot to fix in it, the main stuff is done. Ive also started with the planet creation sandbox and focused on working into instancing even though it is not quite there yet (im thinking of removing the explore mode entirely or do it completely different) new features: improved sandbox mode with actual simulation (very early), a new intro animation, different tools to select, move and change the starting velocity of each planet set a base for both the planet and spacecraft creation sandboxes as these mechanics will make the development of the campaign a bit easier, hopefully created a simple logo, probably to be changed, i dont really like it but id appreciate feedback refactored the scale system to make working with different distances and planet’s radius a lot easier, this new system is so clean i actually love it As you can see progress is extremely slow, i want to make this right and also make sure that the project is well structured enough to hold up. Also did a simple check on performance and after a couple tweaks, average fps sit around 3000, fr, on my little rtx 3060 so thats great
JSP Good but slow progress (im not finishing this game before stardance ends probably) I want to focus on having the 4 main gamemodes ready to have a good base for the camping, which is gonna be epic! new features/changes: wrote the story for the campaign mode, yet to be showcased, but it is pretty cool, more on that later removed the explore mode, this was a thing i had in mind at the very beginning of the development but it doesnt really fit my view right now, will make a comeback at some point, but the previous implementation was just a bunch of dead code created a simple spaceship building scene, wip as you can see in the video added a very simple splash screen improved the planet creation sandbox, now with a paint tool (a bit buggy, for now) that lets you generate a real-time texture and save it to a png file, biggest progress here was made in the engine itself actually. This took so much time fighting with translation of screen-space coords to world-space coords to UV coords, im actually impressed it even works lmao. this was almost gonna get scrapped till i realized the UV unwrapping of the sphere was a cubic projection and that was messing everything up I am struggling so much with blender and my sandbox, it looks like they hate each other, also WHY DOES BLENDER USE Z+ UP, anyway, stay tuned! Its hard to make devlogs when progress is so slow but i hope you like it PD: I just fixed the colors looking like confetti (look at the color of the blue paint brush), apparently i was multiplying the alpha channel by 255 in the texture class because of a previous implementation and that was causing some sort of overflow in the shaders, thus the weird colors, so paint tool is officially finished, hopefully
JSP I’ve been stuck with a super upsetting bug with the engine’s render class and the ownership of the output buffer that made the engine’s sandbox editor be completely unusable for however long this “postprocessing pipeline update” lasted. it is now fixed and i could continue developing this game finally. As the engine now supports adding many layers of postprocessing on top of the main render pipeline, i started cooking up atmospheric and star shaders, although only the first one is finished. i ported the atmosphere shader from a tutorial posted by nvidia on atmospheric scattering from a many years ago but the end result is honestly amazing, way better than what i had in mind. This is supposed to give the same feeling as the atmospheres from outer wilds, which is part of my inspiration for this project (and also my fav game in general) new features add “Has atmosphere” option to the planet builder mode, with a lot of options and parameters to control and make your own planets, showcased in the video… made all entities with the planet component now have an option to show an atmosphere, although it is disabled by default. this results on the earth shown in the main menu to now also have a atmosphere I will be focusing on finishing the planet builder game mode first, as it is ~60% done (probably less), i just need to add the entire terrain tool and save the planet settings to a file to be able to use it later or use it in the gravity sandbox PD: i know it seems like im focusing too much into the small/extra gamemodes but this is supposed to function as a base for the campaign mode, which i dont think will be released in the first public version unfortunately
JSP I’ve officially finished the planet builder sandbox gamemode finally, probably will tweak a lot of things but the main stuff is done. i spent quite a lot trying to fix a problem with the depth texture that isnt even fixed right now lmao, quick explanation: distances are huge and so the depth texture loses a lot of precision, to combat this i decide to add reverse-z to the engine’s renderer but this didnt really solve the issue as it probably needs even more work adding an inifinite “far” plane or logarithmic depth but i think its fine for now, ill explain this more in depth with the next devlog on the origin engine. new features added oceans to the planet builder, very simple for now but as a first version i think it works just fine, i spent at least 8 hours with this already lol, added basic controls to the ui to modify the shader’s uniforms and hopefully its good enough added loading/saving to the planet builder and to the sandbox, you can now save your projects using json serialization, a geometry-to-file algorithm and a texture-to file algorithm. note that the planets you create in the planet builder can also be used in the gravity sandbox added the terrain tool so you can now modify the geometry of your planet as you like, creating mountains, valleys or oceans Next up is to finish the gravity sandbox gamemode, hopefully that should be a lot quicker as most of it is already done, but you know how this usually goes HELP: if you have any ideas on how to make the depth texture more precise given the huge distances please let me know, theres not a lot of information out there
JSP Currently finishing the gravity sandbox gamemode! I still need to make quite a big change as im thinking of unifying the “gravity body” struct i use in the sandbox with the “planet component” i use in the rest of the game, so this will probably take a while but, for now, the sandbox game mode seems to be the next thing to be finished! new stuff! the gravity sandbox now has gravity!!!! note that it is not super realistic nasa-level simulation, i was thinking of something a lot more arcade. this is very well reflected in the fictional scale (its around 1:100000), because games must be fun first, then realistic if possible separated the gravity sandbox file to hold the built-in planet’s registry in a different file (its around ~1300 lines of code rn lol, after the simplification…) added a nice destroy animation for the planets, improved the velocity tool and made the selection tool follow the planets the intro animation now locks into the sun, which is now the origin of the scene + changes to the style of the sun added trails to the planets in the simulation (that you can toggle, of course) small UI improvements Whats next u say? applying the same load/save system that i used in the planet builder sandbox, only that now i wont have to create a vertex data to file system (yay) Im also starting to 3d model in blender the “assembly building” where you will be able to build your spaceships in the other game mode, but im really bad at it so ill leave it for later, once the spacecraft builder game mode is finished i will probably ship the first version
JSP Huge progress!! (yes, really) I’ve made some cool stuff an this game now looks a lot more professional, these last changes we’re surprisingly fast and fun to do (finally for once lmao), although the following changes, most of them, are still work in progress. I’ve officially decided that I’m not gonna be updating the engine’s repository solely for this project as im a bit more focused on making my game work rather than making the engine reliable and well-structured for any usecase, even tho the engine will still recieve updates any way cuz i really need them for the game, but the main focus is to not suffocate the engine with specific jsp stuff. new stuff audio system: custom imgui wrapper that lets me make sound effects for buttons on hover and press + background music system that lets me control simple fade out and transition to other songs, currently only in the main menu user settings: instead of making the same json slop ive made for the rest of the load/saving stuff, i made a fancy system that lives in the engine’s core and that lets you save any kind of settings a lot easier. user settings are now correctly saved when changed on user/settings.json created a simple intro text for the first run that explains a some information made the settings window accessible from anywhere, not tied to the main menu anymore FANCY TRANSITIONS between gamemodes, it now fades in/out to black with a little loading icon in the bottom right corner, this took longer than id like to explain unfortunately added a color history for the paint tool in the planet sandbox improved atmosphere UI controls in the planet sandbox fix water shader sometimes rendering on top of an atmosphere As you might be able to guess, some of these changes weren’t really necessary but im sort of procrastinating so that i dont have to model the assembly building for the next game mode cuz i really suck at it and will be painful most likely I’ve though of adding a “first person view” move mode to the spacecraft sandbox as it would be cool to see your creation from an engineer’s point of view and also because that way i already will have coded the controls for the campaign :))
JSP Unfortunately hackatime doesnt support blender so the ~2.5 hours i spent modeling the assembly building for the spacecraft editor sandbox will not count but its fine. I’ve also done some deep debugging to the engine as it now supports embedded materials even when they dont have any texture, before this change everything looked like a wierd artifact in black/purple colors (check out the second image if ud like to see it, its pretty in a way) what was added/changed Created a not-final but decent model for the assembly building you will be creating your custom spaceship in Added first person camera control, that is used by this gamemode to get a different “perspective” on your awesome creation. you can toggle between the normal orbital view and the fp view some engine-level optimizations This now means im FREE… to actually start developing the spacecraft building sandbox, so we are back to it lol. im hoping it doesnt take me that much but i still need to finish to understand how exactly i want this to be as this is probably the only shared code that the campaign game mode will use, so i better make it good as it “counts” double PD: already said this, but the second screenshot is just so you comprehend what ive been struggling with for the past 48 hours :(
JSP Been working on the spaceship builder gamemode and its pretty fun! right now the system is very simple but solid. i had to model a couple test things and fix many bugs but it is going quite fast. The current system is a simple attachment-part system where each attachment holds up information about allowed part’s categories to attach and the normal vector of the attachment. Unfortunately removing parts is not really an option yet cuz i need to see how i will make that possible later on summary on new features: started the actual spaceship building gamemode, currently it features just basic part placement logic small changes to sound effects and music (not shown in the video) Apart from obvious structural changes, id also want to add some sort of customization to your spaceships, with different colors, flags, sigils idk. I dont want to make building a spaceship something hard but just a simple thing you do to have your own individual experience, obviously you wont be able to make some cursed stuff as it wont just fly into space without an engine, but the idea is that everything with enough parts should work
JSP I really enjoy creating and coding shaders and so i started adding some cool effects to the spacecraft editor, didnt really add any new parts but i think that what i added was pretty interesting. I’ve also been working on improving a bit the user experience and making things obvious to use without explaining anything, this is probably the most fun i had doing this project in a while :) what was added Added “Blueprint” view for your spaceship, watch the video to see what it is! currently very early version tho Added a help window that changes based on the gamemode Added geometry center (blue) and center of mass (yellow) to the spaceship Small fixes to transition between movesets Added a border shader to mark the bounds of the building workspace Added a few icons that really need some improvement The idea of the blueprint mode is to edit different things from the spaceship, and also to see the different stages of your little ship! more on this later, im not specially creative enough to write a lot today lol Ill also probably add a dynamic cursor system but idk
JSP Worked on polishing and improving a few quality of life features and overall stability, also I took my time to translate every single text in the game to spanish, although the new dynamic language system should work for adding any new language fairly quickly. this is a very important change because doing this after the campaign would be a nightmare. language is also saved to settings new stuff Added a dynamic language system and support for playing the game in spanish, if you want any new languages or help translate and thus be added to the credits please reach out Added a full credits panel where it shows all the licenses and 3rd party code/art used, AI disclosure and other stuff Fixed some weird seg faults when going back to main menu from the blueprint view Updated all icons, all of them were used in the sandbox game mode Added some new settings to the blueprint view inside the spaceship building game mode What I wanna do now is to finally finish the spaceship sandbox finally but its taking longer than expected and it requires a lot of brainpower that many times is less appealing to do compared to playing persona 5 royal lmao. Note: once the source code is published, sending feedback, playtesting or translating would maybe mean that i put you in the credits! fr i might need some help tho
JSP Can’t really express enough how much I enjoy making shaders, the look really good. i might make a video about it with the new hackclub video challenge, we might see, I’m kinda shy for these sort of things :)) Today’s devlog is pretty much to show only one thing. I’ve been doing some really small changes to UI, a few bug fixes but the important thing is the new Central Body system for the sandbox mode (the code is pretty rough right now but hopefully ill improve it), this now allows you to choose the central body that your planets will orbit around So now, instead of having only the sun in the middle you can now select a BLACK HOLE instead, which i think its a lot cooler. Note that the whole black hole is completely done by a single glsl fragment shader, how cool is that? I’ve reused a small amount of code from the atmosphere shader and then researched a bit on similar projects Apart from this I’ve also added a new “extra” option to allow the player to change the tint of the skybox, so you can create even weirder solar systems, any new suggestions on what else to add are welcome! After this im gonna do a small refactoring change that is really stupid and needs to be changed in the entire code base, its just a small thing with the new language system
JSP https://github.com/aloyak/JSP https://aloyak.itch.io/jsp?secret=nkYXIEVo8woJvblBQRYMIrWSFc I feel like im getting very close to a first ever release and finally start with the campaign mode! I finished some polishing stuff and fixed a bit, i dont think the spacecraft builder mode is ready 100% but ill use it in the campaing mode either way so ill have to update it regardless I’ve officially published the github repository where you can check out the huge amount of code this project already has lol. I’ve also created a new itchio page, this is the secret link (for feedback): https://aloyak.itch.io/jsp?secret=nkYXIEVo8woJvblBQRYMIrWSFc added things: Published the github repo and the itchio page! With a lot of new screenshots and art. I’ve also added the source files of the textures (.xfc gimp files, including the itchio banners) as well as the 3D models I’ve made (in blender) which can all be found in the assets_src/ folder Added a way to delete different parts in the spaceship building mode Added a few new parts to the spaceship building mode, refactored the whole system to make it “easier” (not really) to add new parts and things Added a full README + LICENSE to the repo Added a new shader , it is the small fog that you see in the vide when building a spaceship in order to hide the lack of detail in the exterior, the shader fades out the more you look up so you can see the beautiful skybox Added load/saving to the spacecraft building game mode, you can now save your ship’s to load them later just like with planets and sandboxes Fix some memory management problems where i forgot to delete some pointers => no memory leaks or crashes! I dont think this will be the last devlog before the first ship, but maybe, who knows right? Looking forward to you all trying my game! (the part that is done) PD: 100 hours
JSP Pre-ship checklist is complete! I’m so ready to ship the first version and start developing the campaign, which is the main thing of this game. I’ve actually started it a little bit, it now has an interior level system completely different to the gamemode system i had for the rest of the game, this is pretty exiting! stuff that ive done before shipping Built the game for windows, took a little bit but performance is 1:1 and everything works perfectly, the only thing was that i had to change the backend of the audio engine to use something else but that was fairly quick! Reduced the size of the game MASSIVELY , it went from around 350MB to ~35MB , thats literally 10 times less!! managed to do this by compressing the audio files, although the change is almost unnoticeable, and also making the engine bake some textures on build time, just like real fancy engines do! Changed a bit the main menu/ campaing mode but for now it is all a placeholder Created a new itch.io banner Made the HELP menu show up by default, i dont really like this but i think its probably the best for people to rate it nicely, wont be in the final version… Added a input mode (another one) to the spaceship building mode that allows you to hover the attachment points and it will tell you with a little popup what category of part can go there If you are rating my project, please ishowspeed i need this now in all fairness i hope people like my game! im not even close to finishing it lol Right after this first ship i will work on updating the engine to support new features that the campaign mode will certainty need 100%, like a working physics engine, ive thought of porting what i currently have to use a new one i found and that is getting very popular called “Box3D”, we’ll see, byeeeeeee
JSP I want to dedicate this devlog to @Rupnil as he always says that devlogs need to be 3-4 hours max, so i can explain why thats not always possible. Out of the 8 hours i devlog today, around 7.5 of them were spent ONLY debugging ONE SINGLE BUG for 2 whole days. I started losing my mind lmfao the bug: All the built-in and embedded textures became completely broken and ONLY on super specific conditions on certain parts and game modes. But the worst part was that rolling back to a version from days ago DID NOT solve the issue at all . I even considered that my GPU gave up on my and it was just showing gpu artifact slop in my screen the fix: Apparently there was a small bug with gpu memory allocation in the backend of dear imgui (apparently ONLY in the SDL2-OpenGL backend lmfao) and only for the docking branch of the repo. Rolling back to an old dear imgui version from the main branch solved the issue but damn. Ive also reported the issue as much as i could in the official repo. Pretty much, updating the engine to the latest version automatically updated its dependencies and thus leaked the bug to my game Appart from that I’ve spent a little bit on starting to develop the open-universe system where you can travel around planets! More on that in the next devlog probably. I already have though about the planet’s names, positions and stuff! pretty exiting!! PD: In the mean time ive also being updating the engine at the same time to improve the physics system, which is a lot better right now!
JSP This is one of the most exiting devlogs so far!! I’ve managed to get a very basic “solar system working, not all the time and of course it isnt perfect but it is really cool, heres its lore: (note that planets are placeholders right now, and distances/scale should be a lot bigger in the future) The “Halcyon” System Somewhere very very far from our current home, humanity has managed to establish a multi-planetary life in a new system after traveling for generations in their own space station The Halcyon system is composed of 5 planets (maybe more in the future) that orbit around a massive black hole (it doesnt have a name yet) “Gaia” is the earth-like planet whose own satellite, “Vesta”, is a red dwarf star that provides just enough light and heat in order to live (seen in the demo video) “Ying” and “Yan” (names will probably change), are two tiny planets that follow exact opposite orbits around the black hole, when one of them is at the perihelion, the other ones at the aphelion “Kepler” is a huge rocky planet at the outskirts of the system where small human colonies currently live Note that the campaign will be linear and happen entirely inside this place, but you will also have a “exploration” game mode that will allow you to find and see new secrets hidden… :)) Technical stuff (i.e. what was added) Created the base for the Halcyon System, planets follow a predetermined elliptical orbit in real-time. Note that for debugging, scale is around 10 to 100 times less! Added a simple physics based player controller, this took a lot of engine refactoring too. The player is affected by the gravity of the near planets and, when close enough to a planet’s surface, it is automatically aligned with the gravity vector and its also affected by the atmosphere’s drag (if theres any), this was by far the most difficult thing to do Added a little Free Camera controller as well What will be added in the future This is only the start . Theres still a few complicated things to do: Add double precision and floating origin to solve the problems that will appear when distances become as big as id like them to be Add a chunked collision mesh system for planets with complex geometry, like mountains or things like that. Right now they are all controlled by a simple kinematic sphere collider This system currently breaks the player movement when planets are moving, this is why i set “time scale” to 0. To fix this ive been thinking of creating a local physics world that sets the planet you are on to be the origin of the physics, making it look like if the planet was static, this will by by far what will take the most amount of work probably i also wanna update the atmospheric shader as it is by far the thing worsening the game’s performance, and id like to make the sky fully tint when your inside it PD: Thank you so much for all the people that support/follow this project, it already has 21 followers . thank you, really!
JSP Worked on so many things before getting started with the complicated stuff, ill tell more about that in the bottom section, but for now, im pretty happy with what ive just added, even tho progress is pretty slow!!! What have i added? Full/complete atmospheric effect , it now not only looks good from outside, now from the inside too!!! Its a small trick but when the camera gets close enough to a planet, its atmosphere’s density scales up making the sky blue like here on earth or greatly improving the sunrises and sunsets , they do look beatiful Added floating origin: double precision was not enough so ive added a system that teleports all the entities in the scene when the player gets too far from the origin, this works surprisingly good and it was very simple to do, hopefully it wont break physics later on, but so far its great! This allows the solar system to go from ~10000 units wide to over ~3000000!! that is great! This was a engine-level change mostly tho You can finally use the planets you discover in the campaign mode in the sandbox mode Dynamic settings!!! I made it so that when you first load into the game, the UI scales to your resolution and your target fps are set to your monitor’s refresh rate, might not look like something important but this is actually HUGE Whats cooking up currently! Need a system to allow the player to be placed on top of moving planets (it currently works but breaks sometimes), and also to allow those planets to rotate. This will be achieved with a completely new physics world that will live localy on the closest planet the player is to Chunked mesh collider system i really dont know how to this, because of the terrain of my planets (TODO), collisions will be complicated to calculate, if you know about anything that could help, please send it!!! PD: I wish i could spend more time actually coding than thinking, if that were to be the case id have 300 hours+ in this project already
JSP Omg i need a break! just one more change bro and i will start doing the hard and boring stuff, just one more i swear! This sums up everything ive done for the past few hours, although the new improvements are actually quite important, i feel like im somewhat rushing them instead of focusing on the exploration mode New things!! Simple LOD system for planets, there wasnt a big performance change, but the model swap is very unnoticeable and nice so thats great! Added a simple spoiler warning to the exploration mode, the original idea was that you should unlock it after playing the campaign but i guess its fine lol I FIXED THE DEPTH BUFFER PRECISION ISSUE!!!! it was such a small change omg, i just dynamically changed the near plane of the camera based on how far you are to a planet, pretty nice WIP Work in progress: I’m porting the whole game to the new action-based input system so that the game supports controllers natively without any kind of steam layer on top, this is till very early and i still dont know how to make some stuff be fun to use with a controller…. I finish this, finish the two major things on the exploration mode that are 100% gonna be quick, make some decent amount of content for it, add the custom spaceship controller and launch system, make the first ~5 minutes of the campaign mode, and then SHIP THIS PROJECT (this will surely go as planned) PD: the video u see is completely controlled with my gamepad, not the best controls yet but its better than nothing!
JSP! I’ve finished porting the game to the new action based input system, its not great yet, theres a lot to polish but at least you can play 80% of the game just as good as with a keyboard/mouse (even better sometimes!) What’s the new input system? The game now asks for “actions” callbacks instead of directly asking for raw input. This new layer in the middle allows to make different devices have their own way to control each actions, so it now supports all the gamepads you probably have: xbox, playstation, steam, nintendo, generic ones too It is almost steam deck ready! Ive been playing this game on my steam deck and it works great! (you can get around 900 fps when unrestricted) Playing the game with a controller plus a little help from the little mouse trackpad really makes this game fun to play (100% coverage with this setup) Now i will finally start doing the boring physics stuff that will hopefully not take so long but idk, we’ll have to see Other stuff that was added Improved a bit the gravity based movement mode, it now adds the atmosphere’s drag gradually depending on its density, being the density higher the closer you are to the surface, this makes entering planets feel better Fixed some messed up formatting style in my code I dont know if start a new project for no more than 2 weeks and then go back, ive been having some cool new ideas but for now ill stick to this project PD: the picture is an old version (0.12.1), latest version with good controller support is 0.14.0
JSP We are SO back! I thought it would take me weeks to solve this issue but it wasnt that hard, thanks claude lol for helping. It’s not perfect just yet but its honestly crazy how my own engine managed to handle what im about to explain What took soo long The game now handles a transition from a global physics world to a new extra physics world that lives locally when the player enters a new planet (the origin of the new physics world would be the planet’s center), this means that you can perfectly walk on the surface of all the planets while they move around in the orbits without any weird behaviors This took a good amount of engine refactoring and a few changes to some systems (specially the floating origin) I need to fix a couple things like the drag when you are entering a planet, but that should be handled later on when you actually use a spaceship to enter and not just yourself with your spacesuit Other stuff that is cool Added a helmet overlay! (very inspired by outer wilds, id like some suggestions to make it more original honestly, but right now it decent). It is currently work in progress tho, and theres a lot of information missing… Small UI improvements: rounded borders, removed window’s transparency, added window close sound effects (need to find a better one tho), little better controller support… I just this idea to have vehicles but that will take super long, its added to the ideas file but thats certainty not being considered for short term, Any suggestions are welcome tho PD: video is very bad res bc i had to compress it unfortunately
J.S.P. Very exciting changes to the exploration mode yay !! I’ve been working on precisely TWO (2) things but one of them is way too early for me to be able to show you anything, more on that in the end Whats new? I’ve create a custom blender addon that lets me create procedural noise-based planets! It is really powerful and it gets you really good results for how simple it is really. In a way, its nothing but a vertex shader but coded in python lol It generates 3D spherical noise and applies it into an icosphere with a variety of parameters. Some of them arent precisely working but they are fine for now (specially the “ridged” option) You can try it yourself, its open source too! https://github.com/aloyak/JSP/blob/main/assets_src/blender/addons/planet_generator.py Terrain System I’m developing a way for the player to correctly collide with the geometry of these planets, but this is mostly engine-sided changes and I’m not very deep into it yet. I’m currently researching how to handle multi-threading async functions… more information about this in my latest engine’s devlog: https://stardance.hackclub.com/projects/1029/devlogs/34738 Known issues These are not really important right now, but for some reason I’ve realized that the splash screen takes different amounts of time depending on where you run the game?? what? A steam deck is around 3 seconds, my computer (the intended duration) is 4 seconds and in a friend’s laptop it is ~0.5 seconds
JSP! I’m back! and I finally have a new decent version that im probably gonna ship shortly after I publish this devlog. Its been so long since the last devlog because a number of factors, I had some vacations, my main pc is now just a steam deck connected to a monitor and also I’m kind of struggling to continue this project, I hope this isnt the last version but working on the project and adding or fixing things is very complicated and requires a lot of research to do it right, and it is exhausting What was added?? Included the new planet models to the halcyon system, you can now correctly explore them by using the new terrain system I added to the engine! Added some small help windows/hints for the new stuff before shipping! Fixed some audio bugs and added a sound effect for when you close a window Fixed the in-helmet HUD UI, the input vectors now correctly show the direction the thrust is being applied to, kinda like in Outer Wilds!! I’m most likely to be focusing on continuing the engine for a little bit, it really really does require some refactoring and I also need to clean some likely dead code or at least re-understand the code i wrote as it has lines from almost a 10 months ago! Hopefully someone could help and contribute to the project maybe or make something new out of it too! Im still planing on continuing to develop it but not at this pace considering im about to start college :))
Ships:
This is my 3D game about space exploration and kessler cascades, it has a campaign mode coming up but i havent finished that yet, for now enjoy the 3 game modes! i built this on top of my custom engine so its been a lot of hard work, please try it out!!!!
This is my 3D exploration-sandbox game that I built with my custom game engine! I’ve added quite a lot of stuff like a simple exploration game mode that allows you to move around a hand-crafted solar system i called “Halcyon”. there are also a lot of other game modes you can try and have fun with before I finally add the campaign game mode for the final version! In the picture you can see an in-game screenshot of the player walking around the surface of the earth-like planet “Gaia”, hope you like my game! With <3, 4loyak!...
|
1792828335.4881313
|
1792914735.4881313
|
|
14130
|
Immortal Cultivation Mod (修仙) by @m3e660 | Stardan Immortal Cultivation Mod (修仙) by @m3e660 | Stardance...
|
m3e660
|
4
|
345.45
|
3100
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-13T17:07:11Z", "hours": 76.0, "multiplier": 18.81, "payout": 1254, "blessing": "neutral", "text": "I WANT MY POLAROID GO GEN 3 PLSSSSS I AM JUST A TINY BIT AWAY", "repo": "https://github.com/m3e66/immortal_cultivation_mod-source", "demo": "https://modrinth.com/mod/immortal-cultivation-mod"}, {"ship_num": 2, "ts": "2026-08-23T01:53:50Z", "hours": 96.0, "multiplier": 15.99, "payout": 1340, "blessing": "neutral", "text": "I want my VR ahaahahahahah plssss Nothing much to say here just look at the images and video in the previous logs", "repo": "https://github.com/m3e66/immortal_cultivation_mod-source", "demo": "https://modrinth.com/mod/immortal-cultivation-mod"}, {"ship_num": 3, "ts": "2026-07-11T00:52:33Z", "hours": 44.0, "multiplier": 18.82, "payout": 297, "blessing": "neutral", "text": "This update adds a huge amount of new content! You can now explore newly added structures, use new spells, control and evolve zombies through the new 怨气 and 控尸 systems, and wear new design accessories. The 金丹 system has also been remade with its own pocket dimension, breakthrough system, and new mechanics. Spell casting has been reworked, flying swords are now fully usable, and a complete forging system lets you craft weapons using materials, molds, purity, and temperature. There are also plenty of new items, crops, effects, and fixes to improve the overall experience!", "repo": "https://github.com/m3e66/immortal_cultivation_mod-source", "demo": "https://modrinth.com/mod/immortal-cultivation-mod"}, {"ship_num": 4, "ts": "2026-06-16T02:19:15Z", "hours": 23.0, "multiplier": 10.72, "payout": 209, "blessing": "neutral", "text": "Getting Started The first steps of cultivation. Enlightenment Pill Use an Enlightenment Pill to step from mortal life into Qi Refining. The stat menu shows qi, realm, max health, max age, luck, moral, soul, thoughts, spirit roots, and cultivation progress. Spells Fireball (Lianqi Early, Fire, 10 Qi) Shoots a fireball that deals damage and ignites targets. Lingbeng (Lianqi Late, Thunder, 50 Qi) Enter a breaking-force state. Punch a block or entity to release an explosion. Recasting stacks the explosion radius. Regeneration (Lianqi Middle, Wood, 20 Qi) Restores health with a short healing effect. Beam (Lianqi Early, Light, 30 Qi) Allows you to sense nearby entities. Earth Escape (Lianqi Late, Earth) Sink underground. Move faster while underground. Consumes Qi over time until you surface. Cleanse (Lianqi Early, Water, 10 Qi) Removes harmful effects from yourself. Qi Gathering (Lianqi Early, Wind, 0 Qi) Greatly increases Qi regeneration. You cannot attack or block while active. Damage taken is tripled. Ignite Flare (Lianqi Early, Fire, 10 Qi) Fires a straight flare. Ignites the block it hits. Spirit Sight (Lianqi Early, Light, 5 Qi/sec) Grants night vision while active. Zhenshan Palm (Foundation Establishment Middle, Earth, 130 Qi) Releases a giant hand-shaped earth wave for 3 seconds. Destroys blocks touched by the palm. Light Ball (Foundation Establishment Late, Light, 30 Qi summon, 10 Qi per shot) Summons 6 light balls in a hexagon behind you. Can stack up to 3 rings. Punch to fire one ball. Shift-punch to fire all balls. Each shot deals 50 damage. Each shot can break through up to 24 blocks.", "repo": "https://github.com/m3e66/immortal_cultivation_mod-source", "demo": "https://modrinth.com/mod/immortal-cultivation-mod"}]...
|
[{"post_id": 81380, "ts": "202 [{"post_id": 81380, "ts": "2026-10-21T02:39:43Z", "hours": 10.3219, "text": "Devlog #33** A shentong ability:湮灭未尽之人 and a dummy for testing purposes A lot of bug fixing and small thing like better formatting of the gui etc"}, {"post_id": 80679, "ts": "2026-10-18T13:51:12Z", "hours": 8.0572, "text": "Devlog #32 Added new effect in domain like abilities: Lilies, ice, big space warp (don’t yell at this devlog, I wrote it on the phone)"}, {"post_id": 80384, "ts": "2026-10-17T14:03:45Z", "hours": 10.4, "text": "Devlog #31 Added BLAST QI, where you can BLAST YOUR QI in your enemies face and be cool And fix the flying sword thing And fix a whole a lot of fix"}, {"post_id": 79682, "ts": "2026-10-15T01:38:45Z", "hours": 8.0478, "text": "Devlog #30 Remaking the whole life sim system adding new event (making them actually have somewhat of a story) added new battle system and more small thing to better help the experience And ton of bugs"}, {"post_id": 79208, "ts": "2026-10-13T01:21:10Z", "hours": 9.6014, "text": "Devlog #29 Remake all the magic circle texture and automated it (tool here https://m3e66.github.io/xiuxian-circle-generator/ ) Optimize all the code Added new body types 赤炎灵体 — Crimson Flame Body +25% fire damage; burning enemies take 10% extra damage from you 玄冰灵体 — Profound Ice Body +25% ice damage; attacks build Frost, briefly freezing enemies after 5 stacks 紫霄雷体 — Violet Thunder Body +25% lightning damage; every fifth lightning attack summons an extra thunderbolt dealing 50% damage 青木长生体 — Evergreen Longevity Body +15% maximum HP; +25% natural HP regeneration; +10% healing effectiveness 厚土玄体 — Profound Earth Body +20% armor; standing still for 3s grants an additional 10% damage reduction until moving 庚金剑体 — Geng Metal Sword Body +20% sword damage; +10% sword attack speed; sword strikes ignore 10% armor 沧海灵体 — Vast Sea Body +20% water damage; +20% maximum Qi; water spells cost 15% less Qi 逐风灵体 — Windchaser Body +20% movement speed; +15% attack speed; dodging grants +10% damage for 3s 先天道体 — Innate Dao Body +15% cultivation gain; all spells cost 10% less Qi; +5% all elemental damage 无垢灵体 — Immaculate Spirit Body +30% negative-effect resistance; debuffs last 25% less time; +15% healing received 九窍玲珑体 — Nine-Orifice Exquisite Body +25% Qi regeneration; +10% maximum Qi; spell cooldowns reduced by 10% 万毒之体 — Myriad Poison Body Immune to poison; poison attacks deal +25% damage; poisoned enemies restore 1% max Qi when killed 血煞魔体 — Blood Fiend Body +20% melee damage; heal for 5% of melee damage dealt; healing from pills reduced by 20% 不灭金身 — Imperishable Golden Body +15% maximum HP; +15% damage reduction; when HP falls below 20%, gain 30% damage reduction for 5s 吞灵之体 — Spirit-Devouring Body Killing an enemy restores 5% max Qi; attacks against shields and Qi barriers deal +20% damage 荒古圣体 — Ancient Desolate Sacred Body +25% maximum HP; +20% physical damage; +15% armor; Qi regeneration reduced by 15% 太阴神体 — Supreme Yin Divine Body +30% dark and ice damage; +20% Qi regeneration at night; sunlight reduces Qi regeneration by 15% 太阳神体 — Solar Divine Body +30% fire and light damage; immune to burning; +20% HP regeneration in sunlight"}, {"post_id": 78918, "ts": "2026-10-12T01:31:10Z", "hours": 10.5922, "text": "Devlog #28 Added 8 guide books for different part of the mod Added new bear model"}, {"post_id": 78651, "ts": "2026-10-11T05:20:58Z", "hours": 10.4994, "text": "Devlog #27 Improve overall guidance and improve existing model"}, {"post_id": 77981, "ts": "2026-10-09T03:03:43Z", "hours": 9.3439, "text": "Devlog #26 I going to improve the overall survivability of the mod: So there is going to be like more guides book in coming And more item that were creative only now actually getting ways to get the items"}, {"post_id": 76814, "ts": "2026-10-04T17:37:22Z", "hours": 9.2553, "text": "Devlog #25 Add a lot of new weapons A lot of new fire And more clothes"}, {"post_id": 75392, "ts": "2026-09-29T22:21:34Z", "hours": 9.3814, "text": "Devlog #24 121 NEW SPELL ICONSSS MY SOULLLSLLSLSLLS I pick the best 20 icon i love"}, {"post_id": 72892, "ts": "2026-09-23T23:37:48Z", "hours": 10.9486, "text": "Devlog #23 REVISE MOSTLY OF THE VFX AND ADD ALOTTTTT OF DRIP"}, {"post_id": 67505, "ts": "2026-09-13T17:02:49Z", "hours": 8.2731, "text": "Devlog #22 Not much like I said school started, it was more planning and stuff, revised npc battle logic"}, {"post_id": 64408, "ts": "2026-09-08T19:30:48Z", "hours": 15.1625, "text": "Devlog #21 Added whip physics Added new item mechinacs Added straw doll Added a luck system"}, {"post_id": 61873, "ts": "2026-09-05T01:00:25Z", "hours": 12.3611, "text": "Devlog #20 School is starting and college stuff is like piling on so my brain is slowing down, so there isnt much stuff i did when you compare it to the hours in this devlog. Mirror Thingy It is like a shield can absorb some dmg Straw Doll Like a totem of undying Jei Compatibility You can see the forging recipes in Jei now!"}, {"post_id": 59887, "ts": "2026-09-01T21:31:56Z", "hours": 11.3725, "text": "Devlog #19 Some mobs, yea that is really it"}, {"post_id": 59086, "ts": "2026-08-31T18:20:43Z", "hours": 10.5844, "text": "Devlog #18 Working on flying boat or valkyrie skies like things, I dont think that is copyright as it is not the main part of my mod, if it is tell me in the comments thanks Flying Boats Four core tiers control maximum capture size: Low: 100×100×100 Medium: 200×200×200 High: 400×400×400 Sect: 800×800×800 Existing ships can still be minimized into an item and placed again later The lingzhou core GUI is where you manage the ship. It shows the ship’s status, tier, size, fuel/灵气, current pilot, permissions, settings, movement mode, anchor controls, shutdown, and storage Fuel use is based on how many blocks the ship actually has and what it is doing. Hovering uses fuel, while an anchored ship does not The ship helm is used to pilot the lingzhou. While controlling it, the mouse wheel can be used to change the ship’s speed Autopilot lets you enter destination coordinates and have the ship travel toward them automatically Players and other entities move together with the ship. You can walk around the deck, jump, climb stairs, and move around normally while the ship is flying If part of the ship gets disconnected, that section is no longer supported by the lingzhou and falls back into the world as normal blocks Turning off the lingzhou core removes the ship’s magical lift. The ship keeps whatever momentum it already had and begins falling under gravity Etc Fix system prices Fix textures Fix names of items Added JEI compatibility for 鼎 forging Added recipes for a lot of weapons Removed combo system Added a fox beast"}, {"post_id": 55551, "ts": "2026-08-27T14:05:21Z", "hours": 9.8333, "text": "Devlog #17 MORE STRUCTURES i got into the phase of building so more structres!"}, {"post_id": 54475, "ts": "2026-08-25T14:27:13Z", "hours": 8.5392, "text": "Devlog #16 Did some structures, and there is the talisman data like I said Talismans Tier 1 清尘符 — Dust-Cleansing: Extinguishes fire and removes blindness and darkness 微光符 — Dim-Light: Creates light ball for 2–3 minutes, hold while aiming at a block to anchor it, you can use water extinguishes it 敛声符 — Sound-Gathering: For 25 seconds, nearby mobs lose you as their target when more than 2.5 blocks away 火球符 — Fireball: Fires 8 fireballs. Each deals 10 damage in a 2.4 block explosion 风刃符 — Wind-Blade: Fires 3 wind blades dealing 11 damage each and pushing targets backward Tier 2 星火符 — Sparkfire: Fires 5 flames dealing 30 damage each and igniting for 4 seconds 薄金护符 — Thin-Gold Protection: Give shield worth 200 + 1% maximum HP for 15 seconds 缠丝困符 — Spirit-Silk Binding: Fires 6 strands dealing 1 damage each. Strands stack slowness for 5 seconds and 4+ strands nearly immobilize the target 短途神行符 — Short-Journey Divine-Step: Give speed VIII and jump boost III for 30 seconds 传音符 — Voice-Transmission: Sends a written message to another player with in 100 blocks in the same dimension 修复符 — Repair: Repairs the damaged item held in the opposite hand Tier 3 避邪安魂符 — Evil-Warding Soul-Calming: Evil ward for 5 minutes, clears and prevents darkness/nausea, and restores 1% maximum Thoughts each second for 3 minutes 镇扰符 — Disturbance-Suppressing: Hostile mobs within a certain range get slowness II 爆风符 — Blast-Wind: Produces a blast dealing 50 damage, applying daze, and deflecting projectiles 火狱焚邪符 — Evil-Burning Fire-Prison: Creates a 10-block explosion, deals 50 area damage 五雷小伐符 — Lesser Five-Thunder: Deals 40 damage and give slowness III for 1.75 seconds 标记符 — Marking: Permanently marks a entity up to 300 blocks away for owner,and marked mobs are also prevented from naturally despawning 遁空符 — Void-Escape: Teleports in the direction you are looking, normally up to 20 blocks. Repeated uses within 5 seconds lower the maximum to 17, 14, then 12 blocks 化兵符 — Weapon-Manifestation: Creates an owner only temporary sword lasting 25 seconds Tier 4 金光护体符 — Golden-Light Body Protection: Adds a shield worth 600 + 1% maximum HP for 25 seconds 封灵符 — Spirit-Sealing: Seals everyone’s qi within 3 blocks of impact, interrupts casting 破障开山符 — Barrier-Breaking Mountain-Opening: Creates a massive 20-block explosion dealing 500 area damage Tier 5 千里传讯符 — Thousand-Li Message: Long range version of the Voice Transmission Talisman, but it is 1,000 blocks in the same dimension Tier 6 玄焰焚界符 — World-Scorching Black Flame: Creates a black-flame domain that grows from a 5 block radius and deals 100 damage per second. It destroys terrain, consumes dropped items and projectiles, and grows by consuming matter and victims, potentially reaching 48 blocks 五岳辟厄符 — Five-Mountains Calamity-Warding: Grants luck for 10 minutes and stacks three times: +15, then +7, then +3 Ancient 禁空符 — Forbidden-Air: Places a field 24-block radius lasts 8 seconds. It suppresses jumping and flight, and pulls flyingentities downward"}, {"post_id": 52657, "ts": "2026-08-22T22:04:35Z", "hours": 10.8006, "text": "Devlog #15 Uhm a lot of update and unfinished things so it is more of a sneak peek so, there not going to be a long devlog, maybe i am just lazy :). Cosmic Void New dimension that is like space use for mostly travel and battles Talismans A lot I added a lot but it is for later show you guys some pics tho"}, {"post_id": 46112, "ts": "2026-08-13T03:24:25Z", "hours": 11.3525, "text": "Devlog #14 Hmmm why does the picture devlog get more view than the videos, let this be a test then Added: Tutorial System Qi Sensing Thingy Remake Spatial Pouch and like 20 new spells and 4 new method Remake Spatial Pouch Replace the whole backpack like spatial pouch system to a pocket like dimension (in the in the picture) you can place all functionable block and still use it by left clicking it and double click to remove it. (oh and redstone work :) i know there is people that can do smth op with redstone) Tutorial System Full tutorial system that guide you through everything, because so much people said there is a big learning curve, so boom :) Qi Sensing Thingy You can sense entities, items and qi ahhhhh there is not too much stuff or maybe i am too lazy…. definitely not that trust"}, {"post_id": 44036, "ts": "2026-08-09T15:23:44Z", "hours": 11.2058, "text": "Devlog #13 Sooo, did a few entities and most important zhenpan and flags for the magic circle. Zhenpan When empty shift right click to store a magic center When full shift right click to place a magic center back down When store magic center the radius of the magic center is changed to 5 if higher When right click summon a temp magic center of the radius 5 that appear for 20 sec The cost is calculated based on the spirit stones in inventory first then player’s qi Flags Now in the magic center there is a new tab with a gui (in the pics) where you can put flags, they modified the effect of your magic circle. But each newly added flag will increase the cost of the magic center by 1.3x, so the cost can reach to 2693457 qi when using a maxed out zhenpan. Formation Flag Effects Blank Formation Flag — No active effect, used to forge specialized flags Duration Flag — Adds 3 seconds to a temporary Magic Center’s lifetime per flag Amplifier Flag — Adds 1 extra attack whenever an formation triggers Spirit Gathering Flag — Reduces formation fuel/energy consumption by 25% per flag, it does not add the normal ×1.5 flag cost Swift Formation Flag — Makes normal formation effects trigger 30% faster per flag and increases fuel consumption by 30% Qi Return Flag — Restores 10 Qi per flag when a player kills an enemy inside the formation"}, {"post_id": 39851, "ts": "2026-08-03T03:24:18Z", "hours": 12.4425, "text": "Devlog #13 Oops, I got the 8 hours warning and I forgot about it and not I have 12 hours…. sigh. So this update I mainly update the magic ritual mod I have before, and before you ask yes this is the right project, I merge the magic ritual mod with this mod and then revamped the whole thing. This devlog is kinda short because I am getting lazy. Magic Ritual Combo system The Ritual Dagger is your primary tool for creating and managing magic rituals. Right-click with the dagger to open the Magic Circle Selection screen, where you can choose a magic circle type to place at your feet. Shift + Right-click to open the Radius Selection screen, where you can place a Magic Center Block with a chosen radius Attack Red - Grants Strength I Defense Blue - Grants Resistance I Regeneration Green - Grants Regeneration I There are certain pattern for special effect after putting it in its pattern you can punch the center with the dagger and the new magic center is formed Combo visuals and glyph behavior Basic center have one image pattern Combo center have two image pattern If glyph mode is turned off, there is an entering animation"}, {"post_id": 37945, "ts": "2026-07-30T23:57:05Z", "hours": 10.8044, "text": "Devlog #12 A bit in a rush so no video this time, but i added pics so it should be fine. Battle System 战斗状态/Battle Mode: activates when hitting something, or dmg from players, cultivators, or mobs counts too, normally lasts 15 seconds Manual mode: press Y to lock combat mode on until pressed again it can be disabled in settings Normal attacks (left click just normal attack) Heavy attacks (hold attack for 0.5 seconds, then release, normal heavy attacks deal 120% weapon dmg) Blocking (hold left and right click together you dont take dmg, but the weapon loses durability and the blocked dmg harms posture) 架势/Posture: maximum posture is 100 + Physical Attack × 100 + Max HP ÷ 2. It regenerates by 1% each second 破势/Zero Posture: at zero posture, the player is stunned for 1.5 seconds, cannot block, takes 25% more dmg, and loses their current spell charge 外放灵气/External qi: qi injected weapons can release long, straight qi slashes, with the dmg, width, and range scaling with injected qi amount Recent Weapons 精铁枪: A 14 dmg spear normal attacks is like normal, while heavy attacks use a thrust animation and forms a qi cone shaped thingy 铁骨扇: Shift right click switches forms: closed form deals 3 dmg and uses a cone heavy attack and open form deals 5 dmg and uses slash attacks 拂尘: Deals 7 dmg normal attacks is normal too, but its heavy attack spins five times in front of the player, damaging everything within 3 blocks. Right click binds a physically weaker target within 5 blocks for 3 seconds, with a 10 second cooldown 飞刀: Deals 4 dmg and you can stack 5 more all together into one. Right click throws normally and heavy attacks throw a faster knife that can break five blocks before exploding. 飞针 and 袖箭: 飞针 deals 4 dmg, has 1,000 durability, and consumes 10 durability per shot. 袖箭 can be held or equipped in a back accessory slot. Normal attacks fire ordinary needles but heavy attacks fire qi powered explosive needles Etc Added more English Remake some gui Remake some models"}, {"post_id": 35415, "ts": "2026-07-26T20:10:28Z", "hours": 11.2708, "text": "Devlog #11 Sorry for the quality of the video, the quality had to be sacrifice for the length I have formed a habit of writing random thoughts I had, so here is more: wow I kinda hate the 10 hours devlog maybe it is because I am working on a big update orrrr I am just too lazy Revamp Update (plus other stuff (it is more of a random update)): More quest for all of the identity Giving a use for the jindan quality Added 烬火心燎 (mental attack kinda) Added 碎轨星陨 (big boom) Added 洞天借灵 (restore alot of qi) Added 时序迟流 (time slow zone) Added a soul system (when npc or player die there are a soul) Added 炼神术 (increase thoughts stat) Added DunWu Stele (can be used to crave spells into it so for spells like 炼神术 that have no spell item you can learn it like this) Added 噬魂幡 (cool stuff too much so just watch the video) Added 怨魂瓶 (used to store soul) New identity 邪修 功法 improvement (when use qi there is new particle effects) Etc (gui update and others) Config There is a new config button: Auto inject qi into weapon Outside qi (when in new battle system when swing your weapon it shoot out qi slash breaking blocks and killing enemies) New battle system Jindan creative flight New Puzzle Update 灵枢算盘 (the minigame to crave 禁制) it is use to upgrade weapons and eventually evolving it 灵脉六角阵 (the minigame that the player encounters when breaking through jindan) 灵气轨迹 (the minigame when learning spells) 雷劫 (Heavenly Tribulation for jindan) Strike 1 — A thin white-blue bolt 50 dmg Strike 2 — Two branching bolts 100 dmg Strike 3 — Three quick lightning 50 each hit Strike 4 — A thicker blue-white bolt 100 and take 30 dmg per sec for 5 sec Strike 5 — Lightning strikes the ground in eight positions around the player 300 dmg Strike 6 — Several smaller bolts repeatedly strike the player for three seconds 30 each Strike 7 — A massive branching bolt 400 dmg Strike 8 — Purple heavenly lightning 50 dmg per sec for 5 sec Strike 9 — Four bolts strike the north, south, east, and west sides of the player, followed by one direct central strike 400 dmg Strike 10 — A continuous pillar of lightning 100 per 3 sec Strike 11 — Golden lightning begins appearing inside the storm, six golden-white bolts rapidly strike around and directly onto the player 80 each Strike 12 — A giant bolt splits into twelve branches before all branches converge on the player’s position 300 dmg Strike 13 — Lightning repeatedly strikes the player 50 each Strike 14 — A ring of lightning forms in the clouds and releases a rain of dozens of smaller lightning bolts 50 per 3 sec Strike 15 — Nine rapid strikes hit the player in succession 2/4/8/16/32/64/128/256/512 Strike 16 — Every lightning arc inside the clouds gathers into one enormous golden-white tribulation bolt 1000 dmg Easy Mode Acheivement “You Are Really Bad” Get this when you die 10 times in 20 mins Get a hat curio called “Noob Hat” All puzzle are easier by a level"}, {"post_id": 33331, "ts": "2026-07-23T04:32:21Z", "hours": 12.9683, "text": "Devlog #10 Ok so I have work on more than what is showed in the video but this feature is very big so the smaller thing can be talked about in the later devlog Restriction Enchantment Thingy Update 禁制 replaces normal enchantment levels for weapons and artifacts. Every artifact can contain multiple Restriction Layers: 1重禁制 2重禁制 3重禁制 …… 36重禁制 72重禁制 Each successfully engraved layer improves the weapon. Higher layers become progressively harder, more expensive, and more dangerous to refine. After reaching 72重禁制, the weapon can evolve into the next level Rules Controls Click a row to select its node. Click to the left or right of the bead, or use the < and > buttons, to move it. Use W/S or the Up/Down Arrow keys to change the selected node. Use A/D or the Left/Right Arrow keys to move the selected bead. Each bead has a Qi value ranging from 0 to 6 . The golden diamond shows the target value. When every node matches its target value at the same time, the formation is completed and all selected Restrictions are engraved onto the artifact. Moving one bead may also affect linked nodes. Nodes Types Normal Node A standard node that can be moved directly. The node turns gold when its value matches its target. Forward Golden Formation Line Linked beads move in the same direction. For example, moving one bead to the right also moves the connected bead to the right. Reversed Cyan Formation Line A cyan formation line marked with a “−” symbol. Linked beads move in opposite directions. For example, moving one bead to the right moves the connected bead to the left. Locked Node A gray node that cannot be moved directly. The player must move connected nodes to push it into the correct position. Locked nodes begin appearing from a total of 46 Restriction layers . Unstable Node A pulsating red-jade bead. It moves automatically after its displayed action interval and may also affect linked nodes. Unstable nodes begin appearing from Restriction layer 55 . Hidden Node Its target value is displayed as “?” The player must determine the correct target by observing the formation’s behavior or by using a hint. Hidden targets and move limits begin appearing from Restriction layer 73 ."}, {"post_id": 31014, "ts": "2026-07-19T02:14:35Z", "hours": 3.8225, "text": "Devlog #9 Ok so after some ratings and feedbacks I have decided to write better devlogs with more explaining and thoughts. Update: NPC I was working on npc on the last update and decided to further more finish this feature with adding a nice feature of … IDENTITY All Npc will all spawn with a random identity 散修 - Rogue Cultivator 剑修 - Sword Cultivator 刀修 - Saber Cultivator 魔修 - Demonic Cultivator 器修 - Artifact Cultivator 尸修 - Corpse Cultivator 世家子弟 - Noble Clan Disciple 皇族 - Royalty 通缉犯 - Wanted Criminal 体修 - Body Cultivator (Yes I actually added translation for chinese things now) This identity feature not only completes the Npc’s personality but for each identity they have there own special items (which really helps my mod’s survivability, adding a way to obtain items now) They also have their own personal dialogue based on their identity. Jindan Added a new breakthrough screen for zhuji to jindan, and a new dimension for your own personal jindan (like a new world you can channel 2000 qi in the center and you can build chunks in your own world) (see pics) Plans: I was going to further improve the Npcs but after adding a hole a lot of new items for each identity, I realized that I have a other system and features I didnt make (pill making system and more higher level spells)"}, {"post_id": 28609, "ts": "2026-07-14T23:19:52Z", "hours": 11.3969, "text": "New NPC Update The NPC system has been expanded into a full cultivation-style character system. NPCs now have random names, gender, identity, cultivation realm, attributes, spiritual roots, methods, spells, personality, inventory, relationship values, and persistent memory-style data. NPCs can now behave differently depending on personality, identity and relationship with the player. They can fight, flee, use spells, heal, trade, give quests, spar, and interact through a new dialogue screen. (PS the gui shown in the pic is only temporay) Major additions include: Talk, Interact, Trade, Quest, Teach/Learn, Inventory, About, Spar, Invite to Sect, Master/Disciple, and Dao Companion. Relationship stats: friendship, trust, affection, hatred Social actions like praise, joke, insult, threaten, and gifting NPCs can follow, stay, join sects, become master/disciple, or become Dao Companion if requirements are met. New NPC identities were added, with identity-based starting items and loot: 散修 剑修 刀修 魔修 器修 尸修 世家子弟 皇族 通缉犯 体修"}, {"post_id": 26263, "ts": "2026-07-10T23:12:53Z", "hours": 37.7453, "text": "Added shield bar at the right of the hotbar Added 护体气 Added 迷尘障 Added 四方界 Added 固石盾 Added tomb1 structure Added ruined_ritual structure When real death occur spawn a corpse of the player containing all the data of the past player Added attribute 怨气 to all zombie and corpse The longer they exist in the world higher the 怨气 attribute (1000 tick is one 怨气) When right click a zombie with a 镇尸符 stop them from moving When right click a corpse the corpse will stand up with the arm straight up like a zombie add exact 镇尸符 sprite on the corpse face and the corpse stop moving Right click them with a empty hand to take the 镇尸符 off 镇魂铃 when right click will heal 5% of the max hp of your zombie a 5 block radius cooldown 2 seconds 引魂锣 when holding will have a red point only visible to the player and when right click on a block your zombie will jump to that block and if punch a entity the zombie will attack the entity The range of the red particle laser is based on the player’s block reach Added 控尸术 Types of zombie and corpse 怨气 = 100; 白僵 怨气 = 500; 黑僵 怨气 = 2,500; 跳僵 怨气 = 12,500; 飞僵 怨气 = 62,500; 游尸 怨气 = 312,500; 伏尸 怨气 = 1,562,500; 不化骨 怨气 = 7,812,500; 旱魃 When right clicking a zombie with blood they can drink it and give +1 怨气 After getting to 1000 怨气 cant consume anymore Shift right click to feed all of blood in the hand Different modes for zombies attack all hostile (in 5 block radius) defensive (attack all mob that attack owner) Added coffin item, shift right click to store a zombie Added 道服 Added a 血晶, crafted by 9 blood, can feed to all zombie and corpse in all levels, each one is +5 Added Curios slots hair, hair accessory, head accessory, neck accessory, inner clothes, cloak, back accessory, waist accessory Moved coffin to back accessory support, including Curios rendering Added blindfold, blindfold2, straw hat, jade pendant, zhenhun bell, and yinhun gong as wearable accessories Added inventory sprites for accessories and fixed missing textures/positioning Made waist tools cycle with V while held/equipped Added jade pendant meditation speed bonus and tooltip Added 道服 chestplate and worked through texture/model binding fixes Added 血晶 from 9 blood, with zombie/corpse feeding support Added custom spawn egg textures where needed Added/updated English and Chinese translations for missing content Added Jindan dimension entry from stat menu Added 金丹 entity in the Jindan world and normal-world player clone Added Jindan breakthrough screen Added particle effects during breakthrough Added shift-right-click 金丹 entity to spend qi and replicate overworld chunks into the Jindan world Reworked spell selection GUI Added spell wheel ordering and remembered toggles Added selected-spell + R cast flow with charging bar Added/updated several spell scaling effects and combo casting behavior Added flying sword weapon/entity logic Added release, recall, control, shoot, ride, and pickup behavior Added qi cost for controlling/shooting Added flying sword FX when shooting Added zombie/corpse grudge progression and ranks Added higher-rank zombie effects like 尸毒, flying, 阴气 area, drought/dry area Added 鼎 forging GUI with temperature bar, material slots, 玉简 slot, result slot, progress bar, and start button Added forging recipes through 玉简, including 飞剑玉简 and 精铁刀玉简 Added mold items: 剑胚, 刀胚, 枪胚, 武器胚 Added weapon materials Added material purity system and tooltip display Added forging temperature/quality logic, average temp/purity tracking, and failure still producing a mold Added tempering by dropping mold into water, with smoke particles Added 灵火 support from Ignite Flare and normal fire support Added blockgen fixes and custom geo block rendering fixes Added forging system: 玉简, materials, temperature GUI, molds, quality/purity/tooltips Added new crops/items like 糯米 seed/plant, 糯米粥, 墨斗线, 桃木剑, 铜钱剑"}, {"post_id": 12339, "ts": "2026-06-20T03:56:26Z", "hours": 0.4739, "text": "There was more than 4 pictures in the post below so here is the others After use a spell one time +1 proficiency Spell proficiency 入门:after learning the spell get to this level 小成:100 need to get to this level 大成: 500 need to get to this level 圆满:1000 need to get to this level 登峰造极:10000 need to get to this level"}, {"post_id": 12304, "ts": "2026-06-20T02:31:23Z", "hours": 5.2906, "text": "Custom combo system (Where you can make your own custom combo system) Add a zhuji level entity (with its own ai) zhuji1 logic when qi low and enemy 15 blocks away use qi gathering when hp low use regeneration when enemy 10 blocks away use fireball when enemy 5 or lower blocks away use lingbeng and punch them, if qi and hp are all 75 percent or higher then can choose to use lingbeng more time before punch when hp low use wind step to run away when enemy 11 block or higher away and hp high, use wind step to chase the enemy Add a jindan level entity (with its own ai) jidan1 logic same spells as zhuji1 but no lingbeng add a zhenshanplam spell inject qi into weapons keybind v to inject qi into any weapons including modded ones cost 1% of max qi after the injecting the amount of qi injected is add to the tooltip of the weapon amount of qi / 10 = the dmg dealt when attack with this weapon after attack use up amount of qi / 10 of the qi in the weapon base dmg of the weapon x 100 = x(the extra qi / 100 ) x 10 = y if the amount of qi in a weapon is bigger then x then weapon -y durability every sec until not overflow Added shield bar at the right of the hotbar Added 护体气 Added 迷尘障 Added 四方界 Added 固石盾 Added tomb1 structure Added ruined_ritual structure"}, {"post_id": 9608, "ts": "2026-06-16T00:23:52Z", "hours": 3.5289, "text": "See the toggle spells list that you toggled In spell selection screen you can press the spell to see description Remake spiritual roots Remade ui"}, {"post_id": 8409, "ts": "2026-06-13T23:43:00Z", "hours": 5.0458, "text": "Added lightning effect for lingbeng Remade ZhenshanPalmEntity Added a passive spell 威压 Change the stats (Hp, Qi, Age, and Progress) Change spell’s cost and damage Added command to modified players stats Removed stat cap Fixed loot tables Added 轮回真决 Added 定身咒 Added 引雷诀 Added 五雷正法 Added 御风诀 Added 吞天魔功"}, {"post_id": 7205, "ts": "2026-06-12T01:03:44Z", "hours": 2.4225, "text": "Look at what your boy cooked up in the lab!!!"}, {"post_id": 6577, "ts": "2026-06-11T01:41:07Z", "hours": 12.0342, "text": "WOW SO MUCH STUFF (look at the pics!!!)"}]...
|
Title: Immortal Cultivation Mod (修仙) by @m3e660 | Title: Immortal Cultivation Mod (修仙) by @m3e660 | Stardance
Devlogs:
WOW SO MUCH STUFF (look at the pics!!!)
Look at what your boy cooked up in the lab!!!
Added lightning effect for lingbeng Remade ZhenshanPalmEntity Added a passive spell 威压 Change the stats (Hp, Qi, Age, and Progress) Change spell’s cost and damage Added command to modified players stats Removed stat cap Fixed loot tables Added 轮回真决 Added 定身咒 Added 引雷诀 Added 五雷正法 Added 御风诀 Added 吞天魔功
See the toggle spells list that you toggled In spell selection screen you can press the spell to see description Remake spiritual roots Remade ui
Custom combo system (Where you can make your own custom combo system) Add a zhuji level entity (with its own ai) zhuji1 logic when qi low and enemy 15 blocks away use qi gathering when hp low use regeneration when enemy 10 blocks away use fireball when enemy 5 or lower blocks away use lingbeng and punch them, if qi and hp are all 75 percent or higher then can choose to use lingbeng more time before punch when hp low use wind step to run away when enemy 11 block or higher away and hp high, use wind step to chase the enemy Add a jindan level entity (with its own ai) jidan1 logic same spells as zhuji1 but no lingbeng add a zhenshanplam spell inject qi into weapons keybind v to inject qi into any weapons including modded ones cost 1% of max qi after the injecting the amount of qi injected is add to the tooltip of the weapon amount of qi / 10 = the dmg dealt when attack with this weapon after attack use up amount of qi / 10 of the qi in the weapon base dmg of the weapon x 100 = x(the extra qi / 100 ) x 10 = y if the amount of qi in a weapon is bigger then x then weapon -y durability every sec until not overflow Added shield bar at the right of the hotbar Added 护体气 Added 迷尘障 Added 四方界 Added 固石盾 Added tomb1 structure Added ruined_ritual structure
There was more than 4 pictures in the post below so here is the others After use a spell one time +1 proficiency Spell proficiency 入门:after learning the spell get to this level 小成:100 need to get to this level 大成: 500 need to get to this level 圆满:1000 need to get to this level 登峰造极:10000 need to get to this level
Added shield bar at the right of the hotbar Added 护体气 Added 迷尘障 Added 四方界 Added 固石盾 Added tomb1 structure Added ruined_ritual structure When real death occur spawn a corpse of the player containing all the data of the past player Added attribute 怨气 to all zombie and corpse The longer they exist in the world higher the 怨气 attribute (1000 tick is one 怨气) When right click a zombie with a 镇尸符 stop them from moving When right click a corpse the corpse will stand up with the arm straight up like a zombie add exact 镇尸符 sprite on the corpse face and the corpse stop moving Right click them with a empty hand to take the 镇尸符 off 镇魂铃 when right click will heal 5% of the max hp of your zombie a 5 block radius cooldown 2 seconds 引魂锣 when holding will have a red point only visible to the player and when right click on a block your zombie will jump to that block and if punch a entity the zombie will attack the entity The range of the red particle laser is based on the player’s block reach Added 控尸术 Types of zombie and corpse 怨气 = 100; 白僵 怨气 = 500; 黑僵 怨气 = 2,500; 跳僵 怨气 = 12,500; 飞僵 怨气 = 62,500; 游尸 怨气 = 312,500; 伏尸 怨气 = 1,562,500; 不化骨 怨气 = 7,812,500; 旱魃 When right clicking a zombie with blood they can drink it and give +1 怨气 After getting to 1000 怨气 cant consume anymore Shift right click to feed all of blood in the hand Different modes for zombies attack all hostile (in 5 block radius) defensive (attack all mob that attack owner) Added coffin item, shift right click to store a zombie Added 道服 Added a 血晶, crafted by 9 blood, can feed to all zombie and corpse in all levels, each one is +5 Added Curios slots hair, hair accessory, head accessory, neck accessory, inner clothes, cloak, back accessory, waist accessory Moved coffin to back accessory support, including Curios rendering Added blindfold, blindfold2, straw hat, jade pendant, zhenhun bell, and yinhun gong as wearable accessories Added inventory sprites for accessories and fixed missing textures/positioning Made waist tools cycle with V while held/equipped Added jade pendant meditation speed bonus and tooltip Added 道服 chestplate and worked through texture/model binding fixes Added 血晶 from 9 blood, with zombie/corpse feeding support Added custom spawn egg textures where needed Added/updated English and Chinese translations for missing content Added Jindan dimension entry from stat menu Added 金丹 entity in the Jindan world and normal-world player clone Added Jindan breakthrough screen Added particle effects during breakthrough Added shift-right-click 金丹 entity to spend qi and replicate overworld chunks into the Jindan world Reworked spell selection GUI Added spell wheel ordering and remembered toggles Added selected-spell + R cast flow with charging bar Added/updated several spell scaling effects and combo casting behavior Added flying sword weapon/entity logic Added release, recall, control, shoot, ride, and pickup behavior Added qi cost for controlling/shooting Added flying sword FX when shooting Added zombie/corpse grudge progression and ranks Added higher-rank zombie effects like 尸毒, flying, 阴气 area, drought/dry area Added 鼎 forging GUI with temperature bar, material slots, 玉简 slot, result slot, progress bar, and start button Added forging recipes through 玉简, including 飞剑玉简 and 精铁刀玉简 Added mold items: 剑胚, 刀胚, 枪胚, 武器胚 Added weapon materials Added material purity system and tooltip display Added forging temperature/quality logic, average temp/purity tracking, and failure still producing a mold Added tempering by dropping mold into water, with smoke particles Added 灵火 support from Ignite Flare and normal fire support Added blockgen fixes and custom geo block rendering fixes Added forging system: 玉简, materials, temperature GUI, molds, quality/purity/tooltips Added new crops/items like 糯米 seed/plant, 糯米粥, 墨斗线, 桃木剑, 铜钱剑
New NPC Update The NPC system has been expanded into a full cultivation-style character system. NPCs now have random names, gender, identity, cultivation realm, attributes, spiritual roots, methods, spells, personality, inventory, relationship values, and persistent memory-style data. NPCs can now behave differently depending on personality, identity and relationship with the player. They can fight, flee, use spells, heal, trade, give quests, spar, and interact through a new dialogue screen. (PS the gui shown in the pic is only temporay) Major additions include: Talk, Interact, Trade, Quest, Teach/Learn, Inventory, About, Spar, Invite to Sect, Master/Disciple, and Dao Companion. Relationship stats: friendship, trust, affection, hatred Social actions like praise, joke, insult, threaten, and gifting NPCs can follow, stay, join sects, become master/disciple, or become Dao Companion if requirements are met. New NPC identities were added, with identity-based starting items and loot: 散修 剑修 刀修 魔修 器修 尸修 世家子弟 皇族 通缉犯 体修
Devlog #9 Ok so after some ratings and feedbacks I have decided to write better devlogs with more explaining and thoughts. Update: NPC I was working on npc on the last update and decided to further more finish this feature with adding a nice feature of … IDENTITY All Npc will all spawn with a random identity 散修 - Rogue Cultivator 剑修 - Sword Cultivator 刀修 - Saber Cultivator 魔修 - Demonic Cultivator 器修 - Artifact Cultivator 尸修 - Corpse Cultivator 世家子弟 - Noble Clan Disciple 皇族 - Royalty 通缉犯 - Wanted Criminal 体修 - Body Cultivator (Yes I actually added translation for chinese things now) This identity feature not only completes the Npc’s personality but for each identity they have there own special items (which really helps my mod’s survivability, adding a way to obtain items now) They also have their own personal dialogue based on their identity. Jindan Added a new breakthrough screen for zhuji to jindan, and a new dimension for your own personal jindan (like a new world you can channel 2000 qi in the center and you can build chunks in your own world) (see pics) Plans: I was going to further improve the Npcs but after adding a hole a lot of new items for each identity, I realized that I have a other system and features I didnt make (pill making system and more higher level spells)
Devlog #10 Ok so I have work on more than what is showed in the video but this feature is very big so the smaller thing can be talked about in the later devlog Restriction Enchantment Thingy Update 禁制 replaces normal enchantment levels for weapons and artifacts. Every artifact can contain multiple Restriction Layers: 1重禁制 2重禁制 3重禁制 …… 36重禁制 72重禁制 Each successfully engraved layer improves the weapon. Higher layers become progressively harder, more expensive, and more dangerous to refine. After reaching 72重禁制, the weapon can evolve into the next level Rules Controls Click a row to select its node. Click to the left or right of the bead, or use the < and > buttons, to move it. Use W/S or the Up/Down Arrow keys to change the selected node. Use A/D or the Left/Right Arrow keys to move the selected bead. Each bead has a Qi value ranging from 0 to 6 . The golden diamond shows the target value. When every node matches its target value at the same time, the formation is completed and all selected Restrictions are engraved onto the artifact. Moving one bead may also affect linked nodes. Nodes Types Normal Node A standard node that can be moved directly. The node turns gold when its value matches its target. Forward Golden Formation Line Linked beads move in the same direction. For example, moving one bead to the right also moves the connected bead to the right. Reversed Cyan Formation Line A cyan formation line marked with a “−” symbol. Linked beads move in opposite directions. For example, moving one bead to the right moves the connected bead to the left. Locked Node A gray node that cannot be moved directly. The player must move connected nodes to push it into the correct position. Locked nodes begin appearing from a total of 46 Restriction layers . Unstable Node A pulsating red-jade bead. It moves automatically after its displayed action interval and may also affect linked nodes. Unstable nodes begin appearing from Restriction layer 55 . Hidden Node Its target value is displayed as “?” The player must determine the correct target by observing the formation’s behavior or by using a hint. Hidden targets and move limits begin appearing from Restriction layer 73 .
Devlog #11 Sorry for the quality of the video, the quality had to be sacrifice for the length I have formed a habit of writing random thoughts I had, so here is more: wow I kinda hate the 10 hours devlog maybe it is because I am working on a big update orrrr I am just too lazy Revamp Update (plus other stuff (it is more of a random update)): More quest for all of the identity Giving a use for the jindan quality Added 烬火心燎 (mental attack kinda) Added 碎轨星陨 (big boom) Added 洞天借灵 (restore alot of qi) Added 时序迟流 (time slow zone) Added a soul system (when npc or player die there are a soul) Added 炼神术 (increase thoughts stat) Added DunWu Stele (can be used to crave spells into it so for spells like 炼神术 that have no spell item you can learn it like this) Added 噬魂幡 (cool stuff too much so just watch the video) Added 怨魂瓶 (used to store soul) New identity 邪修 功法 improvement (when use qi there is new particle effects) Etc (gui update and others) Config There is a new config button: Auto inject qi into weapon Outside qi (when in new battle system when swing your weapon it shoot out qi slash breaking blocks and killing enemies) New battle system Jindan creative flight New Puzzle Update 灵枢算盘 (the minigame to crave 禁制) it is use to upgrade weapons and eventually evolving it 灵脉六角阵 (the minigame that the player encounters when breaking through jindan) 灵气轨迹 (the minigame when learning spells) 雷劫 (Heavenly Tribulation for jindan) Strike 1 — A thin white-blue bolt 50 dmg Strike 2 — Two branching bolts 100 dmg Strike 3 — Three quick lightning 50 each hit Strike 4 — A thicker blue-white bolt 100 and take 30 dmg per sec for 5 sec Strike 5 — Lightning strikes the ground in eight positions around the player 300 dmg Strike 6 — Several smaller bolts repeatedly strike the player for three seconds 30 each Strike 7 — A massive branching bolt 400 dmg Strike 8 — Purple heavenly lightning 50 dmg per sec for 5 sec Strike 9 — Four bolts strike the north, south, east, and west sides of the player, followed by one direct central strike 400 dmg Strike 10 — A continuous pillar of lightning 100 per 3 sec Strike 11 — Golden lightning begins appearing inside the storm, six golden-white bolts rapidly strike around and directly onto the player 80 each Strike 12 — A giant bolt splits into twelve branches before all branches converge on the player’s position 300 dmg Strike 13 — Lightning repeatedly strikes the player 50 each Strike 14 — A ring of lightning forms in the clouds and releases a rain of dozens of smaller lightning bolts 50 per 3 sec Strike 15 — Nine rapid strikes hit the player in succession 2/4/8/16/32/64/128/256/512 Strike 16 — Every lightning arc inside the clouds gathers into one enormous golden-white tribulation bolt 1000 dmg Easy Mode Acheivement “You Are Really Bad” Get this when you die 10 times in 20 mins Get a hat curio called “Noob Hat” All puzzle are easier by a level
Devlog #12 A bit in a rush so no video this time, but i added pics so it should be fine. Battle System 战斗状态/Battle Mode: activates when hitting something, or dmg from players, cultivators, or mobs counts too, normally lasts 15 seconds Manual mode: press Y to lock combat mode on until pressed again it can be disabled in settings Normal attacks (left click just normal attack) Heavy attacks (hold attack for 0.5 seconds, then release, normal heavy attacks deal 120% weapon dmg) Blocking (hold left and right click together you dont take dmg, but the weapon loses durability and the blocked dmg harms posture) 架势/Posture: maximum posture is 100 + Physical Attack × 100 + Max HP ÷ 2. It regenerates by 1% each second 破势/Zero Posture: at zero posture, the player is stunned for 1.5 seconds, cannot block, takes 25% more dmg, and loses their current spell charge 外放灵气/External qi: qi injected weapons can release long, straight qi slashes, with the dmg, width, and range scaling with injected qi amount Recent Weapons 精铁枪: A 14 dmg spear normal attacks is like normal, while heavy attacks use a thrust animation and forms a qi cone shaped thingy 铁骨扇: Shift right click switches forms: closed form deals 3 dmg and uses a cone heavy attack and open form deals 5 dmg and uses slash attacks 拂尘: Deals 7 dmg normal attacks is normal too, but its heavy attack spins five times in front of the player, damaging everything within 3 blocks. Right click binds a physically weaker target within 5 blocks for 3 seconds, with a 10 second cooldown 飞刀: Deals 4 dmg and you can stack 5 more all together into one. Right click throws normally and heavy attacks throw a faster knife that can break five blocks before exploding. 飞针 and 袖箭: 飞针 deals 4 dmg, has 1,000 durability, and consumes 10 durability per shot. 袖箭 can be held or equipped in a back accessory slot. Normal attacks fire ordinary needles but heavy attacks fire qi powered explosive needles Etc Added more English Remake some gui Remake some models
Devlog #13 Oops, I got the 8 hours warning and I forgot about it and not I have 12 hours…. sigh. So this update I mainly update the magic ritual mod I have before, and before you ask yes this is the right project, I merge the magic ritual mod with this mod and then revamped the whole thing. This devlog is kinda short because I am getting lazy. Magic Ritual Combo system The Ritual Dagger is your primary tool for creating and managing magic rituals. Right-click with the dagger to open the Magic Circle Selection screen, where you can choose a magic circle type to place at your feet. Shift + Right-click to open the Radius Selection screen, where you can place a Magic Center Block with a chosen radius Attack Red - Grants Strength I Defense Blue - Grants Resistance I Regeneration Green - Grants Regeneration I There are certain pattern for special effect after putting it in its pattern you can punch the center with the dagger and the new magic center is formed Combo visuals and glyph behavior Basic center have one image pattern Combo center have two image pattern If glyph mode is turned off, there is an entering animation
Devlog #13 Sooo, did a few entities and most important zhenpan and flags for the magic circle. Zhenpan When empty shift right click to store a magic center When full shift right click to place a magic center back down When store magic center the radius of the magic center is changed to 5 if higher When right click summon a temp magic center of the radius 5 that appear for 20 sec The cost is calculated based on the spirit stones in inventory first then player’s qi Flags Now in the magic center there is a new tab with a gui (in the pics) where you can put flags, they modified the effect of your magic circle. But each newly added flag will increase the cost of the magic center by 1.3x, so the cost can reach to 2693457 qi when using a maxed out zhenpan. Formation Flag Effects Blank Formation Flag — No active effect, used to forge specialized flags Duration Flag — Adds 3 seconds to a temporary Magic Center’s lifetime per flag Amplifier Flag — Adds 1 extra attack whenever an formation triggers Spirit Gathering Flag — Reduces formation fuel/energy consumption by 25% per flag, it does not add the normal ×1.5 flag cost Swift Formation Flag — Makes normal formation effects trigger 30% faster per flag and increases fuel consumption by 30% Qi Return Flag — Restores 10 Qi per flag when a player kills an enemy inside the formation
Devlog #14 Hmmm why does the picture devlog get more view than the videos, let this be a test then Added: Tutorial System Qi Sensing Thingy Remake Spatial Pouch and like 20 new spells and 4 new method Remake Spatial Pouch Replace the whole backpack like spatial pouch system to a pocket like dimension (in the in the picture) you can place all functionable block and still use it by left clicking it and double click to remove it. (oh and redstone work :) i know there is people that can do smth op with redstone) Tutorial System Full tutorial system that guide you through everything, because so much people said there is a big learning curve, so boom :) Qi Sensing Thingy You can sense entities, items and qi ahhhhh there is not too much stuff or maybe i am too lazy…. definitely not that trust
Devlog #15 Uhm a lot of update and unfinished things so it is more of a sneak peek so, there not going to be a long devlog, maybe i am just lazy :). Cosmic Void New dimension that is like space use for mostly travel and battles Talismans A lot I added a lot but it is for later show you guys some pics tho
Devlog #16 Did some structures, and there is the talisman data like I said Talismans Tier 1 清尘符 — Dust-Cleansing: Extinguishes fire and removes blindness and darkness 微光符 — Dim-Light: Creates light ball for 2–3 minutes, hold while aiming at a block to anchor it, you can use water extinguishes it 敛声符 — Sound-Gathering: For 25 seconds, nearby mobs lose you as their target when more than 2.5 blocks away 火球符 — Fireball: Fires 8 fireballs. Each deals 10 damage in a 2.4 block explosion 风刃符 — Wind-Blade: Fires 3 wind blades dealing 11 damage each and pushing targets backward Tier 2 星火符 — Sparkfire: Fires 5 flames dealing 30 damage each and igniting for 4 seconds 薄金护符 — Thin-Gold Protection: Give shield worth 200 + 1% maximum HP for 15 seconds 缠丝困符 — Spirit-Silk Binding: Fires 6 strands dealing 1 damage each. Strands stack slowness for 5 seconds and 4+ strands nearly immobilize the target 短途神行符 — Short-Journey Divine-Step: Give speed VIII and jump boost III for 30 seconds 传音符 — Voice-Transmission: Sends a written message to another player with in 100 blocks in the same dimension 修复符 — Repair: Repairs the damaged item held in the opposite hand Tier 3 避邪安魂符 — Evil-Warding Soul-Calming: Evil ward for 5 minutes, clears and prevents darkness/nausea, and restores 1% maximum Thoughts each second for 3 minutes 镇扰符 — Disturbance-Suppressing: Hostile mobs within a certain range get slowness II 爆风符 — Blast-Wind: Produces a blast dealing 50 damage, applying daze, and deflecting projectiles 火狱焚邪符 — Evil-Burning Fire-Prison: Creates a 10-block explosion, deals 50 area damage 五雷小伐符 — Lesser Five-Thunder: Deals 40 damage and give slowness III for 1.75 seconds 标记符 — Marking: Permanently marks a entity up to 300 blocks away for owner,and marked mobs are also prevented from naturally despawning 遁空符 — Void-Escape: Teleports in the direction you are looking, normally up to 20 blocks. Repeated uses within 5 seconds lower the maximum to 17, 14, then 12 blocks 化兵符 — Weapon-Manifestation: Creates an owner only temporary sword lasting 25 seconds Tier 4 金光护体符 — Golden-Light Body Protection: Adds a shield worth 600 + 1% maximum HP for 25 seconds 封灵符 — Spirit-Sealing: Seals everyone’s qi within 3 blocks of impact, interrupts casting 破障开山符 — Barrier-Breaking Mountain-Opening: Creates a massive 20-block explosion dealing 500 area damage Tier 5 千里传讯符 — Thousand-Li Message: Long range version of the Voice Transmission Talisman, but it is 1,000 blocks in the same dimension Tier 6 玄焰焚界符 — World-Scorching Black Flame: Creates a black-flame domain that grows from a 5 block radius and deals 100 damage per second. It destroys terrain, consumes dropped items and projectiles, and grows by consuming matter and victims, potentially reaching 48 blocks 五岳辟厄符 — Five-Mountains Calamity-Warding: Grants luck for 10 minutes and stacks three times: +15, then +7, then +3 Ancient 禁空符 — Forbidden-Air: Places a field 24-block radius lasts 8 seconds. It suppresses jumping and flight, and pulls flyingentities downward
Devlog #17 MORE STRUCTURES i got into the phase of building so more structres!
Devlog #18 Working on flying boat or valkyrie skies like things, I dont think that is copyright as it is not the main part of my mod, if it is tell me in the comments thanks Flying Boats Four core tiers control maximum capture size: Low: 100×100×100 Medium: 200×200×200 High: 400×400×400 Sect: 800×800×800 Existing ships can still be minimized into an item and placed again later The lingzhou core GUI is where you manage the ship. It shows the ship’s status, tier, size, fuel/灵气, current pilot, permissions, settings, movement mode, anchor controls, shutdown, and storage Fuel use is based on how many blocks the ship actually has and what it is doing. Hovering uses fuel, while an anchored ship does not The ship helm is used to pilot the lingzhou. While controlling it, the mouse wheel can be used to change the ship’s speed Autopilot lets you enter destination coordinates and have the ship travel toward them automatically Players and other entities move together with the ship. You can walk around the deck, jump, climb stairs, and move around normally while the ship is flying If part of the ship gets disconnected, that section is no longer supported by the lingzhou and falls back into the world as normal blocks Turning off the lingzhou core removes the ship’s magical lift. The ship keeps whatever momentum it already had and begins falling under gravity Etc Fix system prices Fix textures Fix names of items Added JEI compatibility for 鼎 forging Added recipes for a lot of weapons Removed combo system Added a fox beast
Devlog #19 Some mobs, yea that is really it
Devlog #20 School is starting and college stuff is like piling on so my brain is slowing down, so there isnt much stuff i did when you compare it to the hours in this devlog. Mirror Thingy It is like a shield can absorb some dmg Straw Doll Like a totem of undying Jei Compatibility You can see the forging recipes in Jei now!
Devlog #21 Added whip physics Added new item mechinacs Added straw doll Added a luck system
Devlog #22 Not much like I said school started, it was more planning and stuff, revised npc battle logic
Devlog #23 REVISE MOSTLY OF THE VFX AND ADD ALOTTTTT OF DRIP
Devlog #24 121 NEW SPELL ICONSSS MY SOULLLSLLSLSLLS I pick the best 20 icon i love
Devlog #25 Add a lot of new weapons A lot of new fire And more clothes
Devlog #26 I going to improve the overall survivability of the mod: So there is going to be like more guides book in coming And more item that were creative only now actually getting ways to get the items
Devlog #27 Improve overall guidance and improve existing model
Devlog #28 Added 8 guide books for different part of the mod Added new bear model
Devlog #29 Remake all the magic circle texture and automated it (tool here https://m3e66.github.io/xiuxian-circle-generator/ ) Optimize all the code Added new body types 赤炎灵体 — Crimson Flame Body +25% fire damage; burning enemies take 10% extra damage from you 玄冰灵体 — Profound Ice Body +25% ice damage; attacks build Frost, briefly freezing enemies after 5 stacks 紫霄雷体 — Violet Thunder Body +25% lightning damage; every fifth lightning attack summons an extra thunderbolt dealing 50% damage 青木长生体 — Evergreen Longevity Body +15% maximum HP; +25% natural HP regeneration; +10% healing effectiveness 厚土玄体 — Profound Earth Body +20% armor; standing still for 3s grants an additional 10% damage reduction until moving 庚金剑体 — Geng Metal Sword Body +20% sword damage; +10% sword attack speed; sword strikes ignore 10% armor 沧海灵体 — Vast Sea Body +20% water damage; +20% maximum Qi; water spells cost 15% less Qi 逐风灵体 — Windchaser Body +20% movement speed; +15% attack speed; dodging grants +10% damage for 3s 先天道体 — Innate Dao Body +15% cultivation gain; all spells cost 10% less Qi; +5% all elemental damage 无垢灵体 — Immaculate Spirit Body +30% negative-effect resistance; debuffs last 25% less time; +15% healing received 九窍玲珑体 — Nine-Orifice Exquisite Body +25% Qi regeneration; +10% maximum Qi; spell cooldowns reduced by 10% 万毒之体 — Myriad Poison Body Immune to poison; poison attacks deal +25% damage; poisoned enemies restore 1% max Qi when killed 血煞魔体 — Blood Fiend Body +20% melee damage; heal for 5% of melee damage dealt; healing from pills reduced by 20% 不灭金身 — Imperishable Golden Body +15% maximum HP; +15% damage reduction; when HP falls below 20%, gain 30% damage reduction for 5s 吞灵之体 — Spirit-Devouring Body Killing an enemy restores 5% max Qi; attacks against shields and Qi barriers deal +20% damage 荒古圣体 — Ancient Desolate Sacred Body +25% maximum HP; +20% physical damage; +15% armor; Qi regeneration reduced by 15% 太阴神体 — Supreme Yin Divine Body +30% dark and ice damage; +20% Qi regeneration at night; sunlight reduces Qi regeneration by 15% 太阳神体 — Solar Divine Body +30% fire and light damage; immune to burning; +20% HP regeneration in sunlight
Devlog #30 Remaking the whole life sim system adding new event (making them actually have somewhat of a story) added new battle system and more small thing to better help the experience And ton of bugs
Devlog #31 Added BLAST QI, where you can BLAST YOUR QI in your enemies face and be cool And fix the flying sword thing And fix a whole a lot of fix
Devlog #32 Added new effect in domain like abilities: Lilies, ice, big space warp (don’t yell at this devlog, I wrote it on the phone)
Devlog #33** A shentong ability:湮灭未尽之人 and a dummy for testing purposes A lot of bug fixing and small thing like better formatting of the gui etc
Ships:
Getting Started The first steps of cultivation. Enlightenment Pill Use an Enlightenment Pill to step from mortal life into Qi Refining. The stat menu shows qi, realm, max health, max age, luck, moral, soul, thoughts, spirit roots, and cultivation progress. Spells Fireball (Lianqi Early, Fire, 10 Qi) Shoots a fireball that deals damage and ignites targets. Lingbeng (Lianqi Late, Thunder, 50 Qi) Enter a breaking-force state. Punch a block or entity to release an explosion. Recasting stacks the explosion radius. Regeneration (Lianqi Middle, Wood, 20 Qi) Restores health with a short healing effect. Beam (Lianqi Early, Light, 30 Qi) Allows you to sense nearby entities. Earth Escape (Lianqi Late, Earth) Sink underground. Move faster while underground. Consumes Qi over time until you surface. Cleanse (Lianqi Early, Water, 10 Qi) Removes harmful effects from yourself. Qi Gathering (Lianqi Early, Wind, 0 Qi) Greatly increases Qi regeneration. You cannot attack or block while active. Damage taken is tripled. Ignite Flare (Lianqi Early, Fire, 10 Qi) Fires a straight flare. Ignites the block it hits. Spirit Sight (Lianqi Early, Light, 5 Qi/sec) Grants night vision while active. Zhenshan Palm (Foundation Establishment Middle, Earth, 130 Qi) Releases a giant hand-shaped earth wave for 3 seconds. Destroys blocks touched by the palm. Light Ball (Foundation Establishment Late, Light, 30 Qi summon, 10 Qi per shot) Summons 6 light balls in a hexagon behind you. Can stack up to 3 rings. Punch to fire one ball. Shift-punch to fire all balls. Each shot deals 50 damage. Each shot can break through up to 24 blocks.
This update adds a huge amount of new content! You can now explore newly added structures, use new spells, control and evolve zombies through the new 怨气 and 控尸 systems, and wear new design accessories. The 金丹 system has also been remade with its own pocket dimension, breakthrough system, and new mechanics. Spell casting has been reworked, flying swords are now fully usable, and a complete forging system lets you craft weapons using materials, molds, purity, and temperature. There are also plenty of new items, crops, effects, and fixes to improve the overall experience!
I want my VR ahaahahahahah plssss Nothing much to say here just look at the images and video in the previous logs
I WANT MY POLAROID GO GEN 3 PLSSSSS I AM JUST A TINY BIT AWAY...
|
1792817797.0497022
|
1792904197.0497022
|
|
5003
|
Browse++ by @kallenseelo | Stardance
|
kallenseelo
|
1
|
165.0
|
3160
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-29T03:43:00Z", "hours": 165.0, "multiplier": 19.1, "payout": 3160, "blessing": "neutral", "text": "Browse++ A C++ Browser Engine from Scratch. Overview: Over the course of 2 months and almost 300 hours (165 coding) of work, I built a browser engine that can download, parse, and render websites with tab handling and a lot of other cool features, from almost complete scratch! What’s a Browser Engine? A basic definition of a browser engine is a program that pulls content from a website, then takes that content, gives the elements the properties assigned in the CSS, and then renders the content on the screen. They end up being very difficult to build, as HTML and CSS can run and be run without errors, so that makes it super hard to build an engine that can properly handle, parse, and render a site with a lot of errors. How to use this? If you would like to use my browser engine, there is quite a few ways to do so! NOTE: I do not have an actual Linux laptop, so the Linux version is super buggy (and does not have any networking), but I really hope to fix that in the future, but you can use the more outdated web demo! If you don’t want to download anything, you can use the Web Demo , its a bit behind, but it shows it nicely. If you are willing to download, and you are on windows , you can go to the github here and download to try it! If you want to see the real thing, I have a video going through it here. What am I most proud of? I think the thing I’m most proud of was the amount of browser systems i was able to build from scratch , this was a super fun thing to build, but it had a lot of challenges and ups and down, and a lot of hours fixing bugs that make no sense at all lol! The other thing I’m most proud of is not using any AI on the main engine; there was a bit of AI used for the web demo, as that wasn’t my main focus, but the browser engine overall used absolutely no AI! AI usage GLM 5.2 was used to convert the Windows code to a web server for Linux (way before I supported Linux). Any code changes are clearly marked with ( // CHANGED WITH AI: ... ) if they have been changed with AI, and very little has been changed.", "repo": "https://github.com/k754a/C-Plus-Plus-Web-Engine", "demo": "https://k754a.hackclub.app/"}]...
|
[{"post_id": 56948, "ts": "202 [{"post_id": 56948, "ts": "2026-08-28T23:53:05Z", "hours": 4.8833, "text": "Final work on the readme, getting a standalone windows build! Over the last few days, I’ve been hard at work getting the readme finished up, it was super tedious but now its in a good spot for a ship, and looks awesome! I’ve also gotten the windows build to be standalone! this took a lot of googling, but now with CMake, it now can run on anyone’s computer, without needing anything else!! Other than that, its been a bit of work on the Linux side, i attempted to get some sort of https working, but because its a vm, its super screwy, and i hope to be able to have a computer that has Linux on it for use, but we will see ig. Also made a YT vid https://www.youtube.com/watch?v=I-mCh9xSYeg&t=8s Overall a good day!"}, {"post_id": 54642, "ts": "2026-08-25T17:49:57Z", "hours": 4.9522, "text": "Linux support!!! Over the last few days, I’ve been working on migrating the project from MSBuild to CMake, allowing it to run on both Linux and macOS (though I haven’t been able to test it lol). Linux has been tested, however, and everything works on it (except I haven’t migrated the networking, so that’s still to do!!), so there are still some things that need to be done, but it boots on my Debian VM and renders! So I’m super happy for that. Some other changes were that I got autocompletion (you’ll see it in a sec) as well as getting the open in a new tab working a bit better for both Windows and Linux!! Overall a good day!"}, {"post_id": 52150, "ts": "2026-08-22T07:40:12Z", "hours": 6.0289, "text": "Updated context menu, Desktop Logo, Hover effects, Rework of the input bar, and bug fixes! Ok, its like 1:30 am rn lol, so im going to try to do this fast. First, i updated the context menu, the menu now has a nice drop shadow, and looks so much nicer than before (lemme know what you think about it). second, i added a basic desktop logo (a grayish black circle) that changes based on light or dark mode (the vid shows it well). Another change was hover effects! now hovering over buttons changes the color slighly, making it a bit simpler to see that your over something, and aswell as being a bit more reactive! the input bar rework allows clicking onto the bar, rather than always typing on the bar (for ctr-F coming soon!). Finally, bug fixes, i had a lot of issues with having both custom x pos, and custom y pos, but thats all fixed now! aswell as the backgrounds not updating per tab (thats now fixed too!). Finally II, i worked on the readme a bit! Overall it was a good day (with over 10 hours of work lol), and i still have a few features to add! so yeah, thanks for reading! (as well as excuse the spelling mistakes, there might be a lot lol)"}, {"post_id": 51922, "ts": "2026-08-21T20:50:43Z", "hours": 6.1733, "text": "More HTML style options, browser history, and work on the Readme.md Ok, so over the last 6 hours this is what I worked on. First, I worked on adding more style options, so now you can set font size (another way) and set font boldness (like normal HTML), and you can now add custom number values to the vertical alignment (that in the vid is shown on the homepage!). I also worked on the browser history now, saving it to a txt file. You can scroll back through what you’ve searched before (and add a button to clear it next update).I also was working on the readme, making it clear and better before the ship. Overall a good day, and I think I’ll try to do the settings menu, aswell as support for buttons in the viewer (though they probably won’t do anything thanks to not having JavaScript), so yeah!"}, {"post_id": 51394, "ts": "2026-08-21T02:14:27Z", "hours": 5.9358, "text": "More text formatting and positioning. (and LOTS of bug fixing) Today was a great day of work; I got height adjusting working, and this took way longer than I thought, just with all the bugs and problems I ran into, with old code I had created, but I was able to solve it all. The other notable thing is having another way to color text and the bg of text, but also, I fixed it so that none of the text falls off the edge in the positioning, so overall a good day! I’m actually so close to being done; I’ve wanted to go to 200 hours, then kind of just chill and slow down, and I’m at 14 hours left of that! Then I’ll ship. But I do want to finish the history menu, though I may leave the settings menu on pause. (for now). So yeah!"}, {"post_id": 50790, "ts": "2026-08-20T05:38:54Z", "hours": 5.1342, "text": "HTML text-align handling, history tab, and settings. Ok, I’m going to be honest, I looked at that settings menu and genuinely did NOTHING. It’s going to be a pain, so I’m just avoiding it till I have no choice. Something HUGE, though, I’ve gotten working is getting proper styling so that text can render in the middle and right (with way more text-align and style options to come)! This really opens the door for much more dynamic rendering text, though there are still a few bugs with it (large text goes off screen, and the home screen doesn’t apply the settings), so there is still a lot to fix, but honestly, I didn’t even think it was possible, so this is awesome! Overall a good day; I’m going to continue working on history and styles and then the settings lol."}, {"post_id": 49986, "ts": "2026-08-19T00:38:26Z", "hours": 6.455, "text": "Add context menu and startup URL (and fixed a LOT of bugs)! Sorry it’s been like 2 weeks, but after finishing my other project, I’m back at it! Over the last 2 days, I worked a LOT on the context menu and bug fixes (like loading text files into the engine, and old ones I caught working on this!). The context menu changes its options based on what things you right-click (like a real context menu), so for example, when I click a link, I get way more different options than if I clicked a tab. This allows for a lot of customization, and it’s basically fully implemented (minus a few features I want to add). The startup URL is kind of a part of that; when clicking a link, you have the choice to open it in a new window, and getting a URL that can change on startup really made it easy to add the feature! So overall a good day. What I’m going to work on next is the settings menu. Thanks for reading!"}, {"post_id": 41749, "ts": "2026-08-06T04:16:16Z", "hours": 5.6256, "text": "Settings button, bug fixes, scroll bar drag, and a context menu! This update was just a crazy number of features! I ended up shifting around the top area to make room for a settings button (that I will deal with soon), then I decided to allow scroll bar drag so that you can scroll through a page with the bar, not just your wheel! The big thing was the context menu; this took the most time and was the most difficult, as it was just a pain to get 2 windows rendering, but now, it works super well! I also attempted to work on getting a better layout, but I just screwed a lot of stuff up lol, so that didn’t really work out, but that’s ok!"}, {"post_id": 39793, "ts": "2026-08-03T00:24:38Z", "hours": 3.6864, "text": "Done all comments and released 0.1.0 ! If you want to check out or support this project, you can click the GitHub link! https://github.com/k754a/C-Plus-Plus-Web-Engine I ended up going on a camping trip with the homies, so I didn’t work on this for a bit, but when I came back, I fixed a few more bugs, ended up finishing all the comments for GUI.cpp, and created release 0.1. 0! This is huge, as I was able to fix all known bugs and get a working version out! For version 1.0.0, I want to fully fix the layout engine to render close to a modern browser, add a settings page, fix performance, and add things like buttons and checkboxes on websites! Thanks for reading!"}, {"post_id": 35496, "ts": "2026-07-26T23:35:45Z", "hours": 3.4192, "text": "Quality of life improvements, more comments, and finally fixed the crashes If you want to check out or support this project, you can click the GitHub link! https://github.com/k754a/C-Plus-Plus-Web-Engine Ok, so first off, the huge crash I was getting was because of using a global variable for holding the link and not a local variable, and when 2 threads attempted to use it at the same time, my app would freeze and crash, so now it runs great! Some of the QofL improvements are adding keyboard shortcuts and the ability to close tabs by pressing the middle button down, like a real browser! Then there were a lot more comments that I am so close to being done! Overall a decent 2 days; I’m definitely getting a bit bored of the comments, so my plan is to work on my other project for a bit and come back later! But yeah, a good day. :)"}, {"post_id": 33882, "ts": "2026-07-24T04:53:53Z", "hours": 6.0147, "text": "Local file loading, better comments, and crash fixing! If you want to check out or support this project, you can click the GitHub link! https://github.com/k754a/C-Plus-Plus-Web-Engine Today, I worked a TON; I got through all the comments for the start and collision events for all the buttons and things in GUIRENDER . I also added some new features and fixed some huge bugs! The new feature is file loading! You can now load PNG, JPEG, HTML, TXT, and HTM files straight from the search bar! The main fix, and what took most of my time, was the prerender. as i was working on slimming the new tab create button down, i found a lot of strange bugs, esspicaly with webpages with large amounts of images (like stardance), this lead me down a lot of changes, overall, it was a issue with how i checked to see if i wanted to load it from disk, but it was also a bunch of stuff to do with multithreading, and locking parts, but after a lot of work, i fixed it! I still need to fix up and finish GUIRENDER , but once I’m done with that, it’s off to work on the settings page. Thanks for reading!"}, {"post_id": 33247, "ts": "2026-07-23T00:15:09Z", "hours": 5.6319, "text": "Halfway done rewriting Gui.cpp—Lots of bug fixes and speed improvements! If you want to check out or support this project, you can click the GitHub link! https://github.com/k754a/C-Plus-Plus-Web-Engine Over the last 2 days, I’ve rewritten about half of GUI.cpp (up to the GUIRENDER function), with changes, bug fixes, and speedups that helped the engine a lot! The main speedup came from changing the way I handled the font so that I loaded it once, not every loop. This allowed a lot less SSD usage and a gradual increase of performance, up to about 50% for large sites! I worked a lot on organization and got it so that different functions are grouped together, even moving some to different scripts that fit better! The final change was reworking how images and the home button worked, and it allowed me to drop a function, as well as have much faster image batch loading times! Going through the code made me realize how many bugs and bad code I did. I fixed a lot of it, but I still got a bit to go! Overall it was a good day. My plan for everything else is to finish the rest of GUI.cpp, start work on a settings page, and try to make the parser faster still! Thanks for reading!"}, {"post_id": 32062, "ts": "2026-07-20T23:17:12Z", "hours": 3.9422, "text": "Lots of bug fixes, quality-of-life changes, and the start of a rewrite! try it out! https://k754a.hackclub.app/ I’ve been still a bit busy, but over the last 2 days, I ended up fixing a lot of bugs with crashing, especially with dealing with multithreaded tab handling. Some of the quality-of-life changes I did were creating a new tab handle that allows you to go back to the new tab in history and other small changes! The biggest bug was where, if you searched something and, while it was loading, switched tabs, it would overwrite your tab to the one you switched to, not the original one you searched in. Now that is fully fixed! Overall a good day! I’m going to fully rewrite and comment all 2500+ lines of the GUI and other functions, fix a LOT of bugs, and then add settings, history, and a few other things! Thanks for reading!"}, {"post_id": 29965, "ts": "2026-07-17T05:38:51Z", "hours": 4.44, "text": "Dark mode and bug fixes (with more bugs) and HTTP error codes Today, I recorded most of my link and search handling to be better at handling URLs and links like /home. I also added a dark mode! (Super helpful on the eyes lol) Unfortunately there is a big bug, some websites will just not work anymore (like hackclub), and also websites take super long to load, this is because the images it is processing are in a buffer, and this buffer needs to finish the images of one page before the other, i think i have an idea to fix it, so I hope I will be able too soon! But overall, this update changed a lot of bugs, and I’m hoping it can be even better for the future!"}, {"post_id": 28606, "ts": "2026-07-14T23:12:44Z", "hours": 6.4553, "text": "Lots of optimization, better comments, and bug fixes! Sorry for not posting for a few days; I was super busy and didn’t really have the time. However, I’m back at it! Over the last week, I’ve been changing and updating lots of stuff. The first one was much better comments for the layout.cpp file! I still have a bit left to do, but I was getting pretty tired, so I moved onto making the engine a bit faster! One of the main things I did was use threading, passing the text off to the GPU rather than going from CPU to GPU, as well as multithreading it. This allows about 2 seconds faster search time, and I have some more ideas for changes too! The reason this took so long is the number of bugs I introduced. The Gui.cpp is huge (2000+ lines), so I want to really rewrite it, as there is SO much junk and bad coding practices lol. Overall though, it was a good day, and I think I want to start tackling JavaScript after adding a lot of QofL and fixes to a ton of bugs! Thanks for reading!"}, {"post_id": 23282, "ts": "2026-07-06T04:43:49Z", "hours": 3.3869, "text": "Performance analyzer and comments for our DOM! Today, I created a performance analyzer that could tell me how many microseconds it takes to get through certain programs. This helped a lot with optimization and making things faster! I also finished and optimized the DOM code! Today was a pretty basic day; I’m a bit busy over this coming week, so it’s going to be a bit more broken up, but overall a good day today!"}, {"post_id": 22558, "ts": "2026-07-05T02:28:53Z", "hours": 4.8858, "text": "Performance increases, and a rewrite of the parser! Today was a nice easy day; I rewrote most of the parser, fixing a lot of bugs, and also learned how to use the performance analyzer in C++! The code is much more documented, with every line describing what it’s doing, making it super easy to follow along! The main change was an increase in speed from about 5% CPU usage to 1% and a 50MB reduction in RAM usage, allowing for 10 tabs at once, with only 61MB overall, rather than the 1000MB of something like Chrome! as well as about a 6% faster parse and load time. There is still a lot to optimize and work on, so I’ll keep doing that!"}, {"post_id": 21750, "ts": "2026-07-03T20:49:12Z", "hours": 5.1881, "text": "The first part is rewritten! Today, I worked on rewriting my network code with better comments, names, and methods. This took a while, as I created so many bugs, but it does work! The long part is still yet to come; however, the main things like the parser and the GUI are going to be a headache, but I should get it done! Overall a good day; ~4 files have been changed, with 6 more to go! Then after this, i want to add a history button, a settings page, and just improve performance, and formatting, then I’m done!"}, {"post_id": 21182, "ts": "2026-07-03T00:10:54Z", "hours": 3.2625, "text": "Updated the web version to the latest! Ok, so the main thing i did today was update the web version, and got it to match the main version overall, with everything! I also tried to get better formatting on the text, but i think my code is just so muddled its gonna be impossible, so my plan is to start rewriting it, with the things I’ve learned, and updating the comments (as i have a lot of them, in many wrong spaces)! that should take a bit, but hopefully will pay off in the future! If you want to try the new version, its here: https://k754a.hackclub.app/"}, {"post_id": 20502, "ts": "2026-07-02T03:18:13Z", "hours": 4.0853, "text": "Scroll bar support, bookmarks, and printing sites! Today I got a lot done; the main things were getting scrollbars, bookmarks, and getting sites to print all working! I ended up running into a lot of bugs (especially with the scroll bar), but now it works, so yeah! Currently the browser portion is far behind, and I want to update it, so I’ll try doing that next! Overall today was a good day; I got a lot done and a lot working! Anyways, thanks for reading! Code / Project You can check out the code here: https://github.com/k754a/C-Plus-Plus-Web-Engine And try a older version of it: https://k754a.hackclub.app/ "}, {"post_id": 20310, "ts": "2026-07-01T21:33:17Z", "hours": 3.6294, "text": "New icons and more buttons! Today, I was able to get icons supported into the engine (kind of)! The way I did it was by using a font modifier. I loaded the font I’ve been using and created some custom icons! A lot of the challenge was fixing text, as the new icons had issues with scaling and position, especially the back and forth arrows! Overall it was a great day. I’ll work on getting the printer button and the star button working; then it’s on to improving the engine! (also added a home button!)"}, {"post_id": 19574, "ts": "2026-06-30T22:14:59Z", "hours": 3.1631, "text": "Got Flex and Absolute boxes working on the engine! This took a while, just with fixing all the bugs and the weird reasons why some things would just not work at all lol! It was definitely a learning process for sure, and it should be easier to add more support for everything else in the future! This has to be one of the most difficult projects I’ve ever worked on, but it’s coming along! I want to do something a bit more fun, so my plan is to start work on a UI overall, just to give myself a break from all the crazy stuff! Anyways, thanks for reading! (oh, websites look so much nicer, with the new stuff!)"}, {"post_id": 19420, "ts": "2026-06-30T18:56:13Z", "hours": 4.5111, "text": "Rebuild of the layout engine! Today, I rebuilt a bunch of the layout engine to start support for flexboxes and divs! I mainly switched the code to do 2 passes, first to figure out spacing, size, and position, then to place the elements on it! Overall, this was a kind of boring day; it works basically the exact same rn, so there’s really nothing to show, but I’ll send a screenshot or two of my code! Anyways, the plan next is to get flexboxes working! After that, I might rewrite my engine, as it’s getting a bit ugly and crowded, and I coded some stuff pretty badly the first time around; it probably would only take about 10 hours, working off my code, but I think it would save me time in the future, but I’ll see! Anyways, thanks for reading! Also, if you want to support the project, dropping a star on the GitHub would be awesome; no pressure, though. :) https://github.com/k754a/C-Plus-Plus-Web-Engine"}, {"post_id": 19020, "ts": "2026-06-30T05:52:42Z", "hours": 3.1311, "text": "Lots of bug fixing on the engine! & Making it to the news letter! First of all, I want to thank everyone who has liked, reposted, and checked out my project. I made it to the Stardance newsletter, and it was so awesome :). Thank you so much! Today, I fixed a crazy amount of bugs; the main one was I would have these empty boxes, and it took me a good hour and a half to figure it out, but now text renders so much nicer! The next bug I fixed was clicking links. Up until this point, clicking links did not work at ALL, so now they work! (super happy about that)! History now works for each tab, not just one pool! I’m also starting work on making a YT video for this project. I’ve never made one before, so we will see how it turns out. For tomorrow, I’m going to work on the formatting of the engine, as normal websites have text like how Stardance has the home, notifications, rate, missions, etc, on the side and the main text in the middle, so I’ll hopefully get that working! Anyways, thanks for reading! You can check out my project below. :) Code / Project You can check out the code here: https://github.com/k754a/C-Plus-Plus-Web-Engine And try a older version of it: https://k754a.hackclub.app/ "}, {"post_id": 16595, "ts": "2026-06-27T00:22:18Z", "hours": 5.3503, "text": "Images Working for the Browser Engine! I’m going to be honest with you, this has to be the top 10 worst things I’ve ever coded. 😭😭 But images now can load; there are a few bugs, most images don’t load, and the ones that do load in pairs of 2 have weird bounding boxes. However, they do work, and that’s what I’m happy about! I’m going to do a quick side project, just to have a bit of room so I don’t overdo it, but overall it was good. Next I’ll just fix the bugs and start getting like the formatting of texts to start matching websites! The vid below shows them in action."}, {"post_id": 16093, "ts": "2026-06-26T05:07:23Z", "hours": 3.3942, "text": "Rebuilt part of the browser engine to handle tabs! Today, I worked on getting tabs working! It wasn’t as bad as I thought; the worst part was making all the UI elements and handling the inputs for them! I also found a bug; the engine easily uses my entire CPU’s dedicated GPU and causes issues with other apps lol, but I’ll fix it in a bit! Overall it was just bug fixes, quality-of-life improvements, and tabs! Hopefully tomorrow I’ll do images, then I’m taking a break for a bit and doing something else because I’m burnt out, and that’s a tip for all of you too: don’t overwork yourselves! The vid below shows it in action. Thanks for reading! Also, if you want to support the project, dropping a star on the GitHub would be awesome; no pressure, though. :) https://github.com/k754a/C-Plus-Plus-Web-Engine"}, {"post_id": 15935, "ts": "2026-06-25T21:47:30Z", "hours": 3.0242, "text": "Back and forth arrows, reloading, better formatting, and searching on the browser! Today was huge; I was able to get better formatting for text, search for things, and get buttons like back and forth and reloading working! My next task to tackle is images! The vid below shows all of the changes in action! Thanks for reading!"}, {"post_id": 15459, "ts": "2026-06-25T04:13:52Z", "hours": 2.7303, "text": "Links, and better rendering! Today I got links, and rendering improved rendering! Words now render together, rather than making a new line each time. I also got links, and that allows you to browse something like Wikipedia (the video below) much easier! For next time, I’m going to get the back and forward arrow and reload a working website! And may start work on getting the browser to have divs! Thanks for reading!"}, {"post_id": 15204, "ts": "2026-06-24T18:29:06Z", "hours": 2.1114, "text": "Today, I got a bunch of colors working! The browser engine can now render different colored backgrounds, texts, and highlights! This actually wasn’t too bad, as the hardest part was just fixing all the bugs from CSS being such a bad language, but overall it turned out awesome!"}, {"post_id": 14842, "ts": "2026-06-24T03:19:32Z", "hours": 2.5572, "text": "Version 0.1.0 of the Browser Engine! If you don’t know what I’m building, I’m creating a custom browser engine in C++ from scratch, something like Chromium, but a lot more bare bones. Today, I did a bunch of things. I got my first CSS attributes to detect and work! Text now is not hardcoded and dynamically scales based on the CSS! This really wasn’t too hard, so I moved on to the next thing, getting a working UI! The UI I’ve created is basic, but it allows you to search without using the terminal and search multiple things! Overall this was an awesome day for today; my plan over the coming days is to support more CSS and work on fixing performance and overflow bugs! Thanks for reading. :) Code / Project You can check out the code here: https://github.com/k754a/C-Plus-Plus-Web-Engine And try a older version of it: https://k754a.hackclub.app/ The video shows the standalone app, and searching 2 different sites."}, {"post_id": 14688, "ts": "2026-06-23T21:39:00Z", "hours": 3.2131, "text": "CSS Parsing! I got CSS working! I was able to get my CSS parser working on the engine and parse properly. This wasn’t as easy as I thought, as my first attempt worked but was dreadfully slow (10+ seconds), so a lot of the time went into rewrites and optimizations, bringing it from 10+ to about 2 seconds for huge CSS (1000+ lines of CSS)! Code / Project You can check out the code here: https://github.com/k754a/C-Plus-Plus-Web-Engine And try a older version of it: https://k754a.hackclub.app/ Video below shows it loading the hackclub website!"}, {"post_id": 13373, "ts": "2026-06-21T22:06:37Z", "hours": 2.1894, "text": "The browser now has a GUI! This took a bit and a few tutorials, but now you’re able to browse the web with no styles, one font, and just things like headers, but for now this is super awesome! I’ve been going pretty hard at it the last few days, and I lowkey need a break, or else I’m gonna get super burnt out, so I might just start a side project for the fun of it, something easy when I’m feeling a bit sluggish. When I come back, I’ll work on adding a UI around the browser (to get fully away from the terminal), and then it’s just getting CSS parsed and working, which isn’t too bad at all. You can check out the code and try the project below. C++ Browser Engine You can try it online! : https://k754a.hackclub.app/ Source code: https://github.com/k754a/C-Plus-Plus-Web-Engine"}, {"post_id": 12960, "ts": "2026-06-21T06:40:22Z", "hours": 1.6656, "text": "C++ Browser Engine You can try it online! : https://k754a.hackclub.app/ Source code: https://github.com/k754a/C-Plus-Plus-Web-Engine Got started work on the GUI using SDL3! Today, I worked on getting a GUI up and running; for now it’s just a window, but I’ll get it working! I also started work on a logo, as I felt a bit burnt out during today, but nothing really came of it, as all my designs I tried sucked; the best one I linked below. I also created the first readme!"}, {"post_id": 12643, "ts": "2026-06-20T17:28:53Z", "hours": 0.7358, "text": "This is a super short devlog, I updated the server so that it uses my latest code, and supports HTTPS! you can try it out with the link below. https://k754a.hackclub.app/"}, {"post_id": 12395, "ts": "2026-06-20T07:09:43Z", "hours": 2.2253, "text": "C++ Browser Engine You can try it online! : https://k754a.hackclub.app/ Source code: https://github.com/k754a/C-Plus-Plus-Web-Engine Got the DOM tree working! Ok, in this devlog, I fixed the DOM tree issues; it seemed to be a combo of issues with the parser (I fixed that) and some actually easy fixes from the DOM tree; it just took a rewrite! I was also able to code a way to see the tree: DOM TREE ├── [ROOT] │ ├── [!DOCTYPE] │ │ ├── [html] │ │ │ ├── [body] │ │ │ │ ├── [h1] │ │ │ │ │ └──── \" Heading test \" │ │ │ │ ├── [p] │ │ │ │ │ └──── \" Paragraph test \" │ │ │ │ ├── [p] │ │ │ │ │ └──── \" Multiple \" │ │ │ │ │ ├── [strong] │ │ │ │ │ │ └──── \" Char \" │ │ │ │ │ └──── \" Test \" We are super close to getting our first text on the screen! (Maybe just a devlog or 2). The vid below shows it in action! Thanks for reading :)"}, {"post_id": 12205, "ts": "2026-06-19T22:30:15Z", "hours": 1.7031, "text": "Today I Worked on the DOM tree, for my C++ Web Engine from scratch! Code / Project You can check out the code here: https://github.com/k754a/C-Plus-Plus-Web-Engine And try a older version of it: https://k754a.hackclub.app/ Today was my first attempt at building a DOM tree and also learning structure types and building trees. This first attempt, after learning a lot about how trees work, doesn’t really work fully; it seems to have issues when parsing tokens and just processing them overall, so the hope is that I can rebuild this for next time! Overall this was a pretty boring day; hopefully I’ll get the DOM tree working, then it’s straight to rendering!"}, {"post_id": 11748, "ts": "2026-06-19T04:11:02Z", "hours": 2.1842, "text": "Fixed my parser! Today’s update: I fixed my parser. The main issue was that it didn’t parse in order; it would do it like this: Text that should be in <a></a> The problem was that I couldn’t use this for my DOM tree, and getting my DOM program to do this would be slow and inefficient. Also, the cause of this was because I didn’t check for conditions that it was a start, middle, or end tag. I did it so I bunched the start and end together, and this was a huge problem because it ended up being put at the bottom, which wouldn’t work at all! Fixing it took a hot minute, but tomorrow I should have DOM’s working. Ok, thanks for reading that! The before and after are in the images below. Code / Project You can check out the code here: https://github.com/k754a/C-Plus-Plus-Web-Engine And try a older version of it: https://k754a.hackclub.app/"}, {"post_id": 10978, "ts": "2026-06-18T00:22:11Z", "hours": 3.2256, "text": "HTTPS Working I was able to get HTTPS working on the C++ engine and get it to properly parse. Most websites work on it, but they were a bit slow, so I ended up rebuilding parts of the tokenizer to be faster, changing the speed overall from 3+ seconds to under 0.2 seconds. The main problem is Google websites don’t load at all, so I’ll fix that in the future. Code / Project You can check out the code here: https://github.com/k754a/C-Plus-Plus-Web-Engine And try a older version of it: https://k754a.hackclub.app/ The video below shows it in action, loading the Hack Club web page super fast."}, {"post_id": 10261, "ts": "2026-06-16T22:03:22Z", "hours": 2.195, "text": "C++ Browser Engine You can try it online! : https://k754a.hackclub.app/ Source code: https://github.com/k754a/C-Plus-Plus-Web-Engine I built a custom tokenizer for HTTP to be able to load and render websites! I’m building a super-fast, pure custom C++ browser engine from scratch, and the thing I built today was an HTML parser! HTML parsers are super hard to code, thanks to HTML being a very loose markup language. There can be tons of stuff, like: Missing divs <div> Hello World! </p></div> Missing end tags <img src= \"image.png\" Even nested divs! <div class= \"container\" ><span> Nested Elements </span></div> So I needed to build a parser that could handle all of it. Another challenge I’ve been trying is forcing myself to stop making variables for everything and trying to be minimal and fast! This new update also added local HTML loading; this lets me test much faster and test certain things, especially for the DOM and render tree! Some struggles I ran into while building this project were just the amount of errors and debugging I had to do to figure out what went wrong, as well as working with large pieces of code with constant changes. This part really taught me about data types, how to find and remove elements from multiple different classes and types, how to make loops efficient, and how to use vectors! My plan for the next devlog will be building a DOM tree or getting HTTPS to work. After doing some research, I found that I can use: #include <wininet.h> to help get this thing working, so that’s my plan! Okay, this was super long. Thanks for looking at it. The video linked below is a demo of it loading and tokenizing some text locally on a machine!"}, {"post_id": 9517, "ts": "2026-06-15T21:46:02Z", "hours": 3.3375, "text": "In this devlog I built the first half of my parser for the web engine; it can go through a website and match tokens! There are a few issues; some things, like conditions (like <a href=> arnt supported), as well as I can’t pull text from things like headers and stuff. I also made an animation so people can see how it works! The animations basically shows how my buffer system, and determining the order of tokens works, to prevent things like mismatches!"}, {"post_id": 8360, "ts": "2026-06-13T21:58:37Z", "hours": 1.1603, "text": "I was able to build a website demo for people to try out. To make this, I ran it on the Nest servers from Hack Club! However, I used a bit of AI, as I had never set up a server, as well as my project being only built for Windows. However, AI still hasn’t and will not be used in the main project. I did this as a bit of a time saver and to not have to commit 40+ times to test it lol. https://k754a.hackclub.app/"}, {"post_id": 7951, "ts": "2026-06-13T08:10:50Z", "hours": 1.3631, "text": "First version of the browser. It is currently all through the terminal; there is no formatting, CSS, JavaScript, fonts, styles, or even structure to the text. However, any HTTP website can now be rendered into readable text, even if it’s a bit hard to see, lol! The next version of this, I’m going to hook up a rendering pipeline (not sure to what yet, though). Then it will be allowing different fonts and structures, and then finally, support for some CSS. What I have just described will probably take 200 hours!"}, {"post_id": 7836, "ts": "2026-06-13T02:24:42Z", "hours": 1.7817, "text": "I update the web browser engine to allow the download of full files from websites in HTTP. This will pave the way to let me parse the website for the next devlog! Some more changes I made were a bit more error handling and also refining some of the output to make it cleaner and retiring some of the older debug logs. The next difficult part will be some basic parsing and pulling out text Then I’ll attempt to render text without position (this will take about ~4 hours), and then I’ll work on formatting."}, {"post_id": 7688, "ts": "2026-06-12T20:48:29Z", "hours": 1.8869, "text": "I built the first version of my web client. It can now pull HTML data from HTTP sites, using a TCP socket. If you don’t know what I’m working on, I’m building a pure C++ browser engine, to load and render websites like google without the use of AI and libraries. Note that it does not work for https, as to build a handshake between the 2 is super difficult, even for a good programmer. The next step will be to pull an entire webpage off and save it in RAM. Thanks for reading, and I hope you follow my journey!"}, {"post_id": 7066, "ts": "2026-06-11T20:43:24Z", "hours": 1.8558, "text": "Using C++ and native windows libraries, i was able to connect to a website and pull some data off of it. this was super difficult, but im super happy it worked, its able to connect to any IPV4, http site. my next plan is to start pulling files, like html into ram from websites. "}, {"post_id": 4053, "ts": "2026-06-07T07:22:15Z", "hours": 1.5675, "text": "The overall of my essay, is just laying out how im going to be building a web engine from scratch. its not going to run JavaScirpt or interface with HTTPS off the bat, as i have to code all of that and it sucks. https://github.com/k754a/C-Plus-Plus-Web-Engine/blob/main/README.md (this is a link to it as i could not upload a pdf file.) Overall, this will be one of the most complex projects I’ve ever tried/attempted to take on, even over https://github.com/k754a/C-Custom-Code-Editor by a long shot. This will 100% test my research, development, and C++ skills, but I believe that even if I’m not able to pull this off, I will learn a lot about how browsers work and good C++ practices. I hope you will follow my progress on GitHub and Stardance as I build this!"}]...
|
Title: Browse++ by @kallenseelo | Stardance
Devlo Title: Browse++ by @kallenseelo | Stardance
Devlogs:
The overall of my essay, is just laying out how im going to be building a web engine from scratch. its not going to run JavaScirpt or interface with HTTPS off the bat, as i have to code all of that and it sucks. https://github.com/k754a/C-Plus-Plus-Web-Engine/blob/main/README.md (this is a link to it as i could not upload a pdf file.) Overall, this will be one of the most complex projects I’ve ever tried/attempted to take on, even over https://github.com/k754a/C-Custom-Code-Editor by a long shot. This will 100% test my research, development, and C++ skills, but I believe that even if I’m not able to pull this off, I will learn a lot about how browsers work and good C++ practices. I hope you will follow my progress on GitHub and Stardance as I build this!
Using C++ and native windows libraries, i was able to connect to a website and pull some data off of it. this was super difficult, but im super happy it worked, its able to connect to any IPV4, http site. my next plan is to start pulling files, like html into ram from websites.
I built the first version of my web client. It can now pull HTML data from HTTP sites, using a TCP socket. If you don’t know what I’m working on, I’m building a pure C++ browser engine, to load and render websites like google without the use of AI and libraries. Note that it does not work for https, as to build a handshake between the 2 is super difficult, even for a good programmer. The next step will be to pull an entire webpage off and save it in RAM. Thanks for reading, and I hope you follow my journey!
I update the web browser engine to allow the download of full files from websites in HTTP. This will pave the way to let me parse the website for the next devlog! Some more changes I made were a bit more error handling and also refining some of the output to make it cleaner and retiring some of the older debug logs. The next difficult part will be some basic parsing and pulling out text Then I’ll attempt to render text without position (this will take about ~4 hours), and then I’ll work on formatting.
First version of the browser. It is currently all through the terminal; there is no formatting, CSS, JavaScript, fonts, styles, or even structure to the text. However, any HTTP website can now be rendered into readable text, even if it’s a bit hard to see, lol! The next version of this, I’m going to hook up a rendering pipeline (not sure to what yet, though). Then it will be allowing different fonts and structures, and then finally, support for some CSS. What I have just described will probably take 200 hours!
I was able to build a website demo for people to try out. To make this, I ran it on the Nest servers from Hack Club! However, I used a bit of AI, as I had never set up a server, as well as my project being only built for Windows. However, AI still hasn’t and will not be used in the main project. I did this as a bit of a time saver and to not have to commit 40+ times to test it lol. https://k754a.hackclub.app/
In this devlog I built the first half of my parser for the web engine; it can go through a website and match tokens! There are a few issues; some things, like conditions (like <a href=> arnt supported), as well as I can’t pull text from things like headers and stuff. I also made an animation so people can see how it works! The animations basically shows how my buffer system, and determining the order of tokens works, to prevent things like mismatches!
C++ Browser Engine You can try it online! : https://k754a.hackclub.app/ Source code: https://github.com/k754a/C-Plus-Plus-Web-Engine I built a custom tokenizer for HTTP to be able to load and render websites! I’m building a super-fast, pure custom C++ browser engine from scratch, and the thing I built today was an HTML parser! HTML parsers are super hard to code, thanks to HTML being a very loose markup language. There can be tons of stuff, like: Missing divs <div> Hello World! </p></div> Missing end tags <img src= "image.png" Even nested divs! <div class= "container" ><span> Nested Elements </span></div> So I needed to build a parser that could handle all of it. Another challenge I’ve been trying is forcing myself to stop making variables for everything and trying to be minimal and fast! This new update also added local HTML loading; this lets me test much faster and test certain things, especially for the DOM and render tree! Some struggles I ran into while building this project were just the amount of errors and debugging I had to do to figure out what went wrong, as well as working with large pieces of code with constant changes. This part really taught me about data types, how to find and remove elements from multiple different classes and types, how to make loops efficient, and how to use vectors! My plan for the next devlog will be building a DOM tree or getting HTTPS to work. After doing some research, I found that I can use: #include <wininet.h> to help get this thing working, so that’s my plan! Okay, this was super long. Thanks for looking at it. The video linked below is a demo of it loading and tokenizing some text locally on a machine!
HTTPS Working I was able to get HTTPS working on the C++ engine and get it to properly parse. Most websites work on it, but they were a bit slow, so I ended up rebuilding parts of the tokenizer to be faster, changing the speed overall from 3+ seconds to under 0.2 seconds. The main problem is Google websites don’t load at all, so I’ll fix that in the future. Code / Project You can check out the code here: https://github.com/k754a/C-Plus-Plus-Web-Engine And try a older version of it: https://k754a.hackclub.app/ The video below shows it in action, loading the Hack Club web page super fast.
Fixed my parser! Today’s update: I fixed my parser. The main issue was that it didn’t parse in order; it would do it like this: Text that should be in <a></a> The problem was that I couldn’t use this for my DOM tree, and getting my DOM program to do this would be slow and inefficient. Also, the cause of this was because I didn’t check for conditions that it was a start, middle, or end tag. I did it so I bunched the start and end together, and this was a huge problem because it ended up being put at the bottom, which wouldn’t work at all! Fixing it took a hot minute, but tomorrow I should have DOM’s working. Ok, thanks for reading that! The before and after are in the images below. Code / Project You can check out the code here: https://github.com/k754a/C-Plus-Plus-Web-Engine And try a older version of it: https://k754a.hackclub.app/
Today I Worked on the DOM tree, for my C++ Web Engine from scratch! Code / Project You can check out the code here: https://github.com/k754a/C-Plus-Plus-Web-Engine And try a older version of it: https://k754a.hackclub.app/ Today was my first attempt at building a DOM tree and also learning structure types and building trees. This first attempt, after learning a lot about how trees work, doesn’t really work fully; it seems to have issues when parsing tokens and just processing them overall, so the hope is that I can rebuild this for next time! Overall this was a pretty boring day; hopefully I’ll get the DOM tree working, then it’s straight to rendering!
C++ Browser Engine You can try it online! : https://k754a.hackclub.app/ Source code: https://github.com/k754a/C-Plus-Plus-Web-Engine Got the DOM tree working! Ok, in this devlog, I fixed the DOM tree issues; it seemed to be a combo of issues with the parser (I fixed that) and some actually easy fixes from the DOM tree; it just took a rewrite! I was also able to code a way to see the tree: DOM TREE ├── [ROOT] │ ├── [!DOCTYPE] │ │ ├── [html] │ │ │ ├── [body] │ │ │ │ ├── [h1] │ │ │ │ │ └──── " Heading test " │ │ │ │ ├── [p] │ │ │ │ │ └──── " Paragraph test " │ │ │ │ ├── [p] │ │ │ │ │ └──── " Multiple " │ │ │ │ │ ├── [strong] │ │ │ │ │ │ └──── " Char " │ │ │ │ │ └──── " Test " We are super close to getting our first text on the screen! (Maybe just a devlog or 2). The vid below shows it in action! Thanks for reading :)
This is a super short devlog, I updated the server so that it uses my latest code, and supports HTTPS! you can try it out with the link below. https://k754a.hackclub.app/
C++ Browser Engine You can try it online! : https://k754a.hackclub.app/ Source code: https://github.com/k754a/C-Plus-Plus-Web-Engine Got started work on the GUI using SDL3! Today, I worked on getting a GUI up and running; for now it’s just a window, but I’ll get it working! I also started work on a logo, as I felt a bit burnt out during today, but nothing really came of it, as all my designs I tried sucked; the best one I linked below. I also created the first readme!
The browser now has a GUI! This took a bit and a few tutorials, but now you’re able to browse the web with no styles, one font, and just things like headers, but for now this is super awesome! I’ve been going pretty hard at it the last few days, and I lowkey need a break, or else I’m gonna get super burnt out, so I might just start a side project for the fun of it, something easy when I’m feeling a bit sluggish. When I come back, I’ll work on adding a UI around the browser (to get fully away from the terminal), and then it’s just getting CSS parsed and working, which isn’t too bad at all. You can check out the code and try the project below. C++ Browser Engine You can try it online! : https://k754a.hackclub.app/ Source code: https://github.com/k754a/C-Plus-Plus-Web-Engine
CSS Parsing! I got CSS working! I was able to get my CSS parser working on the engine and parse properly. This wasn’t as easy as I thought, as my first attempt worked but was dreadfully slow (10+ seconds), so a lot of the time went into rewrites and optimizations, bringing it from 10+ to about 2 seconds for huge CSS (1000+ lines of CSS)! Code / Project You can check out the code here: https://github.com/k754a/C-Plus-Plus-Web-Engine And try a older version of it: https://k754a.hackclub.app/ Video below shows it loading the hackclub website!
Version 0.1.0 of the Browser Engine! If you don’t know what I’m building, I’m creating a custom browser engine in C++ from scratch, something like Chromium, but a lot more bare bones. Today, I did a bunch of things. I got my first CSS attributes to detect and work! Text now is not hardcoded and dynamically scales based on the CSS! This really wasn’t too hard, so I moved on to the next thing, getting a working UI! The UI I’ve created is basic, but it allows you to search without using the terminal and search multiple things! Overall this was an awesome day for today; my plan over the coming days is to support more CSS and work on fixing performance and overflow bugs! Thanks for reading. :) Code / Project You can check out the code here: https://github.com/k754a/C-Plus-Plus-Web-Engine And try a older version of it: https://k754a.hackclub.app/ The video shows the standalone app, and searching 2 different sites.
Today, I got a bunch of colors working! The browser engine can now render different colored backgrounds, texts, and highlights! This actually wasn’t too bad, as the hardest part was just fixing all the bugs from CSS being such a bad language, but overall it turned out awesome!
Links, and better rendering! Today I got links, and rendering improved rendering! Words now render together, rather than making a new line each time. I also got links, and that allows you to browse something like Wikipedia (the video below) much easier! For next time, I’m going to get the back and forward arrow and reload a working website! And may start work on getting the browser to have divs! Thanks for reading!
Back and forth arrows, reloading, better formatting, and searching on the browser! Today was huge; I was able to get better formatting for text, search for things, and get buttons like back and forth and reloading working! My next task to tackle is images! The vid below shows all of the changes in action! Thanks for reading!
Rebuilt part of the browser engine to handle tabs! Today, I worked on getting tabs working! It wasn’t as bad as I thought; the worst part was making all the UI elements and handling the inputs for them! I also found a bug; the engine easily uses my entire CPU’s dedicated GPU and causes issues with other apps lol, but I’ll fix it in a bit! Overall it was just bug fixes, quality-of-life improvements, and tabs! Hopefully tomorrow I’ll do images, then I’m taking a break for a bit and doing something else because I’m burnt out, and that’s a tip for all of you too: don’t overwork yourselves! The vid below shows it in action. Thanks for reading! Also, if you want to support the project, dropping a star on the GitHub would be awesome; no pressure, though. :) https://github.com/k754a/C-Plus-Plus-Web-Engine
Images Working for the Browser Engine! I’m going to be honest with you, this has to be the top 10 worst things I’ve ever coded. 😭😭 But images now can load; there are a few bugs, most images don’t load, and the ones that do load in pairs of 2 have weird bounding boxes. However, they do work, and that’s what I’m happy about! I’m going to do a quick side project, just to have a bit of room so I don’t overdo it, but overall it was good. Next I’ll just fix the bugs and start getting like the formatting of texts to start matching websites! The vid below shows them in action.
Lots of bug fixing on the engine! & Making it to the news letter! First of all, I want to thank everyone who has liked, reposted, and checked out my project. I made it to the Stardance newsletter, and it was so awesome :). Thank you so much! Today, I fixed a crazy amount of bugs; the main one was I would have these empty boxes, and it took me a good hour and a half to figure it out, but now text renders so much nicer! The next bug I fixed was clicking links. Up until this point, clicking links did not work at ALL, so now they work! (super happy about that)! History now works for each tab, not just one pool! I’m also starting work on making a YT video for this project. I’ve never made one before, so we will see how it turns out. For tomorrow, I’m going to work on the formatting of the engine, as normal websites have text like how Stardance has the home, notifications, rate, missions, etc, on the side and the main text in the middle, so I’ll hopefully get that working! Anyways, thanks for reading! You can check out my project below. :) Code / Project You can check out the code here: https://github.com/k754a/C-Plus-Plus-Web-Engine And try a older version of it: https://k754a.hackclub.app/
Rebuild of the layout engine! Today, I rebuilt a bunch of the layout engine to start support for flexboxes and divs! I mainly switched the code to do 2 passes, first to figure out spacing, size, and position, then to place the elements on it! Overall, this was a kind of boring day; it works basically the exact same rn, so there’s really nothing to show, but I’ll send a screenshot or two of my code! Anyways, the plan next is to get flexboxes working! After that, I might rewrite my engine, as it’s getting a bit ugly and crowded, and I coded some stuff pretty badly the first time around; it probably would only take about 10 hours, working off my code, but I think it would save me time in the future, but I’ll see! Anyways, thanks for reading! Also, if you want to support the project, dropping a star on the GitHub would be awesome; no pressure, though. :) https://github.com/k754a/C-Plus-Plus-Web-Engine
Got Flex and Absolute boxes working on the engine! This took a while, just with fixing all the bugs and the weird reasons why some things would just not work at all lol! It was definitely a learning process for sure, and it should be easier to add more support for everything else in the future! This has to be one of the most difficult projects I’ve ever worked on, but it’s coming along! I want to do something a bit more fun, so my plan is to start work on a UI overall, just to give myself a break from all the crazy stuff! Anyways, thanks for reading! (oh, websites look so much nicer, with the new stuff!)
New icons and more buttons! Today, I was able to get icons supported into the engine (kind of)! The way I did it was by using a font modifier. I loaded the font I’ve been using and created some custom icons! A lot of the challenge was fixing text, as the new icons had issues with scaling and position, especially the back and forth arrows! Overall it was a great day. I’ll work on getting the printer button and the star button working; then it’s on to improving the engine! (also added a home button!)
Scroll bar support, bookmarks, and printing sites! Today I got a lot done; the main things were getting scrollbars, bookmarks, and getting sites to print all working! I ended up running into a lot of bugs (especially with the scroll bar), but now it works, so yeah! Currently the browser portion is far behind, and I want to update it, so I’ll try doing that next! Overall today was a good day; I got a lot done and a lot working! Anyways, thanks for reading! Code / Project You can check out the code here: https://github.com/k754a/C-Plus-Plus-Web-Engine And try a older version of it: https://k754a.hackclub.app/
Updated the web version to the latest! Ok, so the main thing i did today was update the web version, and got it to match the main version overall, with everything! I also tried to get better formatting on the text, but i think my code is just so muddled its gonna be impossible, so my plan is to start rewriting it, with the things I’ve learned, and updating the comments (as i have a lot of them, in many wrong spaces)! that should take a bit, but hopefully will pay off in the future! If you want to try the new version, its here: https://k754a.hackclub.app/
The first part is rewritten! Today, I worked on rewriting my network code with better comments, names, and methods. This took a while, as I created so many bugs, but it does work! The long part is still yet to come; however, the main things like the parser and the GUI are going to be a headache, but I should get it done! Overall a good day; ~4 files have been changed, with 6 more to go! Then after this, i want to add a history button, a settings page, and just improve performance, and formatting, then I’m done!
Performance increases, and a rewrite of the parser! Today was a nice easy day; I rewrote most of the parser, fixing a lot of bugs, and also learned how to use the performance analyzer in C++! The code is much more documented, with every line describing what it’s doing, making it super easy to follow along! The main change was an increase in speed from about 5% CPU usage to 1% and a 50MB reduction in RAM usage, allowing for 10 tabs at once, with only 61MB overall, rather than the 1000MB of something like Chrome! as well as about a 6% faster parse and load time. There is still a lot to optimize and work on, so I’ll keep doing that!
Performance analyzer and comments for our DOM! Today, I created a performance analyzer that could tell me how many microseconds it takes to get through certain programs. This helped a lot with optimization and making things faster! I also finished and optimized the DOM code! Today was a pretty basic day; I’m a bit busy over this coming week, so it’s going to be a bit more broken up, but overall a good day today!
Lots of optimization, better comments, and bug fixes! Sorry for not posting for a few days; I was super busy and didn’t really have the time. However, I’m back at it! Over the last week, I’ve been changing and updating lots of stuff. The first one was much better comments for the layout.cpp file! I still have a bit left to do, but I was getting pretty tired, so I moved onto making the engine a bit faster! One of the main things I did was use threading, passing the text off to the GPU rather than going from CPU to GPU, as well as multithreading it. This allows about 2 seconds faster search time, and I have some more ideas for changes too! The reason this took so long is the number of bugs I introduced. The Gui.cpp is huge (2000+ lines), so I want to really rewrite it, as there is SO much junk and bad coding practices lol. Overall though, it was a good day, and I think I want to start tackling JavaScript after adding a lot of QofL and fixes to a ton of bugs! Thanks for reading!
Dark mode and bug fixes (with more bugs) and HTTP error codes Today, I recorded most of my link and search handling to be better at handling URLs and links like /home. I also added a dark mode! (Super helpful on the eyes lol) Unfortunately there is a big bug, some websites will just not work anymore (like hackclub), and also websites take super long to load, this is because the images it is processing are in a buffer, and this buffer needs to finish the images of one page before the other, i think i have an idea to fix it, so I hope I will be able too soon! But overall, this update changed a lot of bugs, and I’m hoping it can be even better for the future!
Lots of bug fixes, quality-of-life changes, and the start of a rewrite! try it out! https://k754a.hackclub.app/ I’ve been still a bit busy, but over the last 2 days, I ended up fixing a lot of bugs with crashing, especially with dealing with multithreaded tab handling. Some of the quality-of-life changes I did were creating a new tab handle that allows you to go back to the new tab in history and other small changes! The biggest bug was where, if you searched something and, while it was loading, switched tabs, it would overwrite your tab to the one you switched to, not the original one you searched in. Now that is fully fixed! Overall a good day! I’m going to fully rewrite and comment all 2500+ lines of the GUI and other functions, fix a LOT of bugs, and then add settings, history, and a few other things! Thanks for reading!
Halfway done rewriting Gui.cpp—Lots of bug fixes and speed improvements! If you want to check out or support this project, you can click the GitHub link! https://github.com/k754a/C-Plus-Plus-Web-Engine Over the last 2 days, I’ve rewritten about half of GUI.cpp (up to the GUIRENDER function), with changes, bug fixes, and speedups that helped the engine a lot! The main speedup came from changing the way I handled the font so that I loaded it once, not every loop. This allowed a lot less SSD usage and a gradual increase of performance, up to about 50% for large sites! I worked a lot on organization and got it so that different functions are grouped together, even moving some to different scripts that fit better! The final change was reworking how images and the home button worked, and it allowed me to drop a function, as well as have much faster image batch loading times! Going through the code made me realize how many bugs and bad code I did. I fixed a lot of it, but I still got a bit to go! Overall it was a good day. My plan for everything else is to finish the rest of GUI.cpp, start work on a settings page, and try to make the parser faster still! Thanks for reading!
Local file loading, better comments, and crash fixing! If you want to check out or support this project, you can click the GitHub link! https://github.com/k754a/C-Plus-Plus-Web-Engine Today, I worked a TON; I got through all the comments for the start and collision events for all the buttons and things in GUIRENDER . I also added some new features and fixed some huge bugs! The new feature is file loading! You can now load PNG, JPEG, HTML, TXT, and HTM files straight from the search bar! The main fix, and what took most of my time, was the prerender. as i was working on slimming the new tab create button down, i found a lot of strange bugs, esspicaly with webpages with large amounts of images (like stardance), this lead me down a lot of changes, overall, it was a issue with how i checked to see if i wanted to load it from disk, but it was also a bunch of stuff to do with multithreading, and locking parts, but after a lot of work, i fixed it! I still need to fix up and finish GUIRENDER , but once I’m done with that, it’s off to work on the settings page. Thanks for reading!
Quality of life improvements, more comments, and finally fixed the crashes If you want to check out or support this project, you can click the GitHub link! https://github.com/k754a/C-Plus-Plus-Web-Engine Ok, so first off, the huge crash I was getting was because of using a global variable for holding the link and not a local variable, and when 2 threads attempted to use it at the same time, my app would freeze and crash, so now it runs great! Some of the QofL improvements are adding keyboard shortcuts and the ability to close tabs by pressing the middle button down, like a real browser! Then there were a lot more comments that I am so close to being done! Overall a decent 2 days; I’m definitely getting a bit bored of the comments, so my plan is to work on my other project for a bit and come back later! But yeah, a good day. :)
Done all comments and released 0.1.0 ! If you want to check out or support this project, you can click the GitHub link! https://github.com/k754a/C-Plus-Plus-Web-Engine I ended up going on a camping trip with the homies, so I didn’t work on this for a bit, but when I came back, I fixed a few more bugs, ended up finishing all the comments for GUI.cpp, and created release 0.1. 0! This is huge, as I was able to fix all known bugs and get a working version out! For version 1.0.0, I want to fully fix the layout engine to render close to a modern browser, add a settings page, fix performance, and add things like buttons and checkboxes on websites! Thanks for reading!
Settings button, bug fixes, scroll bar drag, and a context menu! This update was just a crazy number of features! I ended up shifting around the top area to make room for a settings button (that I will deal with soon), then I decided to allow scroll bar drag so that you can scroll through a page with the bar, not just your wheel! The big thing was the context menu; this took the most time and was the most difficult, as it was just a pain to get 2 windows rendering, but now, it works super well! I also attempted to work on getting a better layout, but I just screwed a lot of stuff up lol, so that didn’t really work out, but that’s ok!
Add context menu and startup URL (and fixed a LOT of bugs)! Sorry it’s been like 2 weeks, but after finishing my other project, I’m back at it! Over the last 2 days, I worked a LOT on the context menu and bug fixes (like loading text files into the engine, and old ones I caught working on this!). The context menu changes its options based on what things you right-click (like a real context menu), so for example, when I click a link, I get way more different options than if I clicked a tab. This allows for a lot of customization, and it’s basically fully implemented (minus a few features I want to add). The startup URL is kind of a part of that; when clicking a link, you have the choice to open it in a new window, and getting a URL that can change on startup really made it easy to add the feature! So overall a good day. What I’m going to work on next is the settings menu. Thanks for reading!
HTML text-align handling, history tab, and settings. Ok, I’m going to be honest, I looked at that settings menu and genuinely did NOTHING. It’s going to be a pain, so I’m just avoiding it till I have no choice. Something HUGE, though, I’ve gotten working is getting proper styling so that text can render in the middle and right (with way more text-align and style options to come)! This really opens the door for much more dynamic rendering text, though there are still a few bugs with it (large text goes off screen, and the home screen doesn’t apply the settings), so there is still a lot to fix, but honestly, I didn’t even think it was possible, so this is awesome! Overall a good day; I’m going to continue working on history and styles and then the settings lol.
More text formatting and positioning. (and LOTS of bug fixing) Today was a great day of work; I got height adjusting working, and this took way longer than I thought, just with all the bugs and problems I ran into, with old code I had created, but I was able to solve it all. The other notable thing is having another way to color text and the bg of text, but also, I fixed it so that none of the text falls off the edge in the positioning, so overall a good day! I’m actually so close to being done; I’ve wanted to go to 200 hours, then kind of just chill and slow down, and I’m at 14 hours left of that! Then I’ll ship. But I do want to finish the history menu, though I may leave the settings menu on pause. (for now). So yeah!
More HTML style options, browser history, and work on the Readme.md Ok, so over the last 6 hours this is what I worked on. First, I worked on adding more style options, so now you can set font size (another way) and set font boldness (like normal HTML), and you can now add custom number values to the vertical alignment (that in the vid is shown on the homepage!). I also worked on the browser history now, saving it to a txt file. You can scroll back through what you’ve searched before (and add a button to clear it next update).I also was working on the readme, making it clear and better before the ship. Overall a good day, and I think I’ll try to do the settings menu, aswell as support for buttons in the viewer (though they probably won’t do anything thanks to not having JavaScript), so yeah!
Updated context menu, Desktop Logo, Hover effects, Rework of the input bar, and bug fixes! Ok, its like 1:30 am rn lol, so im going to try to do this fast. First, i updated the context menu, the menu now has a nice drop shadow, and looks so much nicer than before (lemme know what you think about it). second, i added a basic desktop logo (a grayish black circle) that changes based on light or dark mode (the vid shows it well). Another change was hover effects! now hovering over buttons changes the color slighly, making it a bit simpler to see that your over something, and aswell as being a bit more reactive! the input bar rework allows clicking onto the bar, rather than always typing on the bar (for ctr-F coming soon!). Finally, bug fixes, i had a lot of issues with having both custom x pos, and custom y pos, but thats all fixed now! aswell as the backgrounds not updating per tab (thats now fixed too!). Finally II, i worked on the readme a bit! Overall it was a good day (with over 10 hours of work lol), and i still have a few features to add! so yeah, thanks for reading! (as well as excuse the spelling mistakes, there might be a lot lol)
Linux support!!! Over the last few days, I’ve been working on migrating the project from MSBuild to CMake, allowing it to run on both Linux and macOS (though I haven’t been able to test it lol). Linux has been tested, however, and everything works on it (except I haven’t migrated the networking, so that’s still to do!!), so there are still some things that need to be done, but it boots on my Debian VM and renders! So I’m super happy for that. Some other changes were that I got autocompletion (you’ll see it in a sec) as well as getting the open in a new tab working a bit better for both Windows and Linux!! Overall a good day!
Final work on the readme, getting a standalone windows build! Over the last few days, I’ve been hard at work getting the readme finished up, it was super tedious but now its in a good spot for a ship, and looks awesome! I’ve also gotten the windows build to be standalone! this took a lot of googling, but now with CMake, it now can run on anyone’s computer, without needing anything else!! Other than that, its been a bit of work on the Linux side, i attempted to get some sort of https working, but because its a vm, its super screwy, and i hope to be able to have a computer that has Linux on it for use, but we will see ig. Also made a YT vid https://www.youtube.com/watch?v=I-mCh9xSYeg&t=8s Overall a good day!
Ships:
Browse++ A C++ Browser Engine from Scratch. Overview: Over the course of 2 months and almost 300 hours (165 coding) of work, I built a browser engine that can download, parse, and render websites with tab handling and a lot of other cool features, from almost complete scratch! What’s a Browser Engine? A basic definition of a browser engine is a program that pulls content from a website, then takes that content, gives the elements the properties assigned in the CSS, and then renders the content on the screen. They end up being very difficult to build, as HTML and CSS can run and be run without errors, so that makes it super hard to build an engine that can properly handle, parse, and render a site with a lot of errors. How to use this? If you would like to use my browser engine, there is quite a few ways to do so! NOTE: I do not have an actual Linux laptop, so the Linux version is super buggy (and does not have any networking), but I really hope to fix that in the future, but you can use the more outdated web demo! If you don’t want to download anything, you can use the Web Demo , its a bit behind, but it shows it nicely. If you are willing to download, and you are on windows , you can go to the github here and download to try it! If you want to see the real thing, I have a video going through it here. What am I most proud of? I think the thing I’m most proud of was the amount of browser systems i was able to build from scratch , this was a super fun thing to build, but it had a lot of challenges and ups and down, and a lot of hours fixing bugs that make no sense at all lol! The other thing I’m most proud of is not using any AI on the main engine; there was a bit of AI used for the web demo, as that wasn’t my main focus, but the browser engine overall used absolutely no AI! AI usage GLM 5.2 was used to convert the Windows code to a web server for Linux (way before I supported Linux). Any code changes are clearly marked with ( // CHANGED WITH AI: ... ) if they have been changed with AI, and very little has been changed....
|
1792878475.348404
|
1793742475.348404
|
|
24310
|
BitDrop by @thestarviper | Stardance
|
thestarviper
|
1
|
160.0
|
3167
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-10T09:55:31Z", "hours": 160.0, "multiplier": 19.75, "payout": 3167, "blessing": "neutral", "text": "PLEASE READ THE HINTS SO YOU KNOW HOW TO PLAY I made a pachinko roguelite game that is inspired by balatro, slay the spire, and ultrapool. The game is a web game that is hosted on itch.io so no need to download anything. Have fun!", "repo": "https://github.com/TheStarViper/Bitdrop", "demo": "https://thestarviper.itch.io/bitdrop"}]...
|
[{"post_id": 44510, "ts": "202 [{"post_id": 44510, "ts": "2026-08-10T09:53:13Z", "hours": 1.0939, "text": "UPDATE #32 FIREFOX SUCKS Summary FIREFOX SUCKS. anyways i added a buncha sfx and ct5 found a bug where the game done goofy mode on firefox so i had to fix that breakdown map hover sfx shop buy sfx cashout sfx basket score sfx node pin sfx louder on playtester request used playtester feedback: this game on firefox compiled weird goofy its up on itchio now wowie #SHIP TIME YAYAYAYAYAYAYAY"}, {"post_id": 44482, "ts": "2026-08-10T08:38:47Z", "hours": 1.9064, "text": "UPDATE #31 Balancing Summary ITS ALL COMING TOGETHER RAHHHHH. I added like 10 new daemons changed icons and balanced the prices along with sending my project into the hackclub slack for playtesting. breakdown added 10 new daemons changed icons of every daemon since they shared the same icon balanced prices of consumables and daemons used playtester feedback: some things were confusing so i added more hints used playtester feedback: a button in the shop was unintuative so i made it so that it worked more intuiatively used playtester feedback: playtester found a bug with one of the new daemons that destroyed itself didnt free up a slot NEXT UPDATE IS JUST SOUND EFFECTS AND MAYBE FEEDBACK FROM SLACK THEN I SHIP YAY IM GETTING THIS DONE BEFORE I SLEEP"}, {"post_id": 44442, "ts": "2026-08-10T06:02:41Z", "hours": 4.5892, "text": "UPDATE #30 A little bit of everything Summary added a loss screen, another pin modifier, changed clone pin graphic, added music, changed map nodes, added overload mechanic breakdown added a loss screen with a loss sound effect added another pin mod called “Amplify” which just gives 1.5x score on hit to the ball changed clone pin graphic to show the pull distance and changes with leveling added main menu music and gameplay music changed map nodes by renaming them and changing colors around made final boss node bigger than it was originally for emphasis added overload mechanic that basically is a multiplier that increases by .08x per pin hit and decreases by .4x per second and adds the multiplier on scoring Things to polish before shipping daemons consumables balancing sfx"}, {"post_id": 43180, "ts": "2026-08-08T09:27:38Z", "hours": 2.7903, "text": "UPDATE #29 Polish Polish Polish Summary added a few consumables and added basket mods breakdown added a consumable to multiply a basket’s mult by 1.5x permanently added a consumable to lower quota on a level by 25% added a pin modifier that makes balls gravitate towards it made it so that consumables in shop can have weights Things to polish before shipping daemons consumables pin mods screenshake more tutorial steps music / sfx balancing"}, {"post_id": 43020, "ts": "2026-08-08T01:57:36Z", "hours": 2.4019, "text": "UPDATE #28 Endless Mode Summary added a win screen for when you win with a button to go endless mode called “ascensions” breakdown made endless mode made win screen (prolly should make it look better) fixed bug where you clicking back in a submenu in escmenu would double click and exit out of esc menu entirely fixed bug where you couldnt exit stats menu in escmenu from main menu Roadmap in order of completion add consumables for baskets to multiply basket mult re-org code before polish and balance cuz its kinda goofy spaghetti silly polish and balance by adding more stuff and things in general to daemons,consumables,stats,settings,pin mods add more screenshakes cuz i only have a few screenshakes music"}, {"post_id": 42465, "ts": "2026-08-07T06:51:18Z", "hours": 3.2836, "text": "UPDATE #27 Tutorial Summary made a hint based tutorial system every time you encounter a new mechanic breakdown made it so that in 1-2ish lines of code you can add a new hint to any aspect of the game hints pop up only on the first time you encounter a mechanic hints darken the background and go away with a glitch effect and sound effect after clicking “got it” button Roadmap in order of completion fix some of the bugs i have noted down in a personal doc that are hard to explain endless mode daemon synergies maybe add consumables for baskets still not decided polish and balance by adding more stuff and things in general to daemons,consumables,stats,settings,pin mods music"}, {"post_id": 42369, "ts": "2026-08-07T01:41:28Z", "hours": 2.8478, "text": "UPDATE #26 Main Menu Summary made a main menu breakdown took the grid background from the map and put it in the main menu took the tri-circle spinning animation from the map and put it in the main menu reused the button class i use everywhere settings button just goes to the settings menu i already made stats button just goes to the stats menu but i think ill change it to a tutorial button terminate button just gives a popup that says “its a web game silly” Roadmap in order of completion add tutorial endless mode daemon synergies maybe add consumables for baskets still not decided polish and balance by adding more stuff and things in general to daemons,consumables,stats,settings,pin mods music"}, {"post_id": 41791, "ts": "2026-08-06T06:19:51Z", "hours": 4.7828, "text": "UPDATE #25 Escape Menu three Summary added settings and stats page to the esc menu thing breakdown made it so that you can add more stats and settings with just one line of code to control or display a variable added a gamespeed notched slider added volume slider added screenshake toggle added a bunch of stats in the stats page moved back button to the bottom of the menu since we are nearing the phase where i ship this project i already have set a roadmap of things i need to do so i figure i could just share it here: add main menu maybe add consumables for baskets still not decided add tutorial endless mode daemon synergies polish and balance by adding more stuff and things in general to daemons,consumables,stats,settings,pin mods music"}, {"post_id": 41566, "ts": "2026-08-05T21:07:59Z", "hours": 4.3561, "text": "UPDATE #24 Escape Menu two Summary pin mods now show what level they are aswell as all the other mods on the pin in the form of colors and dots and hovering shows it more detailed also escape menu has buttons now. breakdown escape menu now has buttons and a different color back button when opening esc menu theres a glitch effect now along with a sound effect and closing does same thing putting a mod on the pin outlines the pin with the color of the mod and a dot for every level of the mod putting multiple mods on a pin divides the outline into multiple parts Next update plan add stats menu add settings menu add main menu maybe add consumables for baskets aswell but prolly the update after this one"}, {"post_id": 41090, "ts": "2026-08-05T01:46:24Z", "hours": 8.2328, "text": "UPDATE #23 Escape Menu Summary modularized code for pin mods, added levels and max levels, started work on an escape menu for settings. breakdown hover on nodes now shows level of the modifier on the node nodes like clone level 1 have it so the payout is split between the two balls and level 2 has it so that it isnt split between the two added menu button next to balance display modularized code for pin modifiers so its easier to add conflicts and such in the future and new features esc puts you in an esc menu to quit run new run settings optinos etc the same as the menu button esc menu stops time and physics aswell as all interaction in game until you unpause fixed issue where reroll text would overflow outside of the reroll box so now it resizes to fit inside of the reroll button node modifiers were also split into a different file Next update plan I got sidequested again for the escape menu so ill be working on that in tandem with the modifiers code and stuff make pins on modifiers visually distinct that can be stacked ontop of each other more work on esc menu"}, {"post_id": 40371, "ts": "2026-08-03T20:39:02Z", "hours": 6.2458, "text": "UPDATE #22 consumable board editor TWOOOO Summary made is so you can stack mods on pins and some are incompatible with others breakdown you can stack mods of different types on pins some mods are incompatible with each other if you modify a pin with an incompatible modifier it will just remove the conflicting modifier from the pin red alert text on consumables with conflicting modifiers hover shows the pins modifiers Next update plan you can stack modifiers on the same pin to level it up more pin modifier types make pins on modifiers visually distinct that can be stacked ontop of each other"}, {"post_id": 39200, "ts": "2026-08-02T00:08:00Z", "hours": 5.2997, "text": "UPDATE #21 consumable board editor Summary added new consumables that modified pins on the board to do different things breakdown added system where you can select nodes now added system where you can select multiple things to modify with a consumable added pin effect “mitosis” splits node into two added pin effect “overclock pin” makes pin valued at 1.5mb instead of 1mb prolly changing this this was just testing added pin effect “volitile pin” makes pin add a random payload from 1-10mb also was just testing prolly will modify this Next update plan add more sound effects make it so mitosis is called miosis and splits the value of the ball into half between the two balls make it so you can modify a pin with multiple modifiers and hovering shows what mods it has make pin modifiers like minecraft enchantments where you can apply some modifiers not with each other like mending + infinity isnt possible in minecraft or fortune + silk touch type thing"}, {"post_id": 38025, "ts": "2026-07-31T05:20:46Z", "hours": 3.1969, "text": "UPDATE #20 more animations Summary got sidetracked from original plan and made daemons look better along with making the map have velocity that keeps momentum after you stop scrolling breakdown made daemons look better using a dual layer system map has velocity that decreasese in speed after you stop scrolling with mouse click or scroll wheel dual layer daemon graphics I think this is kinda cool so basically i have the empty daemon slot image and when a daemon slot is empty it just keeps that sprite up and adds text ontop of that that says empty daemon slot (number). But when you get a daemon it uses the same hueshift function i have from the shop daemons and consumables and hueshifts an overlay with a transparent interior to add color and stuff. Empty daemon slot: empty daemon sprite layered text saying slot number and that it’s empty Occupied daemon slot: empty daemon sprite occupied daemon overlay with hue shift title and description text overlay + level overlay then put hover effects and stuff ontop Next update plan add more sound effects expand consumables system"}, {"post_id": 37419, "ts": "2026-07-30T03:53:05Z", "hours": 2.9794, "text": "UPDATE #19 more animations Summary added buy and sell animations along with fixing a few bugs it was alot faster than initially planned cuz it was just re-purposing existing code breakdown added buy animation for deamons and consumables added sell animations for daemons and consumablse fixed bug where shop didnt refresh when you re-enter after beating a level fixed bug where boss levels had a smaller quota than normal levels screenshake helper function implemented so i can just put screenshake(intensity,duration); anywhere and add screenshake with one line added a glitch location helper function based off my glitch transition code so now you can do TriggerGlitchAt(bounding-box-using-raylib-rectangle, duration); to glitch effect a location for a duration Next update plan maybe 6 hours for this update add more sound effects expand consumables system maybe make daemons look better but that might be for the update after this one"}, {"post_id": 36874, "ts": "2026-07-29T07:14:51Z", "hours": 4.0314, "text": "UPDATE #18 Shop Graphics Update pt 2 Summary updated shop graphics for consumables and made a custom class to make custom shaped polygons breakdown made consumables look better made consumables have a full consumables slot graphic and a not enough money alert made consumables have a background thingy in the shop that looks cool same hue shift graphic trick applied to the consumables like the daemons made insufficient funds for the daemons larger and more clear made a custom class for making polygons with an arbitrary number of vertexs so its faster to make polygons instead of the original way i used which was draw triangle fan made it so the class also detects hovers and clicks built in to make it easier Next update plan im hoping this next update can be completed in like 5 hrs or less to keep the pace of more frequent devlogs add buy animations add sell animations screen shake helper function"}, {"post_id": 36228, "ts": "2026-07-28T05:20:56Z", "hours": 4.4294, "text": "UPDATE #17 Shop Graphics Update pt 1 Summary updated shop graphics and animation breakdown used ai to generate a shop item slot and polished it in microsoft paint you can hover buttons and the main part and plays sfx buttons now have 6 vertexes daemons only get bought on left click release instead of on click since the shop items use sprites now instead of vector drawing i now hue shift the sprite to acheive different colors from one sprite (this took a while) reduced shop to have 4 items instead of 5 for balance and to fit the graphics nicer Next update plan update the consumables section of the shop to look better add buy animations"}, {"post_id": 35691, "ts": "2026-07-27T09:09:29Z", "hours": 3.3542, "text": "UPDATE #16 Map Graphics Update Summary updated the nodes in the map to look better and custom icons along with making the pathways more distinct from the background breakdown swirling things around node passively gliched nodes have funky movement with their animation which i find cool made pathways more distinct from background lines color nodes now have icons instead of text Next steps I currently plan to dedicate the next few updates to improving graphics before i continue with the gameplay changes i have listed below balancing endless mode skill tree overclock shards and daemon leveling daemon synergies more consumables more sfx more animations"}, {"post_id": 35028, "ts": "2026-07-26T05:56:26Z", "hours": 4.0314, "text": "UPDATE #15 Consumables Shop Summary Added consumables to the shop and reduced consumables slots breakdown you can buy and reroll consumables in shop reroll animation rerolls consumables too the consumables are a different shape then daemons in shop i gotta figure out the colors to be more different tho two consumable slots instead of four Next steps i came up with alot more ideas to implement balancing endless mode skill tree overclock shards and daemon leveling daemon synergies more consumables more sfx more animations"}, {"post_id": 34387, "ts": "2026-07-25T02:01:05Z", "hours": 6.0822, "text": "UPDATE #14 Consumables 2 Summary Added two consumables, changed price of rerolls and did some code restructuring. breakdown added a consumable “flash sale” is basically temperance from balatro and gives sell value of all your daemons into your balance added a consumable “dycrypt” and it decrypts unknown nodes so you know what they are moved the payout ball orb stuff to a different file moved the transitions stuff to a different file you can now sell consumables and it adds to the balance aswell two types of consumable one is instant use and one requires selecting something to effect i will use this later on nodes Next steps balancing more consumables more sfx more animations"}, {"post_id": 33390, "ts": "2026-07-23T09:24:36Z", "hours": 3.9456, "text": "UPDATE #13 Consumables Summary Added consumables slots graphics and the use/sell buttons that do nothing so far mainly ripped from the daemon code along with basic backend structure for consumables. also fixed a bug where hovering sfx never stopped playing on glitched nodes Next steps balancing consumables actions more sfx more animations"}, {"post_id": 32852, "ts": "2026-07-22T08:34:06Z", "hours": 5.7922, "text": "UPDATE #12 Audio Summary Added sound effects and shop polish breakdown transition sound (my favorite) bounce sound (need a better one) hover glitched node sound hover daemon sound hover shop item sound hover shop items for more interactivity Next steps balancing consumables more sfx more animations"}, {"post_id": 32205, "ts": "2026-07-21T06:57:06Z", "hours": 1.8539, "text": "UPDATE #11 Graphics Summary Added moving daemon animation and added encrypted nodes into the map that are a mystery of what it is until you click on them Next steps balancing consumables shop polish with hovers sfx near the end more animations"}, {"post_id": 30986, "ts": "2026-07-19T00:25:17Z", "hours": 6.2539, "text": "UPDATE #10 Graphics Summary Added money adding animation, 4 new daemons, and a reroll animation Finer Details rerolls have a glitch animation money scoring summons energy balls that glitch into balance 1 for each remaining ball and 1 for the money winning the level fixed bug where you could have over 5 daemons new daemon “Honeypot Trap” 30% chance to duplicate score new daemon “Firmware Backdoor” +5MB per node hit new daemon “Proxy Chain” multiplier per daemon owned (1.2x,1.4x,1.6x) new daemon “Rootkit Persistence” every 3rd ball scores 3x Next steps balancing consumables shop polish with hovers sfx near the end more animations"}, {"post_id": 30395, "ts": "2026-07-17T21:48:54Z", "hours": 6.2739, "text": "UPDATE #9 Map PT 3 Summary Added menu transitions, fixeds a few bugs Finer Details changes orange glow on current column to green made the nodes offset on the y and x axis a bit so it looks less grid-like added a glitch menu transition fixed bug where you couldnt interact with daemons in the map menu fixed map generation that generates stray nodes fixed map generate that generated incomplete paths level name it now displayed on box on hover light path that shows a path you can take to get to the node if you hover a future node from current node nodes no longer mostly connect to every single other node Next steps consumables shop polish with hovers sfx near the end more animations"}, {"post_id": 29365, "ts": "2026-07-16T08:28:25Z", "hours": 8.6403, "text": "UPDATE #8 The Map PT 2 Summary Polished the map more and added it into the gameplay loop so that it sets the quota and adds money still no animations for these Finer Details levels give money now levels have a random amount of money that increase as you go levels interact with setting rewards and score requirements quota and reward are displayed on hover corner brackets appear with easing in and out size on hover aswell changed based unit to MB from KB cuz KB of data are kinda smol fixed some frame update bugs where the stuff updates after selection making it look weird for a frame faint orange glow on the column of levels you are on Next steps you can’t sell daemons in the map for some reason map polish level node entry point map path generation sometimes generates a void where you cant progress and also every node connects to every other consumables shop polish with hovers sfx near the end more animations"}, {"post_id": 28533, "ts": "2026-07-14T20:51:02Z", "hours": 9.1822, "text": "UPDATE #7 The Map Summary I made it so rerolls cost money, empty daemon slots have a graphic now and started the start of a level map/selector. Finer Details made a hacking style map based on slay the spire’s level selector map currently randomly generates nodes and connections map scrolls using left or right click along with scroll wheel nodes also have random descriptions as ive yet to come up with names for enemies and bosses i thought NETWATCH from cyberpunk 2077 would be cool if you can’t afford a reroll the button gets darker to signal Next steps you can’t sell daemons in the map for some reason finish map to link to game consumables shop polish with hovers sfx near the end more animations"}, {"post_id": 26490, "ts": "2026-07-11T09:42:24Z", "hours": 5.0842, "text": "UPDATE #6 The Black Market part 2 Summary I started finishing the shop system i started last devlog. I added rerolls to the shop aswell as a next round button. I also added 2 new Daemons. Finer Details New Daemon “Schrodinger’s Basket” 50% chance of 2.5x points 50% chance of .5x points New Daemon “Dark Web Node” 5% chance for 15x points on scoring made it so when you buy a daemon it gets sold out instead of infinite stock daemons you have dont show up in shop next button currently goes back to normal game but i want it to go to a levels screen/map like slay the spire made credits balance have a thousands seperator of “ “ instead of nothing and no comma cuz a spacebar looks cooler Next steps I want to add a graphic for empty daemon slots and add consumables of some sort and the upgrading daemon system along with the slay the spire level map. shop could use more polish with hovers and icons."}, {"post_id": 25812, "ts": "2026-07-10T08:45:53Z", "hours": 9.7839, "text": "UPDATE #5 The Shop part 1 Summary I started work on a shop system and have item purchases up now. I added a few new daemons and squashed a few new bugs. Fine Details New Daemon “Loyalty Points” 2x points every 5 pins hit New Daemon “Mesh Network” 1.5x score for every ball in play somehow made it so that the description variables werent being assigned in the class and took an hour to hunt that one down added a shop screen with the ability to buy a daemon extracted button logic from multiple places to a function to draw the button instead increased max score from -9.22 × 10^18 to 1.7 x 10^308 bytes made scores that are extremely large get formmated to scientific notation Next steps Still considering that hands system for later maybe in 3 devlogs I want to add a graphic for empty daemon slots and have you a bought item graphic so you cant buy it again in the same shop. reroll and next round button in shop."}, {"post_id": 24451, "ts": "2026-07-08T00:39:27Z", "hours": 6.2844, "text": "UPDATE #4 The Daemon Frontend Overview I made Daemons almost fully functional and made them affect the gamestate. I also added a visual so you know which ball is being effected by which daemon. Fine Details i accidentally used ^ instead of std::pow for one of my functions so it took a while to debug i added text wrapping to Daemon descriptions so that long descriptions dont overflow added a sell value to daemons and linked it to the credits display lines between daemons and balls fade out made is so that the line picks a random starting point on the left side of the daemon Next steps I’m thinking of making a hands system where you choose how many balls you drop at the start and then you have to wait till they all score before you can drop more balls. I want to add a graphic for empty daemon slots and add a shop system which pops up after you pass the score threshold and all balls finish scoring."}, {"post_id": 23373, "ts": "2026-07-06T09:29:37Z", "hours": 8.7297, "text": "UPDATE #3 The Daemon Backend Overview just worked on backend this update and minor graphical changes. I made it so you can click on the daemons and move them up and down aswell as sell them. Fine Details i also changed the level of the daemon indicator location, added the graphic for overclocking (buff past max level planned in future basically), and made it easier to make daemons. Next steps i wanna add a sell value to the daemons to add to credit balance and make the credit balance actually exist. animations and making the daemons do stuff is next step then get back to pachinko"}, {"post_id": 21983, "ts": "2026-07-04T06:24:52Z", "hours": 7.4675, "text": "UPDATE #2 Overview added a class system for my daemons to try to be able to implement a large amount of them including daemon level, color, effects, etc. Made the balls bounce on pegs with animation and hover animation on daemons. also added the balls have a value shown and when scored the scored data is moved upwards a bit until it disappears Next steps the next steps i hope to achieve before the next devlog is that i hope to have a partly functional daemon system that works with the game or atleast be able to reorder and sell them before next update. AI USE had ai generate the daemons vector graphic"}, {"post_id": 21233, "ts": "2026-07-03T02:04:38Z", "hours": 5.1572, "text": "UPDATE #1 so this is the start of my game “BitDrop” it’s a pachinko roguelike that takes inspiration from games like balatro,slay the spire, ultrapool. How it works Your ball starts with a starting score of something i havent figured out the value of yet and gains score to and cashes out at the bottom. The 5 things on the right are jokers from balatro but like 100% original totally not jokers and are called daemons. There is a target Quota score measured in bytes with the base unit being a kilobyte and so on. The plan currently the plan is to have a limited amount of balls per turn and if you put multiple balls at the same time you gain a higher score multiplier but if you have balls leftover you get more money. The pegs i think would be able to be upgraded and the balls aswell. The baskets will prolly be the same throughout and the daemons will assist with scoring higher What i have so far graphics balls drop have have physics balls bounce off pegs everything else not listed is placeholder graphics but yeaaaaa thats about it and the idea for the gameeeeee thank youuuuuu"}]...
|
Title: BitDrop by @thestarviper | Stardance
Devlo Title: BitDrop by @thestarviper | Stardance
Devlogs:
UPDATE #1 so this is the start of my game “BitDrop” it’s a pachinko roguelike that takes inspiration from games like balatro,slay the spire, ultrapool. How it works Your ball starts with a starting score of something i havent figured out the value of yet and gains score to and cashes out at the bottom. The 5 things on the right are jokers from balatro but like 100% original totally not jokers and are called daemons. There is a target Quota score measured in bytes with the base unit being a kilobyte and so on. The plan currently the plan is to have a limited amount of balls per turn and if you put multiple balls at the same time you gain a higher score multiplier but if you have balls leftover you get more money. The pegs i think would be able to be upgraded and the balls aswell. The baskets will prolly be the same throughout and the daemons will assist with scoring higher What i have so far graphics balls drop have have physics balls bounce off pegs everything else not listed is placeholder graphics but yeaaaaa thats about it and the idea for the gameeeeee thank youuuuuu
UPDATE #2 Overview added a class system for my daemons to try to be able to implement a large amount of them including daemon level, color, effects, etc. Made the balls bounce on pegs with animation and hover animation on daemons. also added the balls have a value shown and when scored the scored data is moved upwards a bit until it disappears Next steps the next steps i hope to achieve before the next devlog is that i hope to have a partly functional daemon system that works with the game or atleast be able to reorder and sell them before next update. AI USE had ai generate the daemons vector graphic
UPDATE #3 The Daemon Backend Overview just worked on backend this update and minor graphical changes. I made it so you can click on the daemons and move them up and down aswell as sell them. Fine Details i also changed the level of the daemon indicator location, added the graphic for overclocking (buff past max level planned in future basically), and made it easier to make daemons. Next steps i wanna add a sell value to the daemons to add to credit balance and make the credit balance actually exist. animations and making the daemons do stuff is next step then get back to pachinko
UPDATE #4 The Daemon Frontend Overview I made Daemons almost fully functional and made them affect the gamestate. I also added a visual so you know which ball is being effected by which daemon. Fine Details i accidentally used ^ instead of std::pow for one of my functions so it took a while to debug i added text wrapping to Daemon descriptions so that long descriptions dont overflow added a sell value to daemons and linked it to the credits display lines between daemons and balls fade out made is so that the line picks a random starting point on the left side of the daemon Next steps I’m thinking of making a hands system where you choose how many balls you drop at the start and then you have to wait till they all score before you can drop more balls. I want to add a graphic for empty daemon slots and add a shop system which pops up after you pass the score threshold and all balls finish scoring.
UPDATE #5 The Shop part 1 Summary I started work on a shop system and have item purchases up now. I added a few new daemons and squashed a few new bugs. Fine Details New Daemon “Loyalty Points” 2x points every 5 pins hit New Daemon “Mesh Network” 1.5x score for every ball in play somehow made it so that the description variables werent being assigned in the class and took an hour to hunt that one down added a shop screen with the ability to buy a daemon extracted button logic from multiple places to a function to draw the button instead increased max score from -9.22 × 10^18 to 1.7 x 10^308 bytes made scores that are extremely large get formmated to scientific notation Next steps Still considering that hands system for later maybe in 3 devlogs I want to add a graphic for empty daemon slots and have you a bought item graphic so you cant buy it again in the same shop. reroll and next round button in shop.
UPDATE #6 The Black Market part 2 Summary I started finishing the shop system i started last devlog. I added rerolls to the shop aswell as a next round button. I also added 2 new Daemons. Finer Details New Daemon “Schrodinger’s Basket” 50% chance of 2.5x points 50% chance of .5x points New Daemon “Dark Web Node” 5% chance for 15x points on scoring made it so when you buy a daemon it gets sold out instead of infinite stock daemons you have dont show up in shop next button currently goes back to normal game but i want it to go to a levels screen/map like slay the spire made credits balance have a thousands seperator of “ “ instead of nothing and no comma cuz a spacebar looks cooler Next steps I want to add a graphic for empty daemon slots and add consumables of some sort and the upgrading daemon system along with the slay the spire level map. shop could use more polish with hovers and icons.
UPDATE #7 The Map Summary I made it so rerolls cost money, empty daemon slots have a graphic now and started the start of a level map/selector. Finer Details made a hacking style map based on slay the spire’s level selector map currently randomly generates nodes and connections map scrolls using left or right click along with scroll wheel nodes also have random descriptions as ive yet to come up with names for enemies and bosses i thought NETWATCH from cyberpunk 2077 would be cool if you can’t afford a reroll the button gets darker to signal Next steps you can’t sell daemons in the map for some reason finish map to link to game consumables shop polish with hovers sfx near the end more animations
UPDATE #8 The Map PT 2 Summary Polished the map more and added it into the gameplay loop so that it sets the quota and adds money still no animations for these Finer Details levels give money now levels have a random amount of money that increase as you go levels interact with setting rewards and score requirements quota and reward are displayed on hover corner brackets appear with easing in and out size on hover aswell changed based unit to MB from KB cuz KB of data are kinda smol fixed some frame update bugs where the stuff updates after selection making it look weird for a frame faint orange glow on the column of levels you are on Next steps you can’t sell daemons in the map for some reason map polish level node entry point map path generation sometimes generates a void where you cant progress and also every node connects to every other consumables shop polish with hovers sfx near the end more animations
UPDATE #9 Map PT 3 Summary Added menu transitions, fixeds a few bugs Finer Details changes orange glow on current column to green made the nodes offset on the y and x axis a bit so it looks less grid-like added a glitch menu transition fixed bug where you couldnt interact with daemons in the map menu fixed map generation that generates stray nodes fixed map generate that generated incomplete paths level name it now displayed on box on hover light path that shows a path you can take to get to the node if you hover a future node from current node nodes no longer mostly connect to every single other node Next steps consumables shop polish with hovers sfx near the end more animations
UPDATE #10 Graphics Summary Added money adding animation, 4 new daemons, and a reroll animation Finer Details rerolls have a glitch animation money scoring summons energy balls that glitch into balance 1 for each remaining ball and 1 for the money winning the level fixed bug where you could have over 5 daemons new daemon “Honeypot Trap” 30% chance to duplicate score new daemon “Firmware Backdoor” +5MB per node hit new daemon “Proxy Chain” multiplier per daemon owned (1.2x,1.4x,1.6x) new daemon “Rootkit Persistence” every 3rd ball scores 3x Next steps balancing consumables shop polish with hovers sfx near the end more animations
UPDATE #11 Graphics Summary Added moving daemon animation and added encrypted nodes into the map that are a mystery of what it is until you click on them Next steps balancing consumables shop polish with hovers sfx near the end more animations
UPDATE #12 Audio Summary Added sound effects and shop polish breakdown transition sound (my favorite) bounce sound (need a better one) hover glitched node sound hover daemon sound hover shop item sound hover shop items for more interactivity Next steps balancing consumables more sfx more animations
UPDATE #13 Consumables Summary Added consumables slots graphics and the use/sell buttons that do nothing so far mainly ripped from the daemon code along with basic backend structure for consumables. also fixed a bug where hovering sfx never stopped playing on glitched nodes Next steps balancing consumables actions more sfx more animations
UPDATE #14 Consumables 2 Summary Added two consumables, changed price of rerolls and did some code restructuring. breakdown added a consumable “flash sale” is basically temperance from balatro and gives sell value of all your daemons into your balance added a consumable “dycrypt” and it decrypts unknown nodes so you know what they are moved the payout ball orb stuff to a different file moved the transitions stuff to a different file you can now sell consumables and it adds to the balance aswell two types of consumable one is instant use and one requires selecting something to effect i will use this later on nodes Next steps balancing more consumables more sfx more animations
UPDATE #15 Consumables Shop Summary Added consumables to the shop and reduced consumables slots breakdown you can buy and reroll consumables in shop reroll animation rerolls consumables too the consumables are a different shape then daemons in shop i gotta figure out the colors to be more different tho two consumable slots instead of four Next steps i came up with alot more ideas to implement balancing endless mode skill tree overclock shards and daemon leveling daemon synergies more consumables more sfx more animations
UPDATE #16 Map Graphics Update Summary updated the nodes in the map to look better and custom icons along with making the pathways more distinct from the background breakdown swirling things around node passively gliched nodes have funky movement with their animation which i find cool made pathways more distinct from background lines color nodes now have icons instead of text Next steps I currently plan to dedicate the next few updates to improving graphics before i continue with the gameplay changes i have listed below balancing endless mode skill tree overclock shards and daemon leveling daemon synergies more consumables more sfx more animations
UPDATE #17 Shop Graphics Update pt 1 Summary updated shop graphics and animation breakdown used ai to generate a shop item slot and polished it in microsoft paint you can hover buttons and the main part and plays sfx buttons now have 6 vertexes daemons only get bought on left click release instead of on click since the shop items use sprites now instead of vector drawing i now hue shift the sprite to acheive different colors from one sprite (this took a while) reduced shop to have 4 items instead of 5 for balance and to fit the graphics nicer Next update plan update the consumables section of the shop to look better add buy animations
UPDATE #18 Shop Graphics Update pt 2 Summary updated shop graphics for consumables and made a custom class to make custom shaped polygons breakdown made consumables look better made consumables have a full consumables slot graphic and a not enough money alert made consumables have a background thingy in the shop that looks cool same hue shift graphic trick applied to the consumables like the daemons made insufficient funds for the daemons larger and more clear made a custom class for making polygons with an arbitrary number of vertexs so its faster to make polygons instead of the original way i used which was draw triangle fan made it so the class also detects hovers and clicks built in to make it easier Next update plan im hoping this next update can be completed in like 5 hrs or less to keep the pace of more frequent devlogs add buy animations add sell animations screen shake helper function
UPDATE #19 more animations Summary added buy and sell animations along with fixing a few bugs it was alot faster than initially planned cuz it was just re-purposing existing code breakdown added buy animation for deamons and consumables added sell animations for daemons and consumablse fixed bug where shop didnt refresh when you re-enter after beating a level fixed bug where boss levels had a smaller quota than normal levels screenshake helper function implemented so i can just put screenshake(intensity,duration); anywhere and add screenshake with one line added a glitch location helper function based off my glitch transition code so now you can do TriggerGlitchAt(bounding-box-using-raylib-rectangle, duration); to glitch effect a location for a duration Next update plan maybe 6 hours for this update add more sound effects expand consumables system maybe make daemons look better but that might be for the update after this one
UPDATE #20 more animations Summary got sidetracked from original plan and made daemons look better along with making the map have velocity that keeps momentum after you stop scrolling breakdown made daemons look better using a dual layer system map has velocity that decreasese in speed after you stop scrolling with mouse click or scroll wheel dual layer daemon graphics I think this is kinda cool so basically i have the empty daemon slot image and when a daemon slot is empty it just keeps that sprite up and adds text ontop of that that says empty daemon slot (number). But when you get a daemon it uses the same hueshift function i have from the shop daemons and consumables and hueshifts an overlay with a transparent interior to add color and stuff. Empty daemon slot: empty daemon sprite layered text saying slot number and that it’s empty Occupied daemon slot: empty daemon sprite occupied daemon overlay with hue shift title and description text overlay + level overlay then put hover effects and stuff ontop Next update plan add more sound effects expand consumables system
UPDATE #21 consumable board editor Summary added new consumables that modified pins on the board to do different things breakdown added system where you can select nodes now added system where you can select multiple things to modify with a consumable added pin effect “mitosis” splits node into two added pin effect “overclock pin” makes pin valued at 1.5mb instead of 1mb prolly changing this this was just testing added pin effect “volitile pin” makes pin add a random payload from 1-10mb also was just testing prolly will modify this Next update plan add more sound effects make it so mitosis is called miosis and splits the value of the ball into half between the two balls make it so you can modify a pin with multiple modifiers and hovering shows what mods it has make pin modifiers like minecraft enchantments where you can apply some modifiers not with each other like mending + infinity isnt possible in minecraft or fortune + silk touch type thing
UPDATE #22 consumable board editor TWOOOO Summary made is so you can stack mods on pins and some are incompatible with others breakdown you can stack mods of different types on pins some mods are incompatible with each other if you modify a pin with an incompatible modifier it will just remove the conflicting modifier from the pin red alert text on consumables with conflicting modifiers hover shows the pins modifiers Next update plan you can stack modifiers on the same pin to level it up more pin modifier types make pins on modifiers visually distinct that can be stacked ontop of each other
UPDATE #23 Escape Menu Summary modularized code for pin mods, added levels and max levels, started work on an escape menu for settings. breakdown hover on nodes now shows level of the modifier on the node nodes like clone level 1 have it so the payout is split between the two balls and level 2 has it so that it isnt split between the two added menu button next to balance display modularized code for pin modifiers so its easier to add conflicts and such in the future and new features esc puts you in an esc menu to quit run new run settings optinos etc the same as the menu button esc menu stops time and physics aswell as all interaction in game until you unpause fixed issue where reroll text would overflow outside of the reroll box so now it resizes to fit inside of the reroll button node modifiers were also split into a different file Next update plan I got sidequested again for the escape menu so ill be working on that in tandem with the modifiers code and stuff make pins on modifiers visually distinct that can be stacked ontop of each other more work on esc menu
UPDATE #24 Escape Menu two Summary pin mods now show what level they are aswell as all the other mods on the pin in the form of colors and dots and hovering shows it more detailed also escape menu has buttons now. breakdown escape menu now has buttons and a different color back button when opening esc menu theres a glitch effect now along with a sound effect and closing does same thing putting a mod on the pin outlines the pin with the color of the mod and a dot for every level of the mod putting multiple mods on a pin divides the outline into multiple parts Next update plan add stats menu add settings menu add main menu maybe add consumables for baskets aswell but prolly the update after this one
UPDATE #25 Escape Menu three Summary added settings and stats page to the esc menu thing breakdown made it so that you can add more stats and settings with just one line of code to control or display a variable added a gamespeed notched slider added volume slider added screenshake toggle added a bunch of stats in the stats page moved back button to the bottom of the menu since we are nearing the phase where i ship this project i already have set a roadmap of things i need to do so i figure i could just share it here: add main menu maybe add consumables for baskets still not decided add tutorial endless mode daemon synergies polish and balance by adding more stuff and things in general to daemons,consumables,stats,settings,pin mods music
UPDATE #26 Main Menu Summary made a main menu breakdown took the grid background from the map and put it in the main menu took the tri-circle spinning animation from the map and put it in the main menu reused the button class i use everywhere settings button just goes to the settings menu i already made stats button just goes to the stats menu but i think ill change it to a tutorial button terminate button just gives a popup that says “its a web game silly” Roadmap in order of completion add tutorial endless mode daemon synergies maybe add consumables for baskets still not decided polish and balance by adding more stuff and things in general to daemons,consumables,stats,settings,pin mods music
UPDATE #27 Tutorial Summary made a hint based tutorial system every time you encounter a new mechanic breakdown made it so that in 1-2ish lines of code you can add a new hint to any aspect of the game hints pop up only on the first time you encounter a mechanic hints darken the background and go away with a glitch effect and sound effect after clicking “got it” button Roadmap in order of completion fix some of the bugs i have noted down in a personal doc that are hard to explain endless mode daemon synergies maybe add consumables for baskets still not decided polish and balance by adding more stuff and things in general to daemons,consumables,stats,settings,pin mods music
UPDATE #28 Endless Mode Summary added a win screen for when you win with a button to go endless mode called “ascensions” breakdown made endless mode made win screen (prolly should make it look better) fixed bug where you clicking back in a submenu in escmenu would double click and exit out of esc menu entirely fixed bug where you couldnt exit stats menu in escmenu from main menu Roadmap in order of completion add consumables for baskets to multiply basket mult re-org code before polish and balance cuz its kinda goofy spaghetti silly polish and balance by adding more stuff and things in general to daemons,consumables,stats,settings,pin mods add more screenshakes cuz i only have a few screenshakes music
UPDATE #29 Polish Polish Polish Summary added a few consumables and added basket mods breakdown added a consumable to multiply a basket’s mult by 1.5x permanently added a consumable to lower quota on a level by 25% added a pin modifier that makes balls gravitate towards it made it so that consumables in shop can have weights Things to polish before shipping daemons consumables pin mods screenshake more tutorial steps music / sfx balancing
UPDATE #30 A little bit of everything Summary added a loss screen, another pin modifier, changed clone pin graphic, added music, changed map nodes, added overload mechanic breakdown added a loss screen with a loss sound effect added another pin mod called “Amplify” which just gives 1.5x score on hit to the ball changed clone pin graphic to show the pull distance and changes with leveling added main menu music and gameplay music changed map nodes by renaming them and changing colors around made final boss node bigger than it was originally for emphasis added overload mechanic that basically is a multiplier that increases by .08x per pin hit and decreases by .4x per second and adds the multiplier on scoring Things to polish before shipping daemons consumables balancing sfx
UPDATE #31 Balancing Summary ITS ALL COMING TOGETHER RAHHHHH. I added like 10 new daemons changed icons and balanced the prices along with sending my project into the hackclub slack for playtesting. breakdown added 10 new daemons changed icons of every daemon since they shared the same icon balanced prices of consumables and daemons used playtester feedback: some things were confusing so i added more hints used playtester feedback: a button in the shop was unintuative so i made it so that it worked more intuiatively used playtester feedback: playtester found a bug with one of the new daemons that destroyed itself didnt free up a slot NEXT UPDATE IS JUST SOUND EFFECTS AND MAYBE FEEDBACK FROM SLACK THEN I SHIP YAY IM GETTING THIS DONE BEFORE I SLEEP
UPDATE #32 FIREFOX SUCKS Summary FIREFOX SUCKS. anyways i added a buncha sfx and ct5 found a bug where the game done goofy mode on firefox so i had to fix that breakdown map hover sfx shop buy sfx cashout sfx basket score sfx node pin sfx louder on playtester request used playtester feedback: this game on firefox compiled weird goofy its up on itchio now wowie #SHIP TIME YAYAYAYAYAYAYAY
Ships:
PLEASE READ THE HINTS SO YOU KNOW HOW TO PLAY I made a pachinko roguelite game that is inspired by balatro, slay the spire, and ultrapool. The game is a web game that is hosted on itch.io so no need to download anything. Have fun!...
|
1792810544.5796192
|
1792896944.5796192
|
|
508
|
Slime Simulator by @RespectableDot | Stardance
|
RespectableDot
|
1
|
166.0
|
3195
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-05T19:22:45Z", "hours": 166.0, "multiplier": 19.34, "payout": 3195, "blessing": "neutral", "text": "A simulator that is about making crazy slimes through natural selection, evolution, and genetic engineering. One thing that made this project challenging was the slime pathfinding. To solve this, I used the A* pathfinding technique. Something I am proud of is the art style. I worked very hard on it and I think it look good. To test my project, just click on the demo link. Thank you to the people who supported and suggested good ideas to the project!", "repo": "https://github.com/Aidnpatrick/Slime-Hub", "demo": "https://respectabledot.itch.io/slime-simulator"}]...
|
[{"post_id": 41491, "ts": "202 [{"post_id": 41491, "ts": "2026-08-05T18:49:31Z", "hours": 3.4703, "text": "Sound! Devlog 35 This will be a short devlog because I don’t know what else to say. Sounds effects I added inside the game: Slime spawning Clicking on slime clicking on ui(button) Slime Noises ocean wind Slime Eating Planting Guns(Lasers, Regular bullets Passive slime noises Active slime noises Night(Crickets) Credit to qubodup and filippe for the slime sound effects."}, {"post_id": 39720, "ts": "2026-08-02T21:12:32Z", "hours": 6.6606, "text": "Optimization and Fixes Devlog 34 2nd to last devlog! Cant wait to ship Things I added: When you press escape or the gear icon at the bottom-right, you can enter the settings page. In here, you can disable or enable features to your likings. This can help run the game faster on lower-end PCs. Placing blocks, plants or effects shows a small special effect. Between and Night, there will be dusk and evening. They will make the sky orange for 15 seconds. There will be more farmers and less unemployed people. Big Fixes: Upgraded the pathfinding system for the slimes. Whenever they are hungry but can’t reach their food, they will find alternate food that is close to them."}, {"post_id": 37321, "ts": "2026-07-29T22:57:14Z", "hours": 7.0725, "text": "Another Batch of Updates Devlog 33 I dont know when to stop this project, I have a lot of things to add… Check out my game here! https://respectabledot.itch.io/slime-simulator Things I added: Day/Night Cycle! Every minute it switches from day to night or vice versa. When at night, slimes and buildings glow so they are easier to see. Also, it looks cool. (The light thing took a long time to figure out) There is a notification bar that tells you what is currently happening in the world. When guns fire, it will create a muzzle flash effect. New Items: FN SCAR: A powerful gun that hits hard. It is kind of inaccurate though. Laser Gun: Its bullets are faster than other guns. Does decent damage."}, {"post_id": 35337, "ts": "2026-07-26T17:35:05Z", "hours": 8.3517, "text": "More Mechanics and Items! Devlog 32 Things I added: Houses are a new building. Currently they don’t really do anything, but later on they can be used for slimes to sleep in. Doctors is a new ability that treats and heal slimes. Their item is a medkit. When you favorite a slime, a star icon will show up above them. This helps keep track of your favorite slimes. Added 8 new cosmetics! New Items! MP5: A submachine gun that fires really fast. Blue staff: A staff that is blue and shoots out 3 blue balls. Katana: The first melee weapon. Does a lot of damage. Medkit: Used by doctors to treat and heal other slimes. M1911: Originally called the pistol. AR-15: Originally called the Rifle. MP-133: Originally called the Shotgun. Things I will add: More cosmetics coming soon! Houses will have a function other than doing the embappe special Game link here: https://respectabledot.itch.io/slime-simulator"}, {"post_id": 33076, "ts": "2026-07-22T17:35:43Z", "hours": 9.6567, "text": "Items and Slime sizes Devlog 31 I forgot to devlog again :( Items and Equipment Slimes can now have items. Items can help them complete tasks or give them a buff. To see what item the slime has, check in the slime stats. Items currently in the game: Hammer: Used for constructing buildings. Hoe: Used by farmers to farm. Pistol: For killing slimes. Rifle: For killing slimes. Slime characteristics and stuff Instead of slimes being the same size, they can be big or small. This makes it more realistic, I guess. Slimes can pass down their family name. If the two parents have different family names, the offspring chooses one of them. UI Changes The section for terrain editing got a small upgrade. Next to the text, there is an image of the block to show you what it looks like. At the top-right corner of the slime statistics page, there is the X button that closes the UI. You can check what equipment the slime is using by going to the slime UI & statistics Other Waves can appear outside of the editing zone so it looks more natural."}, {"post_id": 31412, "ts": "2026-07-19T19:17:11Z", "hours": 2.9606, "text": "Spells! Devlog 30 Check out my game here: https://respectabledot.itch.io/slime-simulator Spells control and influence a slime mentally and physically. Currently, there are only 4 spells. I will plan to add more of them in later updates."}, {"post_id": 30419, "ts": "2026-07-17T22:56:36Z", "hours": 7.5947, "text": "UI Revamp and cosmetics Devlog 29 I am currently working on another update but I forgot to post a devlog, so I will post a devlog for the things I finished then post the ones I haven’t finished yet. Things I added: After taking some feedback, I changed some stuff inside the slime UI. Instead of just plain text, I added pictures and icons to make reading a slime’s information much easier. I also replaced most of the transparent boxes with some better ones that are drawn. For the cosmetics, I added around 10 new hats."}, {"post_id": 29034, "ts": "2026-07-15T18:03:17Z", "hours": 6.9889, "text": "Kingdoms and Colonies👑🔥👑🔥 Devlog 28 Slimes can establish kingdoms if there aren’t any or are far enough away from other kingdoms. If a slime is spawned by the user, the slime will head to the cllosest kingdom(If close enough). But if a slime came from another slime, they will automatically be part of the kingdom. A slime can create a settlement if they are already in a kingdom and is far enough away from it. If a slime has one parent from a kingdom and another from another kingdom, then they will random choose which to live in. A slime farmer can only work in the kingdom’s fields. Things I will add next time: War and Economy will be my next priority. Check out my game here: https://respectabledot.itch.io/slime-simulator"}, {"post_id": 27515, "ts": "2026-07-13T04:30:28Z", "hours": 11.2606, "text": "Another big update but isn’t as tiring Devlog 27 Things I added: Violence is a lot more encouraged between the slimes. There is too much peace. Added lettuce. Instead of the slimes growing meat, they grow lettuce. This is a lot more normal. Slimes have a Walking Animation, which is just them expanding and shrinking constantly. Food generation in farms is reduced because this encourages them to explore the world more. Bug fixes Buttons in the bottom bar will not activate when users are cancelling them. In planting mode, blockable objects like trees will destroy items beneath them. In building mode, changing a tile will cause things that are stuck on top of them to disappear. Things I will add next time: There will be a list of effects. These effects buff or weaken a slime’s body or influence the way it acts. An example could be make it faster, have more health, or make it more prone to attacking other slimes. Clans and kingdoms is already being worked on. Check out my game here: https://respectabledot.itch.io/slime-simulator"}, {"post_id": 26625, "ts": "2026-07-11T15:32:53Z", "hours": 7.8944, "text": "100 HOURS LETS GO Farms. Devlog 26 This is the most tiring update ever. This update is a test, so a lot of things can be broken. Things I added: Added roles. Some slimes get assigned task, like constructing buildings or farming. Added farms. Slimes can plant and produe their own food. All they have to do is place farming soil near windmills that are set up by constructors. The soil will automatically generate crops, which is meat. Made the art for the windmill. It even has an animation! Slimes interacting with other slimes is encouraged. Food spawning is greatly reduced because slimes can now produce their own food. Check out my game here: https://respectabledot.itch.io/slime-simulator"}, {"post_id": 26089, "ts": "2026-07-10T17:53:13Z", "hours": 3.8569, "text": "Miscellaneous Updates Devlog 25 Things I added: Made a sprite for when the slimes die. It looks like a splat. When a slime dies, their family member and friends get sad. You can press “h” to hide UI. Bug Fixes: Fixed a bug where the slimes get stuck after doing eating or interacting. Fixed the tutorial-skipping button. Slimes don’t lose their color anymore Check out my game here: https://respectabledot.itch.io/slime-simulator"}, {"post_id": 25634, "ts": "2026-07-10T01:18:16Z", "hours": 2.4928, "text": "Introduction Update Devlog 24 Made a simple intro. It contains the game’s logo and unity’s logo. Made a tutorial for the start of the game. It teaches you how to spawn slimes. If you have already played, there will be an option to skip. Check out my game: https://respectabledot.itch.io/slime-simulator"}, {"post_id": 25102, "ts": "2026-07-09T02:57:24Z", "hours": 2.9383, "text": "Cosmetics Update Devlog 23 I added 10 kinds of hats that can spawn on the slimes. They don’t affect the slimes, it’s just for appearance. My project is now on itch.io, go check it out! https://respectabledot.itch.io/slime-simulator"}, {"post_id": 24389, "ts": "2026-07-07T22:19:12Z", "hours": 5.8222, "text": "Random Good Updates Devlog 22 Sorry for not devlogging more Made a new button where you can plant weeds and trees. I don’t know what else to say but this took me so long. Reworked the violence behavior in slimes. Before the update, slimes would attack the nearest person when they get upset and hungry (Hangry). But now, slimes may choose to slime out someone nearby OR someone who they already don’t like in their relationships list. This makes it more realistic to real life. Reworked equation for slime violence weight: tasks[2] = distanceSlime > 18 ? 0 : (100 - stats[2] * 0.6f - stats[0] * 0.85f) / 50 + angryBias + baseTasks[2]; When slimes sleep, they will have their own special sprite for that. Also, they will have the “zzz” icon above them. Still working on the issue where slimes get stuck after doing some task. It seems to be fixed though, for now. My project is now on itch, go check it out! https://respectabledot.itch.io/slime-simulator"}, {"post_id": 23626, "ts": "2026-07-06T18:08:25Z", "hours": 1.6611, "text": "Misc. Update Devlog 21 Added palm trees. They act like normal tree but spawn on sand. Also, they generate coconuts. Made a system where the slime’s pathfinding algorithm is a lot more efficient. Whenever they find a place where it’s impossible to go, they will make a mental note of that. This reduces possessing power. My game is now on itch, go check it out! https://respectabledot.itch.io/slime-simulator"}, {"post_id": 23264, "ts": "2026-07-06T03:28:23Z", "hours": 5.8814, "text": "Emotion Update 😀😢😡 Devlog 20 I have something else that I worked on but there is still a little more work to go. I will post it in another devlog. For this update, I added emotion to the slimes. Slimes will get happy when they eat food or when they talk to their friends. They get sad overtime when they don’t do anything or they get attacked. You will know when they get upset when a emoji shows up above them. Emojis will show up for other things too, like when eating, fighting, or interacting with others. I will post the other part in the next devlog. My game is now on itch, go check it out! https://respectabledot.itch.io/slime-simulator"}, {"post_id": 22259, "ts": "2026-07-04T17:10:08Z", "hours": 2.6747, "text": "Miscellaneous Update Devlog 19 My game is now on itch, go check it out! https://respectabledot.itch.io/slime-simulator — Things I added: Added a crosschair. THis makes it a lot easier to see what you are hovering over. The crosschair can highlight on tiles and slimes. Made an about and instructions page. Go to the top-left and you will see the buttons that will take you to the pages. Fixed slime behavior. Sometimes the slimes get stuck after eating so I hope I fixed the issue."}, {"post_id": 21595, "ts": "2026-07-03T17:07:39Z", "hours": 3.0675, "text": "Taking Feedback Devlog 18 Font Change When I showed my project to people asking for some suggestions, they said I should change the font. So I decided to change the font to more of a pixel style, called “Pixel Operator”. It took a while to set up due to my lack of experience. Slime Violence Slime will now be able to attack each other. It starts from them being sad or angry, and being hungry. Then they unleashed their fury onto other slimes. When they hit other slimes, the slimes that are hit lose health. Other Stuff Slime can now slowly regenerate health when they are fed and have energy. Fixed a bug where rocks wont spawn in world editing mode."}, {"post_id": 20544, "ts": "2026-07-02T04:58:51Z", "hours": 3.8733, "text": "Visual Update Devlog 16 Check out my game here: https://respectabledot.itch.io/slime-simulator Particles Water used to look bad because it’s just blue and nothing else, so I added waves for the movement. Leaves now fall off trees. Other graphics When near land(Sand, Grass, rocks), the water becomes more shallow. It is indicated by the water being more light than the others. Added more grass when starting the game. Clouds appear a lot less due to it sometimes blocking the user’s vision. Bug fixes Fixed a bug where slimes were not spawning, caused by a poor algorithm. Temporarily removed the buggy walking animation for the slimes. I also added apples🍎"}, {"post_id": 20090, "ts": "2026-07-01T16:38:46Z", "hours": 6.3022, "text": "World Building Update Devlog 15 Terrain Editing You can now edit your world. All of the blocks will be available. To use this feature, click on the button with the blocks. All of the blocks: Water, Grass, Sand, Rock Programming took a bit longer than I thought, but testing was surprisingly easy. Next time, I could add things other than blocks, maybe like trees and grass. Other stuff There is now world age so you know how old your world is. Small changes in some of the UI"}, {"post_id": 18659, "ts": "2026-06-29T20:59:19Z", "hours": 5.4806, "text": "Map Update Devlog 14 Terrain Generation After implementing A* pathfinding, I added obstacles and other things for the map. I used to perlin noise to make the mountains and rivers feel more real. float noise = Mathf.PerlinNoise(i * 0.05f+ offsetX, j * 0.05f + offsetY); Added trees. I can make them useful for the slimes in later updates. Art I made the sprites for the rocks and water. It didn’t take that long because it didn’t need much detail. Made the art for the “kill slime” button, which is a knife. Bug fixing Fixed a ton of bugs because adding in the new pathfinding messed a lot of things up. A lot of problems came up when making terrain generation, like the slimes behaving weirdly. Future Updates I might add clans and tribes to make things more interesting. Violence will be added very soon. Check out my game here: https://respectabledot.itch.io/slime-simulator"}, {"post_id": 17664, "ts": "2026-06-28T15:31:41Z", "hours": 5.295, "text": "Big Update Devlog 13 Favorites tab You can now favorite slimes. This is for when you like one of them or find one interesting. To use, just click on one of the slimes. Kill tab If you want to get rid of a slime, go to the kill tab and click on the slime. I will add the death animation next time. New pathfinding Replaced the old AI reinforcement learning with the A* pathfinding method. This is because the new system can avoid obstacles and doesn’t take much computing power. UI revamp Made the UI better. Most of the buttons and panels have art and stuff. Things I will add in the future Terrain: You will be able to customize the terrain to make the world more interesting Animations: When walking, the slime will have animation."}, {"post_id": 16090, "ts": "2026-06-26T04:47:00Z", "hours": 6.1744, "text": "A title Devlog 12 Things I implemented Slimes don’t mixed up colors equally anymore. This is because mixing them up equally makes them more dull and grey over time. To stop this, I had to mix the colors up unevenly to maintain the vibrant colors. To track and follow a slime, click on them and press the “Track” button. The slime UI got a major upgrade. It’s now easier to read and more sorted out. You can now spawn food for the slimes. To do it, go to the bar at the bottom. Above the bar, there is a text that tells you what you have selected inside the bar. Clouds have been implemented. Right now they don’t do anything, but they will be able to drop food."}, {"post_id": 15381, "ts": "2026-06-25T00:34:38Z", "hours": 5.0311, "text": "Batch of Updates! Devlog 11 Slime genetics Slimes have more realistic natural genetic creation. Instead of only picking up one of their parent’s colors, they mix the two colors together. Speed and Health changes for an offspring is toned down. Implemented more slime mutations. These includes drastic color changes, faster or slow speeds, or health changes. When testing, I noticed that after a while, the colors started becoming black(I don’t know why). That’s why I made it so that an offspring may be given a bold color(Blue, Red, Green, etc.). UI Made a system where you can view slimes’ friends just by checking their friends list. By clicking on one of their friends or family, it will take you to the selected slime. I made the UIs a lot more responsive and clean."}, {"post_id": 13969, "ts": "2026-06-22T22:33:23Z", "hours": 4.535, "text": "More Mechanics! Devlog 10 Small UI Update The slime information and slime population text boxes are separated. There is now a bar that is gonna contain some button. Right now the only button I added is adding more slimes, but there are gonna be more in the future. Other Things I added Slimes can now have multiple babies instead of only one. I added some grass to make it less barren."}, {"post_id": 12908, "ts": "2026-06-21T04:19:17Z", "hours": 3.1158, "text": "Update Devlog 9 Traits Slimes now have traits! Traits are minor tweaks on the brain of a slime. This brings out personality and characteristics. For now, traits are only obtainable at birth. Slimes aren’t able to pass down traits to their offspring. Other stuff I finished working on the background and is preparing to work on the art of the food. Things I will do next time I will start working on the UI because that makes it easier for people to test my simulator. I will work on more traits, so far I have 7-8 of them."}, {"post_id": 12810, "ts": "2026-06-20T23:26:52Z", "hours": 7.8597, "text": "Big Fat Update 🔨🔨🔥🔥 Devlog 8 I don’t use AI to write any of my devlogs. Relationships Slimes can interact with one another. To do so, they just have to be next to each other. After an interaction, if they haven’t known each other before, they will have an updated friends list. If they have already met each other, then what they think of each other goes up. If two slime’s relationship value go up to a certain number like 30, then they can have babies. DNA and Genes Each Slime have their own characteristics. This includes speed, health, and species. They pass down their genes to their offspring. Offspring’s traits will be slightly changed to maintain diversity and natural selection. For example, a slime with a fast genes will be able to get to a food quicker than the ones that are slow. The faster slime will get to survive and make babies. Color 🔥🔥(My fav update) Slimes have multiple kinds of traits, and that includes color. They can pass down their color to their offspring(Though their offspring’s color may be slightly different). This addition makes the game look a lot better. Problems 😢😢😢 While doing some tests, I noticed that some slimes were dying. This was weird because there were definitely enough food for everyone. When I looked closer, I realized that there was a bug where some slimes get stuck and become braindead. This problem is and still very difficult to fix."}, {"post_id": 11703, "ts": "2026-06-19T02:03:09Z", "hours": 2.3189, "text": "Art! 🔥🔥🔥🔥 Devlog 7 Made a sprite for the slimes. The default color is white because it supposed to be changed into other colors. The movement of slimes is now smooth instead of teleporting to the nearest block. A lot easier ot tell what’s going on. Things I will add later: Better UI will be implemented later. Because right now it’s just a piece of text that tells you the stats of a slime. Demo will be released soon because I need some feedback. Slimes will be able to kill each other. 💀💀💀"}, {"post_id": 11574, "ts": "2026-06-18T21:13:40Z", "hours": 4.0161, "text": "More mechanics! Devlog 6 In this update I added a basic social structure and generations. Things added in this update: When two slimes meet, they gather some information. If one slime’s mental value is bad while meeting, then they will have a bad meeting. If they have a good meeting and keep it up for multiple interactions, then they can have babies. There are a lot less bugs when slimes are interacting with each other. They don’t glitch out nor do they just stop moving. Food now constantly generates, so the slimes can live and thrive. Things I will add later: Parents will soon be able to pass down genes and DNA to their offspring. There will be a more advanced social structure so it doesn’t seem too robotic. Art will be implemented later on. I might put this on itch.io for people to test. My game is now on itch, go check it out! https://respectabledot.itch.io/slime-simulator"}, {"post_id": 11017, "ts": "2026-06-18T01:23:04Z", "hours": 3.3789, "text": "Relationships!😀😀😀😀 Devlog 5 This update is mainly focused on relationships. Slimes can now interact with each other. How it works: ⚙️⚙️⚙️ Slime number 1 will look for another slime within a certain radius. If found, slime number 1 will go to that slime (Slime number 2) and have some sort of interaction. If slime number two is already in the list of contact of slime number one, their bond will go up. Formula for the value of interacting: (100 - stats[2]) / 100 - Vector3.Distance(FindClosest(otherSlimes, Mathf.Infinity, \"pluh\").transform.position, transform.position) / 20; Later updates: 🔨🔨🔨🔨 Big fixes: Sometimes after an interaction, slime glitches out and has a seizure. The seizure is temporary but I still want to fix this issue. Slime mating: If slimes have a very high bond, they can have baby slimes. (Baby slimes will have the genes and DNA of their parents)"}, {"post_id": 10413, "ts": "2026-06-17T03:20:04Z", "hours": 2.1417, "text": "4th Devlog Like & Sub for good payouts (Legit and proved) Things I added: ⭐🐵 Slimes now has an idling state. This mean that when they dont have anything to do, they will just wander around to nearby places or stand still. This mechanic is to make the slimes feel more alive. Made it so that whenever a slime finishes a task, they will have a cooldown for around 2 seconds. Then they can do their thing again. Fixed bugs, like the UI not working right and the slime tweaking out whenever they finish pathfinding. Thing I will add later: 🔨🔨🔨 Slimes will soon have relationships with other slimes. They can be friends or enemies. Since I already coded the pathfinding, it should be easy. Slimes who are enemies will attack each other. DNA and Genes will be added later on. Parents will be able to pass their genes to their offsprings."}, {"post_id": 9735, "ts": "2026-06-16T05:02:30Z", "hours": 2.0414, "text": "Devlog 3.😩😩😩 Things I added: Slimes now have color! There is a statistic text at the top-left. Whenever you click on a slime, it will show the stats of that slime. Fixed a bug where slimes stop whenever they collect food."}, {"post_id": 9560, "ts": "2026-06-15T22:42:40Z", "hours": 0.8458, "text": "Du Bist Gut Genug 🥵🥵 (Ball knowledge) Devlog 3 Things I added: I wanted to make each slime have a unique name, so I added a name generator. How this works is a script will put random words from a text file that contains nouns. Slimes now has different movement speed. The average speed of all of them should be around 0.7 block/sec. (Lowest speed: 1 b/s, Highest speed: 0.4 b/s) Slimes now have hit points. If the hit points go to 0 they will die. (Lowest hitpoint: 70, Highest hitpoint: 140) If the slime has 0 hunger or is too tired, they will slowly start to lose health and die. Made the github repo, so people can see my cool code."}, {"post_id": 9498, "ts": "2026-06-15T21:03:54Z", "hours": 2.3692, "text": "2nd Devlog🥵🥵🥵 Note: Still no github repo for you Things I added: I put together the slime, so now it can walk around and do things slimes do. The slime now has a food source, so the slimes can now walk around and collect some nutrients. Things I will add in the future: Slimes will be able to do more things, and they will be able to interact. They can do things like talk or kill each other."}, {"post_id": 8918, "ts": "2026-06-14T20:53:50Z", "hours": 1.3481, "text": "1st Devlog! Note: No repo yet, I will add it later. Things I added: Made the structure of a slimes’ brain and mechanic. Made my own AI pathfinding thingy. Right now it doesn’t support obstacles, but it will soon. How the slime’s brain works: There was many variables inside. Each variable represents a stat, like hunger points or energy level. Once in a while the brain chooses the highest variable and will act accordingly. ex. If the hunger variable is the highest then the brain will find something to eat. Updates for later: I will actually put everything together and maybe make the repo. The slimes will be seperated into different species. The the much later future, you can influence the slime’s dna and stuff."}]...
|
Title: Slime Simulator by @RespectableDot | Starda Title: Slime Simulator by @RespectableDot | Stardance
Devlogs:
1st Devlog! Note: No repo yet, I will add it later. Things I added: Made the structure of a slimes’ brain and mechanic. Made my own AI pathfinding thingy. Right now it doesn’t support obstacles, but it will soon. How the slime’s brain works: There was many variables inside. Each variable represents a stat, like hunger points or energy level. Once in a while the brain chooses the highest variable and will act accordingly. ex. If the hunger variable is the highest then the brain will find something to eat. Updates for later: I will actually put everything together and maybe make the repo. The slimes will be seperated into different species. The the much later future, you can influence the slime’s dna and stuff.
2nd Devlog🥵🥵🥵 Note: Still no github repo for you Things I added: I put together the slime, so now it can walk around and do things slimes do. The slime now has a food source, so the slimes can now walk around and collect some nutrients. Things I will add in the future: Slimes will be able to do more things, and they will be able to interact. They can do things like talk or kill each other.
Du Bist Gut Genug 🥵🥵 (Ball knowledge) Devlog 3 Things I added: I wanted to make each slime have a unique name, so I added a name generator. How this works is a script will put random words from a text file that contains nouns. Slimes now has different movement speed. The average speed of all of them should be around 0.7 block/sec. (Lowest speed: 1 b/s, Highest speed: 0.4 b/s) Slimes now have hit points. If the hit points go to 0 they will die. (Lowest hitpoint: 70, Highest hitpoint: 140) If the slime has 0 hunger or is too tired, they will slowly start to lose health and die. Made the github repo, so people can see my cool code.
Devlog 3.😩😩😩 Things I added: Slimes now have color! There is a statistic text at the top-left. Whenever you click on a slime, it will show the stats of that slime. Fixed a bug where slimes stop whenever they collect food.
4th Devlog Like & Sub for good payouts (Legit and proved) Things I added: ⭐🐵 Slimes now has an idling state. This mean that when they dont have anything to do, they will just wander around to nearby places or stand still. This mechanic is to make the slimes feel more alive. Made it so that whenever a slime finishes a task, they will have a cooldown for around 2 seconds. Then they can do their thing again. Fixed bugs, like the UI not working right and the slime tweaking out whenever they finish pathfinding. Thing I will add later: 🔨🔨🔨 Slimes will soon have relationships with other slimes. They can be friends or enemies. Since I already coded the pathfinding, it should be easy. Slimes who are enemies will attack each other. DNA and Genes will be added later on. Parents will be able to pass their genes to their offsprings.
Relationships!😀😀😀😀 Devlog 5 This update is mainly focused on relationships. Slimes can now interact with each other. How it works: ⚙️⚙️⚙️ Slime number 1 will look for another slime within a certain radius. If found, slime number 1 will go to that slime (Slime number 2) and have some sort of interaction. If slime number two is already in the list of contact of slime number one, their bond will go up. Formula for the value of interacting: (100 - stats[2]) / 100 - Vector3.Distance(FindClosest(otherSlimes, Mathf.Infinity, "pluh").transform.position, transform.position) / 20; Later updates: 🔨🔨🔨🔨 Big fixes: Sometimes after an interaction, slime glitches out and has a seizure. The seizure is temporary but I still want to fix this issue. Slime mating: If slimes have a very high bond, they can have baby slimes. (Baby slimes will have the genes and DNA of their parents)
More mechanics! Devlog 6 In this update I added a basic social structure and generations. Things added in this update: When two slimes meet, they gather some information. If one slime’s mental value is bad while meeting, then they will have a bad meeting. If they have a good meeting and keep it up for multiple interactions, then they can have babies. There are a lot less bugs when slimes are interacting with each other. They don’t glitch out nor do they just stop moving. Food now constantly generates, so the slimes can live and thrive. Things I will add later: Parents will soon be able to pass down genes and DNA to their offspring. There will be a more advanced social structure so it doesn’t seem too robotic. Art will be implemented later on. I might put this on itch.io for people to test. My game is now on itch, go check it out! https://respectabledot.itch.io/slime-simulator
Art! 🔥🔥🔥🔥 Devlog 7 Made a sprite for the slimes. The default color is white because it supposed to be changed into other colors. The movement of slimes is now smooth instead of teleporting to the nearest block. A lot easier ot tell what’s going on. Things I will add later: Better UI will be implemented later. Because right now it’s just a piece of text that tells you the stats of a slime. Demo will be released soon because I need some feedback. Slimes will be able to kill each other. 💀💀💀
Big Fat Update 🔨🔨🔥🔥 Devlog 8 I don’t use AI to write any of my devlogs. Relationships Slimes can interact with one another. To do so, they just have to be next to each other. After an interaction, if they haven’t known each other before, they will have an updated friends list. If they have already met each other, then what they think of each other goes up. If two slime’s relationship value go up to a certain number like 30, then they can have babies. DNA and Genes Each Slime have their own characteristics. This includes speed, health, and species. They pass down their genes to their offspring. Offspring’s traits will be slightly changed to maintain diversity and natural selection. For example, a slime with a fast genes will be able to get to a food quicker than the ones that are slow. The faster slime will get to survive and make babies. Color 🔥🔥(My fav update) Slimes have multiple kinds of traits, and that includes color. They can pass down their color to their offspring(Though their offspring’s color may be slightly different). This addition makes the game look a lot better. Problems 😢😢😢 While doing some tests, I noticed that some slimes were dying. This was weird because there were definitely enough food for everyone. When I looked closer, I realized that there was a bug where some slimes get stuck and become braindead. This problem is and still very difficult to fix.
Update Devlog 9 Traits Slimes now have traits! Traits are minor tweaks on the brain of a slime. This brings out personality and characteristics. For now, traits are only obtainable at birth. Slimes aren’t able to pass down traits to their offspring. Other stuff I finished working on the background and is preparing to work on the art of the food. Things I will do next time I will start working on the UI because that makes it easier for people to test my simulator. I will work on more traits, so far I have 7-8 of them.
More Mechanics! Devlog 10 Small UI Update The slime information and slime population text boxes are separated. There is now a bar that is gonna contain some button. Right now the only button I added is adding more slimes, but there are gonna be more in the future. Other Things I added Slimes can now have multiple babies instead of only one. I added some grass to make it less barren.
Batch of Updates! Devlog 11 Slime genetics Slimes have more realistic natural genetic creation. Instead of only picking up one of their parent’s colors, they mix the two colors together. Speed and Health changes for an offspring is toned down. Implemented more slime mutations. These includes drastic color changes, faster or slow speeds, or health changes. When testing, I noticed that after a while, the colors started becoming black(I don’t know why). That’s why I made it so that an offspring may be given a bold color(Blue, Red, Green, etc.). UI Made a system where you can view slimes’ friends just by checking their friends list. By clicking on one of their friends or family, it will take you to the selected slime. I made the UIs a lot more responsive and clean.
A title Devlog 12 Things I implemented Slimes don’t mixed up colors equally anymore. This is because mixing them up equally makes them more dull and grey over time. To stop this, I had to mix the colors up unevenly to maintain the vibrant colors. To track and follow a slime, click on them and press the “Track” button. The slime UI got a major upgrade. It’s now easier to read and more sorted out. You can now spawn food for the slimes. To do it, go to the bar at the bottom. Above the bar, there is a text that tells you what you have selected inside the bar. Clouds have been implemented. Right now they don’t do anything, but they will be able to drop food.
Big Update Devlog 13 Favorites tab You can now favorite slimes. This is for when you like one of them or find one interesting. To use, just click on one of the slimes. Kill tab If you want to get rid of a slime, go to the kill tab and click on the slime. I will add the death animation next time. New pathfinding Replaced the old AI reinforcement learning with the A* pathfinding method. This is because the new system can avoid obstacles and doesn’t take much computing power. UI revamp Made the UI better. Most of the buttons and panels have art and stuff. Things I will add in the future Terrain: You will be able to customize the terrain to make the world more interesting Animations: When walking, the slime will have animation.
Map Update Devlog 14 Terrain Generation After implementing A* pathfinding, I added obstacles and other things for the map. I used to perlin noise to make the mountains and rivers feel more real. float noise = Mathf.PerlinNoise(i * 0.05f+ offsetX, j * 0.05f + offsetY); Added trees. I can make them useful for the slimes in later updates. Art I made the sprites for the rocks and water. It didn’t take that long because it didn’t need much detail. Made the art for the “kill slime” button, which is a knife. Bug fixing Fixed a ton of bugs because adding in the new pathfinding messed a lot of things up. A lot of problems came up when making terrain generation, like the slimes behaving weirdly. Future Updates I might add clans and tribes to make things more interesting. Violence will be added very soon. Check out my game here: https://respectabledot.itch.io/slime-simulator
World Building Update Devlog 15 Terrain Editing You can now edit your world. All of the blocks will be available. To use this feature, click on the button with the blocks. All of the blocks: Water, Grass, Sand, Rock Programming took a bit longer than I thought, but testing was surprisingly easy. Next time, I could add things other than blocks, maybe like trees and grass. Other stuff There is now world age so you know how old your world is. Small changes in some of the UI
Visual Update Devlog 16 Check out my game here: https://respectabledot.itch.io/slime-simulator Particles Water used to look bad because it’s just blue and nothing else, so I added waves for the movement. Leaves now fall off trees. Other graphics When near land(Sand, Grass, rocks), the water becomes more shallow. It is indicated by the water being more light than the others. Added more grass when starting the game. Clouds appear a lot less due to it sometimes blocking the user’s vision. Bug fixes Fixed a bug where slimes were not spawning, caused by a poor algorithm. Temporarily removed the buggy walking animation for the slimes. I also added apples🍎
Taking Feedback Devlog 18 Font Change When I showed my project to people asking for some suggestions, they said I should change the font. So I decided to change the font to more of a pixel style, called “Pixel Operator”. It took a while to set up due to my lack of experience. Slime Violence Slime will now be able to attack each other. It starts from them being sad or angry, and being hungry. Then they unleashed their fury onto other slimes. When they hit other slimes, the slimes that are hit lose health. Other Stuff Slime can now slowly regenerate health when they are fed and have energy. Fixed a bug where rocks wont spawn in world editing mode.
Miscellaneous Update Devlog 19 My game is now on itch, go check it out! https://respectabledot.itch.io/slime-simulator — Things I added: Added a crosschair. THis makes it a lot easier to see what you are hovering over. The crosschair can highlight on tiles and slimes. Made an about and instructions page. Go to the top-left and you will see the buttons that will take you to the pages. Fixed slime behavior. Sometimes the slimes get stuck after eating so I hope I fixed the issue.
Emotion Update 😀😢😡 Devlog 20 I have something else that I worked on but there is still a little more work to go. I will post it in another devlog. For this update, I added emotion to the slimes. Slimes will get happy when they eat food or when they talk to their friends. They get sad overtime when they don’t do anything or they get attacked. You will know when they get upset when a emoji shows up above them. Emojis will show up for other things too, like when eating, fighting, or interacting with others. I will post the other part in the next devlog. My game is now on itch, go check it out! https://respectabledot.itch.io/slime-simulator
Misc. Update Devlog 21 Added palm trees. They act like normal tree but spawn on sand. Also, they generate coconuts. Made a system where the slime’s pathfinding algorithm is a lot more efficient. Whenever they find a place where it’s impossible to go, they will make a mental note of that. This reduces possessing power. My game is now on itch, go check it out! https://respectabledot.itch.io/slime-simulator
Random Good Updates Devlog 22 Sorry for not devlogging more Made a new button where you can plant weeds and trees. I don’t know what else to say but this took me so long. Reworked the violence behavior in slimes. Before the update, slimes would attack the nearest person when they get upset and hungry (Hangry). But now, slimes may choose to slime out someone nearby OR someone who they already don’t like in their relationships list. This makes it more realistic to real life. Reworked equation for slime violence weight: tasks[2] = distanceSlime > 18 ? 0 : (100 - stats[2] * 0.6f - stats[0] * 0.85f) / 50 + angryBias + baseTasks[2]; When slimes sleep, they will have their own special sprite for that. Also, they will have the “zzz” icon above them. Still working on the issue where slimes get stuck after doing some task. It seems to be fixed though, for now. My project is now on itch, go check it out! https://respectabledot.itch.io/slime-simulator
Cosmetics Update Devlog 23 I added 10 kinds of hats that can spawn on the slimes. They don’t affect the slimes, it’s just for appearance. My project is now on itch.io, go check it out! https://respectabledot.itch.io/slime-simulator
Introduction Update Devlog 24 Made a simple intro. It contains the game’s logo and unity’s logo. Made a tutorial for the start of the game. It teaches you how to spawn slimes. If you have already played, there will be an option to skip. Check out my game: https://respectabledot.itch.io/slime-simulator
Miscellaneous Updates Devlog 25 Things I added: Made a sprite for when the slimes die. It looks like a splat. When a slime dies, their family member and friends get sad. You can press “h” to hide UI. Bug Fixes: Fixed a bug where the slimes get stuck after doing eating or interacting. Fixed the tutorial-skipping button. Slimes don’t lose their color anymore Check out my game here: https://respectabledot.itch.io/slime-simulator
100 HOURS LETS GO Farms. Devlog 26 This is the most tiring update ever. This update is a test, so a lot of things can be broken. Things I added: Added roles. Some slimes get assigned task, like constructing buildings or farming. Added farms. Slimes can plant and produe their own food. All they have to do is place farming soil near windmills that are set up by constructors. The soil will automatically generate crops, which is meat. Made the art for the windmill. It even has an animation! Slimes interacting with other slimes is encouraged. Food spawning is greatly reduced because slimes can now produce their own food. Check out my game here: https://respectabledot.itch.io/slime-simulator
Another big update but isn’t as tiring Devlog 27 Things I added: Violence is a lot more encouraged between the slimes. There is too much peace. Added lettuce. Instead of the slimes growing meat, they grow lettuce. This is a lot more normal. Slimes have a Walking Animation, which is just them expanding and shrinking constantly. Food generation in farms is reduced because this encourages them to explore the world more. Bug fixes Buttons in the bottom bar will not activate when users are cancelling them. In planting mode, blockable objects like trees will destroy items beneath them. In building mode, changing a tile will cause things that are stuck on top of them to disappear. Things I will add next time: There will be a list of effects. These effects buff or weaken a slime’s body or influence the way it acts. An example could be make it faster, have more health, or make it more prone to attacking other slimes. Clans and kingdoms is already being worked on. Check out my game here: https://respectabledot.itch.io/slime-simulator
Kingdoms and Colonies👑🔥👑🔥 Devlog 28 Slimes can establish kingdoms if there aren’t any or are far enough away from other kingdoms. If a slime is spawned by the user, the slime will head to the cllosest kingdom(If close enough). But if a slime came from another slime, they will automatically be part of the kingdom. A slime can create a settlement if they are already in a kingdom and is far enough away from it. If a slime has one parent from a kingdom and another from another kingdom, then they will random choose which to live in. A slime farmer can only work in the kingdom’s fields. Things I will add next time: War and Economy will be my next priority. Check out my game here: https://respectabledot.itch.io/slime-simulator
UI Revamp and cosmetics Devlog 29 I am currently working on another update but I forgot to post a devlog, so I will post a devlog for the things I finished then post the ones I haven’t finished yet. Things I added: After taking some feedback, I changed some stuff inside the slime UI. Instead of just plain text, I added pictures and icons to make reading a slime’s information much easier. I also replaced most of the transparent boxes with some better ones that are drawn. For the cosmetics, I added around 10 new hats.
Spells! Devlog 30 Check out my game here: https://respectabledot.itch.io/slime-simulator Spells control and influence a slime mentally and physically. Currently, there are only 4 spells. I will plan to add more of them in later updates.
Items and Slime sizes Devlog 31 I forgot to devlog again :( Items and Equipment Slimes can now have items. Items can help them complete tasks or give them a buff. To see what item the slime has, check in the slime stats. Items currently in the game: Hammer: Used for constructing buildings. Hoe: Used by farmers to farm. Pistol: For killing slimes. Rifle: For killing slimes. Slime characteristics and stuff Instead of slimes being the same size, they can be big or small. This makes it more realistic, I guess. Slimes can pass down their family name. If the two parents have different family names, the offspring chooses one of them. UI Changes The section for terrain editing got a small upgrade. Next to the text, there is an image of the block to show you what it looks like. At the top-right corner of the slime statistics page, there is the X button that closes the UI. You can check what equipment the slime is using by going to the slime UI & statistics Other Waves can appear outside of the editing zone so it looks more natural.
More Mechanics and Items! Devlog 32 Things I added: Houses are a new building. Currently they don’t really do anything, but later on they can be used for slimes to sleep in. Doctors is a new ability that treats and heal slimes. Their item is a medkit. When you favorite a slime, a star icon will show up above them. This helps keep track of your favorite slimes. Added 8 new cosmetics! New Items! MP5: A submachine gun that fires really fast. Blue staff: A staff that is blue and shoots out 3 blue balls. Katana: The first melee weapon. Does a lot of damage. Medkit: Used by doctors to treat and heal other slimes. M1911: Originally called the pistol. AR-15: Originally called the Rifle. MP-133: Originally called the Shotgun. Things I will add: More cosmetics coming soon! Houses will have a function other than doing the embappe special Game link here: https://respectabledot.itch.io/slime-simulator
Another Batch of Updates Devlog 33 I dont know when to stop this project, I have a lot of things to add… Check out my game here! https://respectabledot.itch.io/slime-simulator Things I added: Day/Night Cycle! Every minute it switches from day to night or vice versa. When at night, slimes and buildings glow so they are easier to see. Also, it looks cool. (The light thing took a long time to figure out) There is a notification bar that tells you what is currently happening in the world. When guns fire, it will create a muzzle flash effect. New Items: FN SCAR: A powerful gun that hits hard. It is kind of inaccurate though. Laser Gun: Its bullets are faster than other guns. Does decent damage.
Optimization and Fixes Devlog 34 2nd to last devlog! Cant wait to ship Things I added: When you press escape or the gear icon at the bottom-right, you can enter the settings page. In here, you can disable or enable features to your likings. This can help run the game faster on lower-end PCs. Placing blocks, plants or effects shows a small special effect. Between and Night, there will be dusk and evening. They will make the sky orange for 15 seconds. There will be more farmers and less unemployed people. Big Fixes: Upgraded the pathfinding system for the slimes. Whenever they are hungry but can’t reach their food, they will find alternate food that is close to them.
Sound! Devlog 35 This will be a short devlog because I don’t know what else to say. Sounds effects I added inside the game: Slime spawning Clicking on slime clicking on ui(button) Slime Noises ocean wind Slime Eating Planting Guns(Lasers, Regular bullets Passive slime noises Active slime noises Night(Crickets) Credit to qubodup and filippe for the slime sound effects.
Ships:
A simulator that is about making crazy slimes through natural selection, evolution, and genetic engineering. One thing that made this project challenging was the slime pathfinding. To solve this, I used the A* pathfinding technique. Something I am proud of is the art style. I worked very hard on it and I think it look good. To test my project, just click on the demo link. Thank you to the people who supported and suggested good ideas to the project!...
|
1792842791.8326545
|
1792929191.8326545
|
|
9570
|
Capital Chaos by @sol4r_on_hackclub | Stardance
|
sol4r_on_hackclub
|
1
|
171.6
|
3336
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-22T19:42:41Z", "hours": 171.0, "multiplier": 19.54, "payout": 3336, "blessing": "neutral", "text": "Welcome to Capital Chaos! One of Stardance’s most awaited projects ;) (hopefully anyways) We’ve got chaos, a bunch of random events, a boss fight and so much more for you to explore. SKIP if you are on Linux/MacOS (or you can vote based on the videos - completely up to you) as I only have a windows executable for now. I am honestly super proud of this, and the community built around this game. I hope you enjoy it as well. There have been TONNES of challenges, such as pathfinding, the initial grid also seemed really daunting. To the vacancy count which was literally plaguing me for the past MONTH and got fixed today (it was one line… i know.. maybe I should have used AI). But besides, it’s a sick project. I hope you all love it. Unzip the file in the release and it should be good to go. READ THE README FOR INSTRUCTIONS AND CONTROLS!! THERE IS NO TUTORIAL Read the story, watch the videos if you can and just enjoy the game! It will be on steam in 8-9 months so maybe subscribe?", "repo": "https://github.com/Sol4rOnGit/PocketCity", "demo": "https://github.com/Sol4rOnGit/PocketCity/releases"}]...
|
[{"post_id": 57569, "ts": "202 [{"post_id": 57569, "ts": "2026-08-29T19:13:24Z", "hours": 0.5961, "text": "Thank you all so much for the support! Framework 12 is on it’s way (and this wait is painful). After 171 hours! 19.54x is actually insane and I appreciate it a lot. Join the Discord! I made a discord (click above) and i’ll give you all an early supporter role before I put it out on YouTube and stuff for the “wishlist” when the full game comes out (if you want to stay in touch after stardance is done. ALSO IF YOU COMMENTED WHILE THE GAME WAS STILL CALLED POCKET CITY DM ME ILL GIVE U A SPECIAL ROLE The game beta is still up and you can try it out Currently just doing some minor stuff to the game (Fixed some normal/easy mode not settings correct phases. B2 Bomber should destroy itself and stop the nuke siren once launched), and slowly adding a tutorial but I’m like 90% focused on revising for uni entrance exams"}, {"post_id": 52586, "ts": "2026-08-22T19:35:44Z", "hours": 3.4139, "text": "BETA TEST! Nvm I have to devlog my final changes But lemme talk to those stardance reviewers real quick. Scroll down to see the endless content of my story, and all the community feedback (also on my youtube). Playing the game is a bit of a learning curve so you can watch my videos and stuff on it as well. I’d say watch this one: Boss Fight for the boss fight and maybe one of the other ones that you find interesting. Maybe this one because it has over 1,000 views and still climbing! The game is released there but it is windows only for now (i will release linux and maybe mac on the actual release game don’t worry but I’m super restricted for time right now) SKIP IF YOU’RE ON LINUX / MAC For everyone: Changes: Amended GameAudioManager to adjust for max voices which uses a List based system that appends and unappends. Boss fight also toggles and untoggles the game audio dependant on each audio source, because the game could currently have hundreds or even thousands of audio source which is really bad optimisation. So each audio source that I want to track has a ManagedAudioSource attached which automatically registers and unregisters itself from the GameAudioManager. I also edited the boss fight to make it a touch harder and amended the moves ;) And come and beta test NOWWW. leave all your comments, suggestions etc. on THE NEW DISCORD COMMUNITY!! or youtube, i’ll read it all and, again, thank you all for your support . I don’t know what to put as the image so here."}, {"post_id": 51908, "ts": "2026-08-21T20:18:25Z", "hours": 8.8033, "text": "Final DevLog before First Ship - Boss Battle I don’t think words can explain what I made so click here to watch a video on my probably final major addition (no pressure) & also help with a small dilemma I have. NO!! that does not mean this game will stop development, but i think i finally have enough hours (+10-15 more safety) to get a Framework 12! (and then i will be able to crack on with entrance exams - so i guess development will slow a touch). Of course I’ll ship once the game is polished enough. You might see a devlog or two from the “Capital Chaos Website” - follow me ;) I really hope you guys all enjoy it and now I need to do the readme and stuff. I also realised I was one of the most viewed on Stardance which is honestly amazing and I appreciate all of the support :) And thank you to all the new friends I’ve made and all the followers and commenters. It’s honestly been insane."}, {"post_id": 49800, "ts": "2026-08-18T18:52:58Z", "hours": 3.8472, "text": "Game Sountrack? But before I talk about that, lemme just say the game audio is almost finished, we have menu sounds for clicks and stuff, and i added support for main menu music. The firetruck hoses actually do stuff, floods sound like floods, theres some peaceful background nature sounds and yeah it makes the game feel so much nicer. although i forgot place sounds which was a massive oversight. also my wifi is still working. no idea why, but not complaining. and i’m cooking on a soundtrack lowk although none of it seems correlated in any way and idk how i’ll make it fit into this game but you know what maybe it’ll just all go into some random album. None of the hours put into these songs count but its okay. i’m no pro tho so. all i’ll say is i love some bass"}, {"post_id": 49147, "ts": "2026-08-17T19:36:51Z", "hours": 2.6206, "text": "I’m getting new wifi lol, & 150 hours so yeah i won’t be here and probably will have to post a 10 hour thing BUT on the plus side, we got a nice death screen that has a bunch of quotes that you can read below [SerializeField] private string[] quotes = { \"Opportunities multiply as they are seized \\n - Sun Tzu\", \"If you are going through hell, keep going \\n - Winston Churchill\", \"No empire was built on the first draft\", \"Fall seven times, stand up eight\", \"That which does not kill us, makes us stronger \\n - Friedrich Nietzsche\", \"Out of ash, a new foundation\", \"I have not failed. I just found 10,000 ways that don't work \\n - Thomas Edison\", \"A man is not finished when he is defeated. He is finished when he quits \\n - Richard M. Nixon\", \"It does not matter how slowly you go as long as you do not stop \\n - Confucius\", \"Out of difficulties grow miracles \\n - Jean de La Bruyère\", \"The greater the obstactle, the more glory in overcoming it \\n - Molière\", \"A Pocket Sized City is too small for your ambition. Build again \\n - The Dev\", \"Success usually comes to those who are too busy to be looking for it \\n - Henry David Thoreau\", \"Go big or go home\", \"You can't give up just yet. Stay determined... \\n - Undertale\" }; Maybe you’ll catch the little easter egg there as well ;) Working on adding game audio!! and probably finally enough hours to get the framework 12 (btw I wouldn’t recommend this as a daily laptop (f13 better), I just want something I can write on lol)"}, {"post_id": 48073, "ts": "2026-08-16T11:08:59Z", "hours": 3.8794, "text": "INSANE tree optimisations Went from 60-80 fps @ 4K to 400-450 (in game). Yes a 6 to 7x increase. How you ask? GPU Mesh Instance drawing offloading the CPU work of handling thousands of game objects. In English, I’m no longer spawning thousands of tree objects, but instead telling the GPU to draw the tree instances every frame. This seems quite unintuitive because you’re now drawing thousands of things every second. BUT this means that there are no game objects, so the CPU doesn’t even know that these exist. Also the GPU draws it thousands of times anyways. A game object handles transforms, rotations, etc. that the CPU has to keep track of whether it is active or not. This had the added benefit of the trees having no overhead when the trees are disabled, so you regain all of your framerate! Also I used some neat little script that combined the meshes all together in the GameObject prefab. Now it really should be able to run on your potato PC/Laptop. Combine script using UnityEngine; public class MeshCombineUtility : MonoBehaviour { [ContextMenu(\"Combine Children Meshes\")] public void Combine() { MeshFilter[] meshFilters = GetComponentsInChildren<MeshFilter>(); CombineInstance[] combine = new CombineInstance[meshFilters.Length]; Matrix4x4 matrix = transform.worldToLocalMatrix; for (int i = 0; i < meshFilters.Length; i++) { if (meshFilters[i].gameObject == gameObject) continue; combine[i].mesh = meshFilters[i].sharedMesh; combine[i].transform = matrix * meshFilters[i].transform.localToWorldMatrix; } Mesh combinedMesh = new Mesh(); combinedMesh.CombineMeshes(combine, true, true); #if UNITY_EDITOR string directory = $\"Assets/Assets/Mesh/Tree/{gameObject.name}.asset\"; UnityEditor.AssetDatabase.CreateAsset(combinedMesh, directory); UnityEditor.AssetDatabase.SaveAssets(); Debug.Log($\"Combined mesh saved to {directory}\"); #endif } } Draw section of GPU Mesh Instancing private void DrawTreeMeshes() { if (treeMesh == null || treeMaterial == null) return; foreach (var kvp in generatedChunks) { ChunkData chunk = kvp.Value; if (chunk.spawnedTrees == null || chunk.spawnedTrees.Count == 0) continue; int batchSize = 1023; int totalTrees = chunk.spawnedTrees.Count; for(int i = 0; i < totalTrees; i+=batchSize) { int length = Mathf.Min(batchSize, totalTrees - i); Matrix4x4[] subMatrices = new Matrix4x4[length]; for (int j = 0; j < length; j++) { subMatrices[j] = chunk.spawnedTrees[i + j].matrix; } int meshIndex = Mathf.Abs(chunk.chunkCord.GetHashCode() + i) % treeMesh.Length; Graphics.DrawMeshInstanced(treeMesh[meshIndex], 0, treeMaterial, subMatrices, length); } } }"}, {"post_id": 47547, "ts": "2026-08-15T14:59:51Z", "hours": 1.4756, "text": "You won’t believe it. I got it working FIRST TRY That’s actually crazy to be honest. Tells you how much expirience those 8 hours of menu development have given me. Someone give me a Unity menu doctorate or sum But on a serious note, we have game difficulty selection and its all nice and self contained. With controller support of course. You can see we have Previous Saves but that isn’t really functional yet. One of the things I learnt is to never rely on the UI giving you the data, only the click, so you’d manually add the elements and then call .value or .isOn respective to the component, and the same goes for dropdowns although I didn’t use one here. Let me know if you think it looks clean or any improvements to the UI readability, etc."}, {"post_id": 47161, "ts": "2026-08-14T20:58:41Z", "hours": 10.3042, "text": "I HATE Menus (in Unity at least) Genuinely hate them. But yeah we got settings menu working (which genuinely took like 5-6 hours because of stupid unity legacy stuff vs new stuff and then unity 6 vs 2023 version stuff i was used to) AHHHH I don’t remember it being this painful in Godot to be honest so maybe Godot is better for that? i had to get rid of VSync because it only worked on refresh. Created a debug menu to test performance, just to see that the only useful thing there was FPS and like RAM usage, and some engine stuff like active Rigidbodys. I couldn’t see the CPU utilisation or GPU utilisation which was… the thing I wanted to see. Although don’t worry performance does seem to be reasonable and early to mid game I can push over 1000 FPS on potato settings (specs at bottom if you care about them). It does obviously go down as the game continues on, but I think it’s quite optimised. Even with shadows its on 500+ FPS with a mid sized down. Although adding trees will quarter your FPS numbers. but it looks pretty so there’s your tradeoff. Although problematically if you turn trees off and you had already generated trees the fps stays low even though you’re not rendering it? I don’t know why unity is so weird. The game is quite unbalanced, but we’re in the final polishing stages (my target is 150 hours for the framework and hopefully it’s secure! (vote nice and high thanks - i did put a lot of effort into this game.) Up next: Difficulty selection Polishing Rebalancing updates Release!"}, {"post_id": 45186, "ts": "2026-08-11T14:41:21Z", "hours": 5.9322, "text": "NEW NAME!!! Flash Floods + Main Menu If you remember, Pocket City is a game that already exists so now it’s called Capital Chaos. Thank you YouTube comments! And all of you as well, for the suggestions. Ofc new video to go with it: watch by clicking here! I created flash floods that.. well flood the entire map. It’s meant to be a little toned down of a disaster, thats more survivable because it gives the game a touch more balance. It stops all services from working, so that could be detrimental during a virus attack. But on the other hand, it stops every single fire and prevents new ones and explosions. A lifesaver if theres a nuke, it gets completely nullified. Also new main menu, I think it looks pretty neat. Especially compared to the old one."}, {"post_id": 43501, "ts": "2026-08-08T20:10:46Z", "hours": 9.3828, "text": "Nukes… from a plane A famous plane. The B2 Bomber. Idk gng I got bored. No but it drops a nuke that decimates everything in a decent radius and then sets everything in a bigger radius on fire, and now we have a new rare event called a “military invasion”.. that spawns like 8 helicotpers AS WELL as the b2 bomber. The B2 Bomber starts a few clicks out and then flies toward the set target building. Then it drops the nuke, and you have a few seconds to try and kill the nuke before it kills you, and on impact (yes we are finally using rigidbodys as they are intended) it explodes. You better have that turret system ready. Of course, it’s clearly not enough. So maybe I’ll add a anti-missile system as a YouTube comment said. Speaking of YouTube, thank you for all the support :) 100+ comments goes crazy, and we’re on 73 subs up from the previous 29 literally 3 weeks ago. Not subscribed? Help a fellow dev out: TechScope Channel"}, {"post_id": 36089, "ts": "2026-07-27T23:24:15Z", "hours": 6.7969, "text": "WORKING AIR DEFENCE + ATTACK HELICOPTERS So we got working air defence turrets with some predictive aiming, and attack helicopters that shoot missiles at random buildings. Although you’re unlikely to get 3 attack helicopters at once… for now. The helicopters blades do spin, they bob up and down, they go towards buildings. They shoot out these missiles, which pathfind their way to the targetted building. They all have a healthsystem which means that the turrets do some damage on collisions only though, one turret might take a while but two (or the 7 you see below) will MOW them down. Still have to hook it all up to the Finance Manager, Special Building placement and other boring stuff, but… I need more IDEAS!! (read this thx) …for more Military stuff that can be added. Tank wars? Who knows. I was thinking of a military invasion as being one of the rare events which spawns like 10 missiles and 5 attack helicopters and maybe a B2 bomber or some stuff. I also need more allied options, maybe I’ll add like an anti-bomb turret that is specifically for the B2 bomber or something and does 100000 damage. Or maybe your own airbase that spawns an allied helicopter and now you have dogwars. or maybe your own plane. idk So yes @Adam_Lotfalla this is what the helicopter was for. Yay more things to worry about!!! Still have integrations left! I’ll see you (hopefully) tomorrow once that’s done. but its midnight now so goodbye."}, {"post_id": 35447, "ts": "2026-07-26T21:18:10Z", "hours": 1.8178, "text": "Hmmmm… What’s cooking? (Blender just WON’T count toward my hours but prolly spent 2-3 extra hours here) The helicopter blades actually spin. And W Unity particle system for the missile."}, {"post_id": 33603, "ts": "2026-07-23T17:37:47Z", "hours": 2.6228, "text": "I NEED YOUR HELP Pocket City already exists as a game. I know this is stupid and I should have checked this before starting since I had the intention of publishing it to steam but here we are. If you want more details, or more knowledge about the game check this video out: Video Oops…"}, {"post_id": 32074, "ts": "2026-07-20T23:48:35Z", "hours": 6.6703, "text": "UFOs in an Alien Invasion 💔💔 The second rare event addition to Pocket City! Get a chunk of your population zapped up by some not so friendly aliens… Any more ideas, let me know below! But it was pretty neat to implement. 3D modelled it and everything. 3 hours of doing god knows what. Tried to figure quality settings out and probably did smth else but was too busy with the World Cup to remember what I did. Probably bug fixes and stuff. Oh yeah and you see a pretty cool ripple pulse thing that propogates through the map. Although it is a little weak right now but i’ll fix that next time. Super tired. mb"}, {"post_id": 27226, "ts": "2026-07-12T16:41:03Z", "hours": 4.4661, "text": "Bugs are genuinely taking the life out of me Genuinely the worst thing ever. I STILL can’t figure it out but I had to post my weekly devlog anyways. Can you believe we’re 28 weeks into 2026??! Here’s the chaos where I accidentally created a “Pocket Empire” (Day 1105) Watch the video (click the title) if you wanna see how I ended up here and a minor crash out. very minor."}, {"post_id": 26578, "ts": "2026-07-11T14:19:18Z", "hours": 9.2114, "text": "I’m being forced to post Yeah thanks stardance. 10 hour limit for what. Probably spam filter. Also MASSIVE BUG(s). One is that the game just randomly deletes all the buildings from a chunk. No idea why, I’ve been at it for so long. Another issue is the stupid vacancy counter which has been broken FOREVER but atleast now it doesn’t go negative. I have a serious feeling I will have to spend a week just POLISHING the game. Whatever, Currently working through a new feature of allowing you to use your money that you spent so long accumulating to try and fix the chaos that you went through. This is done through the “Council FX” which I may rename if you guys can think of a better name, and you can see the countless things to do such as: Taking On DEBT!! YAY!! 100k that gains 1% every day. Seems low.. but it will pile up very quickly since it’s compound interest. Overclocking the grid for free placement + infinite water/power Maximising Housing/Business revenue Curing all infections … and many more as well as the ??? at level 100… who knows what that does. £2.5 million btw. Of course, those levels are the XP, which has finally given that a use. And no you wont be at level 11000 just like that, i’m just being lazy for testing. Also rebalanced so that all of the commercial buildings have ~10-15% of their previous employment caps. So that you’re not just spamming residential. It also makes industrial more useful as they have more employers even though they produce less money."}, {"post_id": 23054, "ts": "2026-07-05T19:50:43Z", "hours": 2.3469, "text": "Main menu 👀 I need help. UI clearly isn’t for me"}, {"post_id": 22419, "ts": "2026-07-04T21:33:08Z", "hours": 7.5172, "text": "CRIME!!! + C# Generics I added Arson and added a Police manager that goes out and solves these crimes. Lots more to come, let me know of any ideas you have! But before that let me teach you ALL something. C# Generics. I had a bunch of scripts that all did ABOUT the same thing but with different. This was FindClosestHospital, FindClosestFireStation and the thing I was adding which was FindClosestPoliceStation. It felt quire redundant to copy the same lines but instead of Hopsital it was replaced with FireStation or PoliceStation. //Generic functions private T FindClosestReachableService<T>(Vector2Int targetPos, Func<T, bool> hasAvailableVehicles, out List<Vector2Int> bestRoute) where T : Building { T closestBuilding = null; bestRoute = null; int shortestRouteLength = int.MaxValue; bool foundBuildingOfThisType = false; foreach (var kvp in gridManager.GetMapGrid()) { GridManager.GridTile tile = kvp.Value; if (tile.buildingScript != null && tile.buildingScript is T serviceBuilding) { foundBuildingOfThisType = true; if (!hasAvailableVehicles(serviceBuilding)) continue; List<Vector2Int> testRoute = CalculateRoadPath(tile.buildingScript.gridPos, targetPos); if (testRoute == null || testRoute.Count == 0) continue; if (testRoute.Count < shortestRouteLength) { shortestRouteLength = testRoute.Count; bestRoute = testRoute; closestBuilding = serviceBuilding; } } } if (!foundBuildingOfThisType) { bestRoute = null; return null; } return closestBuilding; } Above is an example of the C# generic. We have “T” type, and I think this is a good place to learn about them. Instead of defining the function as returning something like Building , we make T a type. and you can see it passed in a little <T> after the function name. We can also pass in entire functions like Func<T, bool> which is utilised as shown below: Building bestStation = FindClosestReachableService<PoliceStation>(building.gridPos, ps => ps.HasPolice(), out route); you can see ps => ps.HasPolice() calls that out. And finally, to define what T is meant to be, I’ve added where T : Building . You can do this many times, such as by having both a T as well as a U! and you’d have a repeated where T : Building where U: PotatoChips or something idk what U is meant to be bro. This was my first time using it but it’s pretty cool and if you’re using C# I’d recommend learning it as it saved me like 200 lines of code and changing something 3 times to change the same thing! And yes, I added a third thing which is Arson! which is a crime based thing, and you have a visual that shows up as a timer. if a police doesn’t solve the crime it sets on fire. It’s not too bad but it adds a use for the police, with much more to come for the police to deal with in the future! Also added asteroid BOMBARDMENT as a debuff. Yeah it’s brutal. 3 strikes… thats up to 108 tiles DESTROYED and set on fire. And of course, the image is from a youtube video: Click me!"}, {"post_id": 20327, "ts": "2026-07-01T22:02:59Z", "hours": 4.1806, "text": "BETTER UI + XP At the top of the image you can see a little progress bar… yep I’ve added XP now. Got plans for that, probably going to allow you to unlock stuff later. Like the lockdown ability etc. The UI has been overhauled. The actual images are a touch on the placeholder side apart from the road but it looks pretty good. You cycle between road, zoning and special building placement with 1, 2 and 3. Use R to rotate between the modes like residential, commercial and industrial zoning as well as Utilities & Emergency for the special buildings. Then finally T to rotate between those specific buildings. Complicated? Maybe? But it’s also a lot faster. I have completely lost my muscle memory of spamming R like the “good old days” though. Looks good? Bad? Horrible update and the game should never be changed ever again? Best update in the world and I should win £1 trillion? What do you think?"}, {"post_id": 17186, "ts": "2026-06-27T21:52:31Z", "hours": 9.9433, "text": "MAKE IT RAIN ASTEROIDS Pretty long run honestly. But before that, let’s talk about retrofitting your buildings. Earthquakes are pretty bad. Very bad when you loose your 100k building in a moment. So upgrade it. Yes it’ll cost you 35 to 55k now. But is your peace of mind worth that? And I added asteroids! These fly down and annihilate everything in a 3 unit radius and then set everything else in the 6 unit radius on fire. Lots of minor bug fixes as well, trying to get the game really polished now. Some rejigging of the game’s back end, such as creating a new abstract class for employer and reworking the systems to ensure that they run more smoothly and I believe almost finally fixing the unemployment/vacancy problem. I say almost because every 5 runs I see the game yell at me that it didn’t count something correctly but honestly I’ve spent so long on this I don’t even know if it’d be harder to just rewrite the entire employment system. For more detail, see my video linked below! See if you guys like it, my first proper long form I Added ASTEROIDS that ANNIHILATE your Adorable City And boy will this thing cook your economy."}, {"post_id": 15293, "ts": "2026-06-24T20:46:40Z", "hours": 7.6331, "text": "POLITICS!! + Debugging Hell v2 I mean I guess it is? Not too sure. Event Manager completely overhauled. Double events now no longer have the chance of repeating the same event. Created a new GameEffects script which just takes a bunch of simple code away from EventManager and plays the basic functions such as the “tax revenue increases” which you see below. This was quite a headache to create, and I severely underestimated how much time this would take. I have 2 extra nested classes inside of EventManager for Political Question and Political Scenario. [... inside EventManager.cs ...] public class PoliticalQuestion { public string Question; public TaskCompletionSource<bool> TaskCompletionSource = new TaskCompletionSource<bool>(); public Action onAccept; public PoliticalQuestion(string question, Action onAccept) { Question = question; this.onAccept = onAccept; } } public class PoliticalScenario { public string description; public Action runnable; public PoliticalScenario(string featureDescription, Action functionality) { description = featureDescription; runnable = functionality; } } [Header(\"Political Question Variables\")] public List<PoliticalQuestion> PendingQuestions = new List<PoliticalQuestion>(); public event Action onQueueChanged; private PoliticalScenario[] goodFeatures; private PoliticalScenario[] badFeatures; The political question is sent off to the UI manager, which displays it as shown below. Then it handles user input pressing Y/Enter or N/Esc to accept the user choice, and returns it back to the Event Manager. Seems simple enough, yet there are many ways to do it but I think that the above implementation works the best out of all the ones that I tried. I attempted to use Game Manager as a middleman but that did not work out - so I resorted to passing an entire class. The political scenario allows for the string to actually do something, so that the game knows what to process and what the user agreed to without creating a bunch of variables, and can allow for stacked political question events which is nice. Game’s looking really neat, and the multipliers and stuff can make the game go very crazy very quickly. Too much of a good thing is a bad thing!! Debugged the entire system for like a solid 3 hours it was actually bad. Came first in the UK tho!! I’m back after those 6 exams are done. Yes I know the UI looks pretty bad but it’s good enough for pre-beta testing. Oh yeah, speaking of UI everything is more bold. Figured out how to do that."}, {"post_id": 14641, "ts": "2026-06-23T20:29:50Z", "hours": 2.74, "text": "I HAVE A PLANN For the spinal sprint toward completion. Should end up taking me to hour 70-75? Then we polish the UI and add a main menu… lacking feature I guess. Anyways, reorganised the code base and split game manager up, created folders and fixed dependencies for everything. There is now an event manager, which handles all of the events separately, and as you can see from this simple to-do list (should my next project be the to do list to end all to do lists with calendar integration and stuff???) that I have completed the first bit “Weighted Event system”. So now nothing has an equal chance of happening! Also as a side effect made adding new effects a lot easier due to the nested WeightedEvents class which was similar to an idea I had in my old minecraft mod plugin and transferred the skills across the languages. Quite nice neat code actually, that isn’t 600 lines long, so I can quickly show it to you below. It’s very applicable and I believe I have used it twice or three times in the past 4 months alone. The declarations for the events now look like this, very centralised and easy to add/remove events and modify the weightings. Called in the Start() function. weightedEvents.Add(new WeightedEvent(\"Nothing\", 20, () => { })); weightedEvents.Add(new WeightedEvent(\"Earthquake\", 5, Earthquake)); weightedEvents.Add(new WeightedEvent(\"Fire\", 40, SetBuildingOnFire)); weightedEvents.Add(new WeightedEvent(\"Virus\", 20, () => { TriggerVirusOutbreak(); } )); and the class is just simply storing the name, the weight and a weighted Event. public class WeightedEvent { public string name; public int weight; public Action weightedEvent; public WeightedEvent(string name, int weight, Action weightedEvent) { this.name = name; this.weight = weight; this.weightedEvent = weightedEvent; } } we do need to store the total weight which happens on the Start() function currently. When playRandomEvent() is called, we increase the cursor by the event’s weight until it is greater than the rolled random number between 0 and the total weight, at which point the class’ event is called. Broke nothing in the end! That’s great isn’t it, especially after migrating a bunch of “legacy” code. Hopefully didn’t jinx it."}, {"post_id": 12737, "ts": "2026-06-20T20:33:13Z", "hours": 4.3403, "text": "Okay now i SUCK at my own video game. Don’t worry it’s hard mode. Also lost 2 hours of work somewhere cuz it didn’t save? Don’t understand how. That’s always great isn’t it. But still, 62 days in and I’m fried because of one silly mistake I made 40 days ago. Really teaches you consequences I guess. Spent my time completely overhauling how everything works. You used to make too much money, so I made the revenue even more population based, by making the max revenue a multiplier of the max population. Completely rewrote the losing population, unemployment and vacancy calculations to prevent strange negative numbers which was irritating me for the past one and a half weeks. Also overhauled the inflation to use a formula instead of a very rudimentary lookup table from if statements which is staged into a end-game (130 days+) and early game stage with 20% and 2% simple interest respectively (no not compound for once - that would make the game too hard. Extreme mode?) The game is actually like a good game now. I don’t know how to explain apart from that though."}, {"post_id": 11524, "ts": "2026-06-18T20:22:52Z", "hours": 2.1214, "text": "I FINALLY LOST IN MY OWN GAME!! Rebalancing the game slowly but surely. Currently added inflation, which increases the price of everything as the days go by. It gets less severe the longer you play but the inflation rate stays high. The game days now vary, take 5 seconds at the start and slowly get faster and faster toward 1.5s linearly. The inflation rate also increases with bands as the game progresses so you need to keep up. This makes the game a good progression, but make one mistake during an earthquake and it might be ggs for you. There is now finally a game over function… although no restart but don’t worry about it. It just pauses the game and tells you that the game is finished. Next up: Detailed Finances, Rubbish? (follow thx)"}, {"post_id": 10848, "ts": "2026-06-17T19:53:45Z", "hours": 1.2564, "text": "Currently rebalancing the video game to make the game progression more realistic as it is currently extremely difficult at the start and stupidly impossible to die toward the end. Completely forgot to tell you guys that you can follow my projects on my YouTube: Video Like & sub if you can… mb for the self promo though. Sadly I have 6 exams next week so the next 2 weeks are most likely going to be slow ones… not dominating the leaderboards anymore."}, {"post_id": 10754, "ts": "2026-06-17T17:25:21Z", "hours": 4.8722, "text": "Working healthcare! The game now has a virus… and it spreads pretty quickly. Houses get infected, added to the random event chances on top of earthquakes and fires. I created hospitals that dispatch ambulances as required. Now all services cost money. Using the same A* algorithm from last time, but a little more complex due to the nature of the virus spreading to random buildings. This requires the game to check for any viruses. I created an UI that displays the day progression, using actions & delegates again. The day length is now no longer fixed, but instead it becomes smaller the longer you stay on the map, to try and add difficulty ramping. The game is currently very difficult at the start and incredibly easy at the end, so I’m trying to reverse this a bit and make it hard at the start but terrible towards the end. Also just realised there’s no ending lol - you just become broke and softlock yourself. Never done it to myself which really speaks out about how UNBALANCED the game is. I think it’s time to work on game balancing now before implementing new features, and over half way to shipping? maybe at 65-80 hours in at this rate?"}, {"post_id": 8771, "ts": "2026-06-14T16:10:08Z", "hours": 4.5692, "text": "WORKING PATHFINDING ON THE GRID! Created new assets so the game looks complete now! You can see the firetruck going from the Fire station all the way to the burning building where it will extinguish it. Yes, it follows the roads as intended and uses the A* algorithm to figure out the best path. And they shoot water out, so visual feedback for everything. This was super fun as it was the first time I’ve implemented the A* in a video game on a grid that procedurally generated. The coal power generator, fire station and fire trucks have models now, I think I made them good enough to fit with the game. Police station and healthcare to still be implemented but it’s looking good so far. This required creating a new services manager, creating a pathfinding script, updating global services and how everything interacts with the fire, and creating reverse pathfinding and small details. It’s coming together really cleanly now."}, {"post_id": 8393, "ts": "2026-06-13T23:23:02Z", "hours": 7.1706, "text": "Debugging HELL I added fires, which you can see in the corner. Unity Particle system actually really cool for that by the way. This forced me to rewrite how fires work and add new bits to the Building parent class. That was fine. Had to update the UI to show you that an earthquake was happening, which works more reliably than last time and I figured the ghost error out. I decided to implement water & energy requirements. Overhauled ChunkManager to allow for this, as each chunk needs enough. If it doesn’t produce enough, it imports from other chunks. If it can’t do that, everyone starts packing it up and leaving. Added this to city stats. Then modelled a cute little water tower as you can see below. Then I added energy, lots of chaos. Trying really hard to avoid circular loops to avoid a stack overflow, but it’s looking pretty good. User warnings now show up, like when an earthquake happens, or if a building burns down or if you can’t do something or don’t have money for something. Now I think I have time to do the fun part - creating chaotic fun stuff to make the city feel even more alive. But it’s looking pretty good right now. It’s getting close to being shipped, almost 40 hours in. Like & follow for the link ;) Now I really need to sleep. OH NO AND REVISE FOR THE PHYSICS TEST ON TUESDAY"}, {"post_id": 8051, "ts": "2026-06-13T13:04:47Z", "hours": 2.0944, "text": "It’s been a really long time since I’ve posted. Some progress going on here. Little sneak peak of the fires… yep. You thought the game was gonna be peaceful? On another 7+ hour sprint today"}, {"post_id": 7093, "ts": "2026-06-11T21:27:16Z", "hours": 4.3672, "text": "Clean codebase always pays off (unless you want to keep your job apparently?) Fixed the vacancies counter, as before I was using = instead of +=. Told you it’s the little things that catch you out. Created a safer version of the draft forceRemoveElement() that accounts for jobs and residents when destroying a building (houses/shops/industry). This now updates the game realistically, e.g. if you destroy a house, then you reduce from the population. If the residents were employed, then it removes positions from buildings. If they were unemployed, then we remove it from the stats. Since I am not storing direct references between buildings but creating a game pool for performance, this makes the operations require lots of calling. This could probably be optimised in the future but I will do that near the first release due to the ever-changing code base. This required updating GameManager.cs to have LosePopulation(), LoseJobs() with a helper RemoveWorkersFromBuildings() function. Luckily the lists in GridMananger that I made like 20 hours ago for “future proofing” came in useful. Finally, you can press F to show city statistics and it updates in real time."}, {"post_id": 6481, "ts": "2026-06-10T22:00:31Z", "hours": 1.0161, "text": "What’s the difference between these two: int maxEmployees = 50; int employees = 25; float taxRevenue = 1500.0f; ONE : float revenue = (employees / maxEmployees) * taxRevenue; TWO: float revenue = (employees * taxRevenue) / maxEmployees; Mathematically, they’re the same. a/b * c = c/b * a However, I missed one thing while coding (a lot harder to see when it’s not just this). They’re both integers. now what C# does is it divides 25/50. we get 0.5. but they’re both integers, so it tries to store it as an integer, which floors it to a 0. Therefore, it’ll suddenly jump to max revenue when the company is full. obviously not what was intended. Option 2 makes you multiply the integer with a float, and stores 25 * 1500 as a float, which can now be nicely divided by 50 to get the value that we inteded. Sometimes… actually, no MOST of the time it’s the little things that catch you out. Anyways, this has very much balanced the game. The companies get as many employees as they can, then grow by 1 employee each day. Their revenue scales with the employee count, so now residential houses are useful for once. If anything, essential. Next up: Road tax, Land tax. This might be the one time you want tax… or maybe it’s too much?"}, {"post_id": 6445, "ts": "2026-06-10T20:48:12Z", "hours": 1.1464, "text": "Sometimes, the most productive thing you can do is destroying everything for a clean slate. So that’s what I did and refactored my codebase, painting my GitHub red. The old city generation code ended up becoming messy spaghetti code that made it difficult to debug and work on it. And that sort of legacy code when I look back in a month is what ends up shelving projects for years on end. This half an hour will save me many in the future. I also removed the cluster expansion method of building expansion completely as it created annoying expansions that didn’t make sense of everything being 1 square off a road. Also created a GameManager and moved aspects of GridManager and FinanceManager to the new script, to try and centralise the logic and stop having random bits such as the day manager in the FinanceMananger, which didn’t make an sense. Also yes, I wasted 20 minutes trying to figure out what was going wrong when I forgot to add GameManager.cs to the scene 💔"}, {"post_id": 6367, "ts": "2026-06-10T18:39:39Z", "hours": 3.0794, "text": "It can’t POSSIBLY BE THAT HARD CAN IT? No but you have to mix up TAGS AND LAYERS. There’s some error you got 5 builds ago but NEVER APPEARED AGAIN. EVEN HOURS INTO TESTING. HOW DID IT FIX ITSELF?! The UI now updates how much you gained in the past day! But anyways, you can finally toggle between the layers… after too much debugging (and realising it was just me being stupid). But it’s okay I’ll hopefully get that laptop from this blood sweat and tears. Look how gorgeous it looks now!"}, {"post_id": 5918, "ts": "2026-06-09T22:00:15Z", "hours": 5.0561, "text": "Did you know it costs more to remove a road than create one?! Strange… Finally have a working economy in the game now! It’s VERY unbalanced. You WILL become very rich. And residential is currently useless, and everything just has a set employee count for now. But that will change soon, and we’ll make the game intelligent. Also the game clock is currently in the Finance Manager which is a little odd so maybe I’ll fix that later. But, I have used actions & delegates to optimise the game handling of the ridiculous amount of scripts for each building that will be running once the cities become larger and larger. Created a UI manager to update the script, which uses the above actions & delegates from the script manager. Created a Finance Manager which led me to have to recode GridManager for monetary support, but that was honestly less painful than it sounds. I also spent a considerable amount of time debugging last post’s Zoning. The code has multiple ways of producing a building and this caused me to have to go back and go through all of the code line by line to figure all the pathways out and debug it eventually. And yes, as promised I made it cost money to zone. Every action, such as creating a road and destroying them cost money and using my amazing research skills of using the first google result, destroying a road costs double placing a road! I think I should sleep. See you soon!"}, {"post_id": 5134, "ts": "2026-06-08T20:27:14Z", "hours": 2.4142, "text": "CITY ZONING! Annoyed that a massive skyscraper decided to spawn right next to a nice cozy cottage? Not anymore! You can zone areas by residential, commercial and industrial. There is also a “No Build” zone for areas that you just want to keep clear for now. This will eventually cost you money, because paperwork is really expensive apparently. (And to keep the game balanced of course). But there’s no money yet. I think you should like & follow to see how the game’s economy works."}, {"post_id": 4989, "ts": "2026-06-08T17:13:15Z", "hours": 2.5267, "text": "Pocket City Dev 5 The terrain was a little bland, so I decided to spice it up with nature. To fill the grid up, I decided to implement trees. Created a few basic tree grid varieties and implemented it into GridManager.cs. However, this forced me to spawn all of the trees in the Start() function which causes a longer loading time, CPU spike and worst of all it makes it so that after the initial radius no more trees spawn. Increasing the radius exponentially increases the amount of trees being added (because each ring has more grid sections to cover). So i had to pivot. I created a new Chunk Manager, split the main grid up into 16x16 chunks, and checked the player camera and only loaded the surrounding chunks. This makes trees spawn around the player continuously. However, this would become laggy as it would happen every frame. Two ways I decided to prevent this: Check if the player had changed chunks. If it’s still the same chunk, early return to skip the entire code process. Check if the nature has already been loaded. Only load if not loaded. This obviously saves on time complexity, and allows me to have the freedom of creating varying tree density. It also makes it so that the trees do not regenerate constantly. And that completes the visuals for now. Probably will add more foliage and other variety in the future, but for now this will suffice. Finally, this has a severe performance penalty. To cater for lower-end devices, I added a toggle which will later come to a settings menu for ~4x the performance without impacting gameplay. Optimisations, such as chunkloading and LODs will be added later to increase the performance with trees, but that will come after the core game is finalised."}, {"post_id": 3868, "ts": "2026-06-06T23:09:38Z", "hours": 2.8567, "text": "Hello everyone! The city is finally generating. They automatically generate alongside roads or try grow in clusters with each other. Game looks pretty sweet. Almost 9 hours in, I think it’s time to get some sleep now."}, {"post_id": 3730, "ts": "2026-06-06T19:33:02Z", "hours": 4.095, "text": "Coming first in the UK leaderboard is pretty honourable. Anyways, working on Pocket City and we’ve almost got generation of buildings and I’ve got a lot of things lined up for this project. I really need that framework 12 💔. The roads have a cursor and you can destroy and create them in a row as well, camera movement is more polished with a sprint key. Got all the building assets and everything ready. What a entry to stardance & hackclub!"}, {"post_id": 3473, "ts": "2026-06-06T12:53:43Z", "hours": 1.3806, "text": "Procedural road addition, so that when you add a tile (which is still done through code currently), it will decide which road layout to add, be it an intersection, 4 way, 3 way, a road turn or anything else. Added clean camera movement with WSAD + scroll as well."}, {"post_id": 3429, "ts": "2026-06-06T11:20:47Z", "hours": 1.0264, "text": "Hello! I’m working on creating a top-down 2D-styled but 3D game where you control a city. I’ve got this grid layout so far and it works fabulously and I somehow got the rotations correct on the first try 🤣"}]...
|
Title: Capital Chaos by @sol4r_on_hackclub | Stard Title: Capital Chaos by @sol4r_on_hackclub | Stardance
Devlogs:
Hello! I’m working on creating a top-down 2D-styled but 3D game where you control a city. I’ve got this grid layout so far and it works fabulously and I somehow got the rotations correct on the first try 🤣
Procedural road addition, so that when you add a tile (which is still done through code currently), it will decide which road layout to add, be it an intersection, 4 way, 3 way, a road turn or anything else. Added clean camera movement with WSAD + scroll as well.
Coming first in the UK leaderboard is pretty honourable. Anyways, working on Pocket City and we’ve almost got generation of buildings and I’ve got a lot of things lined up for this project. I really need that framework 12 💔. The roads have a cursor and you can destroy and create them in a row as well, camera movement is more polished with a sprint key. Got all the building assets and everything ready. What a entry to stardance & hackclub!
Hello everyone! The city is finally generating. They automatically generate alongside roads or try grow in clusters with each other. Game looks pretty sweet. Almost 9 hours in, I think it’s time to get some sleep now.
Pocket City Dev 5 The terrain was a little bland, so I decided to spice it up with nature. To fill the grid up, I decided to implement trees. Created a few basic tree grid varieties and implemented it into GridManager.cs. However, this forced me to spawn all of the trees in the Start() function which causes a longer loading time, CPU spike and worst of all it makes it so that after the initial radius no more trees spawn. Increasing the radius exponentially increases the amount of trees being added (because each ring has more grid sections to cover). So i had to pivot. I created a new Chunk Manager, split the main grid up into 16x16 chunks, and checked the player camera and only loaded the surrounding chunks. This makes trees spawn around the player continuously. However, this would become laggy as it would happen every frame. Two ways I decided to prevent this: Check if the player had changed chunks. If it’s still the same chunk, early return to skip the entire code process. Check if the nature has already been loaded. Only load if not loaded. This obviously saves on time complexity, and allows me to have the freedom of creating varying tree density. It also makes it so that the trees do not regenerate constantly. And that completes the visuals for now. Probably will add more foliage and other variety in the future, but for now this will suffice. Finally, this has a severe performance penalty. To cater for lower-end devices, I added a toggle which will later come to a settings menu for ~4x the performance without impacting gameplay. Optimisations, such as chunkloading and LODs will be added later to increase the performance with trees, but that will come after the core game is finalised.
CITY ZONING! Annoyed that a massive skyscraper decided to spawn right next to a nice cozy cottage? Not anymore! You can zone areas by residential, commercial and industrial. There is also a “No Build” zone for areas that you just want to keep clear for now. This will eventually cost you money, because paperwork is really expensive apparently. (And to keep the game balanced of course). But there’s no money yet. I think you should like & follow to see how the game’s economy works.
Did you know it costs more to remove a road than create one?! Strange… Finally have a working economy in the game now! It’s VERY unbalanced. You WILL become very rich. And residential is currently useless, and everything just has a set employee count for now. But that will change soon, and we’ll make the game intelligent. Also the game clock is currently in the Finance Manager which is a little odd so maybe I’ll fix that later. But, I have used actions & delegates to optimise the game handling of the ridiculous amount of scripts for each building that will be running once the cities become larger and larger. Created a UI manager to update the script, which uses the above actions & delegates from the script manager. Created a Finance Manager which led me to have to recode GridManager for monetary support, but that was honestly less painful than it sounds. I also spent a considerable amount of time debugging last post’s Zoning. The code has multiple ways of producing a building and this caused me to have to go back and go through all of the code line by line to figure all the pathways out and debug it eventually. And yes, as promised I made it cost money to zone. Every action, such as creating a road and destroying them cost money and using my amazing research skills of using the first google result, destroying a road costs double placing a road! I think I should sleep. See you soon!
It can’t POSSIBLY BE THAT HARD CAN IT? No but you have to mix up TAGS AND LAYERS. There’s some error you got 5 builds ago but NEVER APPEARED AGAIN. EVEN HOURS INTO TESTING. HOW DID IT FIX ITSELF?! The UI now updates how much you gained in the past day! But anyways, you can finally toggle between the layers… after too much debugging (and realising it was just me being stupid). But it’s okay I’ll hopefully get that laptop from this blood sweat and tears. Look how gorgeous it looks now!
Sometimes, the most productive thing you can do is destroying everything for a clean slate. So that’s what I did and refactored my codebase, painting my GitHub red. The old city generation code ended up becoming messy spaghetti code that made it difficult to debug and work on it. And that sort of legacy code when I look back in a month is what ends up shelving projects for years on end. This half an hour will save me many in the future. I also removed the cluster expansion method of building expansion completely as it created annoying expansions that didn’t make sense of everything being 1 square off a road. Also created a GameManager and moved aspects of GridManager and FinanceManager to the new script, to try and centralise the logic and stop having random bits such as the day manager in the FinanceMananger, which didn’t make an sense. Also yes, I wasted 20 minutes trying to figure out what was going wrong when I forgot to add GameManager.cs to the scene 💔
What’s the difference between these two: int maxEmployees = 50; int employees = 25; float taxRevenue = 1500.0f; ONE : float revenue = (employees / maxEmployees) * taxRevenue; TWO: float revenue = (employees * taxRevenue) / maxEmployees; Mathematically, they’re the same. a/b * c = c/b * a However, I missed one thing while coding (a lot harder to see when it’s not just this). They’re both integers. now what C# does is it divides 25/50. we get 0.5. but they’re both integers, so it tries to store it as an integer, which floors it to a 0. Therefore, it’ll suddenly jump to max revenue when the company is full. obviously not what was intended. Option 2 makes you multiply the integer with a float, and stores 25 * 1500 as a float, which can now be nicely divided by 50 to get the value that we inteded. Sometimes… actually, no MOST of the time it’s the little things that catch you out. Anyways, this has very much balanced the game. The companies get as many employees as they can, then grow by 1 employee each day. Their revenue scales with the employee count, so now residential houses are useful for once. If anything, essential. Next up: Road tax, Land tax. This might be the one time you want tax… or maybe it’s too much?
Clean codebase always pays off (unless you want to keep your job apparently?) Fixed the vacancies counter, as before I was using = instead of +=. Told you it’s the little things that catch you out. Created a safer version of the draft forceRemoveElement() that accounts for jobs and residents when destroying a building (houses/shops/industry). This now updates the game realistically, e.g. if you destroy a house, then you reduce from the population. If the residents were employed, then it removes positions from buildings. If they were unemployed, then we remove it from the stats. Since I am not storing direct references between buildings but creating a game pool for performance, this makes the operations require lots of calling. This could probably be optimised in the future but I will do that near the first release due to the ever-changing code base. This required updating GameManager.cs to have LosePopulation(), LoseJobs() with a helper RemoveWorkersFromBuildings() function. Luckily the lists in GridMananger that I made like 20 hours ago for “future proofing” came in useful. Finally, you can press F to show city statistics and it updates in real time.
It’s been a really long time since I’ve posted. Some progress going on here. Little sneak peak of the fires… yep. You thought the game was gonna be peaceful? On another 7+ hour sprint today
Debugging HELL I added fires, which you can see in the corner. Unity Particle system actually really cool for that by the way. This forced me to rewrite how fires work and add new bits to the Building parent class. That was fine. Had to update the UI to show you that an earthquake was happening, which works more reliably than last time and I figured the ghost error out. I decided to implement water & energy requirements. Overhauled ChunkManager to allow for this, as each chunk needs enough. If it doesn’t produce enough, it imports from other chunks. If it can’t do that, everyone starts packing it up and leaving. Added this to city stats. Then modelled a cute little water tower as you can see below. Then I added energy, lots of chaos. Trying really hard to avoid circular loops to avoid a stack overflow, but it’s looking pretty good. User warnings now show up, like when an earthquake happens, or if a building burns down or if you can’t do something or don’t have money for something. Now I think I have time to do the fun part - creating chaotic fun stuff to make the city feel even more alive. But it’s looking pretty good right now. It’s getting close to being shipped, almost 40 hours in. Like & follow for the link ;) Now I really need to sleep. OH NO AND REVISE FOR THE PHYSICS TEST ON TUESDAY
WORKING PATHFINDING ON THE GRID! Created new assets so the game looks complete now! You can see the firetruck going from the Fire station all the way to the burning building where it will extinguish it. Yes, it follows the roads as intended and uses the A* algorithm to figure out the best path. And they shoot water out, so visual feedback for everything. This was super fun as it was the first time I’ve implemented the A* in a video game on a grid that procedurally generated. The coal power generator, fire station and fire trucks have models now, I think I made them good enough to fit with the game. Police station and healthcare to still be implemented but it’s looking good so far. This required creating a new services manager, creating a pathfinding script, updating global services and how everything interacts with the fire, and creating reverse pathfinding and small details. It’s coming together really cleanly now.
Working healthcare! The game now has a virus… and it spreads pretty quickly. Houses get infected, added to the random event chances on top of earthquakes and fires. I created hospitals that dispatch ambulances as required. Now all services cost money. Using the same A* algorithm from last time, but a little more complex due to the nature of the virus spreading to random buildings. This requires the game to check for any viruses. I created an UI that displays the day progression, using actions & delegates again. The day length is now no longer fixed, but instead it becomes smaller the longer you stay on the map, to try and add difficulty ramping. The game is currently very difficult at the start and incredibly easy at the end, so I’m trying to reverse this a bit and make it hard at the start but terrible towards the end. Also just realised there’s no ending lol - you just become broke and softlock yourself. Never done it to myself which really speaks out about how UNBALANCED the game is. I think it’s time to work on game balancing now before implementing new features, and over half way to shipping? maybe at 65-80 hours in at this rate?
Currently rebalancing the video game to make the game progression more realistic as it is currently extremely difficult at the start and stupidly impossible to die toward the end. Completely forgot to tell you guys that you can follow my projects on my YouTube: Video Like & sub if you can… mb for the self promo though. Sadly I have 6 exams next week so the next 2 weeks are most likely going to be slow ones… not dominating the leaderboards anymore.
I FINALLY LOST IN MY OWN GAME!! Rebalancing the game slowly but surely. Currently added inflation, which increases the price of everything as the days go by. It gets less severe the longer you play but the inflation rate stays high. The game days now vary, take 5 seconds at the start and slowly get faster and faster toward 1.5s linearly. The inflation rate also increases with bands as the game progresses so you need to keep up. This makes the game a good progression, but make one mistake during an earthquake and it might be ggs for you. There is now finally a game over function… although no restart but don’t worry about it. It just pauses the game and tells you that the game is finished. Next up: Detailed Finances, Rubbish? (follow thx)
Okay now i SUCK at my own video game. Don’t worry it’s hard mode. Also lost 2 hours of work somewhere cuz it didn’t save? Don’t understand how. That’s always great isn’t it. But still, 62 days in and I’m fried because of one silly mistake I made 40 days ago. Really teaches you consequences I guess. Spent my time completely overhauling how everything works. You used to make too much money, so I made the revenue even more population based, by making the max revenue a multiplier of the max population. Completely rewrote the losing population, unemployment and vacancy calculations to prevent strange negative numbers which was irritating me for the past one and a half weeks. Also overhauled the inflation to use a formula instead of a very rudimentary lookup table from if statements which is staged into a end-game (130 days+) and early game stage with 20% and 2% simple interest respectively (no not compound for once - that would make the game too hard. Extreme mode?) The game is actually like a good game now. I don’t know how to explain apart from that though.
I HAVE A PLANN For the spinal sprint toward completion. Should end up taking me to hour 70-75? Then we polish the UI and add a main menu… lacking feature I guess. Anyways, reorganised the code base and split game manager up, created folders and fixed dependencies for everything. There is now an event manager, which handles all of the events separately, and as you can see from this simple to-do list (should my next project be the to do list to end all to do lists with calendar integration and stuff???) that I have completed the first bit “Weighted Event system”. So now nothing has an equal chance of happening! Also as a side effect made adding new effects a lot easier due to the nested WeightedEvents class which was similar to an idea I had in my old minecraft mod plugin and transferred the skills across the languages. Quite nice neat code actually, that isn’t 600 lines long, so I can quickly show it to you below. It’s very applicable and I believe I have used it twice or three times in the past 4 months alone. The declarations for the events now look like this, very centralised and easy to add/remove events and modify the weightings. Called in the Start() function. weightedEvents.Add(new WeightedEvent("Nothing", 20, () => { })); weightedEvents.Add(new WeightedEvent("Earthquake", 5, Earthquake)); weightedEvents.Add(new WeightedEvent("Fire", 40, SetBuildingOnFire)); weightedEvents.Add(new WeightedEvent("Virus", 20, () => { TriggerVirusOutbreak(); } )); and the class is just simply storing the name, the weight and a weighted Event. public class WeightedEvent { public string name; public int weight; public Action weightedEvent; public WeightedEvent(string name, int weight, Action weightedEvent) { this.name = name; this.weight = weight; this.weightedEvent = weightedEvent; } } we do need to store the total weight which happens on the Start() function currently. When playRandomEvent() is called, we increase the cursor by the event’s weight until it is greater than the rolled random number between 0 and the total weight, at which point the class’ event is called. Broke nothing in the end! That’s great isn’t it, especially after migrating a bunch of “legacy” code. Hopefully didn’t jinx it.
POLITICS!! + Debugging Hell v2 I mean I guess it is? Not too sure. Event Manager completely overhauled. Double events now no longer have the chance of repeating the same event. Created a new GameEffects script which just takes a bunch of simple code away from EventManager and plays the basic functions such as the “tax revenue increases” which you see below. This was quite a headache to create, and I severely underestimated how much time this would take. I have 2 extra nested classes inside of EventManager for Political Question and Political Scenario. [... inside EventManager.cs ...] public class PoliticalQuestion { public string Question; public TaskCompletionSource<bool> TaskCompletionSource = new TaskCompletionSource<bool>(); public Action onAccept; public PoliticalQuestion(string question, Action onAccept) { Question = question; this.onAccept = onAccept; } } public class PoliticalScenario { public string description; public Action runnable; public PoliticalScenario(string featureDescription, Action functionality) { description = featureDescription; runnable = functionality; } } [Header("Political Question Variables")] public List<PoliticalQuestion> PendingQuestions = new List<PoliticalQuestion>(); public event Action onQueueChanged; private PoliticalScenario[] goodFeatures; private PoliticalScenario[] badFeatures; The political question is sent off to the UI manager, which displays it as shown below. Then it handles user input pressing Y/Enter or N/Esc to accept the user choice, and returns it back to the Event Manager. Seems simple enough, yet there are many ways to do it but I think that the above implementation works the best out of all the ones that I tried. I attempted to use Game Manager as a middleman but that did not work out - so I resorted to passing an entire class. The political scenario allows for the string to actually do something, so that the game knows what to process and what the user agreed to without creating a bunch of variables, and can allow for stacked political question events which is nice. Game’s looking really neat, and the multipliers and stuff can make the game go very crazy very quickly. Too much of a good thing is a bad thing!! Debugged the entire system for like a solid 3 hours it was actually bad. Came first in the UK tho!! I’m back after those 6 exams are done. Yes I know the UI looks pretty bad but it’s good enough for pre-beta testing. Oh yeah, speaking of UI everything is more bold. Figured out how to do that.
MAKE IT RAIN ASTEROIDS Pretty long run honestly. But before that, let’s talk about retrofitting your buildings. Earthquakes are pretty bad. Very bad when you loose your 100k building in a moment. So upgrade it. Yes it’ll cost you 35 to 55k now. But is your peace of mind worth that? And I added asteroids! These fly down and annihilate everything in a 3 unit radius and then set everything else in the 6 unit radius on fire. Lots of minor bug fixes as well, trying to get the game really polished now. Some rejigging of the game’s back end, such as creating a new abstract class for employer and reworking the systems to ensure that they run more smoothly and I believe almost finally fixing the unemployment/vacancy problem. I say almost because every 5 runs I see the game yell at me that it didn’t count something correctly but honestly I’ve spent so long on this I don’t even know if it’d be harder to just rewrite the entire employment system. For more detail, see my video linked below! See if you guys like it, my first proper long form I Added ASTEROIDS that ANNIHILATE your Adorable City And boy will this thing cook your economy.
BETTER UI + XP At the top of the image you can see a little progress bar… yep I’ve added XP now. Got plans for that, probably going to allow you to unlock stuff later. Like the lockdown ability etc. The UI has been overhauled. The actual images are a touch on the placeholder side apart from the road but it looks pretty good. You cycle between road, zoning and special building placement with 1, 2 and 3. Use R to rotate between the modes like residential, commercial and industrial zoning as well as Utilities & Emergency for the special buildings. Then finally T to rotate between those specific buildings. Complicated? Maybe? But it’s also a lot faster. I have completely lost my muscle memory of spamming R like the “good old days” though. Looks good? Bad? Horrible update and the game should never be changed ever again? Best update in the world and I should win £1 trillion? What do you think?
CRIME!!! + C# Generics I added Arson and added a Police manager that goes out and solves these crimes. Lots more to come, let me know of any ideas you have! But before that let me teach you ALL something. C# Generics. I had a bunch of scripts that all did ABOUT the same thing but with different. This was FindClosestHospital, FindClosestFireStation and the thing I was adding which was FindClosestPoliceStation. It felt quire redundant to copy the same lines but instead of Hopsital it was replaced with FireStation or PoliceStation. //Generic functions private T FindClosestReachableService<T>(Vector2Int targetPos, Func<T, bool> hasAvailableVehicles, out List<Vector2Int> bestRoute) where T : Building { T closestBuilding = null; bestRoute = null; int shortestRouteLength = int.MaxValue; bool foundBuildingOfThisType = false; foreach (var kvp in gridManager.GetMapGrid()) { GridManager.GridTile tile = kvp.Value; if (tile.buildingScript != null && tile.buildingScript is T serviceBuilding) { foundBuildingOfThisType = true; if (!hasAvailableVehicles(serviceBuilding)) continue; List<Vector2Int> testRoute = CalculateRoadPath(tile.buildingScript.gridPos, targetPos); if (testRoute == null || testRoute.Count == 0) continue; if (testRoute.Count < shortestRouteLength) { shortestRouteLength = testRoute.Count; bestRoute = testRoute; closestBuilding = serviceBuilding; } } } if (!foundBuildingOfThisType) { bestRoute = null; return null; } return closestBuilding; } Above is an example of the C# generic. We have “T” type, and I think this is a good place to learn about them. Instead of defining the function as returning something like Building , we make T a type. and you can see it passed in a little <T> after the function name. We can also pass in entire functions like Func<T, bool> which is utilised as shown below: Building bestStation = FindClosestReachableService<PoliceStation>(building.gridPos, ps => ps.HasPolice(), out route); you can see ps => ps.HasPolice() calls that out. And finally, to define what T is meant to be, I’ve added where T : Building . You can do this many times, such as by having both a T as well as a U! and you’d have a repeated where T : Building where U: PotatoChips or something idk what U is meant to be bro. This was my first time using it but it’s pretty cool and if you’re using C# I’d recommend learning it as it saved me like 200 lines of code and changing something 3 times to change the same thing! And yes, I added a third thing which is Arson! which is a crime based thing, and you have a visual that shows up as a timer. if a police doesn’t solve the crime it sets on fire. It’s not too bad but it adds a use for the police, with much more to come for the police to deal with in the future! Also added asteroid BOMBARDMENT as a debuff. Yeah it’s brutal. 3 strikes… thats up to 108 tiles DESTROYED and set on fire. And of course, the image is from a youtube video: Click me!
Main menu 👀 I need help. UI clearly isn’t for me
I’m being forced to post Yeah thanks stardance. 10 hour limit for what. Probably spam filter. Also MASSIVE BUG(s). One is that the game just randomly deletes all the buildings from a chunk. No idea why, I’ve been at it for so long. Another issue is the stupid vacancy counter which has been broken FOREVER but atleast now it doesn’t go negative. I have a serious feeling I will have to spend a week just POLISHING the game. Whatever, Currently working through a new feature of allowing you to use your money that you spent so long accumulating to try and fix the chaos that you went through. This is done through the “Council FX” which I may rename if you guys can think of a better name, and you can see the countless things to do such as: Taking On DEBT!! YAY!! 100k that gains 1% every day. Seems low.. but it will pile up very quickly since it’s compound interest. Overclocking the grid for free placement + infinite water/power Maximising Housing/Business revenue Curing all infections … and many more as well as the ??? at level 100… who knows what that does. £2.5 million btw. Of course, those levels are the XP, which has finally given that a use. And no you wont be at level 11000 just like that, i’m just being lazy for testing. Also rebalanced so that all of the commercial buildings have ~10-15% of their previous employment caps. So that you’re not just spamming residential. It also makes industrial more useful as they have more employers even though they produce less money.
Bugs are genuinely taking the life out of me Genuinely the worst thing ever. I STILL can’t figure it out but I had to post my weekly devlog anyways. Can you believe we’re 28 weeks into 2026??! Here’s the chaos where I accidentally created a “Pocket Empire” (Day 1105) Watch the video (click the title) if you wanna see how I ended up here and a minor crash out. very minor.
UFOs in an Alien Invasion 💔💔 The second rare event addition to Pocket City! Get a chunk of your population zapped up by some not so friendly aliens… Any more ideas, let me know below! But it was pretty neat to implement. 3D modelled it and everything. 3 hours of doing god knows what. Tried to figure quality settings out and probably did smth else but was too busy with the World Cup to remember what I did. Probably bug fixes and stuff. Oh yeah and you see a pretty cool ripple pulse thing that propogates through the map. Although it is a little weak right now but i’ll fix that next time. Super tired. mb
I NEED YOUR HELP Pocket City already exists as a game. I know this is stupid and I should have checked this before starting since I had the intention of publishing it to steam but here we are. If you want more details, or more knowledge about the game check this video out: Video Oops…
Hmmmm… What’s cooking? (Blender just WON’T count toward my hours but prolly spent 2-3 extra hours here) The helicopter blades actually spin. And W Unity particle system for the missile.
WORKING AIR DEFENCE + ATTACK HELICOPTERS So we got working air defence turrets with some predictive aiming, and attack helicopters that shoot missiles at random buildings. Although you’re unlikely to get 3 attack helicopters at once… for now. The helicopters blades do spin, they bob up and down, they go towards buildings. They shoot out these missiles, which pathfind their way to the targetted building. They all have a healthsystem which means that the turrets do some damage on collisions only though, one turret might take a while but two (or the 7 you see below) will MOW them down. Still have to hook it all up to the Finance Manager, Special Building placement and other boring stuff, but… I need more IDEAS!! (read this thx) …for more Military stuff that can be added. Tank wars? Who knows. I was thinking of a military invasion as being one of the rare events which spawns like 10 missiles and 5 attack helicopters and maybe a B2 bomber or some stuff. I also need more allied options, maybe I’ll add like an anti-bomb turret that is specifically for the B2 bomber or something and does 100000 damage. Or maybe your own airbase that spawns an allied helicopter and now you have dogwars. or maybe your own plane. idk So yes @Adam_Lotfalla this is what the helicopter was for. Yay more things to worry about!!! Still have integrations left! I’ll see you (hopefully) tomorrow once that’s done. but its midnight now so goodbye.
Nukes… from a plane A famous plane. The B2 Bomber. Idk gng I got bored. No but it drops a nuke that decimates everything in a decent radius and then sets everything in a bigger radius on fire, and now we have a new rare event called a “military invasion”.. that spawns like 8 helicotpers AS WELL as the b2 bomber. The B2 Bomber starts a few clicks out and then flies toward the set target building. Then it drops the nuke, and you have a few seconds to try and kill the nuke before it kills you, and on impact (yes we are finally using rigidbodys as they are intended) it explodes. You better have that turret system ready. Of course, it’s clearly not enough. So maybe I’ll add a anti-missile system as a YouTube comment said. Speaking of YouTube, thank you for all the support :) 100+ comments goes crazy, and we’re on 73 subs up from the previous 29 literally 3 weeks ago. Not subscribed? Help a fellow dev out: TechScope Channel
NEW NAME!!! Flash Floods + Main Menu If you remember, Pocket City is a game that already exists so now it’s called Capital Chaos. Thank you YouTube comments! And all of you as well, for the suggestions. Ofc new video to go with it: watch by clicking here! I created flash floods that.. well flood the entire map. It’s meant to be a little toned down of a disaster, thats more survivable because it gives the game a touch more balance. It stops all services from working, so that could be detrimental during a virus attack. But on the other hand, it stops every single fire and prevents new ones and explosions. A lifesaver if theres a nuke, it gets completely nullified. Also new main menu, I think it looks pretty neat. Especially compared to the old one.
I HATE Menus (in Unity at least) Genuinely hate them. But yeah we got settings menu working (which genuinely took like 5-6 hours because of stupid unity legacy stuff vs new stuff and then unity 6 vs 2023 version stuff i was used to) AHHHH I don’t remember it being this painful in Godot to be honest so maybe Godot is better for that? i had to get rid of VSync because it only worked on refresh. Created a debug menu to test performance, just to see that the only useful thing there was FPS and like RAM usage, and some engine stuff like active Rigidbodys. I couldn’t see the CPU utilisation or GPU utilisation which was… the thing I wanted to see. Although don’t worry performance does seem to be reasonable and early to mid game I can push over 1000 FPS on potato settings (specs at bottom if you care about them). It does obviously go down as the game continues on, but I think it’s quite optimised. Even with shadows its on 500+ FPS with a mid sized down. Although adding trees will quarter your FPS numbers. but it looks pretty so there’s your tradeoff. Although problematically if you turn trees off and you had already generated trees the fps stays low even though you’re not rendering it? I don’t know why unity is so weird. The game is quite unbalanced, but we’re in the final polishing stages (my target is 150 hours for the framework and hopefully it’s secure! (vote nice and high thanks - i did put a lot of effort into this game.) Up next: Difficulty selection Polishing Rebalancing updates Release!
You won’t believe it. I got it working FIRST TRY That’s actually crazy to be honest. Tells you how much expirience those 8 hours of menu development have given me. Someone give me a Unity menu doctorate or sum But on a serious note, we have game difficulty selection and its all nice and self contained. With controller support of course. You can see we have Previous Saves but that isn’t really functional yet. One of the things I learnt is to never rely on the UI giving you the data, only the click, so you’d manually add the elements and then call .value or .isOn respective to the component, and the same goes for dropdowns although I didn’t use one here. Let me know if you think it looks clean or any improvements to the UI readability, etc.
INSANE tree optimisations Went from 60-80 fps @ 4K to 400-450 (in game). Yes a 6 to 7x increase. How you ask? GPU Mesh Instance drawing offloading the CPU work of handling thousands of game objects. In English, I’m no longer spawning thousands of tree objects, but instead telling the GPU to draw the tree instances every frame. This seems quite unintuitive because you’re now drawing thousands of things every second. BUT this means that there are no game objects, so the CPU doesn’t even know that these exist. Also the GPU draws it thousands of times anyways. A game object handles transforms, rotations, etc. that the CPU has to keep track of whether it is active or not. This had the added benefit of the trees having no overhead when the trees are disabled, so you regain all of your framerate! Also I used some neat little script that combined the meshes all together in the GameObject prefab. Now it really should be able to run on your potato PC/Laptop. Combine script using UnityEngine; public class MeshCombineUtility : MonoBehaviour { [ContextMenu("Combine Children Meshes")] public void Combine() { MeshFilter[] meshFilters = GetComponentsInChildren<MeshFilter>(); CombineInstance[] combine = new CombineInstance[meshFilters.Length]; Matrix4x4 matrix = transform.worldToLocalMatrix; for (int i = 0; i < meshFilters.Length; i++) { if (meshFilters[i].gameObject == gameObject) continue; combine[i].mesh = meshFilters[i].sharedMesh; combine[i].transform = matrix * meshFilters[i].transform.localToWorldMatrix; } Mesh combinedMesh = new Mesh(); combinedMesh.CombineMeshes(combine, true, true); #if UNITY_EDITOR string directory = $"Assets/Assets/Mesh/Tree/{gameObject.name}.asset"; UnityEditor.AssetDatabase.CreateAsset(combinedMesh, directory); UnityEditor.AssetDatabase.SaveAssets(); Debug.Log($"Combined mesh saved to {directory}"); #endif } } Draw section of GPU Mesh Instancing private void DrawTreeMeshes() { if (treeMesh == null || treeMaterial == null) return; foreach (var kvp in generatedChunks) { ChunkData chunk = kvp.Value; if (chunk.spawnedTrees == null || chunk.spawnedTrees.Count == 0) continue; int batchSize = 1023; int totalTrees = chunk.spawnedTrees.Count; for(int i = 0; i < totalTrees; i+=batchSize) { int length = Mathf.Min(batchSize, totalTrees - i); Matrix4x4[] subMatrices = new Matrix4x4[length]; for (int j = 0; j < length; j++) { subMatrices[j] = chunk.spawnedTrees[i + j].matrix; } int meshIndex = Mathf.Abs(chunk.chunkCord.GetHashCode() + i) % treeMesh.Length; Graphics.DrawMeshInstanced(treeMesh[meshIndex], 0, treeMaterial, subMatrices, length); } } }
I’m getting new wifi lol, & 150 hours so yeah i won’t be here and probably will have to post a 10 hour thing BUT on the plus side, we got a nice death screen that has a bunch of quotes that you can read below [SerializeField] private string[] quotes = { "Opportunities multiply as they are seized \n - Sun Tzu", "If you are going through hell, keep going \n - Winston Churchill", "No empire was built on the first draft", "Fall seven times, stand up eight", "That which does not kill us, makes us stronger \n - Friedrich Nietzsche", "Out of ash, a new foundation", "I have not failed. I just found 10,000 ways that don't work \n - Thomas Edison", "A man is not finished when he is defeated. He is finished when he quits \n - Richard M. Nixon", "It does not matter how slowly you go as long as you do not stop \n - Confucius", "Out of difficulties grow miracles \n - Jean de La Bruyère", "The greater the obstactle, the more glory in overcoming it \n - Molière", "A Pocket Sized City is too small for your ambition. Build again \n - The Dev", "Success usually comes to those who are too busy to be looking for it \n - Henry David Thoreau", "Go big or go home", "You can't give up just yet. Stay determined... \n - Undertale" }; Maybe you’ll catch the little easter egg there as well ;) Working on adding game audio!! and probably finally enough hours to get the framework 12 (btw I wouldn’t recommend this as a daily laptop (f13 better), I just want something I can write on lol)
Game Sountrack? But before I talk about that, lemme just say the game audio is almost finished, we have menu sounds for clicks and stuff, and i added support for main menu music. The firetruck hoses actually do stuff, floods sound like floods, theres some peaceful background nature sounds and yeah it makes the game feel so much nicer. although i forgot place sounds which was a massive oversight. also my wifi is still working. no idea why, but not complaining. and i’m cooking on a soundtrack lowk although none of it seems correlated in any way and idk how i’ll make it fit into this game but you know what maybe it’ll just all go into some random album. None of the hours put into these songs count but its okay. i’m no pro tho so. all i’ll say is i love some bass
Final DevLog before First Ship - Boss Battle I don’t think words can explain what I made so click here to watch a video on my probably final major addition (no pressure) & also help with a small dilemma I have. NO!! that does not mean this game will stop development, but i think i finally have enough hours (+10-15 more safety) to get a Framework 12! (and then i will be able to crack on with entrance exams - so i guess development will slow a touch). Of course I’ll ship once the game is polished enough. You might see a devlog or two from the “Capital Chaos Website” - follow me ;) I really hope you guys all enjoy it and now I need to do the readme and stuff. I also realised I was one of the most viewed on Stardance which is honestly amazing and I appreciate all of the support :) And thank you to all the new friends I’ve made and all the followers and commenters. It’s honestly been insane.
BETA TEST! Nvm I have to devlog my final changes But lemme talk to those stardance reviewers real quick. Scroll down to see the endless content of my story, and all the community feedback (also on my youtube). Playing the game is a bit of a learning curve so you can watch my videos and stuff on it as well. I’d say watch this one: Boss Fight for the boss fight and maybe one of the other ones that you find interesting. Maybe this one because it has over 1,000 views and still climbing! The game is released there but it is windows only for now (i will release linux and maybe mac on the actual release game don’t worry but I’m super restricted for time right now) SKIP IF YOU’RE ON LINUX / MAC For everyone: Changes: Amended GameAudioManager to adjust for max voices which uses a List based system that appends and unappends. Boss fight also toggles and untoggles the game audio dependant on each audio source, because the game could currently have hundreds or even thousands of audio source which is really bad optimisation. So each audio source that I want to track has a ManagedAudioSource attached which automatically registers and unregisters itself from the GameAudioManager. I also edited the boss fight to make it a touch harder and amended the moves ;) And come and beta test NOWWW. leave all your comments, suggestions etc. on THE NEW DISCORD COMMUNITY!! or youtube, i’ll read it all and, again, thank you all for your support . I don’t know what to put as the image so here.
Thank you all so much for the support! Framework 12 is on it’s way (and this wait is painful). After 171 hours! 19.54x is actually insane and I appreciate it a lot. Join the Discord! I made a discord (click above) and i’ll give you all an early supporter role before I put it out on YouTube and stuff for the “wishlist” when the full game comes out (if you want to stay in touch after stardance is done. ALSO IF YOU COMMENTED WHILE THE GAME WAS STILL CALLED POCKET CITY DM ME ILL GIVE U A SPECIAL ROLE The game beta is still up and you can try it out Currently just doing some minor stuff to the game (Fixed some normal/easy mode not settings correct phases. B2 Bomber should destroy itself and stop the nuke siren once launched), and slowly adding a tutorial but I’m like 90% focused on revising for uni entrance exams
Ships:
Welcome to Capital Chaos! One of Stardance’s most awaited projects ;) (hopefully anyways) We’ve got chaos, a bunch of random events, a boss fight and so much more for you to explore. SKIP if you are on Linux/MacOS (or you can vote based on the videos - completely up to you) as I only have a windows executable for now. I am honestly super proud of this, and the community built around this game. I hope you enjoy it as well. There have been TONNES of challenges, such as pathfinding, the initial grid also seemed really daunting. To the vacancy count which was literally plaguing me for the past MONTH and got fixed today (it was one line… i know.. maybe I should have used AI). But besides, it’s a sick project. I hope you all love it. Unzip the file in the release and it should be good to go. READ THE README FOR INSTRUCTIONS AND CONTROLS!! THERE IS NO TUTORIAL Read the story, watch the videos if you can and just enjoy the game! It will be on steam in 8-9 months so maybe subscribe?...
|
1792842667.2298918
|
1792929067.2298918
|
|
44760
|
NHNK by @bali0531 | Stardance
|
bali0531
|
3
|
203.0
|
3419
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-06T17:48:14Z", "hours": 85.0, "multiplier": 19.62, "payout": 1664, "blessing": "neutral", "text": "Last ship was about optimizing stuff and fixing small bugs, while this ship is a bit more focused on new features, a new OOBE page, dev mode for advanced statistics about the application, and another batch of bug and UI fixes. So the main goal was to make the app look better and provide a better experience while using it overall + making it easier to diagnose possible problems through the devmode. UI/UX fixes include a new OLED theme, fixed overlapping elements, fixed contrast of the pages. For the UX part a new Out Of Box Experience, its basically a new login/info flow on first start, so now instead of separate pages for TOS/PP login, institution search etc, everything is on one seemless experience. It had some bug fixes too, like the .ics calendar exporting and auto-updating has been fixed now. Also fixed the broken widgets too so now it actually shows what classes you have that day. In terms of New Functions this ship introduces a new Dev mode by clicking the version number fast multiple times, it has a lot of informations about the startup, resource usage etc. For the future plans, I don’t have any new idea for now, the ones I had turned out to be not possible because of the api I have to use, I will probably fix the findings from the reviews of this ship + google playstore closed testing findings too. If you have any good idea make sure to write it down in the reviews / on the github page. (or on discord at @ bali411)", "repo": "https://github.com/Bali0531-RC/NHNK", "demo": "https://github.com/Bali0531-RC/NHNK/releases"}, {"ship_num": 2, "ts": "2026-08-29T18:07:52Z", "hours": 59.0, "multiplier": 18.22, "payout": 934, "blessing": "neutral", "text": "The previous ship was about fixing up the basics and making everyting work as intended. If you are interested in the main points of this project etc make sure to read the previous ship description too. In this ship I focused on optimizing the app, making the load time shorter, fixing some bugs like haptics etc, also logged the readme and website rework too. This ship is mainly for ending this stage before I start working on new features and more fixes. I optimized almost everything I can, made loading parallel where it was possible etc. Next ship will be packed with new features, I plan to add a dev mode to help find and debug edge cases or loading issues / resource leaks, also planning to add an “OOBE” to make the onboarding more seamless and modern. (No new images for this ship, since most of the changes are code related and not cosmetical. )", "repo": "https://github.com/Bali0531-RC/NHNK", "demo": "https://github.com/Bali0531-RC/NHNK/releases"}, {"ship_num": 3, "ts": "2026-08-11T18:50:41Z", "hours": 59.0, "multiplier": 17.56, "payout": 821, "blessing": "neutral", "text": "This project’s (NHNK = “Nem Hivatalos Neptun Kliens”, or in english “Unofficial Neptun Client” so you can say unc) goal is to make the life of university students easier, by creating a mobile app that lets them view their schedule, grades, statistics, upcoming events, messages and a lot more in one place, without the need to login every 30 minutes. The main problem was figuring out how the official university system “Neptun” works, and finding their API routes, but after figuring that out, the app works perfectly fine. This project makes major improvements over the official websites, First of all, every university has their own URL for the management site, that the students have to find / memorize, my app only needs the name of the university, and it automatically uses the saved address(es) from our list. Most universities have multiple urls/servers for “Neptun”, so if one is down, there is another. This again requires the users to figure out which server is up and usable, my app auto selects a server from the fallback list, if the default website is not available, and makes the switching seamless without even the users notice. The “Neptun” website also require users to login after 30min inactivity again, while in the same time most universities enabled the function to require 2fa for all accounts. While this is good for security, it makes checking your schedule grades etc a hassle. My app only needs users to enter their details once, and it wont ask for them again (except if the auth fails because of invalid credentials.), I know it might seems a security issue, that the app wont log users out, but the app is fully read only, as its only meant to check your data. these are the main improvements, but there are a lot more fun and usable features in the app, like detailed statistics etc. You can try the app out on https://nhnk.bali0531.hu via the live demo, or you can download it from github releases (and google play store too soon), but it requires a hungarian university student status to log in. (For non hungarian people who are interested in the app, a DEMO mode is also available in the app itself, but at that point you can just check it out on the website without downloading anything.", "repo": "https://github.com/Bali0531-RC/NHNK", "demo": "https://github.com/Bali0531-RC/NHNK/releases"}]...
|
[{"post_id": 63063, "ts": "202 [{"post_id": 63063, "ts": "2026-09-06T17:32:06Z", "hours": 5.5081, "text": "Added an OLED theme, picked it on my phone, and most of the screen was still grey. Rather than argue with my own eyes I took a screenshot and read the actual pixel values out of it, which took about a minute and saved me a lot of guessing. The background was 121212 when I had asked for pure black. Turned out the theme was never reaching the screen. The app builds its colour scheme without setting a surface colour, so every page fell back to Material’s own default grey and quietly ignored the palette it had been handed. One line, and the background went to 000000 and the cards to 080808. The bit I liked was the leftovers. A few tiles stayed light and I was about to go and edit the seventy something places that paint card backgrounds by hand, until I noticed the colour was 3B4548. That is not grey. Grey has equal channels. It was the teal accent bleeding in, because Material tints raised surfaces with your primary colour, so that was one setting too rather than an afternoon of find and replace. Also checked the contrast while I was in there and every accent clears AA on black between 9.37 and 18.80 to one, and found that choosing OLED did not survive the phone flipping to light mode and back, because the theme listener was overwriting whatever you picked. Not finished yet, the tile fix still needs a look on a real device."}, {"post_id": 62859, "ts": "2026-09-06T12:01:46Z", "hours": 9.5653, "text": "The old setup opened with a page of legal text and then asked whether you wanted to pick your school from a list or type in a Neptun URL, which is a strange thing to ask someone who has not been told what the app does yet. One of the reviews said it was a bit hard to set up and that was the honest version of it. It is four steps now with a bar across the top so you can see where the end is. Terms first, then a screen that actually says what NHNK is, then your school, then the login. The school search used to live behind that how do you want to log in question and now it is just the third step, so there is one less screen to get through. While testing it I typed obuda and got nothing back, because the school is called Óbudai Egyetem and I had not thought about accents. Nobody types those into a search box. It folds them now and there are tests so it stays that way. The screen I deleted was also quietly running the update check and the language prompt, which I only noticed on the last read through before removing it. Testing any of this used to mean wiping my own login, so debug builds install separately now."}, {"post_id": 62309, "ts": "2026-09-05T16:43:11Z", "hours": 5.9292, "text": "The next release replaces the login flow, so before touching anything I sat down and read the one I already have. It is four screens before anyone sees a timetable, all of them living in a single file of 2148 lines with five page classes in it. Disclosure, then pick how you want to log in, then find your university, then your Neptun code and password. The university list is 54 entries that I typed in by hand, and the app openly admits in its own description that your school might not be there. That is the part I keep coming back to, because someone whose university is missing has to understand what a Neptun URL is before they can get in. I also found out I had a note wrong. I had written down that the app forces Hungarian and needs country detection added. It does not. It already reads the phone language and falls back to English for anything it does not have. Good thing I checked before building a feature that exists. The genuinely awkward bit is the disclaimer. Translations get downloaded from GitHub while the app runs, which is lovely for adding languages and completely wrong for legal text, since nothing downloaded should be able to rewrite what the disclaimer says. So it is compiled in, and the one screen that most needs to be understood is the one screen stuck in two languages. I do not have a clean answer for that yet. Smaller things I wrote down. A class called SetupPageInstitudeSelection, spelled that way in eleven places. One university with its URL fixed up by hand inside the login handler. The Linux desktop build does not compile at all, which I only discovered because I tried to run the first-run flow there rather than wipe my own account off my phone. Four screens is not really the problem. Not knowing which of them people give up on is."}, {"post_id": 62096, "ts": "2026-09-05T10:46:49Z", "hours": 6.6283, "text": "Someone sent me a screenshot of the home screen widget saying they had no classes, last updated 00:00. They had a class at nine. The 00:00 was not a rounding problem or a timezone problem, it was every day, for everyone, since the widget shipped. When the app caches your week it stores the date as midnight on purpose, because the check for whether the cache is a day old compares whole days. The widget read that same value and printed the clock part of it, so it was showing you the definition of midnight rather than when anything happened. Reading the fetch path to fix it turned up a worse one. If a refresh fails the app puts the old rows back so you still have something to look at, which is right, but then it saves them again with today’s date on them. A week of failed refreshes and the cache still swears it is current. Restored rows keep their original timestamp now. The widget cannot fetch anything by itself, so past a day it says to open the app instead of telling you your day is empty. I nearly shipped that badly too, because the new timestamp only gets written on a real fetch, so every existing user would have been told to refresh the moment they updated. It falls back to the old date for them until their next fetch. An empty widget is fine. An empty widget that looks confident is not."}, {"post_id": 61698, "ts": "2026-09-04T18:56:47Z", "hours": 2.2917, "text": "The statistics page asks you to type how many credits your degree is, which has always annoyed me because Neptun obviously knows. So I went looking, and it will not tell me. There is an endpoint for it sitting in my own code that I have never called, except it only exists on the old API and the modern one has no equivalent among the ten endpoints I use. The one call that touches your programme at all already runs on every startup, and it returns three fields: whether the training is current, its id, and its name. Not a credit count anywhere. I even tried working it out from the programme name and that failed too, because it is a plain string with no BSc or MSc in it. So the box where you type 180 stays, and the release that was going to remove it does not exist. An evening to find that out is a lot cheaper than half a feature."}, {"post_id": 61464, "ts": "2026-09-04T12:10:44Z", "hours": 10.0589, "text": "Tap the version seven times and the app now has a developer tab: startup timings, every request it makes, how stale each cache is, and how many frames it dropped. The interesting part was not building it, it was working out what it is allowed to say, because this thing is holding somebody’s Neptun password. So the list of stored keys is an allowlist rather than a blocklist, meaning a key I add next year is hidden until I say otherwise, and the cached grades and messages only ever show their size. The redaction lives in the recorder instead of the screen, which matters more than it sounds, because one of my own URLs turned out to be a credential and a log that printed URLs would have published it."}, {"post_id": 60573, "ts": "2026-09-03T00:32:04Z", "hours": 10.0933, "text": "Next release I want a developer tab that shows what the app is storing and every request it makes, which sounds harmless right up until you remember my app is holding somebody’s Neptun password. So before writing any of it I went through all 77 things it keeps on disk, and only 46 can have their value put on screen. The trap was sorting by key name, because CachedMarkbook_3 sounds like nothing and is actually somebody’s grades, so that whole group gets to show its size and age and nothing else. The one that nearly got me is the calendar export link, which keeps working with no session at all, meaning the URL is the credential, and a network log that prints URLs would have published it in plain text."}, {"post_id": 60246, "ts": "2026-09-02T14:26:30Z", "hours": 5.3231, "text": "Someone reviewing the last ship said my contrast was bad, the corners did not match and things needed more padding, so instead of squinting at it I went and measured all three. Every accent colour in the light theme failed WCAG AA, and the worst was the one I use for links and section headers, sitting at 1.43 to 1, which is pale blue text on pale grey. Then I counted the corner radii and found fifteen different values across 88 places, which is exactly the kind of thing you stop seeing in your own app. The padding one turned out to be a single number, the search box above the message list had zero bottom padding, and while I was looking at spacing I finally noticed the week switcher on the timetable has always been two separate boxes of different widths with mismatched corners, pretending to be one panel."}, {"post_id": 59878, "ts": "2026-09-01T21:18:00Z", "hours": 10.0089, "text": "I added screen reader labels to the payments, messages and periods cards, then dumped the accessibility tree off the phone to actually hear what came out. Good thing, because the order was backwards: every card read its details first and the name of the thing last, so a subject announced itself as “6 credits, not completed, Introduction to Programming”. That was true of the markbook labels I shipped months ago as well, which nobody had ever mentioned to me. Also finished the calendar export fix from last time, so exporting your timetable no longer tells you the file type is unsupported."}, {"post_id": 59071, "ts": "2026-08-31T17:55:45Z", "hours": 9.8689, "text": "Spent this one adding screen reader labels to the cards that never had any, and then dumping the accessibility tree off the phone to check what actually comes out. Two things fell out of that: the order was backwards everywhere, so cards read their details before the name of the thing, and that was true of labels I shipped months ago too. The honest scoreboard is three of seven card types verified, payments is impossible for me to check because my account has no bills on it, and I have not run an actual screen reader yet, only read the tree, which tells me nothing about focus order or whether you can even swipe to them. So this one is going into closed testing before it gets a tag."}, {"post_id": 58018, "ts": "2026-08-30T11:09:29Z", "hours": 9.7206, "text": "Someone told me the timetable export says “unsupported file type” on their phone, and then mine did it too, which at least made it easy to chase. Turns out the plugin I use picks the file type from a big list of extensions and there is no entry for ics, so it falls through to / and Android hands that to whatever generic file previewer the manufacturer ships, which obviously cannot read a calendar. The annoying part is the phone had the right app the whole time, because Honor’s calendar registers itself for text/calendar and I just never asked for it. One extra argument and the export now offers the calendar first, which ships in the next update."}, {"post_id": 57516, "ts": "2026-08-29T18:00:19Z", "hours": 2.3325, "text": "Last time I said the real problem was that startup waits for the keystore at all, and that fixing it meant making six getters async across a pile of call sites. Did it, and it went from 239ms to 144ms because the timetable comes out of the cache and never needed a password in the first place. What I did not expect was that the compiler only caught 22 of the 27 places that broke, because the last five build the old API request body by gluing strings together, and a string is happy to take a Future and turn it into “Instance of ‘Future<String?>’”. So those five would have quietly posted that to the university as my password instead of failing, which I only found because I went looking after the analyser had already gone green."}, {"post_id": 57413, "ts": "2026-08-29T15:39:47Z", "hours": 9.7889, "text": "Last release I added timers to the app. This one I finally pointed them at startup, and the answer was annoying: 153ms of a 251ms cold start was one function, and 128ms of that was six separate trips to the Android keystore to read six saved values one at a time. None of which the timetable needs, because it draws from cache. I have a fix half done that reads them once and starts before anything asks, but while measuring I noticed the bigger problem is that startup waits for those values at all, and unpicking that means changing six getters used in 46 places, so that is the next few evenings."}, {"post_id": 56915, "ts": "2026-08-28T22:43:52Z", "hours": 9.1436, "text": "I have been shipping features for weeks without ever measuring any of them. So I plugged the phone in and actually timed things, and the Upcoming screen I added last week turned out to fire eight calendar requests one after another. One slow week took 3.2 seconds and the other seven just sat in the queue behind it. Sending them four at a time took the whole thing from 3987ms to 297ms. Then while I was reading the log I noticed every haptic in the app has been throwing an exception instead of vibrating, because I gave Android an amplitude list of the wrong length in all seven places, so vibration has never once worked."}, {"post_id": 56621, "ts": "2026-08-28T13:34:18Z", "hours": 10.9206, "text": "My app ships a 22.9 MB emoji font to draw 28 emoji. It’s bundled on purpose, so the icons look identical on every phone instead of Samsung doing its own thing. Fine goal. But it’s the whole font, 1485 codepoints, sitting in the base module so every single user downloads all of it. Subset it to the ones I actually use and it’s 1.93 MB.Most of what was left after subsetting turned out to be the SVG table. Google ships every glyph twice, once as COLR and once as SVG, and Skia only draws the COLR one, so 6.1 MB of it was duplicate artwork nothing would ever read.Also learned to measure the thing that matters. Uncompressed it’s a 21 MB saving, which sounds great, but the font compresses inside the APK so the real number is 7.30 MB to 1.01 MB, and the APK went 67.6 to 61.0. Still good, just not the number I wanted to write. Separately, my last release failed twice for reasons that had nothing to do with me: CI tracked Flutter stable, stable moved to 3.47, and it raised the minimum Gradle and then the minimum AGP. Pinned CI to the version I actually build with."}, {"post_id": 56177, "ts": "2026-08-27T20:14:51Z", "hours": 10.6, "text": "Last ship’s feedback was blunt: five people said they couldn’t tell what the project was because they don’t read Hungarian. The UI switched to English fine, but the demo data never did, so you’d open it and still get “Analízis I. (előadás)” and “bejelentkezési időszak”. So every bit of fake data the demo makes up now follows the app language. Timetable, exams, deadlines, grades, four semesters of history, payments, periods, mail. Two things had to stay Hungarian underneath though: the period icons are picked by string-matching the period name (Neptun only ever replies in Hungarian), and the “is this payment cancelled” check keys off the word “törölt”. Translating those naively would’ve silently killed every period icon and made cancelled payments look paid. Kept the raw values for the logic, translate only what’s on screen.Found a bug doing it too. Switched to Hungarian and half the demo stayed English, because markbook/payments/periods cache their data for 24h and nobody had exempted demo mode. The calendar already did. Now they all do.Also killed 9 languages. German, Romanian, Russian, Turkish, Ukrainian, Arabic, Spanish, Chinese and Pirate were all downloadable and all mostly half-translated, so picking one left you in a mix of two languages, which is worse than just being in one. Magyar and English only now."}, {"post_id": 55132, "ts": "2026-08-26T16:25:24Z", "hours": 16.6372, "text": "Spent the last stretch on the parts of the project that aren’t the app itself. Rewrote the README three times. First pass just bolted an English version onto the Hungarian one and it ballooned to 351 lines. Second pass I tried to make it “proper” and somehow ended up at 3,185 words, which is longer than most of my essays and nobody was ever going to read it. Third pass I threw that out and wrote it like I’d explain the thing to a friend. Ended up at 184 lines, shorter than what I started with, in two languages instead of one.Then rewrote the whole website. The old one had a big slogan hero, “Neptun, the way it should work on your phone”, which sounds nice but doesn’t tell you what the thing actually is. New one just says it: an unofficial Neptun client for Android, with a little spec row underneath (platform, licence, tracking, price) so you get the whole picture in about two seconds. 13 files, ~5k lines. Also finally wired the site into the app repo as a submodule so they stop drifting apart. Not the most exciting work but the feedback from last ship was that people couldn’t tell what the project was if they didn’t speak Hungarian, so this was the fix."}, {"post_id": 45330, "ts": "2026-08-11T18:32:36Z", "hours": 11.6211, "text": "Your exams were always in the app, you just had to guess which week to scroll to. Built an Upcoming screen that pulls every exam, deadline and open registration period into one list with countdowns, plus a degree progress ring and proper subject pages that finally put the grade, the classes and the exam together."}, {"post_id": 44854, "ts": "2026-08-10T21:49:43Z", "hours": 7.0381, "text": "Was adding a stats page and realised the app had been downloading all 6 of my semesters this whole time and then throwing away everything except the last one. So now there’s actual history: semester averages, credits, grade distribution, on charts I painted by hand because adding a chart library for two graphs felt dumb.Also found out cancelled payments were counting as money you’d spent, so it was telling you that you’d paid 5000 Ft you never paid. Fixed that too. 1.2.3 is out."}, {"post_id": 44620, "ts": "2026-08-10T14:47:36Z", "hours": 8.6858, "text": "I was shipping 20 MB that nobody downloads"}, {"post_id": 44179, "ts": "2026-08-09T19:26:38Z", "hours": 8.5783, "text": "Added live demo for the app to the website."}, {"post_id": 43585, "ts": "2026-08-08T22:40:44Z", "hours": 20.7336, "text": "Fixed some bugs, added widgets, offline mode and a lot more stuff. 5/14 days done until playstore prod release."}, {"post_id": 42540, "ts": "2026-08-07T10:46:27Z", "hours": 2.4797, "text": "Play Store closed testing is in progress!"}]...
|
Title: NHNK by @bali0531 | Stardance
Devlogs:
Pla Title: NHNK by @bali0531 | Stardance
Devlogs:
Play Store closed testing is in progress!
Fixed some bugs, added widgets, offline mode and a lot more stuff. 5/14 days done until playstore prod release.
Added live demo for the app to the website.
I was shipping 20 MB that nobody downloads
Was adding a stats page and realised the app had been downloading all 6 of my semesters this whole time and then throwing away everything except the last one. So now there’s actual history: semester averages, credits, grade distribution, on charts I painted by hand because adding a chart library for two graphs felt dumb.Also found out cancelled payments were counting as money you’d spent, so it was telling you that you’d paid 5000 Ft you never paid. Fixed that too. 1.2.3 is out.
Your exams were always in the app, you just had to guess which week to scroll to. Built an Upcoming screen that pulls every exam, deadline and open registration period into one list with countdowns, plus a degree progress ring and proper subject pages that finally put the grade, the classes and the exam together.
Spent the last stretch on the parts of the project that aren’t the app itself. Rewrote the README three times. First pass just bolted an English version onto the Hungarian one and it ballooned to 351 lines. Second pass I tried to make it “proper” and somehow ended up at 3,185 words, which is longer than most of my essays and nobody was ever going to read it. Third pass I threw that out and wrote it like I’d explain the thing to a friend. Ended up at 184 lines, shorter than what I started with, in two languages instead of one.Then rewrote the whole website. The old one had a big slogan hero, “Neptun, the way it should work on your phone”, which sounds nice but doesn’t tell you what the thing actually is. New one just says it: an unofficial Neptun client for Android, with a little spec row underneath (platform, licence, tracking, price) so you get the whole picture in about two seconds. 13 files, ~5k lines. Also finally wired the site into the app repo as a submodule so they stop drifting apart. Not the most exciting work but the feedback from last ship was that people couldn’t tell what the project was if they didn’t speak Hungarian, so this was the fix.
Last ship’s feedback was blunt: five people said they couldn’t tell what the project was because they don’t read Hungarian. The UI switched to English fine, but the demo data never did, so you’d open it and still get “Analízis I. (előadás)” and “bejelentkezési időszak”. So every bit of fake data the demo makes up now follows the app language. Timetable, exams, deadlines, grades, four semesters of history, payments, periods, mail. Two things had to stay Hungarian underneath though: the period icons are picked by string-matching the period name (Neptun only ever replies in Hungarian), and the “is this payment cancelled” check keys off the word “törölt”. Translating those naively would’ve silently killed every period icon and made cancelled payments look paid. Kept the raw values for the logic, translate only what’s on screen.Found a bug doing it too. Switched to Hungarian and half the demo stayed English, because markbook/payments/periods cache their data for 24h and nobody had exempted demo mode. The calendar already did. Now they all do.Also killed 9 languages. German, Romanian, Russian, Turkish, Ukrainian, Arabic, Spanish, Chinese and Pirate were all downloadable and all mostly half-translated, so picking one left you in a mix of two languages, which is worse than just being in one. Magyar and English only now.
My app ships a 22.9 MB emoji font to draw 28 emoji. It’s bundled on purpose, so the icons look identical on every phone instead of Samsung doing its own thing. Fine goal. But it’s the whole font, 1485 codepoints, sitting in the base module so every single user downloads all of it. Subset it to the ones I actually use and it’s 1.93 MB.Most of what was left after subsetting turned out to be the SVG table. Google ships every glyph twice, once as COLR and once as SVG, and Skia only draws the COLR one, so 6.1 MB of it was duplicate artwork nothing would ever read.Also learned to measure the thing that matters. Uncompressed it’s a 21 MB saving, which sounds great, but the font compresses inside the APK so the real number is 7.30 MB to 1.01 MB, and the APK went 67.6 to 61.0. Still good, just not the number I wanted to write. Separately, my last release failed twice for reasons that had nothing to do with me: CI tracked Flutter stable, stable moved to 3.47, and it raised the minimum Gradle and then the minimum AGP. Pinned CI to the version I actually build with.
I have been shipping features for weeks without ever measuring any of them. So I plugged the phone in and actually timed things, and the Upcoming screen I added last week turned out to fire eight calendar requests one after another. One slow week took 3.2 seconds and the other seven just sat in the queue behind it. Sending them four at a time took the whole thing from 3987ms to 297ms. Then while I was reading the log I noticed every haptic in the app has been throwing an exception instead of vibrating, because I gave Android an amplitude list of the wrong length in all seven places, so vibration has never once worked.
Last release I added timers to the app. This one I finally pointed them at startup, and the answer was annoying: 153ms of a 251ms cold start was one function, and 128ms of that was six separate trips to the Android keystore to read six saved values one at a time. None of which the timetable needs, because it draws from cache. I have a fix half done that reads them once and starts before anything asks, but while measuring I noticed the bigger problem is that startup waits for those values at all, and unpicking that means changing six getters used in 46 places, so that is the next few evenings.
Last time I said the real problem was that startup waits for the keystore at all, and that fixing it meant making six getters async across a pile of call sites. Did it, and it went from 239ms to 144ms because the timetable comes out of the cache and never needed a password in the first place. What I did not expect was that the compiler only caught 22 of the 27 places that broke, because the last five build the old API request body by gluing strings together, and a string is happy to take a Future and turn it into “Instance of ‘Future<String?>’”. So those five would have quietly posted that to the university as my password instead of failing, which I only found because I went looking after the analyser had already gone green.
Someone told me the timetable export says “unsupported file type” on their phone, and then mine did it too, which at least made it easy to chase. Turns out the plugin I use picks the file type from a big list of extensions and there is no entry for ics, so it falls through to / and Android hands that to whatever generic file previewer the manufacturer ships, which obviously cannot read a calendar. The annoying part is the phone had the right app the whole time, because Honor’s calendar registers itself for text/calendar and I just never asked for it. One extra argument and the export now offers the calendar first, which ships in the next update.
Spent this one adding screen reader labels to the cards that never had any, and then dumping the accessibility tree off the phone to check what actually comes out. Two things fell out of that: the order was backwards everywhere, so cards read their details before the name of the thing, and that was true of labels I shipped months ago too. The honest scoreboard is three of seven card types verified, payments is impossible for me to check because my account has no bills on it, and I have not run an actual screen reader yet, only read the tree, which tells me nothing about focus order or whether you can even swipe to them. So this one is going into closed testing before it gets a tag.
I added screen reader labels to the payments, messages and periods cards, then dumped the accessibility tree off the phone to actually hear what came out. Good thing, because the order was backwards: every card read its details first and the name of the thing last, so a subject announced itself as “6 credits, not completed, Introduction to Programming”. That was true of the markbook labels I shipped months ago as well, which nobody had ever mentioned to me. Also finished the calendar export fix from last time, so exporting your timetable no longer tells you the file type is unsupported.
Someone reviewing the last ship said my contrast was bad, the corners did not match and things needed more padding, so instead of squinting at it I went and measured all three. Every accent colour in the light theme failed WCAG AA, and the worst was the one I use for links and section headers, sitting at 1.43 to 1, which is pale blue text on pale grey. Then I counted the corner radii and found fifteen different values across 88 places, which is exactly the kind of thing you stop seeing in your own app. The padding one turned out to be a single number, the search box above the message list had zero bottom padding, and while I was looking at spacing I finally noticed the week switcher on the timetable has always been two separate boxes of different widths with mismatched corners, pretending to be one panel.
Next release I want a developer tab that shows what the app is storing and every request it makes, which sounds harmless right up until you remember my app is holding somebody’s Neptun password. So before writing any of it I went through all 77 things it keeps on disk, and only 46 can have their value put on screen. The trap was sorting by key name, because CachedMarkbook_3 sounds like nothing and is actually somebody’s grades, so that whole group gets to show its size and age and nothing else. The one that nearly got me is the calendar export link, which keeps working with no session at all, meaning the URL is the credential, and a network log that prints URLs would have published it in plain text.
Tap the version seven times and the app now has a developer tab: startup timings, every request it makes, how stale each cache is, and how many frames it dropped. The interesting part was not building it, it was working out what it is allowed to say, because this thing is holding somebody’s Neptun password. So the list of stored keys is an allowlist rather than a blocklist, meaning a key I add next year is hidden until I say otherwise, and the cached grades and messages only ever show their size. The redaction lives in the recorder instead of the screen, which matters more than it sounds, because one of my own URLs turned out to be a credential and a log that printed URLs would have published it.
The statistics page asks you to type how many credits your degree is, which has always annoyed me because Neptun obviously knows. So I went looking, and it will not tell me. There is an endpoint for it sitting in my own code that I have never called, except it only exists on the old API and the modern one has no equivalent among the ten endpoints I use. The one call that touches your programme at all already runs on every startup, and it returns three fields: whether the training is current, its id, and its name. Not a credit count anywhere. I even tried working it out from the programme name and that failed too, because it is a plain string with no BSc or MSc in it. So the box where you type 180 stays, and the release that was going to remove it does not exist. An evening to find that out is a lot cheaper than half a feature.
Someone sent me a screenshot of the home screen widget saying they had no classes, last updated 00:00. They had a class at nine. The 00:00 was not a rounding problem or a timezone problem, it was every day, for everyone, since the widget shipped. When the app caches your week it stores the date as midnight on purpose, because the check for whether the cache is a day old compares whole days. The widget read that same value and printed the clock part of it, so it was showing you the definition of midnight rather than when anything happened. Reading the fetch path to fix it turned up a worse one. If a refresh fails the app puts the old rows back so you still have something to look at, which is right, but then it saves them again with today’s date on them. A week of failed refreshes and the cache still swears it is current. Restored rows keep their original timestamp now. The widget cannot fetch anything by itself, so past a day it says to open the app instead of telling you your day is empty. I nearly shipped that badly too, because the new timestamp only gets written on a real fetch, so every existing user would have been told to refresh the moment they updated. It falls back to the old date for them until their next fetch. An empty widget is fine. An empty widget that looks confident is not.
The next release replaces the login flow, so before touching anything I sat down and read the one I already have. It is four screens before anyone sees a timetable, all of them living in a single file of 2148 lines with five page classes in it. Disclosure, then pick how you want to log in, then find your university, then your Neptun code and password. The university list is 54 entries that I typed in by hand, and the app openly admits in its own description that your school might not be there. That is the part I keep coming back to, because someone whose university is missing has to understand what a Neptun URL is before they can get in. I also found out I had a note wrong. I had written down that the app forces Hungarian and needs country detection added. It does not. It already reads the phone language and falls back to English for anything it does not have. Good thing I checked before building a feature that exists. The genuinely awkward bit is the disclaimer. Translations get downloaded from GitHub while the app runs, which is lovely for adding languages and completely wrong for legal text, since nothing downloaded should be able to rewrite what the disclaimer says. So it is compiled in, and the one screen that most needs to be understood is the one screen stuck in two languages. I do not have a clean answer for that yet. Smaller things I wrote down. A class called SetupPageInstitudeSelection, spelled that way in eleven places. One university with its URL fixed up by hand inside the login handler. The Linux desktop build does not compile at all, which I only discovered because I tried to run the first-run flow there rather than wipe my own account off my phone. Four screens is not really the problem. Not knowing which of them people give up on is.
The old setup opened with a page of legal text and then asked whether you wanted to pick your school from a list or type in a Neptun URL, which is a strange thing to ask someone who has not been told what the app does yet. One of the reviews said it was a bit hard to set up and that was the honest version of it. It is four steps now with a bar across the top so you can see where the end is. Terms first, then a screen that actually says what NHNK is, then your school, then the login. The school search used to live behind that how do you want to log in question and now it is just the third step, so there is one less screen to get through. While testing it I typed obuda and got nothing back, because the school is called Óbudai Egyetem and I had not thought about accents. Nobody types those into a search box. It folds them now and there are tests so it stays that way. The screen I deleted was also quietly running the update check and the language prompt, which I only noticed on the last read through before removing it. Testing any of this used to mean wiping my own login, so debug builds install separately now.
Added an OLED theme, picked it on my phone, and most of the screen was still grey. Rather than argue with my own eyes I took a screenshot and read the actual pixel values out of it, which took about a minute and saved me a lot of guessing. The background was 121212 when I had asked for pure black. Turned out the theme was never reaching the screen. The app builds its colour scheme without setting a surface colour, so every page fell back to Material’s own default grey and quietly ignored the palette it had been handed. One line, and the background went to 000000 and the cards to 080808. The bit I liked was the leftovers. A few tiles stayed light and I was about to go and edit the seventy something places that paint card backgrounds by hand, until I noticed the colour was 3B4548. That is not grey. Grey has equal channels. It was the teal accent bleeding in, because Material tints raised surfaces with your primary colour, so that was one setting too rather than an afternoon of find and replace. Also checked the contrast while I was in there and every accent clears AA on black between 9.37 and 18.80 to one, and found that choosing OLED did not survive the phone flipping to light mode and back, because the theme listener was overwriting whatever you picked. Not finished yet, the tile fix still needs a look on a real device.
Ships:
This project’s (NHNK = “Nem Hivatalos Neptun Kliens”, or in english “Unofficial Neptun Client” so you can say unc) goal is to make the life of university students easier, by creating a mobile app that lets them view their schedule, grades, statistics, upcoming events, messages and a lot more in one place, without the need to login every 30 minutes. The main problem was figuring out how the official university system “Neptun” works, and finding their API routes, but after figuring that out, the app works perfectly fine. This project makes major improvements over the official websites, First of all, every university has their own URL for the management site, that the students have to find / memorize, my app only needs the name of the university, and it automatically uses the saved address(es) from our list. Most universities have multiple urls/servers for “Neptun”, so if one is down, there is another. This again requires the users to figure out which server is up and usable, my app auto selects a server from the fallback list, if the default website is not available, and makes the switching seamless without even the users notice. The “Neptun” website also require users to login after 30min inactivity again, while in the same time most universities enabled the function to require 2fa for all accounts. While this is good for security, it makes checking your schedule grades etc a hassle. My app only needs users to enter their details once, and it wont ask for them again (except if the auth fails because of invalid credentials.), I know it might seems a security issue, that the app wont log users out, but the app is fully read only, as its only meant to check your data. these are the main improvements, but there are a lot more fun and usable features in the app, like detailed statistics etc. You can try the app out on https://nhnk.bali0531.hu via the live demo, or you can download it from github releases (and google play store too soon), but it requires a hungarian university student status to log in. (For non hungarian people who are interested in the app, a DEMO mode is also available in the app itself, but at that point you can just check it out on the website without downloading anything.
The previous ship was about fixing up the basics and making everyting work as intended. If you are interested in the main points of this project etc make sure to read the previous ship description too. In this ship I focused on optimizing the app, making the load time shorter, fixing some bugs like haptics etc, also logged the readme and website rework too. This ship is mainly for ending this stage before I start working on new features and more fixes. I optimized almost everything I can, made loading parallel where it was possible etc. Next ship will be packed with new features, I plan to add a dev mode to help find and debug edge cases or loading issues / resource leaks, also planning to add an “OOBE” to make the onboarding more seamless and modern. (No new images for this ship, since most of the changes are code related and not cosmetical. )
Last ship was about optimizing stuff and fixing small bugs, while this ship is a bit more focused on new features, a new OOBE page, dev mode for advanced statistics about the application, and another batch of bug and UI fixes. So the main goal was to make the app look better and provide a better experience while using it overall + making it easier to diagnose possible problems through the devmode. UI/UX fixes include a new OLED theme, fixed overlapping elements, fixed contrast of the pages. For the UX part a new Out Of Box Experience, its basically a new login/info flow on first start, so now instead of separate pages for TOS/PP login, institution search etc, everything is on one seemless experience. It had some bug fixes too, like the .ics calendar exporting and auto-updating has been fixed now. Also fixed the broken widgets too so now it actually shows what classes you have that day. In terms of New Functions this ship introduces a new Dev mode by clicking the version number fast multiple times, it has a lot of informations about the startup, resource usage etc. For the future plans, I don’t have any new idea for now, the ones I had turned out to be not possible because of the api I have to use, I will probably fix the findings from the reviews of this ship + google playstore closed testing findings too. If you have any good idea make sure to write it down in the reviews / on the github page. (or on discord at @ bali411)...
|
1792878441.7529333
|
1793742441.7529333
|
|
30756
|
Stardancer (formerly Unnamed Platformer) by @zahra Stardancer (formerly Unnamed Platformer) by @zahran | Stardance...
|
zahran
|
1
|
220.0
|
3505
|
[{"ship_num": 1, "ts": "2026-1 [{"ship_num": 1, "ts": "2026-10-12T20:37:52Z", "hours": 220.0, "multiplier": 13.35, "payout": 3505, "blessing": "neutral", "text": "For HackClub Stardance, I created Stardancer , a 30-level platformer featuring a unique mechanic: mid-level shapeshifting to unlock new abilities and powers! I used C++ and SFML (the Simple and Fast Multimedia Library) to code this game. During the development of this game, I ran into a couple of technical challenges. Collision was among the biggest; I had initially decided on AABB (Axis-Aligned Bounding Box) collision, but after implementing that I realized that it led to erroneous collision interactions, misalignments, and more issues. So, I switched to SAT (Separating Axis Theorem) collision instead. This, combined with general collision response logic, made coding collision one of the hardest endeavours of this project. There were many other challenges throughout development, however none are too disruptive to the experience of the final game. I’m still extremely proud of myself and this project for many reasons: This is the largest project I’ve ever made; Despite many challenges, bugs, and pieces of complex logic to work through, I made a fully functional and complete game; I managed to make this with no external engines; I was able to use my C++ and new SFML skills to create something I can proudly say I made! IMPORTANT NOTE FOR REVIEWERS!! PLEASE READ!!! A complete playthrough of the game takes a large amount of time due to how levels are structured: to play a level, you must beat the level before it, which poses an issue for one of the shapes which is only unlocked in the last set. I realize most reviewers do not have the time required to play through the full game and gain a complete understanding of its features. For this reason, I strongly urge reviewers to skim through/watch my full walkthrough video linked in my README, as well as check out the “Credits Easter Egg” section in that video. Playing through all 30 levels sequentially takes time, but you can unlock every level directly from the Credits screen so you can test all shape powers hands-on right away! This way, a reviewer will be able to understand the scope and gameplay of the game in a short amount of time. With that being said, I truly hope you enjoy my game.", "repo": "https://github.com/HughMann635/Stardancer", "demo": "https://zahran-635.itch.io/stardancer"}]...
|
[{"post_id": 79153, "ts": "202 [{"post_id": 79153, "ts": "2026-10-12T20:35:30Z", "hours": 8.0819, "text": "Unnamed Platformer - Devlog 27 WE’RE FINALLY HERE! What I did: I did a lot of final polish and testing before getting the game ready for release. Initially I was going to use Emscripten to port my game over to web assembly (inspired by this video: https://www.youtube.com/watch?v=1kiwpAIU454 ) but I soon realized that it was much more complex than it looked, and kind of took away from the spirit of being entirely made out of C++ and SFML. So, I decided to simply publish an executable rather than port the game over to web. I set up the release build and whatnot (which took a while because of cmake config issues and whatnot) but I finally got a release build working n it feels great! I ported to itch.io, now I just gotta finish up the itch page and readme, as well as record a walkthrough video for macOS and Linux users as I couldn’t figure out how to configure the game for either. Challenges: The whole odyssey of deciding how to port my game over was a slight hassle, but nothing too bad. Also, while recording my walkthrough vid, I ended up discovering A LOT of hidden bugs, so I managed to pick all those off and there shouldn’t be any left…hopefully. Plans for next time: Ship! This devlog will be my last for this project, and for this challenge. Aside from being done with everything, I accidentally created a completely new project according to Hackatime when I was renaming the file folder, executable, etc. from “WorldofBlockman” (my placeholder name) to Stardancer so everything would be more consistent with my final title. so any work I do on my project won’t count towards heartbeats and thus I can’t post another devlog (15 minutes minimum/devlog). Still, it’s been such an amazing journey, I learned so much and I made this game that I’m super proud of 🥹 even though this game gave me hell sometimes, I have virtually no regrets about any of it. This has been my biggest project ever, and many more to come in the future hopefully. K…bye guys."}, {"post_id": 74692, "ts": "2026-09-28T00:34:26Z", "hours": 9.5458, "text": "Unnamed Platformer - Devlog 26 Stardance extension + fatigue = holy procrastination 😂✌️ What I did: More random stuff: Level timer that stores each level’s personal best, displays a live timer in the level, and lets you access your PR for each level from level select menu Fixed issue where you couldn’t close game while in settings menu Death count (it just tracks deaths over every single level, accessed from level select menu, manual restarts count as death too) and coin count as well Adjusted some levels a bit Added a feature to handbook where items you haven’t come across yet are blacked out and have hidden descs, and add notification to handbook when you unlock these items Update README a little bit cause I was feeling lazy and didn’t want to do anything else Fix some bugs concerning rotation and tipping, as well as making it so you do not rotate when passing thru a 1 tile high gap (this is specially an issue with the square where it can feel a bit janky otherwise) I will note that some of these were multifaceted changes that took quite a bit of effort and iterations, but I couldn’t be bothered explaining everything I did here. And more playtesting too. Challenges: Probably the handbook feature…it was the longest one out of all of them. Plans for next time: I want to be done with pretty much everything related to the actual game by next devlog, so I can focus on the README and finally shipping! K bye guys"}, {"post_id": 70860, "ts": "2026-09-19T21:41:39Z", "hours": 9.0317, "text": "Unnamed Platformer - Devlog 25 I’m so tired omg What I did: Bunch of miscellaneous stuff: Added basic vfx: so far we only have a click sound, I’ll add more later but it took me a while to figure out how to get SFML’s audio system working since I also had to find out why my audio files weren’t loading in either. Added coins to every level: added new tile type for coin, added a coin into each level, added effects, etc. Fix bugs/gameplay issues such as the triangle being unable to teleport after a restart/new level, rearrange some levels to fit coin placements, find out some new bugs and try (and fail) to fix them, so decide to deal with them another day. Add simple death animation to the player. Make it so levels must be completed in progressive order (e.g. you start at level 1, cannot progress till you have completed), also add different colors to boxes on level select menu (check vid) Probably a few more things related to general playtesting but i can’t remember Challenges: Making level buttons in the levelmenu was kind of frustrating not only because of the selection aspect but also getting them to visually render in the proper colors. Honestly though, now the main challenge is dealing with my own fatigue, especially since I’ve been joining more clubs and getting more homework, so hopefully I can clutch up over the final few days cuz I highkey need that framework 13 🥺✌️ Plans for next time: I added a list of bugs I want to tackle/stuff I want to add: //BUGS!!!!! //cant close window while in settings menu //rotation bugs //levels 13, 17, 26, 4, 8, look into //as well as other levels but these ones I can remember //TO ADD!!!!! //speedrun timer //death count //updating handbook (notif icon, hidden objects) //more sfx (death especially) K bye guys"}, {"post_id": 68850, "ts": "2026-09-15T21:16:00Z", "hours": 7.4011, "text": "Unnamed Platformer - Devlog 24 The game is finally coming together… 🥹🔥 What I did: All the menus in the game are completed! Ngl, credits was really easy ofc, but I was deciding how I should go about doing it, still didnt take too long tho. Then settings was a lot harder 😭 volume adjustment was quite easy, but the real problem came with creating the keybind section, since I had already coded hard inputs all throughout my code. So I pretty much had to add a new system + helper func in vars.h, then replace every instance of isKeyPressed with that system+helper, then code the menu in the ui file (Which took forever cuz of bugs with msg updating + event handling + key updates + etc.). Well, it’s (mostly) done now, which is good. And ofc I was also testing the game for general bugs too. Challenges: The keybind menu took me a hella long time to get done…thats about it, aside from some other tiny bugs. Plans for next time: add vfx, polish up every single one of the menus…and then I’ll see where to go from there. Hopefully I can finish most of my stuff by the start of next week. K bye guys"}, {"post_id": 66830, "ts": "2026-09-12T19:00:20Z", "hours": 9.0458, "text": "Unnamed Platformer - Devlog 23 Hey guys. What I did: I did a lot of playtesting/bug hunting as usual, but I was mainly creating the entire handbook menu. Which took surprisingly long, cuz of designing the menu + figuring out how to include all the different tile icons + creating descriptions + making stuff functional + formatting + colors + bugs + you get the idea. Anyway I’m pretty happy with how it looks so far, I doubt I’ll make any major changes in the future. Also I did find a couple of bugs while testing, but i didn’t really do anything about them, I want to completely create all the core functions before tackling any small bugs/issues. Challenges: There were a few bugs and I went through a few designs for the menu, but overall everything was hella light so I wouldn’t say there were any real challenges. Plans for next time: Create credits menu, then work on adding vfx, add settings menu (thinking of adding volume + keybind toggles), polish up all the menus…and then I’ll see where to go from there. I’m pretty worried cuz now that school’s started (im in gr11 now) I’m probably gonna have a good amount of schoolwork, clubs, etc. that I’ll also have to make time for…so wish me luck ig. K bye guys"}, {"post_id": 63924, "ts": "2026-09-07T23:45:05Z", "hours": 6.8869, "text": "Unnamed Platformer - Devlog 22 School starts tomorrow ✌️so i decided to make a shorter devlog…also I’m so tired What I did: Honestly you can’t really tell that I did much at first glance. I was mainly playtesting a lot and polishing stuff up, and making sure all the background stuff was fine. For now I dont think I’ll return to background stuff for a while. Although I did manage to add a particle effect for the black holes (both the ones in the background as well as the actual obstacles). I was also experimenting with a horizon for a bit, but then I decided I don’t want it and scrapped a good chunk of time worth of changes. Challenges: Deciding how to add in particles was a bit challenging, specially the math part. But other than that it was a pretty chill 7 hours. Plans for next time: Hopefully finish menus, then: work on vfx, polish up all the menus, tackle any big issues with levels or physics, and finally work on bringing my game onto itch.io! not all in one go, though. K bye guys"}, {"post_id": 61060, "ts": "2026-09-03T19:34:17Z", "hours": 9.8472, "text": "Unnamed Platformer - Devlog 21 Background design is a bit easier now that I have a plan…also I did not lose track of time 👍 What I did: I added in every single sky element I want to have: comets, planets, black holes, stars, floating rocks, and a moon. I think I might tweak some elements later down the line (specifically the moon(adding craters) and black holes(I’ll think of some extra effects) ), but for now I’m fairly satisfied with how far I’ve come. Looking at the game now gives me a sense of pride at seeing everything finally come together after so long 🥹✌️ Challenges: Making comets was a bit of a hassle, because I had to decide how to do it (which took me some time for brainstorming + more time cuz of discarded changes + even more minutes of brainstorming), and implement it. It’s pretty complex cuz there’s a cooldown on each comet, then you have to set the spawn point and angle/speed, calculate the trail’s points, draw them, draw the head too etc etc…so it was pretty tedious, but comets are the most rewarding visually imo out of all the features. Other than that, I spent a bit of time per other feature figuring out how to implement each of them, but none of them were as complex as the comet. Plans for next time: Finish up any bugs or other issues in sky-related stuff, then I’ll try to make a visible horizon again and see if I’ve changed my mind since last time. Either that or I’ll start working more on smaller vfx, specially trying to find out how to make a particle effect. K bye guys"}, {"post_id": 59814, "ts": "2026-09-01T19:29:23Z", "hours": 11.1828, "text": "Unnamed Platformer - Devlog 20 Background design is a hell of a lot harder than I thought it would be…also I lost track of time 😭😭 What I did: I got started on background design, and partially implemented a background. I actually had a pretty different idea in mind compared to what I have now: the rest of the planet visible, stretching into the horizon, with mountains and volcanoes etc etc. scattered along its surface. After spending a while implementing that, I realized it a) didn’t look right, since everything was just following the player around at normal cam speed, and b) I didn’t like the idea anymore to begin with. So after scrapping all those changes, I started researching how to add a scrolling effect so it would look more natural. I found out how to implement a parallax scroll effect, which basicallymeans that objects in the background move along slower than objects closer to the front of the screen. I also restructured my scenes.h file which contains all background-related stuff, and made a couple of other small changes and fixes with certain levels. I know I don’t have much to show for it, but that’s mainly because I spent a lot of time tweaking certain elements and just undoing backgrounds I ended up not liking 😭🥀 Challenges: Deciding what to do visuals-wise cost me some time bcuz I kept going back on my old ideas, but restructuring scenes.h was the hardest part since after deciding what to do for visuals, I had to base the logic in scenes.h off that. Also it took me a while to decide how to add in a parallax scroll system. Plans for next time: Work on more background stuff. right now I’ve set up a lot of background elements’ structs and whatnot, but I’ve only redrawn the stars and added a rough brightening/dimming effect. Also Im gonna have to start thinking about what I’m going to add on each of the sub-menus accessible from the main menu (credits, handbook, and settings). K bye guys"}, {"post_id": 56961, "ts": "2026-08-29T00:22:59Z", "hours": 9.99, "text": "Unnamed Platformer - Devlog 19 The UI is coming along pretty nicely! Pt. 2 What I did: I believe I’ve fully created everything UI- and menu-wise, aside from 3 additional menus (credits, a ‘handbook’ that contains info about stuff, and a settings page) that are currently blank. I created a hovering effect for buttons that makes it so when you hover over a button, the button goes downward slightly and the shadow moves to match. Aside from that, I polished up/tweaked some minor details, and the only things I’ll add menu wise are probably those 3 sub-menus on the main menu and a universal backwards-nav button. The biggest thing (time-wise) was figuring out how to make the code more readable and actually making it more readable. I created two new functions for making text and button objects which made my life a lot easier, also the button-hover code took quite a few lines so I put that into a function too. Aside from that, I made a couple fixes here and there to make it more efficient memory wise. And even then, I ended up breaking stuff which took me a while to fix, such as the issue with unpausing ur game in the vid. Challenges: Probably efficiency stuff, since deciding how to do it + implementation took a while and had a couple of bugs due to me not accounting for stuff. For example: my hover function would change states on its own, but since sometimes you don’t need to directly change state or you need to do other things too, I made it into a boolean that each individual case takes and does its own thing with. Plans for next time: Start on background stuff probably, I don’t want to do anymore UI stuff for now. I have a fewideas in mind for my background visuals, but I hope they won’t be too hard/impossible to implement. K bye guys"}, {"post_id": 55174, "ts": "2026-08-26T17:32:12Z", "hours": 9.9275, "text": "Unnamed Platformer - Devlog 18 The UI is coming along pretty nicely! What I did: Designed a full level select menu (there are a couple more things left to add), add a heads up display for the current level, and add proper mouse input and extra details to buttons such as shadows (havent implemented shadows for everything, I’ll explain why) and changing color when hovering. Even though it doesn’t sound like much, it took me a surprisingly long time because my text wasn’t centering…What I didn’t realize is that sf::Text creates invisible offsets for some reason, so when I used getGlobalBounds() it would return that offset too and mess up the centering. I ended up doing some research and realized I had to use the local bounds (i.e. untransformed) when centering. Challenges: Ig the biggest ‘challenge’ was centering buttons with text, because at first I actually tried to manually fine tune coordinates and whatnot. But then I found out I had to use localbounds and blah blah. Another thing is, I spent a lot of time fine tuning sizes, colors, shadow darknesses and depths, etc. which took a lot of my time. Also no ai used this time either, although I did spend a lot of time researching why my text wouldn’t center itself. Plans for next time: I’ll just polish up existing menus, and work on background elements. Also I want to add a kind of handbook accessible from the main menu that tells you what stuff does, different powerups, etc. But most importantly, I’m gonna try to find out how to make shadow creation more efficient. For every text/button, I need a shadow. That means I have to add it as a member in the class, copy the actual object, change the color and offset it, then draw it too. Since I have so many objects that make shadows (all of them in the end, ideally), I’m probably going to make a shadow-making function for readability. Other than that I’ll just play the game and test levels a bunch, which I’ve already been doing a lot to make sure everything is as it should be. K bye guys P.S. there’s also still a couple bugs ( UI-related or otherwise) that I have to fix as well"}, {"post_id": 53440, "ts": "2026-08-24T00:04:55Z", "hours": 9.9042, "text": "Unnamed Platformer - Devlog 17 It’s actually no longer “Unnamed Platformer”, it’s “Worlds of Blockman”, I might change that later idk What I did: I designed level 30, playtested every level extensively and tweaked some levels, and made a basic main menu, level hud and pause menu. And it took me ~10 hours. Well, that’s not all I did. I also changed up the colors of the square to differentiate it from spikes and buttons, and I added a visual indicator for the triangle’s teleport. When you tp the triangle fades to a darker shade of green, and when it gets off cooldown (3 secs) it fades back to its normal color and then you can tp again. Also, level design took quite a long time since I was kind of making it up as I went along, and the whole game states implementation wasn’t too hard in itself, but I ran into errors with loading my font. I added the .ttf file to my assets folder and wrote the correct file name in font.loadFromFile() and whatnot, but turns out I didn’t have the actual font downloaded in the build folder or my project. So after a bit less than an hour I added it in and it fixed the issue. also I spent a bit of time deciding how the different menus would actually look which ate up some time. Challenges: ngl the font-loading thing was kind of the only hard part 😭most other stuff was solved relatively quickly and easily AI used, if any: None, also most likely no AI will be used in the future since the future just holds visual stuff which should not be hard enough to merit the help of AI. Plans for next time: Level select menu, add more stuff to main menu, also make it so the current level shows in the background when you go to the pause menu. also add mouse inputs so you can use those instead of kb inputs in the menu, and start on some more vfx and sfx. I’m also really tired"}, {"post_id": 51378, "ts": "2026-08-21T01:20:51Z", "hours": 9.9719, "text": "Unnamed Platformer - Devlog 16 Actually didn’t get a lot done over the last few days, let me explain. What I did: The biggest and only new feature I added was a major adjustment to black holes. Earlier they were just 2 tile x 2 tile circles that killed you upon touching. I’ve reworked them to how they’re supposed to be: 6 px x 6 px black circles, with a surrounding 6 tile x 6 tile ring. now if you enter the ring, you lose the ability to move normally (you can still jump tho) get pulled toward the black center, which kills you if you touch it Which is how it’s supposed to be (nevermind the astrophysical inaccuracy lmao). This took me 2 hours 😭 and then I designed levels 26 and 27. I also re-added the old texture system I implemented and then took down earlier cuz it was making things look hella grainy, but only for environment tiles cuz there’s no big changes visually compared to redrawing them every frame. Unfortunately it doesn’t seem to be doing much in terms of efficiency. I also designed levels 28 and 29 (ss of level 29 attached), and playtested every level from 1 to 28 and adjusted each one to remove any unwanted ways you can cheese a level, as well as to just make some of them less punishing for small mistakes. I also (FINALLY) designed level 6. I added extra sections and polished up some elements that were making the level impossible if you didn’t play it perfectly. I did 2 other things as well: I made it so blocks can’t be pushed by any character other than the square (before you could just push blocks w/ anything) and I reduced horizontal movespeed in zero-g. There’s still a lot more I have to do, mainly ui/menu stuff and visual polish. Challenges: Black hole physics took me a while since my first few implementations were completely wrong, and then I locked in nd figured out how to make it pull correctly. Also, level design is proving to be surprisingly challenging, I rly didn’t think it would take this long, but what with conceptualizing + creating + playtesting each level, especially the later ones where I want to make them more complex and difficult, it eats up a lot of time per level. Even going back through older levels and tweaking them can take a while, cuz you gotta track down all the problematic sections and figure out how to fix them. I also have a humble 18 more days till school starts so I gotta lock in🙏 AI used, if any: None, level design is hard but its not THAT hard Plans for next time: Finish level 30, playtest levels 29 and 30, and hopefully get started on + finish a main menu and level select menu. Im so behind on my schedule it aint even funny so wish me luck"}, {"post_id": 49286, "ts": "2026-08-18T00:22:13Z", "hours": 10.0053, "text": "Unnamed Platformer - Devlog 15 Actually got a lot done over the last few days ig What I did: first off, I reset my old changes and made it so env tiles layer over obstacles. At first I tried to assign an individual character to each combination (spike in water, block in zero-gravity, etc etc) but that didn’t work since I couldn’t get them to lay over each other. So what I did is I split my statictilelist into two: statictilelist now held all non-moving entities like spikes, ground, etc. while envtilelist held all my environment tiles. Then I changed my map loading function to take two map strings: one assigned tiles based on entities and the other pass assigned them based on environment. And now I can lay environments over things without breaking my game! Yippee! I also fixed an issue where blocks could clip through obstacles in zero-g when you moved them upward. The issue was blocks unconditionally being mtv-moved when the player was below them, so the player forced them through anything. I added an extra check before mtv-moving and made obstacle detection variables global to fix it. I also ran into an issue where spikes would incorrectly kill you even if you were not touching them, just near: the issue was that I wasn’t running SAT collision, just going straight to death logic if the initial AABB check turned out true (I run an AABB check first because running SAT for everything makes the game super laggy). both of these lowkey took me a while 😭 As for level design I reworked level 6 (still can’t play it) and level 17 (finished), and I designed levels 18-25 (I attached a video of level 24). Also in the vid I switched shapes randomly, that’s just because I had different keybinds earlier and it was js muscle memory kicking in. Challenges: Aside from a bunch of small bugs, the biggest challenges were the issue where spikes would kill you even if you weren’t touching them and the issue with blocks being pushed up forever in zerog. Even then, for both issues it was still easy to fix since it was easy to diagnose and a few lines per fix, even if it took me a while to find those few lines 🥀🥀 However, there’s still an issue where blocks sink slightly upon spawning in zero-g. This makes it impossible to play level 6, so I’ll have to look into/rework/do something to zero-g logic because I really want to keep its existing level mechanic. AI used, if any: None 🔥 Plans for next time: Finish levels 26-30, finish level 6, and test all the levels to make sure they’re not too hard/impossible/possible to cheese. Aside from that, I’ll most likely bring back the texture thing I implemented last time cuz it did actually make the game run a bit smoother, but I’ll only do it for environment tiles. K bye guys"}, {"post_id": 46621, "ts": "2026-08-14T00:27:19Z", "hours": 10.0767, "text": "Unnamed Platformer - Devlog 14 I’m genuinely so done What I did: I designed levels 5 and 7-16 (ss of a few levels should be attached idk which they are). I have a cool idea in mind for level 6 but my current code makes it hard to implement, and I also have a cool idea in mind for level 17 but my code made it hard to implement. So I changed everything up like an idiot. My 17th level features a massive pool, but that requires me to draw 1000+ water tiles. Since I redraw tiles every frame, it causes a big load on the computer. So I had the brilliant idea of creating an sf::RenderTexture . spoiler it’s not so brilliant. That led to a massive chain reaction where there were a bunch of nullptr issues at first, which I spent about 40 minutes on before actually getting the game to run. Then everything was super grainy due to aliasing issues caused by drawing everything to a RenderTexture, PLUS since I was drawing everything at the start of the frame and not updating it, stuff like buttons and doors would never update. SO, my dumb ahh moved half my static/environment tiles to dynamictilelist , reserved for strictly blocks which are the only tiles that can change position, and I did this cuz these would draw every frame and they didn’t have the same grainy look as the ones drawn to a texture. the result is probably self explanatory. That caused SO MANY ISSUES that I can’t even begin to describe them all, so after 50 minutes I undid 50 minutes worth of changes, added some spaghetti code to make it a bit more presentable, and call it a day. Challenges: Level design was fun, and easy. I did that for all of yesterday and the first half-ish of today. The vain attempt at making my code more efficient by changing how static tiles were drawn and then going on to deeply regret it and consider undoing it all the next day, was not. Also I probably shouldn’t have bothered trying seeing as I was pretty tired anyway, but ig my stupidity/ambition/idek led me to try. I’m genuinely too tired to bother elaborating, but it goes somewhat like this: I started on the texture-caching thing -> I ran into nullptr errors -> I got those out of the way -> I ran into issues with rendering and updating -> out of frustration I undid all my progress and started anew -> I decided to implement anti-aliasing -> I will probably(definitely) reset my code to where I had been right before I decided to do this stupid implementation AI used, if any: none. If I had I would’ve probably been done with this bs by now. Plans for next time: Realistically I’ll likely just undo all the changes I made to drawing processes, find out how to draw environment tiles underneath other entities/obstacles (which will be useful for many of my levels with spikes or the like in environments), and…thats it. Also, for level design, I want to have all preliminary designs down by the end of this Sunday (3 more days), and then I can playtest and refine later. I wanna cry P.S. the level with the white room is level 6 and it’s currently unfinished lmao"}, {"post_id": 44761, "ts": "2026-08-10T19:13:08Z", "hours": 9.9139, "text": "Unnamed Platformer - Devlog 13 No motivation… What I did: I solved the issue of vertically stacked blocks clipping through each other and through the player, which was a pretty big chunk of my time since I went through like 10 different approaches and changed up a bunch of stuff along the way. I ended up taking out the SAT collision function I had built and just plugging mtvCheck() (which checks the mtv( )) and the movement logic straight into the collision loops instead. I had to reorder a good chunk of logic too since a lot of the clipping was coming from stuff resolving in the wrong order relative to other stuff. Also did some cleanup: deleted the grounded member off the block class since entity already has one and I was just using two variables for the same thing like an idiot. I added an R keybind so I can restart instantly instead of walking into a spike every time I want to reset (useful for testing + as an actual game feature). I also made the player’s rotation reset on spawn so you don’t respawn tilted at some weird angle from your last death and shrunk the spike hitbox down a bit from 20x20 to 18x18 because I was dying to one-pixel overlaps that looked like it shouldn’t have counted and that are pretty frustrating to deal with. Also did a bunch of level design. I’ve only done levels 1 through 4 so I lowkey gotta lock in. Challenges: The stacked block thing took forever because the symptoms kept changing depending on how many blocks were stacked, which direction they were pushed from, whether the player was involved, etc etc, so it never felt like I was chasing ONE bug, more like four bugs wearing a trenchcoat. Eventually I just started brute-force testing every combo I could think of (2 stacked, 3 stacked, stacked + pushed, stacked + player jumping into it) until I ran out of ways to break it. Also I ran into some issues when designing levels: blockonhead , which makes it so you cannot jump if a block is on your head, was triggering if any block was lined up above your head, even if it was like on a platform way above you. I managed to fix that, and other than that + the block issue there wasn’t too many big obstacles this time. AI used, if any: none, since I’m not using it at all for game design and didn’t need to use it to solve block clipping issues since I just brute forced a bunch of possible solutions. Plans for next time: More level design…I’ll try to get most of the levels done by next devlog. K bye guys"}, {"post_id": 37384, "ts": "2026-07-30T02:06:51Z", "hours": 9.8561, "text": "Unnamed Platformer - Devlog 12 Man* Realizes True Meaning of ‘If it ain’t broke, don’t fix it’ What I did: First I ported pushable blocks to SAT collision so they use the same system as the player and it’s not split between two systems. Well. That broke blocks. so I spent 2 hours or so cross referencing my old versions and adding and deleting changes till it started working again. After that, I made sure blocks moved properly in zero-g. (they didn’t so I had to fix that too) Aside from that, I made a bunch of miscellaneous changes, such as fixing level progression bugs and altering player constants, but most importantly making sure blocks worked properly. Somewhere along the line I was investigating how stacked blocks interacted. I noticed they were clipping through the ground because of collision checks happening after the position of blocks was updated, and after some thought I tried adding another collision check pass to my main game loop. It worked like a charm! I added two extra checks for safety and it stopped working like a charm. The issue is my checkCollisions function is hella inefficient. 500+ lines of searching through every character in the tilemap (36x64, plus an extra column for new lines making it 36x65=2340) 6 times (!!!) Not only that, in some cases (block/player collision detection) I was nesting full passes within full passes, which caused insane lag, especially with my SAT collision which does a lot of math each frame. So I decided I wanted it to be more efficient (spoiler: it’s not efficient yet). I split my old tilelist into static tiles and dynamic tiles…and instantly regretted it. Challenges: Basically when I split tilelist into two separate vectors ( statictilelist which is everything except for blocks + dynamictilelist which is just blocks since nothing else moves lmao), I think I accidentally deleted a lot of existing logic that was the duct tape to my spaghetti code**. Aside from that, when I passed through tilelist it always passed through every tile, but with my new logic I had to decide which one to use. my stupid ahh didnt realize that there might be a chance I have to pass through both of them though 😭 well guess what there were a lot more gaps in my logic. All of these combined into the logic I had spent the last few hours working so hard to perfect, falling apart in 5 seconds. Similar to the whole block to SAT thing I worked out most of the issues just by adding, tweaking, and removing a bunch of checks as well as looking back at my old logic to figure out what I forgot. Among these general changes I also added a new grounded member to the block class, and tried to get it to register if it’s on top of a player. Unfortunately it didn’t work. It’s ok I’ll brute force my way to the root of the problem tomorrow. (Btw this doesn’t even cover the issues I faced prior to this😭 ✌️ ) AI used, if any: Now that the core elements of the game (physics) are out of the way, I’ve pretty much been grinding through bugs myself since it’s just existing logic and I’m not really adding much that’s new or unfamiliar. Honestly, I think it’s gonna stay this way because I don’t intend to use AI to design the game, I was using it more to help solve physics issues and the like. Plans for next time: I’ll try to hopefully fix the new block clipping issues. then idek anymore. Maybe i shouldn’t have tried to build the engine from scratch. K bye guys *I’m not actually over 18 **Tuff line?"}, {"post_id": 35959, "ts": "2026-07-27T19:01:15Z", "hours": 9.8747, "text": "Unnamed Platformer - Devlog 11 Rotation is finally working! Mostly. Anyway I have to post now cuz of the 10 hour limit per devlog. What I did: I fully implemented rolling and rotation physics across all player shapes! Shapes now physically rotate based on movement speed, tip over cliff edges, and smoothly snap back to a flat face when you stop moving. I also added a feature where shapes automatically realign when entering water or zero-G. To make everything smooth and frame-rate independent, I overhauled the settling and snapping math using fmod for shortest-path rotation and wrap-around handling. Challenges: Getting the angle snapping and tipping logic to work was the biggest hurdle. Non-square shapes were getting locked out of tipping due to floating-point issues, which I fixed with an epsilon tolerance check. There are still a couple of bugs that I’ll tackle later, notably the fact that shapes sometimes spin an extra time upon settling. but the core system is more or less functional now. AI used, if any: I managed to work out the math myself but I needed to ask AI with help debugging. Plans for next time: I’ll probably work on some visual effects for the next couple days + fine-tune and debug my physics a bit more. K bye guys"}, {"post_id": 33845, "ts": "2026-07-24T02:43:36Z", "hours": 7.1331, "text": "Unnamed Platformer - Devlog 10 I’m tired 😭 What I did: I ported the rest of my entities over to SAT collision. Every tile that can be collided with now uses SAT. I refactored some of my functions to handle the new logic properly across the board, and got rid of the old standalone AABB collision code for ground tiles. I also decided to make pushable blocks hybrid for simplicity: aside from general environment collisions which use SAT, I didn’t change much of the old AABB code. I also added an O(1) center/radius projection for circles to fix random micro-stutters, and updated drawdebug() so it stops drawing every vertex and instead renders one dynamic vector targeting the nearest tile vertex. (Circles in SFML are actually 30-sided polygons, so earlier the collision checks were looking at 15 different axes + all those axes were being drawn in the debug overlay.) Challenges: Thankfully most of the porting to SAT stuff was easy, I only had a couple of minor setbacks here and there. However, the harder part was getting the circle center-to-vertex collision logic down. I had to find out how to do it + add completely new logic to my function + add checks in my collision code to determine if the shape was a circle + rewrite my drawdebug() code. It took a while and a lot of my sanity but I got it done in the end AI used, if any: Used AI to help debug the updated circle collision detection system + its separate debug overlay code. Plans for next time: I’m going to work on rolling physics for real. I hope it goes well 👍 K bye guys"}, {"post_id": 32739, "ts": "2026-07-22T02:37:49Z", "hours": 9.0553, "text": "Unnamed Platformer - Devlog 9 I was “busy” watching the World Cup bronze/final matches over the weekend. No way we got a 10 goal third place game while everyone started throwing hands at the end of the final😭 What I did: I finally got started on SAT collision like I said I would, and it’s actually working! Mostly. I built all the fundamentals so far: vertex extraction, edge normal calculation, projection ranges, minimum translation vector (MTV) calculation, etc etc. I hooked it into checkCollisions for ground tiles, and the MTV push resolution actually stops shapes from clipping through geometry now, and it’s also sign-corrected and whatnot so it always pushes the right direction. I also made a debug overlay that draws vertices and axis normals directly in the game window, which saved my sanity countless times and looks pretty cool too. On top of collision math I had to go back and fix 3 out of my 5 characters’ movement code because switching to SAT caused bugs in features that worked just fine under the old AABB system, aside from all the general bugs I had to deal with. The hexagon’s double jump stopped working entirely, circle’s acceleration started randomly resetting mid-sprint, and octagon’s wall jump turned into an absolute mess (more on that below). The main thing was that my old flags for checking wall collisions were set with assumptions that crumble once you switch from checking 4 fixed direction to a bunch of axes. Challenges: Oh boy… The wall jump bug was hella frustrating: after switching to SAT, the octagon would do exactly one wall jump and then just slide down the second, no matter how many times I hit jump. It took me forever to figure out it was a chain of three separate bugs stacked on top of each other: wall contact flags getting cleared before the function ever read them, my walljumped flag never resetting between wall touches so it permanently locked my horizontal movement, and then once THAT was fixed, SAT was re-zeroing my wall-jump velocity on the same frame it fired because the player was technically still overlapping the wall geometry. So I fixed those and immediately got a NEW bug where wall jumping turned into a pogo stick that spam-bounced me up the wall, because a vertical MTV was getting misread as “landed on the ground,” which reset the wall jump lock and let it refire every single frame. Also spent quite a bit of time before realizing this one line I had, if (grounded) velocity.y = 0 , worked fine with AABB but not so much with SAT’s own grounding logic, since my SAT function sets grounded = true when it sees downward velocity, and that line was zeroing velocity before SAT checked it. Removed it and a lot of my bugs disappeared. AI used, if any: SAT math I mostly figured out myself, after reading through a ton of Stack Overflow threads, articles, watching a lot of YT videos, etc. on my own time. I did use AI to clarify/debug a couple of parts though. However, I ended up needing it a lot more for debugging the problems that stemmed from it, i.e. the octagon, hexagon and circle issues. Plans for next time: SAT works for ground tiles but I’ve still got all my other entities on the old AABB system so I gotta port those over. Although, probably the biggest thing is trying to make my code more efficient because sometimes the game randomly slows down/freezes and makes random clips occur. If this isn’t lag (which it might not be, I could just be stupid) I’ll still have to look into whats happening. Then, once ground collision is 100% finished: rolling physics, aka the reason I made this change in the first place. Gonna have to look into the math/physics behind that, but it should be pretty easy since I already got this down. Once this is done, the shapes should be tipping and rolling around instead of just sliding around like ice cubes. We’ll see how that goes. K bye guys"}, {"post_id": 30455, "ts": "2026-07-18T00:46:19Z", "hours": 6.8525, "text": "Unnamed Platformer - Devlog 8 Bro idk What I did: I finally wrapped up the character roster by implementing and debugging the last two shapes: the hexagon and the octagon. The biggest milestone was completely overhauling and fixing the wall jump implementation for the octagon (which took me like 1.5 hrs out of which 50 minutes worth of changes were discarded). I ended up shifting all the wall-jump physics directly into the jump event handler, rather than splitting the logic between two different functions (my jump and updatepos functions). This allowed me to make it so I can properly maintain and destroy momentum for wall bounces On top of physics stuff, I built the level progression system. When you touch the exit tile, the game increases your level index and loads the next stage. It’s finally starting to feel like a real game! Although, not really, since every level after the second is the exact same weird ahh testing level cuz I needed to make sure my system worked. Challenges: The real nightmare was the octagon’s wall jump. I spent about 50 minutes writing changes because the physics wouldn’t cooperate, only to discard them because I got too confused 🥀I had half of the wall jump math in jump() and the other half in updatepos() and it was making the normal movement code immediately overwrite/neutralize the walljump code the very next frame. Another thing was making it so you couldnt just hold down the w or up key and automatically bounce up forever. I had to add an input debounce check so you have to release+re-tap the key to jump again. Everything else was honestly smooth sailing and any other bugs took maybe <15 mins to solve. AI used, if any: I didn’t use much AI, since the two big features I added were pretty easy to implement/debug, but I did ask it to help me a bit with wall jump logic since I was pretty fried. Plans for next time: Now that the physics is working, I’ve decided I want to get rid of it all. Sliding shapes feel hella unnatural (also the hitboxes are pretty weird), so I’ve decided on making the shapes roll around/have accurate hitboxes using SAT (Separating Axis Theorem) vector math. I asked Gemini how long it would take and it literally told me to avoid it if I can 😭 so we’ll see how many hairs I lose over the course of trying to implement SAT. It’ll probably be all I do from now until around the start of August when I’ll be going on vacation K bye guys"}, {"post_id": 29243, "ts": "2026-07-16T00:59:37Z", "hours": 6.4681, "text": "Unnamed Platformer - Devlog 7 I typed words into a code editor and made shapes move around What I did: I finally took on the shape-switching system and got it working! I had to completely change how the player class worked, so I made it into a pure virtual class to handle polymorphism (which lets me switch between different shapes) and replaced the old static player setup with a dynamic shape-switching state w/ unique pointers. For shapes so far I implemented the circle with rolling physics and friction, and the triangle which can teleport forward a short distance. Also, keeping source code in header files was causing circular include errors, so I reorganized all the player class code into a brand new players.cpp file. And finally I made it so falling below the screen kills the player, which is a pretty small feature but still. Pretty much what was happening was that I needed to access my tilesettings.h file in my players.h class for movement-related checks, but tilesettings.h also needed players.h for hitbox/collision stuff. So I had to take out my code from my player header file and move it to player.cpp , which was lowkey a nightmare since I ran into a bunch of compiler and linker errors that took me an hour to fix😭 Anyway, Gemini helped rescue me (since my Claude 5-hour limit somehow ended after the first question I asked it today), so thanks Gemini. Challenges: Pretty chill today, since today was more designing and testing new features that were easy to implement; however the real nightmare was splitting my files. Moving code to players.cpp broke everything with a bunch of “multiple definition” linker errors. I didn’t define my global variables as inline at first, but since they were getting defined across many files I had mark them as inline. Also, the triangle’s teleport mechanic let you phase into solid tiles at first, so I made a position prediction system using swept AABB bounds. In fact, creating this swept check was the feature that needed me to call tilesettings.h in players.h in the first place, which led to my cortisol spiking when the compiler stopped working for an hour AI used, if any: Used Gemini to help me figure out why the compiler+linker were throwing errors, and some basic debugging in my other features. Plans for next time: I’m gonna design my other two shapes now (octagon and hexagon), then start making this into an actual game with multiple levels, progressing to the next level when you reach the finish, etc etc. Also, I feel like the sliding movement is kinda unnatural, but idk if I’m going to change it because I already have a whole system down and starting from scratch would be a chore. Anyway, I’ll think about it. K bye guys"}, {"post_id": 28035, "ts": "2026-07-14T01:42:05Z", "hours": 4.6406, "text": "Unnamed Platformer - Devlog 6 Guess what? More block physics issues! I’m gonna lose my mind! What I did: Implemented logic with the buttons and doors; now, being on a button opens a corresponding door. Also fixed EVEN MORE BUGS with block pushing logic. I also resolved block-block vertical clipping and horizontal stacking bugs. I replaced the ground collision function I had made with a manual check for blocks landing on other blocks; groundCollide (that function) was not accounting for if a block landed on top of the player. This fixes vertical clipping through players and blocks and unintentional behavior with horizontally stacked blocks. Additionally, I added a system to make sure you can’t get crushed by a door too. When I first discovered that could happen, I implemented a half baked system, but it didn’t work since it pretty much made the block/player fall through the door even if the button hadn’t been pressed prior. I replaced the old block-crush prevention logic with a new system. Now the button class has another variable, presscheck , which acts like sticky keys (idk how else to put it) even after you’re not on the button. It checks for if a player or block is within the closed door’s hitbox and if so props the door open until they leave, but it can only register that after you push the button. Challenges: Buttons not changing color; color change logic was in my constructor and not the draw function so it never updated. Other than that, general implementation was also tricky to plan out because I had to decide how they were gonna work (how buttons would be linked to doors; decided on an ID system) and then how to implement that (using dynamic casts just as my button class uses). And then the block clipping glitch was another nightmare, though it did take me less than an hour which is nice. Also, it took me a while to think of how I would figure out how to make doors not close on players/blocks, but I thought up a solution pretty quickly which is nice 👍 AI used, if any: Used Claude to help me figure out the part that stops the block from falling through the player (I was genuinely™ too exhausted with dealing with bugs to try to solve it myself 😭😭) + used Gemini and a bit of Claude for general debugging. Plans for next time: I’ll polish up some visual stuff, but I think I’ll leave block-related bugs alone for now. As you can see there are some clipping issues still with the door, but idk if I want to tackle those right now. Either way my main focus for next time (and like all of the next week or two) will be getting the shape-switching system down. I’ll also try to create some map layouts that force the player to utilize block placement on buttons to navigate doors, because it would be a shame for me to have spent all my sanity on a feature only like 5 levels use. K bye guys P.S. Last time, when I said I spent all weekend working on button-related stuff, I meant the pushable blocks too (since those can activate the buttons)"}, {"post_id": 27428, "ts": "2026-07-12T23:59:57Z", "hours": 5.0344, "text": "Unnamed Platformer - Devlog 5 I pretty much spent the last weekend working entirely on button-related stuff. Turns out there were a lot of bugs and other physics-related issues I had to address. Anyway I think they’re all good now. What I did: Day 1: I fixed a bug where nested loops using the same name (pos) caused only the first pushable block to register collisions. I also implemented a side-detection fix so the player doesn’t accidentally push blocks when standing on top of them + added a border/outline to pushable blocks for visual clarity. I also started work on button and door tile classes. Day 2: I made it so you can push blocks vertically in zero-gravity. A really big fix was a global physics bug. I had been using a gravity called blockgravity for block physics, but since it was a global variable, one block’s position dictated all the other’s physics. E.g. one block in a zero-g tile meant everything else was now unable to fall. I moved blockgravity into the block class and now a block entering a zero-g zone floats without shutting off gravity for every other block on the map. I also decided on two new features: a button that can be stood upon/have a block placed on it, and a door that opens when its button is pushed. I added each one’s sprite and loaded them into my map. Also, I made another big change to my plans: having spend so much time on block physics, I’ve decided they’ll become a core feature of the game and not just a small gimmick of the triangle shape. Challenges: The hardest problem (by miles) was the block push collision. the issue turned out to be one loop variable shadowing another, which meant only the first block in the list was ever processed. Another tricky bug was zerogactive being reset before the block push loop ran, meaning zero-g vertical pushing never triggered. Ironically I ended up removing the zero-g check because if you’re going to push a block vertically, you’re not going to be on solid ground anyway. Also I accidentally mismatched curly brackets so that made life a lot harder. Also, I faced a bunch of other bugs while trying to polish up collision. Imma be honest, about an hour or so from this devlog was useless cuz it was me trying to implement a solution, confusing myself, and just discarding all my changes😭💔 Also, I spent like 20 minutes trying to get the button looking good (it’s supposed to be an octagon, but the sides are uneven). AI used, if any: I used Claude for debugging my physics code, as well as helping me figure out why the upwards/downwards block push wasn’t working. Plans for next time: I’m going to try and begin implementing the 5 player shapes and their power-ups. I’ll start with the circle probably, since it seems the simplest (just get faster over time). Also, I’m going to make it so that each button actually is linked to a door, since right now they’re just visuals. K bye guys"}, {"post_id": 26274, "ts": "2026-07-10T23:35:39Z", "hours": 8.5728, "text": "Unnamed Platformer - Devlog 4 I hate AABB with a passion. I spent 8.5 hours over 2 days (hardest lock in yet 🔥) on 2 features and Im pretty sure there are still bugs in each. What I did: On day 1 I added collision detection for pretty much all my objects, added some custom physics (e.g. water and zero g now have custom physics), and implemented AABB collision. Since I got it working yesterday(mostly), I deleted the initial ground class I had for testing SFML and most features, as well as any related functions like the check ground function in the player class. On day 2 I spent 4 hours trying to get the block to push. It took me a while cuz I initially tried to just copy the groundcollide() function and tweak whatever I needed to. However that didn’t work, so after hitting up Stack Overflow + Claude I realized I had to change up a LOT of my pre existing code. I added a master entity class for anything that is affected by physics (all players + the block + more features in the future probably) then added more functions and commands in my checkCollisions function in order to get my block mechanic mostly working. I also ended up adding many more features to my block class(velocity, gravity, and a grounded check) since it has to react to physics and the environment. Overall the introduction of an entity class that everything else inherits from was a big help in getting the game to work properly. Challenges: my game crashed when I attempted to put the check collision function in main.cpp; then, implementing water and zero-g was a lot of trial and error not only to find physics that felt fluid but also because there were a lot of bugs in the logic as well as bugs that stopped the game from running at all. Also, it took me a while to wrap my head around AABB collision; I literally had to draw it out on a piece of paper and ask Claude to grasp the concept 😭 During bug fixes, I ended up breaking a bunch of stuff/realizing a bunch of stuff was still broken and spending a bunch of time fixing it. For example, while trying to fix collision, I ended up discovering a bug in my water/zero-g physics, and then while trying to fix that I broke my spring logic too. And creating the logic for pushing the block is a whole other can of worms. It took me 4 hours of implementing different strategies and adding different functions only to have a half baked block-pushing function. 😭 It does kind of work, but you can only push one block: any other blocks act like normal ground tiles. AI used, if any: I asked Claude for help on how to tackle block pushing logic, as well as helping me understand AABB collision. Plans for next time: I’m going to try and hopefully get all the block-pushing logic done without any issues, then fix up any collision-based bugs and work on implementing the rest of my player shapes. K bye guys"}, {"post_id": 25091, "ts": "2026-07-09T02:23:55Z", "hours": 4.3644, "text": "Unnamed Platformer - Devlog 3 My game is kind of coming together! It’ll still be many weeks, but I did something! What I did: finished my tile map parser (I decided to use a unique pointer to parse through each tile type and draw the according one, after a bit of thought). I also started working on collision detection. I created a basic checkCollisions function and added getGlobalBounds to every tile class. Before I did that though I had to do some research on Axis-Aligned Bounding Box collision, and how to implement it in SFML. I’m still far from done, but that’s tomorrow’s problem. Challenges: implementing the map drawing functions (couldn’t figure out how to get the draw functions in the classes to match up with the main class), and after that I was having a lot of trouble with the pointer logic I had implemented (had to use std::move, also there were errors in my file importing structure); then after I got that to work, and implemented the parser into main.cpp, it ended up causing my entire program to crash when I ran build 😭Ended up asking Claude for help for how to fix it; it turned out to be how I had formatted my levels and my level-parsing loop for assigning tile types to tilemap characters. Then lava, water, and zero-g block weren’t drawing properly either. After spending like an hour trying to decode why, I realized sf::Color’s transparency had to be an 8-bit integer rather than a decimal between 0 and 1. Also my doublespike was not drawing properly, so I made it 2 separate convexShape’s rather than 1. Apparently you can’t have mere points holding a single convexShape together, which kind of sucks. AI used, if any: Like I mentioned, I asked Claude for help on how to fix my level loading feature (it ended up being like 3 minute details) and also used it when debugging my initial collision functions (I ended up replacing <10 lines total by its suggestion). Plans for next time: I’m going to try to finish collision. That’s my entire goal, since I still don’t know entirely how I’m gonna deal with every collision possible and it might end up taking me a long time depending on the number of mistakes I make/bugs that pop up. K bye guys (btw the music in the background is because I was listening to music while I was working on this)"}, {"post_id": 23883, "ts": "2026-07-07T02:36:17Z", "hours": 3.9897, "text": "Unnamed Platformer - Devlog 2 I was a little busy yesterday but we’re back on track now. What I did: I think I got a solid amount done today and for a bit of time yesterday: I added a camera feature that scrolls with the player, created the tile map and tile types, and designed the first part of the tile map parser; also changed the background slightly and researched more on building tilemap loaders in SFML (YouTube videos + looking at Github repos and articles). Challenges: For a zero-gravity section I’m thinking of adding, I wanted to put thin gray stripes in those sections. I couldn’t figure out how to do that, so I just decided to depict it as a translucent white block. Also determining the coordinates of the spring pad in the game took a while too. Overall, my other challenges were mostly small bugs and didnt stand out too much. AI used, if any: Used Claude for debugging the switch case for my tile map parser. Also, not AI, but my camera system was more or less entirely designed using a YouTube video that I’ll credit in my readme later. Plans for next time: I want to finish my tile map parser and get an actual level loaded. I’m also going to start deciding what the UI will look like for the main menu, level selects, and pause menu. K bye guys"}, {"post_id": 22443, "ts": "2026-07-04T22:13:21Z", "hours": 3.4311, "text": "Unnamed Platformer - Devlog 1 It’s finally time for me to lock in. This is gonna be a big project to which I hope to add a lot of content, and I’m hoping I can accumulate a lot of good hours from this project. What I did: I set up SFML (the library I’m using to code this game), set up the required files, watched a lot of YouTube videos to get more familiar with SFML, and coded a basic thing where you control a square and jump around. Challenges: This is like my second time using SFML (I used it once for a small project a while ago), so I’m not that familiar with it. No worries though, as it’s nothing a bunch of YouTube videos can’t fix. Also, today was kind of a refresher for my barely existent SFML skills. AI used, if any: I used Claude for learning how to set up SFML and asking it for help on how to fix my jump button not working. (I was missing two characters. : \\ ) Plans for next time: I’ll try to add actual platforms, maybe working obstacles as well. I’ll focus on adding a menu some other time, and actual styling will come much later so the game is gonna look ahh for now. All my devlogs will pretty much follow the format of this one(accomplishments, challenges, plans, additional notes) so that I can lazily copy-paste the same template when I don’t feel like writing a whole new devlog each devlog will feel connected/cohesive and make it easier for readers to follow along on my journey."}]...
|
Title: Stardancer (formerly Unnamed Platformer) by Title: Stardancer (formerly Unnamed Platformer) by @zahran | Stardance
Devlogs:
Unnamed Platformer - Devlog 1 It’s finally time for me to lock in. This is gonna be a big project to which I hope to add a lot of content, and I’m hoping I can accumulate a lot of good hours from this project. What I did: I set up SFML (the library I’m using to code this game), set up the required files, watched a lot of YouTube videos to get more familiar with SFML, and coded a basic thing where you control a square and jump around. Challenges: This is like my second time using SFML (I used it once for a small project a while ago), so I’m not that familiar with it. No worries though, as it’s nothing a bunch of YouTube videos can’t fix. Also, today was kind of a refresher for my barely existent SFML skills. AI used, if any: I used Claude for learning how to set up SFML and asking it for help on how to fix my jump button not working. (I was missing two characters. : \ ) Plans for next time: I’ll try to add actual platforms, maybe working obstacles as well. I’ll focus on adding a menu some other time, and actual styling will come much later so the game is gonna look ahh for now. All my devlogs will pretty much follow the format of this one(accomplishments, challenges, plans, additional notes) so that I can lazily copy-paste the same template when I don’t feel like writing a whole new devlog each devlog will feel connected/cohesive and make it easier for readers to follow along on my journey.
Unnamed Platformer - Devlog 2 I was a little busy yesterday but we’re back on track now. What I did: I think I got a solid amount done today and for a bit of time yesterday: I added a camera feature that scrolls with the player, created the tile map and tile types, and designed the first part of the tile map parser; also changed the background slightly and researched more on building tilemap loaders in SFML (YouTube videos + looking at Github repos and articles). Challenges: For a zero-gravity section I’m thinking of adding, I wanted to put thin gray stripes in those sections. I couldn’t figure out how to do that, so I just decided to depict it as a translucent white block. Also determining the coordinates of the spring pad in the game took a while too. Overall, my other challenges were mostly small bugs and didnt stand out too much. AI used, if any: Used Claude for debugging the switch case for my tile map parser. Also, not AI, but my camera system was more or less entirely designed using a YouTube video that I’ll credit in my readme later. Plans for next time: I want to finish my tile map parser and get an actual level loaded. I’m also going to start deciding what the UI will look like for the main menu, level selects, and pause menu. K bye guys
Unnamed Platformer - Devlog 3 My game is kind of coming together! It’ll still be many weeks, but I did something! What I did: finished my tile map parser (I decided to use a unique pointer to parse through each tile type and draw the according one, after a bit of thought). I also started working on collision detection. I created a basic checkCollisions function and added getGlobalBounds to every tile class. Before I did that though I had to do some research on Axis-Aligned Bounding Box collision, and how to implement it in SFML. I’m still far from done, but that’s tomorrow’s problem. Challenges: implementing the map drawing functions (couldn’t figure out how to get the draw functions in the classes to match up with the main class), and after that I was having a lot of trouble with the pointer logic I had implemented (had to use std::move, also there were errors in my file importing structure); then after I got that to work, and implemented the parser into main.cpp, it ended up causing my entire program to crash when I ran build 😭Ended up asking Claude for help for how to fix it; it turned out to be how I had formatted my levels and my level-parsing loop for assigning tile types to tilemap characters. Then lava, water, and zero-g block weren’t drawing properly either. After spending like an hour trying to decode why, I realized sf::Color’s transparency had to be an 8-bit integer rather than a decimal between 0 and 1. Also my doublespike was not drawing properly, so I made it 2 separate convexShape’s rather than 1. Apparently you can’t have mere points holding a single convexShape together, which kind of sucks. AI used, if any: Like I mentioned, I asked Claude for help on how to fix my level loading feature (it ended up being like 3 minute details) and also used it when debugging my initial collision functions (I ended up replacing <10 lines total by its suggestion). Plans for next time: I’m going to try to finish collision. That’s my entire goal, since I still don’t know entirely how I’m gonna deal with every collision possible and it might end up taking me a long time depending on the number of mistakes I make/bugs that pop up. K bye guys (btw the music in the background is because I was listening to music while I was working on this)
Unnamed Platformer - Devlog 4 I hate AABB with a passion. I spent 8.5 hours over 2 days (hardest lock in yet 🔥) on 2 features and Im pretty sure there are still bugs in each. What I did: On day 1 I added collision detection for pretty much all my objects, added some custom physics (e.g. water and zero g now have custom physics), and implemented AABB collision. Since I got it working yesterday(mostly), I deleted the initial ground class I had for testing SFML and most features, as well as any related functions like the check ground function in the player class. On day 2 I spent 4 hours trying to get the block to push. It took me a while cuz I initially tried to just copy the groundcollide() function and tweak whatever I needed to. However that didn’t work, so after hitting up Stack Overflow + Claude I realized I had to change up a LOT of my pre existing code. I added a master entity class for anything that is affected by physics (all players + the block + more features in the future probably) then added more functions and commands in my checkCollisions function in order to get my block mechanic mostly working. I also ended up adding many more features to my block class(velocity, gravity, and a grounded check) since it has to react to physics and the environment. Overall the introduction of an entity class that everything else inherits from was a big help in getting the game to work properly. Challenges: my game crashed when I attempted to put the check collision function in main.cpp; then, implementing water and zero-g was a lot of trial and error not only to find physics that felt fluid but also because there were a lot of bugs in the logic as well as bugs that stopped the game from running at all. Also, it took me a while to wrap my head around AABB collision; I literally had to draw it out on a piece of paper and ask Claude to grasp the concept 😭 During bug fixes, I ended up breaking a bunch of stuff/realizing a bunch of stuff was still broken and spending a bunch of time fixing it. For example, while trying to fix collision, I ended up discovering a bug in my water/zero-g physics, and then while trying to fix that I broke my spring logic too. And creating the logic for pushing the block is a whole other can of worms. It took me 4 hours of implementing different strategies and adding different functions only to have a half baked block-pushing function. 😭 It does kind of work, but you can only push one block: any other blocks act like normal ground tiles. AI used, if any: I asked Claude for help on how to tackle block pushing logic, as well as helping me understand AABB collision. Plans for next time: I’m going to try and hopefully get all the block-pushing logic done without any issues, then fix up any collision-based bugs and work on implementing the rest of my player shapes. K bye guys
Unnamed Platformer - Devlog 5 I pretty much spent the last weekend working entirely on button-related stuff. Turns out there were a lot of bugs and other physics-related issues I had to address. Anyway I think they’re all good now. What I did: Day 1: I fixed a bug where nested loops using the same name (pos) caused only the first pushable block to register collisions. I also implemented a side-detection fix so the player doesn’t accidentally push blocks when standing on top of them + added a border/outline to pushable blocks for visual clarity. I also started work on button and door tile classes. Day 2: I made it so you can push blocks vertically in zero-gravity. A really big fix was a global physics bug. I had been using a gravity called blockgravity for block physics, but since it was a global variable, one block’s position dictated all the other’s physics. E.g. one block in a zero-g tile meant everything else was now unable to fall. I moved blockgravity into the block class and now a block entering a zero-g zone floats without shutting off gravity for every other block on the map. I also decided on two new features: a button that can be stood upon/have a block placed on it, and a door that opens when its button is pushed. I added each one’s sprite and loaded them into my map. Also, I made another big change to my plans: having spend so much time on block physics, I’ve decided they’ll become a core feature of the game and not just a small gimmick of the triangle shape. Challenges: The hardest problem (by miles) was the block push collision. the issue turned out to be one loop variable shadowing another, which meant only the first block in the list was ever processed. Another tricky bug was zerogactive being reset before the block push loop ran, meaning zero-g vertical pushing never triggered. Ironically I ended up removing the zero-g check because if you’re going to push a block vertically, you’re not going to be on solid ground anyway. Also I accidentally mismatched curly brackets so that made life a lot harder. Also, I faced a bunch of other bugs while trying to polish up collision. Imma be honest, about an hour or so from this devlog was useless cuz it was me trying to implement a solution, confusing myself, and just discarding all my changes😭💔 Also, I spent like 20 minutes trying to get the button looking good (it’s supposed to be an octagon, but the sides are uneven). AI used, if any: I used Claude for debugging my physics code, as well as helping me figure out why the upwards/downwards block push wasn’t working. Plans for next time: I’m going to try and begin implementing the 5 player shapes and their power-ups. I’ll start with the circle probably, since it seems the simplest (just get faster over time). Also, I’m going to make it so that each button actually is linked to a door, since right now they’re just visuals. K bye guys
Unnamed Platformer - Devlog 6 Guess what? More block physics issues! I’m gonna lose my mind! What I did: Implemented logic with the buttons and doors; now, being on a button opens a corresponding door. Also fixed EVEN MORE BUGS with block pushing logic. I also resolved block-block vertical clipping and horizontal stacking bugs. I replaced the ground collision function I had made with a manual check for blocks landing on other blocks; groundCollide (that function) was not accounting for if a block landed on top of the player. This fixes vertical clipping through players and blocks and unintentional behavior with horizontally stacked blocks. Additionally, I added a system to make sure you can’t get crushed by a door too. When I first discovered that could happen, I implemented a half baked system, but it didn’t work since it pretty much made the block/player fall through the door even if the button hadn’t been pressed prior. I replaced the old block-crush prevention logic with a new system. Now the button class has another variable, presscheck , which acts like sticky keys (idk how else to put it) even after you’re not on the button. It checks for if a player or block is within the closed door’s hitbox and if so props the door open until they leave, but it can only register that after you push the button. Challenges: Buttons not changing color; color change logic was in my constructor and not the draw function so it never updated. Other than that, general implementation was also tricky to plan out because I had to decide how they were gonna work (how buttons would be linked to doors; decided on an ID system) and then how to implement that (using dynamic casts just as my button class uses). And then the block clipping glitch was another nightmare, though it did take me less than an hour which is nice. Also, it took me a while to think of how I would figure out how to make doors not close on players/blocks, but I thought up a solution pretty quickly which is nice 👍 AI used, if any: Used Claude to help me figure out the part that stops the block from falling through the player (I was genuinely™ too exhausted with dealing with bugs to try to solve it myself 😭😭) + used Gemini and a bit of Claude for general debugging. Plans for next time: I’ll polish up some visual stuff, but I think I’ll leave block-related bugs alone for now. As you can see there are some clipping issues still with the door, but idk if I want to tackle those right now. Either way my main focus for next time (and like all of the next week or two) will be getting the shape-switching system down. I’ll also try to create some map layouts that force the player to utilize block placement on buttons to navigate doors, because it would be a shame for me to have spent all my sanity on a feature only like 5 levels use. K bye guys P.S. Last time, when I said I spent all weekend working on button-related stuff, I meant the pushable blocks too (since those can activate the buttons)
Unnamed Platformer - Devlog 7 I typed words into a code editor and made shapes move around What I did: I finally took on the shape-switching system and got it working! I had to completely change how the player class worked, so I made it into a pure virtual class to handle polymorphism (which lets me switch between different shapes) and replaced the old static player setup with a dynamic shape-switching state w/ unique pointers. For shapes so far I implemented the circle with rolling physics and friction, and the triangle which can teleport forward a short distance. Also, keeping source code in header files was causing circular include errors, so I reorganized all the player class code into a brand new players.cpp file. And finally I made it so falling below the screen kills the player, which is a pretty small feature but still. Pretty much what was happening was that I needed to access my tilesettings.h file in my players.h class for movement-related checks, but tilesettings.h also needed players.h for hitbox/collision stuff. So I had to take out my code from my player header file and move it to player.cpp , which was lowkey a nightmare since I ran into a bunch of compiler and linker errors that took me an hour to fix😭 Anyway, Gemini helped rescue me (since my Claude 5-hour limit somehow ended after the first question I asked it today), so thanks Gemini. Challenges: Pretty chill today, since today was more designing and testing new features that were easy to implement; however the real nightmare was splitting my files. Moving code to players.cpp broke everything with a bunch of “multiple definition” linker errors. I didn’t define my global variables as inline at first, but since they were getting defined across many files I had mark them as inline. Also, the triangle’s teleport mechanic let you phase into solid tiles at first, so I made a position prediction system using swept AABB bounds. In fact, creating this swept check was the feature that needed me to call tilesettings.h in players.h in the first place, which led to my cortisol spiking when the compiler stopped working for an hour AI used, if any: Used Gemini to help me figure out why the compiler+linker were throwing errors, and some basic debugging in my other features. Plans for next time: I’m gonna design my other two shapes now (octagon and hexagon), then start making this into an actual game with multiple levels, progressing to the next level when you reach the finish, etc etc. Also, I feel like the sliding movement is kinda unnatural, but idk if I’m going to change it because I already have a whole system down and starting from scratch would be a chore. Anyway, I’ll think about it. K bye guys
Unnamed Platformer - Devlog 8 Bro idk What I did: I finally wrapped up the character roster by implementing and debugging the last two shapes: the hexagon and the octagon. The biggest milestone was completely overhauling and fixing the wall jump implementation for the octagon (which took me like 1.5 hrs out of which 50 minutes worth of changes were discarded). I ended up shifting all the wall-jump physics directly into the jump event handler, rather than splitting the logic between two different functions (my jump and updatepos functions). This allowed me to make it so I can properly maintain and destroy momentum for wall bounces On top of physics stuff, I built the level progression system. When you touch the exit tile, the game increases your level index and loads the next stage. It’s finally starting to feel like a real game! Although, not really, since every level after the second is the exact same weird ahh testing level cuz I needed to make sure my system worked. Challenges: The real nightmare was the octagon’s wall jump. I spent about 50 minutes writing changes because the physics wouldn’t cooperate, only to discard them because I got too confused 🥀I had half of the wall jump math in jump() and the other half in updatepos() and it was making the normal movement code immediately overwrite/neutralize the walljump code the very next frame. Another thing was making it so you couldnt just hold down the w or up key and automatically bounce up forever. I had to add an input debounce check so you have to release+re-tap the key to jump again. Everything else was honestly smooth sailing and any other bugs took maybe <15 mins to solve. AI used, if any: I didn’t use much AI, since the two big features I added were pretty easy to implement/debug, but I did ask it to help me a bit with wall jump logic since I was pretty fried. Plans for next time: Now that the physics is working, I’ve decided I want to get rid of it all. Sliding shapes feel hella unnatural (also the hitboxes are pretty weird), so I’ve decided on making the shapes roll around/have accurate hitboxes using SAT (Separating Axis Theorem) vector math. I asked Gemini how long it would take and it literally told me to avoid it if I can 😭 so we’ll see how many hairs I lose over the course of trying to implement SAT. It’ll probably be all I do from now until around the start of August when I’ll be going on vacation K bye guys
Unnamed Platformer - Devlog 9 I was “busy” watching the World Cup bronze/final matches over the weekend. No way we got a 10 goal third place game while everyone started throwing hands at the end of the final😭 What I did: I finally got started on SAT collision like I said I would, and it’s actually working! Mostly. I built all the fundamentals so far: vertex extraction, edge normal calculation, projection ranges, minimum translation vector (MTV) calculation, etc etc. I hooked it into checkCollisions for ground tiles, and the MTV push resolution actually stops shapes from clipping through geometry now, and it’s also sign-corrected and whatnot so it always pushes the right direction. I also made a debug overlay that draws vertices and axis normals directly in the game window, which saved my sanity countless times and looks pretty cool too. On top of collision math I had to go back and fix 3 out of my 5 characters’ movement code because switching to SAT caused bugs in features that worked just fine under the old AABB system, aside from all the general bugs I had to deal with. The hexagon’s double jump stopped working entirely, circle’s acceleration started randomly resetting mid-sprint, and octagon’s wall jump turned into an absolute mess (more on that below). The main thing was that my old flags for checking wall collisions were set with assumptions that crumble once you switch from checking 4 fixed direction to a bunch of axes. Challenges: Oh boy… The wall jump bug was hella frustrating: after switching to SAT, the octagon would do exactly one wall jump and then just slide down the second, no matter how many times I hit jump. It took me forever to figure out it was a chain of three separate bugs stacked on top of each other: wall contact flags getting cleared before the function ever read them, my walljumped flag never resetting between wall touches so it permanently locked my horizontal movement, and then once THAT was fixed, SAT was re-zeroing my wall-jump velocity on the same frame it fired because the player was technically still overlapping the wall geometry. So I fixed those and immediately got a NEW bug where wall jumping turned into a pogo stick that spam-bounced me up the wall, because a vertical MTV was getting misread as “landed on the ground,” which reset the wall jump lock and let it refire every single frame. Also spent quite a bit of time before realizing this one line I had, if (grounded) velocity.y = 0 , worked fine with AABB but not so much with SAT’s own grounding logic, since my SAT function sets grounded = true when it sees downward velocity, and that line was zeroing velocity before SAT checked it. Removed it and a lot of my bugs disappeared. AI used, if any: SAT math I mostly figured out myself, after reading through a ton of Stack Overflow threads, articles, watching a lot of YT videos, etc. on my own time. I did use AI to clarify/debug a couple of parts though. However, I ended up needing it a lot more for debugging the problems that stemmed from it, i.e. the octagon, hexagon and circle issues. Plans for next time: SAT works for ground tiles but I’ve still got all my other entities on the old AABB system so I gotta port those over. Although, probably the biggest thing is trying to make my code more efficient because sometimes the game randomly slows down/freezes and makes random clips occur. If this isn’t lag (which it might not be, I could just be stupid) I’ll still have to look into whats happening. Then, once ground collision is 100% finished: rolling physics, aka the reason I made this change in the first place. Gonna have to look into the math/physics behind that, but it should be pretty easy since I already got this down. Once this is done, the shapes should be tipping and rolling around instead of just sliding around like ice cubes. We’ll see how that goes. K bye guys
Unnamed Platformer - Devlog 10 I’m tired 😭 What I did: I ported the rest of my entities over to SAT collision. Every tile that can be collided with now uses SAT. I refactored some of my functions to handle the new logic properly across the board, and got rid of the old standalone AABB collision code for ground tiles. I also decided to make pushable blocks hybrid for simplicity: aside from general environment collisions which use SAT, I didn’t change much of the old AABB code. I also added an O(1) center/radius projection for circles to fix random micro-stutters, and updated drawdebug() so it stops drawing every vertex and instead renders one dynamic vector targeting the nearest tile vertex. (Circles in SFML are actually 30-sided polygons, so earlier the collision checks were looking at 15 different axes + all those axes were being drawn in the debug overlay.) Challenges: Thankfully most of the porting to SAT stuff was easy, I only had a couple of minor setbacks here and there. However, the harder part was getting the circle center-to-vertex collision logic down. I had to find out how to do it + add completely new logic to my function + add checks in my collision code to determine if the shape was a circle + rewrite my drawdebug() code. It took a while and a lot of my sanity but I got it done in the end AI used, if any: Used AI to help debug the updated circle collision detection system + its separate debug overlay code. Plans for next time: I’m going to work on rolling physics for real. I hope it goes well 👍 K bye guys
Unnamed Platformer - Devlog 11 Rotation is finally working! Mostly. Anyway I have to post now cuz of the 10 hour limit per devlog. What I did: I fully implemented rolling and rotation physics across all player shapes! Shapes now physically rotate based on movement speed, tip over cliff edges, and smoothly snap back to a flat face when you stop moving. I also added a feature where shapes automatically realign when entering water or zero-G. To make everything smooth and frame-rate independent, I overhauled the settling and snapping math using fmod for shortest-path rotation and wrap-around handling. Challenges: Getting the angle snapping and tipping logic to work was the biggest hurdle. Non-square shapes were getting locked out of tipping due to floating-point issues, which I fixed with an epsilon tolerance check. There are still a couple of bugs that I’ll tackle later, notably the fact that shapes sometimes spin an extra time upon settling. but the core system is more or less functional now. AI used, if any: I managed to work out the math myself but I needed to ask AI with help debugging. Plans for next time: I’ll probably work on some visual effects for the next couple days + fine-tune and debug my physics a bit more. K bye guys
Unnamed Platformer - Devlog 12 Man* Realizes True Meaning of ‘If it ain’t broke, don’t fix it’ What I did: First I ported pushable blocks to SAT collision so they use the same system as the player and it’s not split between two systems. Well. That broke blocks. so I spent 2 hours or so cross referencing my old versions and adding and deleting changes till it started working again. After that, I made sure blocks moved properly in zero-g. (they didn’t so I had to fix that too) Aside from that, I made a bunch of miscellaneous changes, such as fixing level progression bugs and altering player constants, but most importantly making sure blocks worked properly. Somewhere along the line I was investigating how stacked blocks interacted. I noticed they were clipping through the ground because of collision checks happening after the position of blocks was updated, and after some thought I tried adding another collision check pass to my main game loop. It worked like a charm! I added two extra checks for safety and it stopped working like a charm. The issue is my checkCollisions function is hella inefficient. 500+ lines of searching through every character in the tilemap (36x64, plus an extra column for new lines making it 36x65=2340) 6 times (!!!) Not only that, in some cases (block/player collision detection) I was nesting full passes within full passes, which caused insane lag, especially with my SAT collision which does a lot of math each frame. So I decided I wanted it to be more efficient (spoiler: it’s not efficient yet). I split my old tilelist into static tiles and dynamic tiles…and instantly regretted it. Challenges: Basically when I split tilelist into two separate vectors ( statictilelist which is everything except for blocks + dynamictilelist which is just blocks since nothing else moves lmao), I think I accidentally deleted a lot of existing logic that was the duct tape to my spaghetti code**. Aside from that, when I passed through tilelist it always passed through every tile, but with my new logic I had to decide which one to use. my stupid ahh didnt realize that there might be a chance I have to pass through both of them though 😭 well guess what there were a lot more gaps in my logic. All of these combined into the logic I had spent the last few hours working so hard to perfect, falling apart in 5 seconds. Similar to the whole block to SAT thing I worked out most of the issues just by adding, tweaking, and removing a bunch of checks as well as looking back at my old logic to figure out what I forgot. Among these general changes I also added a new grounded member to the block class, and tried to get it to register if it’s on top of a player. Unfortunately it didn’t work. It’s ok I’ll brute force my way to the root of the problem tomorrow. (Btw this doesn’t even cover the issues I faced prior to this😭 ✌️ ) AI used, if any: Now that the core elements of the game (physics) are out of the way, I’ve pretty much been grinding through bugs myself since it’s just existing logic and I’m not really adding much that’s new or unfamiliar. Honestly, I think it’s gonna stay this way because I don’t intend to use AI to design the game, I was using it more to help solve physics issues and the like. Plans for next time: I’ll try to hopefully fix the new block clipping issues. then idek anymore. Maybe i shouldn’t have tried to build the engine from scratch. K bye guys *I’m not actually over 18 **Tuff line?
Unnamed Platformer - Devlog 13 No motivation… What I did: I solved the issue of vertically stacked blocks clipping through each other and through the player, which was a pretty big chunk of my time since I went through like 10 different approaches and changed up a bunch of stuff along the way. I ended up taking out the SAT collision function I had built and just plugging mtvCheck() (which checks the mtv( )) and the movement logic straight into the collision loops instead. I had to reorder a good chunk of logic too since a lot of the clipping was coming from stuff resolving in the wrong order relative to other stuff. Also did some cleanup: deleted the grounded member off the block class since entity already has one and I was just using two variables for the same thing like an idiot. I added an R keybind so I can restart instantly instead of walking into a spike every time I want to reset (useful for testing + as an actual game feature). I also made the player’s rotation reset on spawn so you don’t respawn tilted at some weird angle from your last death and shrunk the spike hitbox down a bit from 20x20 to 18x18 because I was dying to one-pixel overlaps that looked like it shouldn’t have counted and that are pretty frustrating to deal with. Also did a bunch of level design. I’ve only done levels 1 through 4 so I lowkey gotta lock in. Challenges: The stacked block thing took forever because the symptoms kept changing depending on how many blocks were stacked, which direction they were pushed from, whether the player was involved, etc etc, so it never felt like I was chasing ONE bug, more like four bugs wearing a trenchcoat. Eventually I just started brute-force testing every combo I could think of (2 stacked, 3 stacked, stacked + pushed, stacked + player jumping into it) until I ran out of ways to break it. Also I ran into some issues when designing levels: blockonhead , which makes it so you cannot jump if a block is on your head, was triggering if any block was lined up above your head, even if it was like on a platform way above you. I managed to fix that, and other than that + the block issue there wasn’t too many big obstacles this time. AI used, if any: none, since I’m not using it at all for game design and didn’t need to use it to solve block clipping issues since I just brute forced a bunch of possible solutions. Plans for next time: More level design…I’ll try to get most of the levels done by next devlog. K bye guys
Unnamed Platformer - Devlog 14 I’m genuinely so done What I did: I designed levels 5 and 7-16 (ss of a few levels should be attached idk which they are). I have a cool idea in mind for level 6 but my current code makes it hard to implement, and I also have a cool idea in mind for level 17 but my code made it hard to implement. So I changed everything up like an idiot. My 17th level features a massive pool, but that requires me to draw 1000+ water tiles. Since I redraw tiles every frame, it causes a big load on the computer. So I had the brilliant idea of creating an sf::RenderTexture . spoiler it’s not so brilliant. That led to a massive chain reaction where there were a bunch of nullptr issues at first, which I spent about 40 minutes on before actually getting the game to run. Then everything was super grainy due to aliasing issues caused by drawing everything to a RenderTexture, PLUS since I was drawing everything at the start of the frame and not updating it, stuff like buttons and doors would never update. SO, my dumb ahh moved half my static/environment tiles to dynamictilelist , reserved for strictly blocks which are the only tiles that can change position, and I did this cuz these would draw every frame and they didn’t have the same grainy look as the ones drawn to a texture. the result is probably self explanatory. That caused SO MANY ISSUES that I can’t even begin to describe them all, so after 50 minutes I undid 50 minutes worth of changes, added some spaghetti code to make it a bit more presentable, and call it a day. Challenges: Level design was fun, and easy. I did that for all of yesterday and the first half-ish of today. The vain attempt at making my code more efficient by changing how static tiles were drawn and then going on to deeply regret it and consider undoing it all the next day, was not. Also I probably shouldn’t have bothered trying seeing as I was pretty tired anyway, but ig my stupidity/ambition/idek led me to try. I’m genuinely too tired to bother elaborating, but it goes somewhat like this: I started on the texture-caching thing -> I ran into nullptr errors -> I got those out of the way -> I ran into issues with rendering and updating -> out of frustration I undid all my progress and started anew -> I decided to implement anti-aliasing -> I will probably(definitely) reset my code to where I had been right before I decided to do this stupid implementation AI used, if any: none. If I had I would’ve probably been done with this bs by now. Plans for next time: Realistically I’ll likely just undo all the changes I made to drawing processes, find out how to draw environment tiles underneath other entities/obstacles (which will be useful for many of my levels with spikes or the like in environments), and…thats it. Also, for level design, I want to have all preliminary designs down by the end of this Sunday (3 more days), and then I can playtest and refine later. I wanna cry P.S. the level with the white room is level 6 and it’s currently unfinished lmao
Unnamed Platformer - Devlog 15 Actually got a lot done over the last few days ig What I did: first off, I reset my old changes and made it so env tiles layer over obstacles. At first I tried to assign an individual character to each combination (spike in water, block in zero-gravity, etc etc) but that didn’t work since I couldn’t get them to lay over each other. So what I did is I split my statictilelist into two: statictilelist now held all non-moving entities like spikes, ground, etc. while envtilelist held all my environment tiles. Then I changed my map loading function to take two map strings: one assigned tiles based on entities and the other pass assigned them based on environment. And now I can lay environments over things without breaking my game! Yippee! I also fixed an issue where blocks could clip through obstacles in zero-g when you moved them upward. The issue was blocks unconditionally being mtv-moved when the player was below them, so the player forced them through anything. I added an extra check before mtv-moving and made obstacle detection variables global to fix it. I also ran into an issue where spikes would incorrectly kill you even if you were not touching them, just near: the issue was that I wasn’t running SAT collision, just going straight to death logic if the initial AABB check turned out true (I run an AABB check first because running SAT for everything makes the game super laggy). both of these lowkey took me a while 😭 As for level design I reworked level 6 (still can’t play it) and level 17 (finished), and I designed levels 18-25 (I attached a video of level 24). Also in the vid I switched shapes randomly, that’s just because I had different keybinds earlier and it was js muscle memory kicking in. Challenges: Aside from a bunch of small bugs, the biggest challenges were the issue where spikes would kill you even if you weren’t touching them and the issue with blocks being pushed up forever in zerog. Even then, for both issues it was still easy to fix since it was easy to diagnose and a few lines per fix, even if it took me a while to find those few lines 🥀🥀 However, there’s still an issue where blocks sink slightly upon spawning in zero-g. This makes it impossible to play level 6, so I’ll have to look into/rework/do something to zero-g logic because I really want to keep its existing level mechanic. AI used, if any: None 🔥 Plans for next time: Finish levels 26-30, finish level 6, and test all the levels to make sure they’re not too hard/impossible/possible to cheese. Aside from that, I’ll most likely bring back the texture thing I implemented last time cuz it did actually make the game run a bit smoother, but I’ll only do it for environment tiles. K bye guys
Unnamed Platformer - Devlog 16 Actually didn’t get a lot done over the last few days, let me explain. What I did: The biggest and only new feature I added was a major adjustment to black holes. Earlier they were just 2 tile x 2 tile circles that killed you upon touching. I’ve reworked them to how they’re supposed to be: 6 px x 6 px black circles, with a surrounding 6 tile x 6 tile ring. now if you enter the ring, you lose the ability to move normally (you can still jump tho) get pulled toward the black center, which kills you if you touch it Which is how it’s supposed to be (nevermind the astrophysical inaccuracy lmao). This took me 2 hours 😭 and then I designed levels 26 and 27. I also re-added the old texture system I implemented and then took down earlier cuz it was making things look hella grainy, but only for environment tiles cuz there’s no big changes visually compared to redrawing them every frame. Unfortunately it doesn’t seem to be doing much in terms of efficiency. I also designed levels 28 and 29 (ss of level 29 attached), and playtested every level from 1 to 28 and adjusted each one to remove any unwanted ways you can cheese a level, as well as to just make some of them less punishing for small mistakes. I also (FINALLY) designed level 6. I added extra sections and polished up some elements that were making the level impossible if you didn’t play it perfectly. I did 2 other things as well: I made it so blocks can’t be pushed by any character other than the square (before you could just push blocks w/ anything) and I reduced horizontal movespeed in zero-g. There’s still a lot more I have to do, mainly ui/menu stuff and visual polish. Challenges: Black hole physics took me a while since my first few implementations were completely wrong, and then I locked in nd figured out how to make it pull correctly. Also, level design is proving to be surprisingly challenging, I rly didn’t think it would take this long, but what with conceptualizing + creating + playtesting each level, especially the later ones where I want to make them more complex and difficult, it eats up a lot of time per level. Even going back through older levels and tweaking them can take a while, cuz you gotta track down all the problematic sections and figure out how to fix them. I also have a humble 18 more days till school starts so I gotta lock in🙏 AI used, if any: None, level design is hard but its not THAT hard Plans for next time: Finish level 30, playtest levels 29 and 30, and hopefully get started on + finish a main menu and level select menu. Im so behind on my schedule it aint even funny so wish me luck
Unnamed Platformer - Devlog 17 It’s actually no longer “Unnamed Platformer”, it’s “Worlds of Blockman”, I might change that later idk What I did: I designed level 30, playtested every level extensively and tweaked some levels, and made a basic main menu, level hud and pause menu. And it took me ~10 hours. Well, that’s not all I did. I also changed up the colors of the square to differentiate it from spikes and buttons, and I added a visual indicator for the triangle’s teleport. When you tp the triangle fades to a darker shade of green, and when it gets off cooldown (3 secs) it fades back to its normal color and then you can tp again. Also, level design took quite a long time since I was kind of making it up as I went along, and the whole game states implementation wasn’t too hard in itself, but I ran into errors with loading my font. I added the .ttf file to my assets folder and wrote the correct file name in font.loadFromFile() and whatnot, but turns out I didn’t have the actual font downloaded in the build folder or my project. So after a bit less than an hour I added it in and it fixed the issue. also I spent a bit of time deciding how the different menus would actually look which ate up some time. Challenges: ngl the font-loading thing was kind of the only hard part 😭most other stuff was solved relatively quickly and easily AI used, if any: None, also most likely no AI will be used in the future since the future just holds visual stuff which should not be hard enough to merit the help of AI. Plans for next time: Level select menu, add more stuff to main menu, also make it so the current level shows in the background when you go to the pause menu. also add mouse inputs so you can use those instead of kb inputs in the menu, and start on some more vfx and sfx. I’m also really tired
Unnamed Platformer - Devlog 18 The UI is coming along pretty nicely! What I did: Designed a full level select menu (there are a couple more things left to add), add a heads up display for the current level, and add proper mouse input and extra details to buttons such as shadows (havent implemented shadows for everything, I’ll explain why) and changing color when hovering. Even though it doesn’t sound like much, it took me a surprisingly long time because my text wasn’t centering…What I didn’t realize is that sf::Text creates invisible offsets for some reason, so when I used getGlobalBounds() it would return that offset too and mess up the centering. I ended up doing some research and realized I had to use the local bounds (i.e. untransformed) when centering. Challenges: Ig the biggest ‘challenge’ was centering buttons with text, because at first I actually tried to manually fine tune coordinates and whatnot. But then I found out I had to use localbounds and blah blah. Another thing is, I spent a lot of time fine tuning sizes, colors, shadow darknesses and depths, etc. which took a lot of my time. Also no ai used this time either, although I did spend a lot of time researching why my text wouldn’t center itself. Plans for next time: I’ll just polish up existing menus, and work on background elements. Also I want to add a kind of handbook accessible from the main menu that tells you what stuff does, different powerups, etc. But most importantly, I’m gonna try to find out how to make shadow creation more efficient. For every text/button, I need a shadow. That means I have to add it as a member in the class, copy the actual object, change the color and offset it, then draw it too. Since I have so many objects that make shadows (all of them in the end, ideally), I’m probably going to make a shadow-making function for readability. Other than that I’ll just play the game and test levels a bunch, which I’ve already been doing a lot to make sure everything is as it should be. K bye guys P.S. there’s also still a couple bugs ( UI-related or otherwise) that I have to fix as well
Unnamed Platformer - Devlog 19 The UI is coming along pretty nicely! Pt. 2 What I did: I believe I’ve fully created everything UI- and menu-wise, aside from 3 additional menus (credits, a ‘handbook’ that contains info about stuff, and a settings page) that are currently blank. I created a hovering effect for buttons that makes it so when you hover over a button, the button goes downward slightly and the shadow moves to match. Aside from that, I polished up/tweaked some minor details, and the only things I’ll add menu wise are probably those 3 sub-menus on the main menu and a universal backwards-nav button. The biggest thing (time-wise) was figuring out how to make the code more readable and actually making it more readable. I created two new functions for making text and button objects which made my life a lot easier, also the button-hover code took quite a few lines so I put that into a function too. Aside from that, I made a couple fixes here and there to make it more efficient memory wise. And even then, I ended up breaking stuff which took me a while to fix, such as the issue with unpausing ur game in the vid. Challenges: Probably efficiency stuff, since deciding how to do it + implementation took a while and had a couple of bugs due to me not accounting for stuff. For example: my hover function would change states on its own, but since sometimes you don’t need to directly change state or you need to do other things too, I made it into a boolean that each individual case takes and does its own thing with. Plans for next time: Start on background stuff probably, I don’t want to do anymore UI stuff for now. I have a fewideas in mind for my background visuals, but I hope they won’t be too hard/impossible to implement. K bye guys
Unnamed Platformer - Devlog 20 Background design is a hell of a lot harder than I thought it would be…also I lost track of time 😭😭 What I did: I got started on background design, and partially implemented a background. I actually had a pretty different idea in mind compared to what I have now: the rest of the planet visible, stretching into the horizon, with mountains and volcanoes etc etc. scattered along its surface. After spending a while implementing that, I realized it a) didn’t look right, since everything was just following the player around at normal cam speed, and b) I didn’t like the idea anymore to begin with. So after scrapping all those changes, I started researching how to add a scrolling effect so it would look more natural. I found out how to implement a parallax scroll effect, which basicallymeans that objects in the background move along slower than objects closer to the front of the screen. I also restructured my scenes.h file which contains all background-related stuff, and made a couple of other small changes and fixes with certain levels. I know I don’t have much to show for it, but that’s mainly because I spent a lot of time tweaking certain elements and just undoing backgrounds I ended up not liking 😭🥀 Challenges: Deciding what to do visuals-wise cost me some time bcuz I kept going back on my old ideas, but restructuring scenes.h was the hardest part since after deciding what to do for visuals, I had to base the logic in scenes.h off that. Also it took me a while to decide how to add in a parallax scroll system. Plans for next time: Work on more background stuff. right now I’ve set up a lot of background elements’ structs and whatnot, but I’ve only redrawn the stars and added a rough brightening/dimming effect. Also Im gonna have to start thinking about what I’m going to add on each of the sub-menus accessible from the main menu (credits, handbook, and settings). K bye guys
Unnamed Platformer - Devlog 21 Background design is a bit easier now that I have a plan…also I did not lose track of time 👍 What I did: I added in every single sky element I want to have: comets, planets, black holes, stars, floating rocks, and a moon. I think I might tweak some elements later down the line (specifically the moon(adding craters) and black holes(I’ll think of some extra effects) ), but for now I’m fairly satisfied with how far I’ve come. Looking at the game now gives me a sense of pride at seeing everything finally come together after so long 🥹✌️ Challenges: Making comets was a bit of a hassle, because I had to decide how to do it (which took me some time for brainstorming + more time cuz of discarded changes + even more minutes of brainstorming), and implement it. It’s pretty complex cuz there’s a cooldown on each comet, then you have to set the spawn point and angle/speed, calculate the trail’s points, draw them, draw the head too etc etc…so it was pretty tedious, but comets are the most rewarding visually imo out of all the features. Other than that, I spent a bit of time per other feature figuring out how to implement each of them, but none of them were as complex as the comet. Plans for next time: Finish up any bugs or other issues in sky-related stuff, then I’ll try to make a visible horizon again and see if I’ve changed my mind since last time. Either that or I’ll start working more on smaller vfx, specially trying to find out how to make a particle effect. K bye guys
Unnamed Platformer - Devlog 22 School starts tomorrow ✌️so i decided to make a shorter devlog…also I’m so tired What I did: Honestly you can’t really tell that I did much at first glance. I was mainly playtesting a lot and polishing stuff up, and making sure all the background stuff was fine. For now I dont think I’ll return to background stuff for a while. Although I did manage to add a particle effect for the black holes (both the ones in the background as well as the actual obstacles). I was also experimenting with a horizon for a bit, but then I decided I don’t want it and scrapped a good chunk of time worth of changes. Challenges: Deciding how to add in particles was a bit challenging, specially the math part. But other than that it was a pretty chill 7 hours. Plans for next time: Hopefully finish menus, then: work on vfx, polish up all the menus, tackle any big issues with levels or physics, and finally work on bringing my game onto itch.io! not all in one go, though. K bye guys
Unnamed Platformer - Devlog 23 Hey guys. What I did: I did a lot of playtesting/bug hunting as usual, but I was mainly creating the entire handbook menu. Which took surprisingly long, cuz of designing the menu + figuring out how to include all the different tile icons + creating descriptions + making stuff functional + formatting + colors + bugs + you get the idea. Anyway I’m pretty happy with how it looks so far, I doubt I’ll make any major changes in the future. Also I did find a couple of bugs while testing, but i didn’t really do anything about them, I want to completely create all the core functions before tackling any small bugs/issues. Challenges: There were a few bugs and I went through a few designs for the menu, but overall everything was hella light so I wouldn’t say there were any real challenges. Plans for next time: Create credits menu, then work on adding vfx, add settings menu (thinking of adding volume + keybind toggles), polish up all the menus…and then I’ll see where to go from there. I’m pretty worried cuz now that school’s started (im in gr11 now) I’m probably gonna have a good amount of schoolwork, clubs, etc. that I’ll also have to make time for…so wish me luck ig. K bye guys
Unnamed Platformer - Devlog 24 The game is finally coming together… 🥹🔥 What I did: All the menus in the game are completed! Ngl, credits was really easy ofc, but I was deciding how I should go about doing it, still didnt take too long tho. Then settings was a lot harder 😭 volume adjustment was quite easy, but the real problem came with creating the keybind section, since I had already coded hard inputs all throughout my code. So I pretty much had to add a new system + helper func in vars.h, then replace every instance of isKeyPressed with that system+helper, then code the menu in the ui file (Which took forever cuz of bugs with msg updating + event handling + key updates + etc.). Well, it’s (mostly) done now, which is good. And ofc I was also testing the game for general bugs too. Challenges: The keybind menu took me a hella long time to get done…thats about it, aside from some other tiny bugs. Plans for next time: add vfx, polish up every single one of the menus…and then I’ll see where to go from there. Hopefully I can finish most of my stuff by the start of next week. K bye guys
Unnamed Platformer - Devlog 25 I’m so tired omg What I did: Bunch of miscellaneous stuff: Added basic vfx: so far we only have a click sound, I’ll add more later but it took me a while to figure out how to get SFML’s audio system working since I also had to find out why my audio files weren’t loading in either. Added coins to every level: added new tile type for coin, added a coin into each level, added effects, etc. Fix bugs/gameplay issues such as the triangle being unable to teleport after a restart/new level, rearrange some levels to fit coin placements, find out some new bugs and try (and fail) to fix them, so decide to deal with them another day. Add simple death animation to the player. Make it so levels must be completed in progressive order (e.g. you start at level 1, cannot progress till you have completed), also add different colors to boxes on level select menu (check vid) Probably a few more things related to general playtesting but i can’t remember Challenges: Making level buttons in the levelmenu was kind of frustrating not only because of the selection aspect but also getting them to visually render in the proper colors. Honestly though, now the main challenge is dealing with my own fatigue, especially since I’ve been joining more clubs and getting more homework, so hopefully I can clutch up over the final few days cuz I highkey need that framework 13 🥺✌️ Plans for next time: I added a list of bugs I want to tackle/stuff I want to add: //BUGS!!!!! //cant close window while in settings menu //rotation bugs //levels 13, 17, 26, 4, 8, look into //as well as other levels but these ones I can remember //TO ADD!!!!! //speedrun timer //death count //updating handbook (notif icon, hidden objects) //more sfx (death especially) K bye guys
Unnamed Platformer - Devlog 26 Stardance extension + fatigue = holy procrastination 😂✌️ What I did: More random stuff: Level timer that stores each level’s personal best, displays a live timer in the level, and lets you access your PR for each level from level select menu Fixed issue where you couldn’t close game while in settings menu Death count (it just tracks deaths over every single level, accessed from level select menu, manual restarts count as death too) and coin count as well Adjusted some levels a bit Added a feature to handbook where items you haven’t come across yet are blacked out and have hidden descs, and add notification to handbook when you unlock these items Update README a little bit cause I was feeling lazy and didn’t want to do anything else Fix some bugs concerning rotation and tipping, as well as making it so you do not rotate when passing thru a 1 tile high gap (this is specially an issue with the square where it can feel a bit janky otherwise) I will note that some of these were multifaceted changes that took quite a bit of effort and iterations, but I couldn’t be bothered explaining everything I did here. And more playtesting too. Challenges: Probably the handbook feature…it was the longest one out of all of them. Plans for next time: I want to be done with pretty much everything related to the actual game by next devlog, so I can focus on the README and finally shipping! K bye guys
Unnamed Platformer - Devlog 27 WE’RE FINALLY HERE! What I did: I did a lot of final polish and testing before getting the game ready for release. Initially I was going to use Emscripten to port my game over to web assembly (inspired by this video: https://www.youtube.com/watch?v=1kiwpAIU454 ) but I soon realized that it was much more complex than it looked, and kind of took away from the spirit of being entirely made out of C++ and SFML. So, I decided to simply publish an executable rather than port the game over to web. I set up the release build and whatnot (which took a while because of cmake config issues and whatnot) but I finally got a release build working n it feels great! I ported to itch.io, now I just gotta finish up the itch page and readme, as well as record a walkthrough video for macOS and Linux users as I couldn’t figure out how to configure the game for either. Challenges: The whole odyssey of deciding how to port my game over was a slight hassle, but nothing too bad. Also, while recording my walkthrough vid, I ended up discovering A LOT of hidden bugs, so I managed to pick all those off and there shouldn’t be any left…hopefully. Plans for next time: Ship! This devlog will be my last for this project, and for this challenge. Aside from being done with everything, I accidentally created a completely new project according to Hackatime when I was renaming the file folder, executable, etc. from “WorldofBlockman” (my placeholder name) to Stardancer so everything would be more consistent with my final title. so any work I do on my project won’t count towards heartbeats and thus I can’t post another devlog (15 minutes minimum/devlog). Still, it’s been such an amazing journey, I learned so much and I made this game that I’m super proud of 🥹 even though this game gave me hell sometimes, I have virtually no regrets about any of it. This has been my biggest project ever, and many more to come in the future hopefully. K…bye guys.
Ships:
For HackClub Stardance, I created Stardancer , a 30-level platformer featuring a unique mechanic: mid-level shapeshifting to unlock new abilities and powers! I used C++ and SFML (the Simple and Fast Multimedia Library) to code this game. During the development of this game, I ran into a couple of technical challenges. Collision was among the biggest; I had initially decided on AABB (Axis-Aligned Bounding Box) collision, but after implementing that I realized that it led to erroneous collision interactions, misalignments, and more issues. So, I switched to SAT (Separating Axis Theorem) collision instead. This, combined with general collision response logic, made coding collision one of the hardest endeavours of this project. There were many other challenges throughout development, however none are too disruptive to the experience of the final game. I’m still extremely proud of myself and this project for many reasons: This is the largest project I’ve ever made; Despite many challenges, bugs, and pieces of complex logic to work through, I made a fully functional and complete game; I managed to make this with no external engines; I was able to use my C++ and new SFML skills to create something I can proudly say I made! IMPORTANT NOTE FOR REVIEWERS!! PLEASE READ!!! A complete playthrough of the game takes a large amount of time due to how levels are structured: to play a level, you must beat the level before it, which poses an issue for one of the shapes which is only unlocked in the last set. I realize most reviewers do not have the time required to play through the full game and gain a complete understanding of its features. For this reason, I strongly urge reviewers to skim through/watch my full walkthrough video linked in my README, as well as check out the “Credits Easter Egg” section in that video. Playing through all 30 levels sequentially takes time, but you can unlock every level directly from the Credits screen so you can test all shape powers hands-on right away! This way, a reviewer will be able to understand the scope and gameplay of the game in a short amount of time. With that being said, I truly hope you enjoy my game....
|
1792759984.4731371
|
1792846384.4731371
|
|
6811
|
Borealis by @onyxtheone | Stardance
|
onyxtheone
|
1
|
383.93
|
4072
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-07-25T20:46:18Z", "hours": 241.0, "multiplier": 19.2, "payout": 4072, "blessing": "neutral", "text": "I built BTBX (Bare Tiny(?) BASIC eXecutor), a self-contained BASIC interpreter that is the operating system. There’s no Linux, no DOS, nothing underneath it. It boots straight off a FAT12 floppy image via a two-stage bootloader (512-byte stage1 + 2KB stage2), flips the CPU into protected mode, sets up the A20 gate, and lands you directly in a BASIC REPL, all inside 640KB of conventional memory. From there it’s a real language: GOTO, GOSUB, FOR/NEXT, WHILE/WEND, IF/THEN/ELSE, multi-dimensional arrays, 32-bit integers plus x87 80-bit floats, string functions (LEFT$, MID$, CHR$, etc.), and a full FAT12 filesystem so you can actually SAVE, LOAD, and DIR your programs on the disk image. There’s also PEEK/POKE for raw memory access, BLOAD/SYS to load and jump into raw machine code, VGA graphics primitives, a PIT-driven BEEP, and — half-finished but present — a SAY command aiming for SAM-style formant speech synthesis. What was challenging? Everything below the interpreter, honestly. Getting the boot chain right (CHS and EDD disk reads, A20 enabling that doesn’t silently hang, jumping into protected mode without immediately triple-faulting) took far longer than any language feature. The BIOS-thunk approach for file I/O (calling back into 16-bit real mode from a 32-bit kernel just to talk to disk) was its own maze. The funniest recent challenge was building a browser demo on top of v86: getting PS/2 keyboard Shift state to survive contact with a web browser turned out to be nearly as hard as writing the A20 gate code itself :3. Real hardware (and QEMU) just work; browsers apparently have opinions about what a Shift key is allowed to do. What am I proud of? That it boots at all, genuinely. A homemade OS with a homemade language on top, running real math through the x87 FPU and reading/writing a real filesystem, in under 640KB, with zero borrowed runtime. Getting arrays, strings, and file I/O all coexisting cleanly in a from-scratch interpreter over ~240 hours feels like the actual milestone here, not any single feature. What should people know to test it? Use make && make run, that's the supported path, tested in QEMU, and it's where shift/symbols work correctly. The browser demo (v86-based) is explicitly beta. booting and typing work, but shift-modified keys are unreliable there due to browser/emulator keyboard quirks (a real physical keyboard emulator interaction gap, not a BASIC bug ^^). Don't judge the interpreter by the demo's keyboard weirdness. Try PRINT, FOR/NEXT loops, SAVE/LOAD/DIR to confirm the filesystem works, and BEEP for audio. SAY is a known work-in-progress ergo don't expect actual speech (yet). Check the source tree if you want to see the boot chain (boot/stage1.asm, boot/stage2.asm) separately from the interpreter (src/kernel/basic.c).", "repo": "https://github.com/onyx-the-one/borealis", "demo": "https://onyx-the-one.github.io/borealis"}]...
|
[{"post_id": 63409, "ts": "202 [{"post_id": 63409, "ts": "2026-09-07T07:11:12Z", "hours": 9.3, "text": "its been a week since my last devlog, i dont have much new to add because with school and other responsibilities i dont have much time for actuall progress on this project. still i accumulated some 9 hours (sorry gizzy) by doing small changed, linting, updating forgotten banners and version numbers and so on. EHCI/USB still fails on the same issues as before. i will be reverting to a superfloppy boot because right now i cant even get debug to write to the disk which is annoying. then once i get the usb driver with all its issues working (sometime next decade) i can give usb boot another shot."}, {"post_id": 58426, "ts": "2026-08-30T20:43:20Z", "hours": 6.0, "text": "i am (still) putting in work on the usb driver, this is proving to be very complicated especially because my hardware is not cooperating. im thinking about switching back to floppy-emulated mode which would be more practical for debugging but at the same time probably introduce new issues i dont even expect yet."}, {"post_id": 53934, "ts": "2026-08-24T17:11:33Z", "hours": 7.1178, "text": "the port resets work on the laptop now. the bit we were waiting on (port-enable-changed) was being acknowledged by the bios’s smm ghost before we ever saw it, so we stopped waiting on the status bit and just read the port state, which can’t be acked away. also fixed before it bit us: two devices answering address 0 at once (enumeration is per-port now, and every device gets a real address before the next port wakes up). the next failure was prettier: every OUT transfer works, every IN transfer dies. the stick takes its orders but can’t talk back. that’s the signature of the qtd buffer list, the one place real ich silicon is strict where qemu is forgiving, so all dma buffers are page-aligned now and the error reports name whichever endpoint stalled. also everyone gotta apreciate the blahaj!"}, {"post_id": 50969, "ts": "2026-08-20T13:23:36Z", "hours": 9.3333, "text": "the stick is a disk now, no bios involved: usb grew enumeration and bot/scsi, fat12 picks whichever backend came up. qemu took the whole chain first try. the laptop found the stick on port 0 and then refused to reset it (my fault), the 50ms delay was port-0x80 writes that only cost real time inside qemu, so there’s a pit-based clock now. plot twist from the log meanwhile: the bios path worked on the laptop, because the toggles that “didn’t help” had quietly moved the stick to floppy emulation, and that path survives the mode switch. so it (partially) boots by accident while we fix it on purpose. also caught in a self-audit: a stall burned a full second, and a short read could report success with half a sector. readme rewritten as i was told to by sw."}, {"post_id": 50492, "ts": "2026-08-19T17:32:16Z", "hours": 5.8606, "text": "im still working on getting a usb driver to work. ehci seems to work kinda but its a loop between giving false data, partial data and occasionally seemingly true data but then usb decides it doesnt like it and ideally fat12 fails durning cache load too, WHICH I FIXED LONG AGO BRUH. but it came back for some reason. so im trying timing, msd, stall handling everything. this may take another decade."}, {"post_id": 49913, "ts": "2026-08-18T21:34:01Z", "hours": 6.4844, "text": "debug spew is a file now. every checkpoint from the first instruction onward (entry asm, the real-mode thunk letters, all the [DEBUG] lines) lands in a buffer, and once the fs proves it can write, the buffer becomes LOG.TXT and the screen clears to the banner. the trick is the default: echo stays on until the file is safely written, so a boot that dies early still shows everything live. the fallback isn’t a code path, it’s just never getting to the quiet part. LOG=0 in CONFIG.TXT keeps the old wallpaper. and the log already caught its first bug: a missing [EZTG] tattled on a stale version entry.asm. debugging is too important to leave on the screen."}, {"post_id": 49489, "ts": "2026-08-18T11:03:57Z", "hours": 9.5697, "text": "the stick talks, and for the first time it’s talking to us, not the bios. this part was the transfer engine: queue heads and transfer descriptors, little linked-list structs the ehci controller fetches out of ram and executes on its own. a control transfer is three of them chained by hand (setup, data, status), data toggles set manually per stage because high-speed lets you. link the queue head into the async ring, poll the active bit, unlink, then ring the doorbell (an actual doorbell bit) so the controller formally forgets the whole thing before the structs get reused. first exchange: GET_DESCRIPTOR at address 0, and the stick answered with its vid/pid like a civilized device. qemu’s stick goes by 46f4:0001; the real one can introduce itself when the laptop’s back. next: scsi over bulk, and fat12 stops caring what a disk is. moral: usb devices are polite, they just want to be asked in struct form."}, {"post_id": 48764, "ts": "2026-08-17T09:14:22Z", "hours": 9.3231, "text": "the laptop’s bios has a party trick: as i described before, int 13h works fine until the cpu enters protected mode, then it never returns, not even for a no-transfer disk reset. bios toggles didn’t help, so borealis is growing a native usb driver. first part: find the ehci controller over pci, do the formal ownership handshake (there’s an actual semaphore register in config space where the os and the bios’s smm ghost take turns. set our bit, wait for theirs to clear, then kill every smi source so the ghost stops getting summoned), reset the controller, spin up an idle async schedule, scan the ports. no packets yet, just a controller that’s officially ours. dev loop is qemu with a stick image on an emulated ehci, boot still from floppy, so the laptop only has to show up for the one hardware-specific part. moral: if the firmware won’t share the hardware, take the hardware."}, {"post_id": 47754, "ts": "2026-08-15T21:50:44Z", "hours": 4.8914, "text": "instrumented the thunk to print a letter per step so a hang names its own murderer. result: Rer , then nothing. R entered real mode, e entered the EDD read, r was about to issue a disk reset, ah=00h, the simplest int 13h call there is, no transfer, and it never returned. if even a no-op reset hangs after the PM excursion, the bios’s whole disk service is dead post-protected-mode on this machine, full stop. so the fix is a native usb driver. helix talks EHCI directly, bios for boot and native for runtime, as it should be, but that’s pci + ownership handoff from the very SMM that broke us + enumeration + BOT/scsi, and you don’t bring that up blind, one teletype letter per reboot, right before losing the hardware. deferred until the laptop’s back on hand; qemu remains unaffected."}, {"post_id": 47202, "ts": "2026-08-14T23:22:02Z", "hours": 5.7114, "text": "working theory: the bios’s legacy usb support, and specifically system management mode. coil runs in pure real mode and its EDD reads work, the bios reads the stick happily at boot. but helix runs in protected mode, and calling the bios means dropping back through a thunk, and that round-trip is where it dies. on a machine this age legacy usb lives in SMM: the bios traps disk interrupts and does the transfer in a mode invisible to the os, assuming a clean real-mode cpu, and our PM excursion breaks that assumption. the tell: teletype (int 10h) works from the thunk, disk (int 13h) hangs. teletype doesn’t touch usb, disk does. photo is the bios setup screen, where i went hunting for a legacy usb toggle which i did not find ;3c"}, {"post_id": 46999, "ts": "2026-08-14T15:56:13Z", "hours": 4.2892, "text": "next wall, immediate: the machine hangs at fat_cache_load, the step where helix reads the FAT and root directory into RAM. in qemu this works instantly but on the laptop the disk read goes out and never comes back. no error, no status, no return. debug output narrows it to exactly the transfer call: everything before prints, everything after doesn’t."}, {"post_id": 46771, "ts": "2026-08-14T08:36:41Z", "hours": 5.2839, "text": "borealis booted on the laptop for the first time. not qemu but actual silicon, a core 2 duo, off a usb stick. coil came up, loaded helix, and the machine made it to the banner plus three debug lines, which is the whole chain working on real firmware: stage1 > stage2 > kernel > protected mode. CHS disk was already known broken cos this bios won’t talk cylinders/heads/sectors to a stick with no real geometry, fair enough — so coil booted over EDD, but helix’s disk layer still assumed CHS and the filesystem never came up. still: it boots, on real hardware. just doesnt get far enough to be useful (yet)."}, {"post_id": 45393, "ts": "2026-08-11T20:28:36Z", "hours": 1.4333, "text": "im still working on real hw boot issues. coil doesnt guess geometry anymore, it brutes it: the new stage2 tries every plausible CHS geometry against a buildtime checksum of the kernel’s first sector and prints the one that actually works. no more “trust the BIOS” and no more “reject the BIOS”, just prove it. on a sane machine it prints g(18.2) and boots like nothing happened. on the laptop it either prints its real geometry and boots, or prints G! plus what the BIOS claimed. either way i finally get an answer instead of a silent reset. in the meantime ill be working on some features like arrows, logging, etc. attached photo of my testing setup"}, {"post_id": 45321, "ts": "2026-08-11T18:14:12Z", "hours": 5.1247, "text": "boot splash is in and shipping on the image. CONFIG.TXT decides, SPLASH.BAS plays on boot, keypress skips. the hook was “just two lines” and then reality happened: config.c wasnt in the makefile, the loader was static, and the first boot loaded the splash then sat at the prompt waiting for me to type RUN myself. three one-line fixes later: coil letters, banner, aurora, prompt. also fixed make pack details. the machine has a boot vibe now next up is proper scrollback, logging, and arrow key support."}, {"post_id": 44866, "ts": "2026-08-10T22:05:04Z", "hours": 2.6764, "text": "the system has a config file now. CONFIG.TXT on the boot disk, key=value, one per line, read at boot. the fun part: the parser tolerates leading line numbers, so EDIT CONFIG.TXT just works with zero new editor code. the editor only speaks numbered lines, so i taught the config reader to ignore them instead (and officially, just use the numbered lines in there its not that hard, but you dont have to for it to work). SPLASH=0/1 is the first key, persistence is free because its a file on the FAT12 disk. the whole reader is ~75 lines, no allocation, no subsystem. config systems should be files, not frameworks ;3c"}, {"post_id": 44673, "ts": "2026-08-10T16:18:27Z", "hours": 4.6592, "text": "SCREEN 13 works, SCRTEST passes end to end, palette cycling is smooth, and as a bonus the fix also killed a stack-vs-bss collision that was waiting to happen. wrote AURORA.BAS to celebrate, it does a starfield and a sine curtain with the classic palette-cycling trick so it stays fast even interpreted. next up (probs): making it the boot splash, config.txt for persistence, then directories and much much more to be excited for!"}, {"post_id": 44301, "ts": "2026-08-09T23:25:07Z", "hours": 5.0344, "text": "ITS THE MEMORY MAP. gfx_is_active sits at 0xA12C0 which is past 0xA0000 aka inside the VGA framebuffer window. reads from there always return 0xFF in text mode, writes vanish into the void. the kernel bss grew past 640k and parked a variable in video memory. the “graphics thunk situation” was never the thunk. it was never even the graphics. one line in the linker script moves bss to 1MiB and everything works. i want to scream (affectionate). theres some more to be done before its usable in practice (because it never really was i guess) but SOON."}, {"post_id": 43938, "ts": "2026-08-09T12:00:21Z", "hours": 5.2647, "text": "spent the whole night inside the realmode thunk with a fine comb. it is NOT the thunk. SCREEN 0 actually switches modes fine, which makes SCREEN 13 doing nothing even weirder. also found out my kernel thinks graphics is already on before i ever turned it on?? the flag says 255. TWO HUNDRED FIFTY FIVE. its supposed to be 0 or 1. memory corruption somewhere (see kpan 7), or im losing my mind. probably both."}, {"post_id": 43586, "ts": "2026-08-08T22:43:36Z", "hours": 4.1406, "text": "boot is finally stable, primes count to a million, so i tried the graphics. SCREEN 13 does nothing. no error, no letters, no mode change. GCLS nothing, LINE nothing, RECT nothing. PALETTE works??? which makes no sense because palette is the one that should be hardest. starting to suspect the video thunk is broken. ive got no idea. but at least im honoring my promise to keep devlogs shorter."}, {"post_id": 43305, "ts": "2026-08-08T14:26:54Z", "hours": 10.0411, "text": "Fixed the boot (fr this time) the whole laptop reset thing turned out to be two bugs stacked on each other: the bootloader was trusting/rejecting BIOS geometry based on vibes, and the kernel entry point was jumping into a debug helper instead of _start , so the CPU executed one stray ret into the void and triple-faulted. coil now makes the BIOS prove its geometry against a build-time checksum before trusting it, and checksums the whole kernel before jumping in. Boot output is an actual diagnostic language now: gk = geometry truthful, gf = BIOS lied, C! = wrong bytes arrived, and nothing resets silently anymore. QEMU boots all the way to BASIC, audio included. Also cleaned up helix.c (boot debug spam now only speaks when something’s actually wrong, RIP “HELIX FAILIURE” typo), evicted BTBX from the prompt, it’s js => now, and am working the BASIC interpreter with a bit of a rewrite: dispatcher no longer depends on include order and prayer, dead duplicate file-I/O code confirmed gone, graphics.inc brace damage found and fixed. Laptop test tomorrow-ish, then the interpreter cleanup lands. see u next time!"}, {"post_id": 41616, "ts": "2026-08-05T22:41:53Z", "hours": 8.7858, "text": "hi people! this one’s a bit different. no new features, but a new name. the project is now called Borealis. the old name, BTBX, made sense when this was a tiny BASIC interpreter and nothing more, but it’s grown into a full bootloader, kernel, and proto-OS, and the name stopped fitting. the system now has three named layers: coil is the two-stage bootloader, helix is the kernel, and BOREALIS is the system as a whole. the names are deliberately scale-neutral. where the project goes from here shouldn’t be constrained by what it’s called. the rename itself was the easy part, the fallout was the real work. i went through every file updating references to the old name, plus the directory structure ( boot/ became coil/ , src/kernel/ became src/helix/ ), the build files, and the image name ( borealis.img now). outside the repo, i also had to update hackatime and stardance so everything points at the right thing. the README on github is fully rewritten to match (may not be pushed at this time), and there’s a note in it about the old name for continuity. technically nothing else changed. same code, same features, same open issues, this was purely an identity update. that’s all for now!"}, {"post_id": 38767, "ts": "2026-08-01T10:16:03Z", "hours": 12.6017, "text": "hi people! im trying to get BTBX to boot properly on an ASUS F5RL laptop. unfortunately, it still isn’t booting correctly, but I managed to narrow the problem down further. I previously ran into issues involving EDD, DH, and a few other parts of the boot process. right now I’m getting the error S1>S2Agk(18.1)Drk{c2,h0,s2}R , which makes it look like the BIOS may be reporting bogus CHS geometry in a way BTBX is not expecting. there’s no working result yet, but I’ll keep investigating the boot and disk-handling path. i hope to get it running soon."}, {"post_id": 34823, "ts": "2026-07-25T20:37:32Z", "hours": 5.6622, "text": "hi people! this time i worked on a v86-compatible version for the in-browser demo. it’s now possible to try the project directly in the browser, although there are still a few input-related issues, including with the shift key. the browser version is mainly there as a quick way to look at the project without setting anything up. for proper testing, though, i’d still recommend using a local environment—the demo is mostly for anyone too busy to set one up. pong does work in it though ^^"}, {"post_id": 33966, "ts": "2026-07-24T10:16:38Z", "hours": 10.9, "text": "hi people! recently i worked on adding proper graphics support to the project. instead of relying on text-mode attribute tricks, i went with direct pixel plotting, since it gives the system a much more flexible foundation for drawing things on screen. i added a new Mode 13h framebuffer API with functions for entering and leaving graphics mode, clearing the screen, plotting and reading individual pixels, drawing lines, rectangles, and circles, and changing the VGA palette. the implementation writes directly to the linear framebuffer at 0xA0000, with palette updates handled through the VGA DAC ports. on the BASIC side, there are now new statements for using these graphics features: SCREEN, GCLS, PSET, LINE, RECT, CIRCLE, and PALETTE. i also connected the new graphics code to the statement dispatcher and updated the built-in HELP text so the commands are documented. finally, i cleaned up the build setup by adding the new graphics source files and removing an old ‘-display curses’ option from the run command. this is a much more versatile approach than only the old text-based graphics, and it gives me a better base for anything visual i add later. that’s all for now!"}, {"post_id": 33368, "ts": "2026-07-23T07:14:31Z", "hours": 9.3667, "text": "hi people! i spent more time working on the graphics system. there still isn’t a finished result to show yet, but i’ve been continuing to work through the implementation and figuring out the pieces needed for proper pixel-based graphics support. it’s taking a bit more iteration than expected, but the goal is still to have a solid graphics foundation rather than rushing in something limited. hopefully i’ll have the completed version ready to show soon. see y’all later!"}, {"post_id": 32259, "ts": "2026-07-21T09:58:51Z", "hours": 13.1136, "text": "hi people! i started working toward graphics support this time. i’m moving away from text-mode tricks and looking at direct pixel plotting instead, since it should be much more flexible to build on later.it’s still a work in progress, but i should have something more complete to show next time. what pmo is that 10 hour limit so i cant just devlog once i have a feature, i have to do it in the middle of nothing an wasting 3 hours anyways. see y’all later!"}, {"post_id": 31938, "ts": "2026-07-20T19:04:38Z", "hours": 7.7667, "text": "hi people! this time i added a set of bitwise operations to the language: AND(x,y), OR(x,y), XOR(x,y), NOT(x), SHL(x,n), and SHR(x,n). these work on values converted to 32-bit integers, and the shift functions keep large shift counts predictable by masking them to 31. i also added HEX$(x) and BIN$(x) string functions for displaying numbers in hexadecimal and binary, without unnecessary leading zeroes. on top of that, the number parser now accepts hexadecimal and binary literals using &H… and &B…. finally, i updated the built-in HELP text so the new functions and literal formats are documented in the system itself. that’s all for now"}, {"post_id": 30166, "ts": "2026-07-17T15:01:06Z", "hours": 6.6506, "text": "hi people! this was mostly a behind-the-scenes work session rather than one with a major new feature to show off. i spent a lot of time working through the project, trying things out, and dealing with the smaller details that tend to take longer than expected. there isn’t one big result for this devlog, but the time was still useful for getting a clearer picture of what needs attention next and making progress on the work that supports the larger features. sometimes development is less about a big visible change and more about putting time into the parts that make future work smoother. that’s all for now!"}, {"post_id": 28528, "ts": "2026-07-14T20:47:26Z", "hours": 15.6667, "text": "hi guys! i took a short break from the project. first voluntarily to take care of my mental health, and then a bit longer than planned because i got sick. after returning, i tackled a smaller but useful feature: RTC support via the TIME command. the command can now work with the real-time clock, which means the system has proper support for reading and handling time instead of relying on a manually managed value. this was a fairly quick feature to work through, so it felt like a good way to get back into the project after the break. also, please excuse the old time shown in the photo, i hadn’t kept it up to date when I took it. that’s all, see you later"}, {"post_id": 22752, "ts": "2026-07-05T10:26:44Z", "hours": 10.2164, "text": "hi people! this time, i mostly worked on cleaning things up after restructuring the working tree, and i also fixed a few issues with the text editor. the biggest breakthrough was figuring out why the prime sieve computation kept failing. in the end, the problem had nothing to do with the math itself. instead, it came from the way the interpreter handled loops and writing to disk. those issues interacted in a way that caused the loop to stop after finding just one number. that problem is now fixed, and while tracking it down i also ran into several other bugs, which i fixed along the way. that’s all!"}, {"post_id": 22233, "ts": "2026-07-04T16:25:58Z", "hours": 9.3667, "text": "After my restructuring I was gonna ship the project but I just dont feel its finished enough so I wanted to add a few more features to make it a bit more standalone. Right now, you would in theory be able to use it on a computer without having to prepare programs on another computer because WE HAVE A TEXT EDITOR!!! finally. So you can write your BASIC and execute it, save the results and view them as much as you want!! There is a prime number sieve being edited on screen but it doesnt run yet because there are some issues in the way my BASIC is interpreted, some issue with loops or whatnot. Thats the next thing to work on."}, {"post_id": 20667, "ts": "2026-07-02T10:09:46Z", "hours": 10.5667, "text": "Nothing incredible, except scut work right now. I was made aware by codefactor that my code was too complex in parts (complexity of 771) and so I cleaned up the file tree so its nice and organized, and I am most way through splitting stmt(), but I was made aware my devlogs are too long so here you go."}, {"post_id": 19587, "ts": "2026-06-30T22:41:33Z", "hours": 8.1828, "text": "I started working on giving the system a voice. Yes, quite literally a dystopian, creepy voice synthetisation function. Originally I was only gonna do ‘BEEP freq, duration’ (which i managed in a good hour at most) but then I got invested in actual phoneme/allophone synthesys (Software Automatic Mouth style) and it turned into a lot more work. Sadly so far i’ve only ever gotten squeals out of it, or all quiet, so i am probably going to give up and do more important work like either a text editor or a directory support, or even a proper C compiler in-system (so far only precompiled binaries work)."}, {"post_id": 16830, "ts": "2026-06-27T10:18:01Z", "hours": 19.9, "text": "I took a small hiatus (climbing in the caucas mountains for my mental health). Anyways i’m back and I added binary loading and execution support (for example precompiled C or whatever). I works, no too visible on the screenshot but look at the screen border (it was flashing). Also sorry for the long devlog but i had some time logged, and logged more now, and somehow ended up with 18 hrs."}, {"post_id": 12181, "ts": "2026-06-19T21:57:01Z", "hours": 7.1, "text": "I have finally fixed the floppy boot including its FAT12 init. There were many, many problems, I was running around in circles but I finally fixed it. The last thing I did was rewrote the EDD stuff front and back, and I assume that fixed it. I, honestly, am not sure. But anyways, now both HDD and floppy boot work including FAT12 init and all functions of BASIC that I have implemented insofar."}, {"post_id": 11569, "ts": "2026-06-18T21:07:42Z", "hours": 6.9667, "text": "The floppy boot issue persists. I have moved past the FAT init failing visibly, but any read actions throw all zeros out. I came across the issue in the past, I feel like I am going in circles here,"}, {"post_id": 10455, "ts": "2026-06-17T05:52:29Z", "hours": 7.1333, "text": "At the moment I am still stuck on the same issue (floppy/HDD). I got the idea that the fs may be misconfigured so I am working a on that too. A lot of theories, and multiple issues i’ve fixed already, but on floppy FAT init still fails."}, {"post_id": 9805, "ts": "2026-06-16T07:38:30Z", "hours": 12.0872, "text": "I dont have any major update, I am stuck fixing a regression where FAT initialization fails exclusively on QEMU floppy boots, while HDDs work fine. I always fix one thing and something else breaks, like EDD probing panics, false failiures, reset storms and others. The end result is always the same, the boot takes a long time (timeouts) and no disk is available."}, {"post_id": 8817, "ts": "2026-06-14T17:30:00Z", "hours": 13.4017, "text": "I decided to put some work into booting in hard-drive (DL 0x80). That in itself wasn’t too big an issue, but it in turn made floppy boot (DL 0x00) nonfunctional. I went back and forth, fixing one, breaking the other, again and again. Right now there is some kind of silent failiure in floppy mode that causes it to take minutes to boot (I think its failing and retrying 3 times on every sector) and then it finds the root dir populated as all zeros. The issue is all the processes come back as successes when reading registers. So right now, only hard drive mode works, but this devlog is already wayyyy too long and I wouldnt want to lose all this time."}, {"post_id": 7914, "ts": "2026-06-13T06:12:33Z", "hours": 5.8778, "text": "And we have a complete functioning FAT12! Reading and writing have been working smoothly. The fs writing wasn’t even that hard to implement, and I also added a few more mathematicals to to once again appoach GWBASIC. We have direct hardware access (PEEK/POKE into ram, etc), arrays, nonblocking input (INKEY$) and I also added 2 string functions."}, {"post_id": 6919, "ts": "2026-06-11T16:23:48Z", "hours": 11.835, "text": "After countless fixes I have managed to get a functioning FAT12 filesystem working, including listing and loading files. Saving (writing) is not functional yet. The key issues were: CHS mismatch, BPB was wrong, broken multisector loading, and other. Next I will try to make writing possible."}, {"post_id": 5983, "ts": "2026-06-10T01:13:01Z", "hours": 6.7942, "text": "I’ve changed some kernel details, like that instead of straight crashing, it might tell you whats wrong before, design details, etc. I changed the approach to disk wiriting from straight dd to a python script that actually makes a mountable volume, and I am still working on getting filesystem working. There has been so so many issues ive been running into as the complexity of the system rises (and so does entropy, I guess). This will take an unprecedented amount of work to get even remotely to the level that is GWBASIC, much less what I aspired to (ISO/IEC 10279:1991)."}, {"post_id": 4220, "ts": "2026-06-07T13:34:33Z", "hours": 10.9408, "text": "I managed to implement longer variable names possible, a lof of trig/calc functions and overall perked up some details. Im heading towards Full BASIC instead of just Tiny BASIC but Im not sure how far I will go with this."}, {"post_id": 3710, "ts": "2026-06-06T19:20:05Z", "hours": 8.9439, "text": "Ive gotten to the point where it actually boots from floppy in QEMU (no hd working) AND to an extent BASIC works. Its not perfect yet but ill get there soon."}, {"post_id": 2998, "ts": "2026-06-05T22:31:16Z", "hours": 6.0936, "text": "What a poor choice this project. I wanna sleep so much and yet I cant fall asleep because I just have to get it running and it will definietly only be an hour or less."}, {"post_id": 2674, "ts": "2026-06-05T10:58:37Z", "hours": 9.0503, "text": "I changed the approach. Instead of just messing around in assembly, I will do most of it in C and assembly is only for the bootloader. Yes, bootloader. Simplest way to keep this as bare-metal and universal as possible was, in my opinion, to just write a kernel, grub, crosscompile for i868 (in distrobox because the toolchain doesnt run on my distro) and boot via QEMU. I got far enough that it compiles and builds into an ISO, but doesnt actaully even boot, instead bugs out in SeaBIOS. Seems I bit off more than I could chew."}, {"post_id": 1934, "ts": "2026-06-04T05:34:44Z", "hours": 7.0881, "text": "After an all-nighter i got it to assemble, but to call it functional would be a joke."}]...
|
Title: Borealis by @onyxtheone | Stardance
Devlog Title: Borealis by @onyxtheone | Stardance
Devlogs:
After an all-nighter i got it to assemble, but to call it functional would be a joke.
I changed the approach. Instead of just messing around in assembly, I will do most of it in C and assembly is only for the bootloader. Yes, bootloader. Simplest way to keep this as bare-metal and universal as possible was, in my opinion, to just write a kernel, grub, crosscompile for i868 (in distrobox because the toolchain doesnt run on my distro) and boot via QEMU. I got far enough that it compiles and builds into an ISO, but doesnt actaully even boot, instead bugs out in SeaBIOS. Seems I bit off more than I could chew.
What a poor choice this project. I wanna sleep so much and yet I cant fall asleep because I just have to get it running and it will definietly only be an hour or less.
Ive gotten to the point where it actually boots from floppy in QEMU (no hd working) AND to an extent BASIC works. Its not perfect yet but ill get there soon.
I managed to implement longer variable names possible, a lof of trig/calc functions and overall perked up some details. Im heading towards Full BASIC instead of just Tiny BASIC but Im not sure how far I will go with this.
I’ve changed some kernel details, like that instead of straight crashing, it might tell you whats wrong before, design details, etc. I changed the approach to disk wiriting from straight dd to a python script that actually makes a mountable volume, and I am still working on getting filesystem working. There has been so so many issues ive been running into as the complexity of the system rises (and so does entropy, I guess). This will take an unprecedented amount of work to get even remotely to the level that is GWBASIC, much less what I aspired to (ISO/IEC 10279:1991).
After countless fixes I have managed to get a functioning FAT12 filesystem working, including listing and loading files. Saving (writing) is not functional yet. The key issues were: CHS mismatch, BPB was wrong, broken multisector loading, and other. Next I will try to make writing possible.
And we have a complete functioning FAT12! Reading and writing have been working smoothly. The fs writing wasn’t even that hard to implement, and I also added a few more mathematicals to to once again appoach GWBASIC. We have direct hardware access (PEEK/POKE into ram, etc), arrays, nonblocking input (INKEY$) and I also added 2 string functions.
I decided to put some work into booting in hard-drive (DL 0x80). That in itself wasn’t too big an issue, but it in turn made floppy boot (DL 0x00) nonfunctional. I went back and forth, fixing one, breaking the other, again and again. Right now there is some kind of silent failiure in floppy mode that causes it to take minutes to boot (I think its failing and retrying 3 times on every sector) and then it finds the root dir populated as all zeros. The issue is all the processes come back as successes when reading registers. So right now, only hard drive mode works, but this devlog is already wayyyy too long and I wouldnt want to lose all this time.
I dont have any major update, I am stuck fixing a regression where FAT initialization fails exclusively on QEMU floppy boots, while HDDs work fine. I always fix one thing and something else breaks, like EDD probing panics, false failiures, reset storms and others. The end result is always the same, the boot takes a long time (timeouts) and no disk is available.
At the moment I am still stuck on the same issue (floppy/HDD). I got the idea that the fs may be misconfigured so I am working a on that too. A lot of theories, and multiple issues i’ve fixed already, but on floppy FAT init still fails.
The floppy boot issue persists. I have moved past the FAT init failing visibly, but any read actions throw all zeros out. I came across the issue in the past, I feel like I am going in circles here,
I have finally fixed the floppy boot including its FAT12 init. There were many, many problems, I was running around in circles but I finally fixed it. The last thing I did was rewrote the EDD stuff front and back, and I assume that fixed it. I, honestly, am not sure. But anyways, now both HDD and floppy boot work including FAT12 init and all functions of BASIC that I have implemented insofar.
I took a small hiatus (climbing in the caucas mountains for my mental health). Anyways i’m back and I added binary loading and execution support (for example precompiled C or whatever). I works, no too visible on the screenshot but look at the screen border (it was flashing). Also sorry for the long devlog but i had some time logged, and logged more now, and somehow ended up with 18 hrs.
I started working on giving the system a voice. Yes, quite literally a dystopian, creepy voice synthetisation function. Originally I was only gonna do ‘BEEP freq, duration’ (which i managed in a good hour at most) but then I got invested in actual phoneme/allophone synthesys (Software Automatic Mouth style) and it turned into a lot more work. Sadly so far i’ve only ever gotten squeals out of it, or all quiet, so i am probably going to give up and do more important work like either a text editor or a directory support, or even a proper C compiler in-system (so far only precompiled binaries work).
Nothing incredible, except scut work right now. I was made aware by codefactor that my code was too complex in parts (complexity of 771) and so I cleaned up the file tree so its nice and organized, and I am most way through splitting stmt(), but I was made aware my devlogs are too long so here you go.
After my restructuring I was gonna ship the project but I just dont feel its finished enough so I wanted to add a few more features to make it a bit more standalone. Right now, you would in theory be able to use it on a computer without having to prepare programs on another computer because WE HAVE A TEXT EDITOR!!! finally. So you can write your BASIC and execute it, save the results and view them as much as you want!! There is a prime number sieve being edited on screen but it doesnt run yet because there are some issues in the way my BASIC is interpreted, some issue with loops or whatnot. Thats the next thing to work on.
hi people! this time, i mostly worked on cleaning things up after restructuring the working tree, and i also fixed a few issues with the text editor. the biggest breakthrough was figuring out why the prime sieve computation kept failing. in the end, the problem had nothing to do with the math itself. instead, it came from the way the interpreter handled loops and writing to disk. those issues interacted in a way that caused the loop to stop after finding just one number. that problem is now fixed, and while tracking it down i also ran into several other bugs, which i fixed along the way. that’s all!
hi guys! i took a short break from the project. first voluntarily to take care of my mental health, and then a bit longer than planned because i got sick. after returning, i tackled a smaller but useful feature: RTC support via the TIME command. the command can now work with the real-time clock, which means the system has proper support for reading and handling time instead of relying on a manually managed value. this was a fairly quick feature to work through, so it felt like a good way to get back into the project after the break. also, please excuse the old time shown in the photo, i hadn’t kept it up to date when I took it. that’s all, see you later
hi people! this was mostly a behind-the-scenes work session rather than one with a major new feature to show off. i spent a lot of time working through the project, trying things out, and dealing with the smaller details that tend to take longer than expected. there isn’t one big result for this devlog, but the time was still useful for getting a clearer picture of what needs attention next and making progress on the work that supports the larger features. sometimes development is less about a big visible change and more about putting time into the parts that make future work smoother. that’s all for now!
hi people! this time i added a set of bitwise operations to the language: AND(x,y), OR(x,y), XOR(x,y), NOT(x), SHL(x,n), and SHR(x,n). these work on values converted to 32-bit integers, and the shift functions keep large shift counts predictable by masking them to 31. i also added HEX$(x) and BIN$(x) string functions for displaying numbers in hexadecimal and binary, without unnecessary leading zeroes. on top of that, the number parser now accepts hexadecimal and binary literals using &H… and &B…. finally, i updated the built-in HELP text so the new functions and literal formats are documented in the system itself. that’s all for now
hi people! i started working toward graphics support this time. i’m moving away from text-mode tricks and looking at direct pixel plotting instead, since it should be much more flexible to build on later.it’s still a work in progress, but i should have something more complete to show next time. what pmo is that 10 hour limit so i cant just devlog once i have a feature, i have to do it in the middle of nothing an wasting 3 hours anyways. see y’all later!
hi people! i spent more time working on the graphics system. there still isn’t a finished result to show yet, but i’ve been continuing to work through the implementation and figuring out the pieces needed for proper pixel-based graphics support. it’s taking a bit more iteration than expected, but the goal is still to have a solid graphics foundation rather than rushing in something limited. hopefully i’ll have the completed version ready to show soon. see y’all later!
hi people! recently i worked on adding proper graphics support to the project. instead of relying on text-mode attribute tricks, i went with direct pixel plotting, since it gives the system a much more flexible foundation for drawing things on screen. i added a new Mode 13h framebuffer API with functions for entering and leaving graphics mode, clearing the screen, plotting and reading individual pixels, drawing lines, rectangles, and circles, and changing the VGA palette. the implementation writes directly to the linear framebuffer at 0xA0000, with palette updates handled through the VGA DAC ports. on the BASIC side, there are now new statements for using these graphics features: SCREEN, GCLS, PSET, LINE, RECT, CIRCLE, and PALETTE. i also connected the new graphics code to the statement dispatcher and updated the built-in HELP text so the commands are documented. finally, i cleaned up the build setup by adding the new graphics source files and removing an old ‘-display curses’ option from the run command. this is a much more versatile approach than only the old text-based graphics, and it gives me a better base for anything visual i add later. that’s all for now!
hi people! this time i worked on a v86-compatible version for the in-browser demo. it’s now possible to try the project directly in the browser, although there are still a few input-related issues, including with the shift key. the browser version is mainly there as a quick way to look at the project without setting anything up. for proper testing, though, i’d still recommend using a local environment—the demo is mostly for anyone too busy to set one up. pong does work in it though ^^
hi people! im trying to get BTBX to boot properly on an ASUS F5RL laptop. unfortunately, it still isn’t booting correctly, but I managed to narrow the problem down further. I previously ran into issues involving EDD, DH, and a few other parts of the boot process. right now I’m getting the error S1>S2Agk(18.1)Drk{c2,h0,s2}R , which makes it look like the BIOS may be reporting bogus CHS geometry in a way BTBX is not expecting. there’s no working result yet, but I’ll keep investigating the boot and disk-handling path. i hope to get it running soon.
hi people! this one’s a bit different. no new features, but a new name. the project is now called Borealis. the old name, BTBX, made sense when this was a tiny BASIC interpreter and nothing more, but it’s grown into a full bootloader, kernel, and proto-OS, and the name stopped fitting. the system now has three named layers: coil is the two-stage bootloader, helix is the kernel, and BOREALIS is the system as a whole. the names are deliberately scale-neutral. where the project goes from here shouldn’t be constrained by what it’s called. the rename itself was the easy part, the fallout was the real work. i went through every file updating references to the old name, plus the directory structure ( boot/ became coil/ , src/kernel/ became src/helix/ ), the build files, and the image name ( borealis.img now). outside the repo, i also had to update hackatime and stardance so everything points at the right thing. the README on github is fully rewritten to match (may not be pushed at this time), and there’s a note in it about the old name for continuity. technically nothing else changed. same code, same features, same open issues, this was purely an identity update. that’s all for now!
Fixed the boot (fr this time) the whole laptop reset thing turned out to be two bugs stacked on each other: the bootloader was trusting/rejecting BIOS geometry based on vibes, and the kernel entry point was jumping into a debug helper instead of _start , so the CPU executed one stray ret into the void and triple-faulted. coil now makes the BIOS prove its geometry against a build-time checksum before trusting it, and checksums the whole kernel before jumping in. Boot output is an actual diagnostic language now: gk = geometry truthful, gf = BIOS lied, C! = wrong bytes arrived, and nothing resets silently anymore. QEMU boots all the way to BASIC, audio included. Also cleaned up helix.c (boot debug spam now only speaks when something’s actually wrong, RIP “HELIX FAILIURE” typo), evicted BTBX from the prompt, it’s js => now, and am working the BASIC interpreter with a bit of a rewrite: dispatcher no longer depends on include order and prayer, dead duplicate file-I/O code confirmed gone, graphics.inc brace damage found and fixed. Laptop test tomorrow-ish, then the interpreter cleanup lands. see u next time!
boot is finally stable, primes count to a million, so i tried the graphics. SCREEN 13 does nothing. no error, no letters, no mode change. GCLS nothing, LINE nothing, RECT nothing. PALETTE works??? which makes no sense because palette is the one that should be hardest. starting to suspect the video thunk is broken. ive got no idea. but at least im honoring my promise to keep devlogs shorter.
spent the whole night inside the realmode thunk with a fine comb. it is NOT the thunk. SCREEN 0 actually switches modes fine, which makes SCREEN 13 doing nothing even weirder. also found out my kernel thinks graphics is already on before i ever turned it on?? the flag says 255. TWO HUNDRED FIFTY FIVE. its supposed to be 0 or 1. memory corruption somewhere (see kpan 7), or im losing my mind. probably both.
ITS THE MEMORY MAP. gfx_is_active sits at 0xA12C0 which is past 0xA0000 aka inside the VGA framebuffer window. reads from there always return 0xFF in text mode, writes vanish into the void. the kernel bss grew past 640k and parked a variable in video memory. the “graphics thunk situation” was never the thunk. it was never even the graphics. one line in the linker script moves bss to 1MiB and everything works. i want to scream (affectionate). theres some more to be done before its usable in practice (because it never really was i guess) but SOON.
SCREEN 13 works, SCRTEST passes end to end, palette cycling is smooth, and as a bonus the fix also killed a stack-vs-bss collision that was waiting to happen. wrote AURORA.BAS to celebrate, it does a starfield and a sine curtain with the classic palette-cycling trick so it stays fast even interpreted. next up (probs): making it the boot splash, config.txt for persistence, then directories and much much more to be excited for!
the system has a config file now. CONFIG.TXT on the boot disk, key=value, one per line, read at boot. the fun part: the parser tolerates leading line numbers, so EDIT CONFIG.TXT just works with zero new editor code. the editor only speaks numbered lines, so i taught the config reader to ignore them instead (and officially, just use the numbered lines in there its not that hard, but you dont have to for it to work). SPLASH=0/1 is the first key, persistence is free because its a file on the FAT12 disk. the whole reader is ~75 lines, no allocation, no subsystem. config systems should be files, not frameworks ;3c
boot splash is in and shipping on the image. CONFIG.TXT decides, SPLASH.BAS plays on boot, keypress skips. the hook was “just two lines” and then reality happened: config.c wasnt in the makefile, the loader was static, and the first boot loaded the splash then sat at the prompt waiting for me to type RUN myself. three one-line fixes later: coil letters, banner, aurora, prompt. also fixed make pack details. the machine has a boot vibe now next up is proper scrollback, logging, and arrow key support.
im still working on real hw boot issues. coil doesnt guess geometry anymore, it brutes it: the new stage2 tries every plausible CHS geometry against a buildtime checksum of the kernel’s first sector and prints the one that actually works. no more “trust the BIOS” and no more “reject the BIOS”, just prove it. on a sane machine it prints g(18.2) and boots like nothing happened. on the laptop it either prints its real geometry and boots, or prints G! plus what the BIOS claimed. either way i finally get an answer instead of a silent reset. in the meantime ill be working on some features like arrows, logging, etc. attached photo of my testing setup
borealis booted on the laptop for the first time. not qemu but actual silicon, a core 2 duo, off a usb stick. coil came up, loaded helix, and the machine made it to the banner plus three debug lines, which is the whole chain working on real firmware: stage1 > stage2 > kernel > protected mode. CHS disk was already known broken cos this bios won’t talk cylinders/heads/sectors to a stick with no real geometry, fair enough — so coil booted over EDD, but helix’s disk layer still assumed CHS and the filesystem never came up. still: it boots, on real hardware. just doesnt get far enough to be useful (yet).
next wall, immediate: the machine hangs at fat_cache_load, the step where helix reads the FAT and root directory into RAM. in qemu this works instantly but on the laptop the disk read goes out and never comes back. no error, no status, no return. debug output narrows it to exactly the transfer call: everything before prints, everything after doesn’t.
working theory: the bios’s legacy usb support, and specifically system management mode. coil runs in pure real mode and its EDD reads work, the bios reads the stick happily at boot. but helix runs in protected mode, and calling the bios means dropping back through a thunk, and that round-trip is where it dies. on a machine this age legacy usb lives in SMM: the bios traps disk interrupts and does the transfer in a mode invisible to the os, assuming a clean real-mode cpu, and our PM excursion breaks that assumption. the tell: teletype (int 10h) works from the thunk, disk (int 13h) hangs. teletype doesn’t touch usb, disk does. photo is the bios setup screen, where i went hunting for a legacy usb toggle which i did not find ;3c
instrumented the thunk to print a letter per step so a hang names its own murderer. result: Rer , then nothing. R entered real mode, e entered the EDD read, r was about to issue a disk reset, ah=00h, the simplest int 13h call there is, no transfer, and it never returned. if even a no-op reset hangs after the PM excursion, the bios’s whole disk service is dead post-protected-mode on this machine, full stop. so the fix is a native usb driver. helix talks EHCI directly, bios for boot and native for runtime, as it should be, but that’s pci + ownership handoff from the very SMM that broke us + enumeration + BOT/scsi, and you don’t bring that up blind, one teletype letter per reboot, right before losing the hardware. deferred until the laptop’s back on hand; qemu remains unaffected.
the laptop’s bios has a party trick: as i described before, int 13h works fine until the cpu enters protected mode, then it never returns, not even for a no-transfer disk reset. bios toggles didn’t help, so borealis is growing a native usb driver. first part: find the ehci controller over pci, do the formal ownership handshake (there’s an actual semaphore register in config space where the os and the bios’s smm ghost take turns. set our bit, wait for theirs to clear, then kill every smi source so the ghost stops getting summoned), reset the controller, spin up an idle async schedule, scan the ports. no packets yet, just a controller that’s officially ours. dev loop is qemu with a stick image on an emulated ehci, boot still from floppy, so the laptop only has to show up for the one hardware-specific part. moral: if the firmware won’t share the hardware, take the hardware.
the stick talks, and for the first time it’s talking to us, not the bios. this part was the transfer engine: queue heads and transfer descriptors, little linked-list structs the ehci controller fetches out of ram and executes on its own. a control transfer is three of them chained by hand (setup, data, status), data toggles set manually per stage because high-speed lets you. link the queue head into the async ring, poll the active bit, unlink, then ring the doorbell (an actual doorbell bit) so the controller formally forgets the whole thing before the structs get reused. first exchange: GET_DESCRIPTOR at address 0, and the stick answered with its vid/pid like a civilized device. qemu’s stick goes by 46f4:0001; the real one can introduce itself when the laptop’s back. next: scsi over bulk, and fat12 stops caring what a disk is. moral: usb devices are polite, they just want to be asked in struct form.
debug spew is a file now. every checkpoint from the first instruction onward (entry asm, the real-mode thunk letters, all the [DEBUG] lines) lands in a buffer, and once the fs proves it can write, the buffer becomes LOG.TXT and the screen clears to the banner. the trick is the default: echo stays on until the file is safely written, so a boot that dies early still shows everything live. the fallback isn’t a code path, it’s just never getting to the quiet part. LOG=0 in CONFIG.TXT keeps the old wallpaper. and the log already caught its first bug: a missing [EZTG] tattled on a stale version entry.asm. debugging is too important to leave on the screen.
im still working on getting a usb driver to work. ehci seems to work kinda but its a loop between giving false data, partial data and occasionally seemingly true data but then usb decides it doesnt like it and ideally fat12 fails durning cache load too, WHICH I FIXED LONG AGO BRUH. but it came back for some reason. so im trying timing, msd, stall handling everything. this may take another decade.
the stick is a disk now, no bios involved: usb grew enumeration and bot/scsi, fat12 picks whichever backend came up. qemu took the whole chain first try. the laptop found the stick on port 0 and then refused to reset it (my fault), the 50ms delay was port-0x80 writes that only cost real time inside qemu, so there’s a pit-based clock now. plot twist from the log meanwhile: the bios path worked on the laptop, because the toggles that “didn’t help” had quietly moved the stick to floppy emulation, and that path survives the mode switch. so it (partially) boots by accident while we fix it on purpose. also caught in a self-audit: a stall burned a full second, and a short read could report success with half a sector. readme rewritten as i was told to by sw.
the port resets work on the laptop now. the bit we were waiting on (port-enable-changed) was being acknowledged by the bios’s smm ghost before we ever saw it, so we stopped waiting on the status bit and just read the port state, which can’t be acked away. also fixed before it bit us: two devices answering address 0 at once (enumeration is per-port now, and every device gets a real address before the next port wakes up). the next failure was prettier: every OUT transfer works, every IN transfer dies. the stick takes its orders but can’t talk back. that’s the signature of the qtd buffer list, the one place real ich silicon is strict where qemu is forgiving, so all dma buffers are page-aligned now and the error reports name whichever endpoint stalled. also everyone gotta apreciate the blahaj!
i am (still) putting in work on the usb driver, this is proving to be very complicated especially because my hardware is not cooperating. im thinking about switching back to floppy-emulated mode which would be more practical for debugging but at the same time probably introduce new issues i dont even expect yet.
its been a week since my last devlog, i dont have much new to add because with school and other responsibilities i dont have much time for actuall progress on this project. still i accumulated some 9 hours (sorry gizzy) by doing small changed, linting, updating forgotten banners and version numbers and so on. EHCI/USB still fails on the same issues as before. i will be reverting to a superfloppy boot because right now i cant even get debug to write to the disk which is annoying. then once i get the usb driver with all its issues working (sometime next decade) i can give usb boot another shot.
Ships:
I built BTBX (Bare Tiny(?) BASIC eXecutor), a self-contained BASIC interpreter that is the operating system. There’s no Linux, no DOS, nothing underneath it. It boots straight off a FAT12 floppy image via a two-stage bootloader (512-byte stage1 + 2KB stage2), flips the CPU into protected mode, sets up the A20 gate, and lands you directly in a BASIC REPL, all inside 640KB of conventional memory. From there it’s a real language: GOTO, GOSUB, FOR/NEXT, WHILE/WEND, IF/THEN/ELSE, multi-dimensional arrays, 32-bit integers plus x87 80-bit floats, string functions (LEFT$, MID$, CHR$, etc.), and a full FAT12 filesystem so you can actually SAVE, LOAD, and DIR your programs on the disk image. There’s also PEEK/POKE for raw memory access, BLOAD/SYS to load and jump into raw machine code, VGA graphics primitives, a PIT-driven BEEP, and — half-finished but present — a SAY command aiming for SAM-style formant speech synthesis. What was challenging? Everything below the interpreter, honestly. Getting the boot chain right (CHS and EDD disk reads, A20 enabling that doesn’t silently hang, jumping into protected mode without immediately triple-faulting) took far longer than any language feature. The BIOS-thunk approach for file I/O (calling back into 16-bit real mode from a 32-bit kernel just to talk to disk) was its own maze. The funniest recent challenge was building a browser demo on top of v86: getting PS/2 keyboard Shift state to survive contact with a web browser turned out to be nearly as hard as writing the A20 gate code itself :3. Real hardware (and QEMU) just work; browsers apparently have opinions about what a Shift key is allowed to do. What am I proud of? That it boots at all, genuinely. A homemade OS with a homemade language on top, running real math through the x87 FPU and reading/writing a real filesystem, in under 640KB, with zero borrowed runtime. Getting arrays, strings, and file I/O all coexisting cleanly in a from-scratch interpreter over ~240 hours feels like the actual milestone here, not any single feature. What should people know to test it? Use make && make run, that's the supported path, tested in QEMU, and it's where shift/symbols work correctly. The browser demo (v86-based) is explicitly beta. booting and typing work, but shift-modified keys are unreliable there due to browser/emulator keyboard quirks (a real physical keyboard emulator interaction gap, not a BASIC bug ^^). Don't judge the interpreter by the demo's keyboard weirdness. Try PRINT, FOR/NEXT loops, SAVE/LOAD/DIR to confirm the filesystem works, and BEEP for audio. SAY is a known work-in-progress ergo don't expect actual speech (yet). Check the source tree if you want to see the boot chain (boot/stage1.asm, boot/stage2.asm) separately from the interpreter (src/kernel/basic.c)....
|
1792878618.2847242
|
1793742618.2847242
|
|
34143
|
Spectralis by @DeltaVortex | Stardance
|
DeltaVortex
|
2
|
332.84
|
4092
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-06T05:56:33Z", "hours": 236.0, "multiplier": 16.89, "payout": 3884, "blessing": "neutral", "text": "Spectralis shiplarp 2 — Stardance —wuzzup guys— So much has happened since shiplarp 1 and I cannot wait to not break down what changed. I will. I’m lazy. Not right now though. Cat or dog? redeem_code.claim() —the celebration— We’ve gone through so many changes since last time that it deserves an actual celebration: a very cool, very awesome custom visualizer for Stardance. Claim yours: Help > Manage Visualizers, then redeem stardance-lts-pulp . —found a bug?— Including the dreaded Tim Cook issues — DM me: Discord: @deltav0rtex Slack: deltavortex Can’t wait to hear the feedback and all the bugs you dig up. —this is the end*— *end for now, redeem codes permitting YIPEE!!!", "repo": "https://github.com/Dareto-Dream/Spectralis", "demo": "https://spectralis.deltavdevs.com"}, {"ship_num": 2, "ts": "2026-08-14T06:50:58Z", "hours": 23.0, "multiplier": 12.89, "payout": 208, "blessing": "neutral", "text": "Spectralis shiplarp — v5.3.0 —shipped it— Notepads. A spin wheel. Dead zones that aren’t OBS-only anymore. Playlists that don’t look like a log file. Spotify that actually behaves. That’s the version. —what’s in it— Notepad system: docked panel, tabs, pop-out window, saves to track tags Spin wheel: weighted entries, saved wheel lists, notepad-fed Dead zones now shift the app’s own layout, not just OBS overlays Spotify: playlist sync, queue, pause, and Discord presence all fixed Fixed: playlist rows missing RowBackground (looked like a terminal, my bad) Fixed: nav rebuilding the entire view every click Fixed: library load blocking window open on big libraries Fixed: spectrum bars snapping instead of moving (FFT overlap bumped to 75%) Fixed: soundcloud playhead, word-mode timestamp export, track-switch click/pop —that’s it— PICKLE!!!", "repo": "https://github.com/Dareto-Dream/Spectralis", "demo": "https://spectralis.deltavdevs.com"}]...
|
[{"post_id": 65615, "ts": "202 [{"post_id": 65615, "ts": "2026-09-10T21:10:25Z", "hours": 9.8333, "text": "Spectralis devlog #44 —Hello again proggers— Did it. Fixed a genuine ton of bugs, following through on the mess from devlog #43. Tempted to just drop 6.1.0 right now, but holding off — want to get a few new features in and brainstorm some more QoL first so this actually feels like a finished product, not just a stopgap. Also: finally going to bed. the bar was “fix the bugs” and I cleared it, going higher anyway Cat or dog? sleep(∞) Okay let’s get into it~ —Yap— Real closure on the websocket/CDN/prod chaos from last devlog. Cleared out a lot in one sitting, and instead of rushing 6.1.0 out the door on relief alone, choosing to actually sit with it a bit longer. —The Great Suffering— 1 — The Bug Backlog, Actually Cleared Worked through the fallout from devlog #43 — websocket issues, the CDN backup failures, all of it — and got a genuine ton of it fixed in one real pass instead of piecemeal patching. 2 — Holding Off On 6.1.0, On Purpose Could ship right now. Choosing not to. Want to work in a few new features and brainstorm more QoL first, so the release feels complete rather than just “the bugs are gone, ship it.” Patience over momentum this time. 3 — Finally Going To Bed After devlog #43’s two-days-no-sleep spiral, actually calling it and going to bed now. Today off is finally getting used the way it was supposed to be used. the sleep debt collector finally caught up —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one about to get real sleep for the first time in a while. Q: Why not just ship 6.1.0 now if the bugs are fixed? A: Because “bug-free” and “actually done” aren’t the same bar, and this one’s worth clearing the second one too. Q: Was this the same chaos from devlog #43? A: Same fires, all put out this round. Q: What kind of new features are being considered? A: Not locked in yet — that brainstorming is the next step, not this devlog. Q: Sleep status, finally? A: Handled. Going now. —This is the end*— *end for now, actual sleep permitting PLAY!!!"}, {"post_id": 65271, "ts": "2026-09-10T08:34:54Z", "hours": 2.5, "text": "Spectralis devlog #43 —Hello again proggers— [2:47am] okay so. websockets again, more of them, and now the CDN backup is failing too which is great, love that for me. on my 4th coffee at this point, energy drink count is starting to get concerning honestly and I’m not gonna pretend it isn’t. pretty sure i debugged the cdn thing at 4am purely out of spite Cat or dog? idk man catch (Exception e) { } at this point Okay let’s get into it, or at least try to~ —Yap— so continuing from devlog #42’s websocket hardening, turns out hardening one part just revealed the next part was also fragile, shocking, anyway. need to push something to prod to actually get it working but can’t do that without interrupting infra which is currently live so that’s a whole separate problem I have to solve first before I can solve the actual problem. love layers. —The Great Suffering— 1 — More Websocket Issues more of them. found while poking at the hardening from last devlog. not sure if figuring this part out took 20 minutes or 3 hours honestly, time’s doing something weird tonight. 2 — CDN Backup Is Failing on top of the websocket stuff, cdn backups just started failing too. not connected to each other as far as i can tell but who knows at this point, everything feels connected at 3am. 3 — Need To Push To Prod, Can’t Without Interrupting Infra the actual fix needs to go to prod but pushing it right now means interrupting live infra, which i don’t want to do blind, so now i need a plan for THAT before the real fix even goes out. process problem wrapped around the actual problem, great. 4 — Shared Play Is Doing The AI-Look Thing Again noticed shared play’s UI is drifting into the same generic-AI-looking territory the main site kept getting flagged for back in devlog #21-#24. damn. gonna have to redo that too. not tonight though, one disaster at a time. 5 — Oh And I Found A Missing Semicolon spent a genuinely embarrassing amount of time on a bug that turned out to be a missing semicolon. send help. actually don’t, just let me suffer, i clearly deserve it at this hour. 6 — No Sleep For 2 Days, Hitting Now it’s catching up. hard. luckily got tomorrow off so plan is stay up tongiht finish this, and just completely pass out tomorrow instead. worth it. probably. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: a human programmer. you. the one reading this at whatever hour you’re reading it, hopefully not also running on 2 days no sleep Q: Is the websocket hardening from #42 actually working? A: mostly? finding more edge cases as i go, which is annoying but also kind of expected honestly Q: Why can’t you just push to prod now? A: because infra’s live and i don’t want to interrupt it blind, need an actual plan for that part first Q: Is shared play getting a full redesign again? A: yeah probably, later though, not adding a 4th fire to tonight Q: Sleep plan? A: none tonight, all of it tomorrow, that’s the whole plan —This is the end — *end for now, semicolons permitting send sleep!!!"}, {"post_id": 65216, "ts": "2026-09-10T06:03:36Z", "hours": 9.7103, "text": "Spectralis devlog #42 —Hello again proggers— Spent this round hardening shared queues, mostly because WebSockets are just genuinely cool and it’s about time they got treated that way in this codebase. a devlog motivated entirely by “websockets are cool” is a valid devlog Cat or dog? ws:// Okay let’s get into it~ —Yap— Shared queues have been functional but not particularly resilient this whole time, riding on shared play’s presence/reactions/queue work from way back in devlog #9. This round was about actually hardening that layer instead of leaving it fragile. —The Great Suffering— 1 — Hardening Shared Queues Went through and shored up a bunch of the underlying bases for shared queues — the stuff that only matters once real connections are dropping, reconnecting, and behaving unpredictably instead of the clean happy-path test case. 2 — Because WebSockets Are Cool Genuinely part of the motivation here. Real-time bidirectional connections are just satisfying to get right, and shared queues are exactly the kind of feature that benefits from taking that layer seriously instead of treating it as plumbing. not every feature needs a dramatic bug story, sometimes it’s just “wanted to do it well” —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one hardening infrastructure purely because it’s fun to get right. Q: Is this related to the shared play work from devlog #9? A: Same general system, this round focused specifically on making the queue layer more resilient. Q: What does “hardening” mean here specifically? A: Making the shared queue behavior hold up better under real conditions — drops, reconnects, timing edge cases — rather than just the clean test path. Q: Any bugs found during this pass? A: Nothing dramatic enough to call out individually, mostly proactive resilience work. Q: What’s next? A: Podcast mode and the randomizer work from devlog #41 are both still ongoing threads. —This is the end*— *end for now, dropped connections permitting P_P!!!"}, {"post_id": 64674, "ts": "2026-09-09T08:17:56Z", "hours": 5.2669, "text": "Spectralis devlog #41 —Hello again proggers— Podcast mode’s in the works, with a real new way to actually find saved podcasts instead of digging for them. Also fixed the randomizing tools so they actually help pick a song instead of just existing decoratively. And: class got canceled for a hurricane watch, so tonight’s an all-nighter by default. free 10 hours courtesy of a hurricane, weird way to get them Cat or dog? shuffle(weighted=True) Okay let’s get into it~ —Yap— Two real features this round plus a forced schedule change. Podcast mode’s genuinely new territory for the app, the randomizer fix is a smaller but meaningful UX improvement, and the hurricane watch just handed over a full night that wasn’t originally planned for grinding. —The Great Suffering— 1 — Podcast Mode, In Progress Building out actual podcast support, including a new way to locate saved podcasts rather than just treating them like any other track and hoping they surface in the right place. Real new territory for the app compared to the music-first feature set so far. 2 — Randomizing Tools, Actually Useful Now The shuffle/randomizer tools existed before but weren’t really doing anything meaningful — mostly there in name. Fixed so they actually aid in song selection now instead of just sitting there as a checkbox nobody trusted. a randomizer that doesn’t actually help you pick anything is just decoration 3 — The Hurricane Watch Situation Class got canceled due to a hurricane watch, which means tonight’s turning into a full grind session that wasn’t originally on the calendar. Silver lining of a weather delay, I suppose. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one getting a bonus grind night courtesy of a hurricane watch. Q: Is podcast mode close to done? A: In progress, this devlog’s the early build phase, not the finish line. Q: What was actually wrong with the randomizer before? A: It existed but didn’t meaningfully help pick songs — more decorative than functional. Fixed to actually aid selection now. Q: Is Song Wars rework from devlog #40 still going? A: Ongoing, this devlog’s focus shifted to podcast mode and the randomizer instead. Q: Stay safe with the hurricane watch, by the way. A: Appreciated. Staying inside, staying coding. —This is the end*— *end for now, hurricane watches permitting POOL!!!"}, {"post_id": 64588, "ts": "2026-09-09T03:01:20Z", "hours": 10.0, "text": "Spectralis devlog #40 —Hello again proggers— 10 straight hours, and the highlight is getting tricked by Suno’s own scraper path. There was a decoy path that looked exactly like the real music endpoint, and it just returned forbidden the whole time. Maybe I’m the bot in this scenario. Unclear. got outsmarted by a decoy URL, humbling Cat or dog? 403 Forbidden Okay let’s get into it~ —Yap— Continuing the reverse-engineering grind from devlog #39, Suno specifically threw a curveball this round. Beyond that, spent real time thinking about what the app actually is and why certain features exist, plus started tearing into Song Wars, which has apparently been quietly buggy for a while. —The Great Suffering— 1 — The Suno Decoy Path Suno provides a path that looks exactly like the real music endpoint, structurally identical, right down to how it responds at a glance. In reality it just returns forbidden every time. Spent real time thinking this was progress before realizing it was a dead end dressed up as a working one. maybe im the bot 2 — Actually Fixed It, After Testing Once the decoy was identified for what it was, found the real path and got it working properly. Testing it thoroughly this time before calling it done, given how devlog #39 went. 3 — Identity Of The App Spent real time thinking through what Spectralis actually is at this point, and justifying why certain features exist rather than just accumulating them because they seemed cool at the time. Less code, more “why does this exist and does it still make sense.” 4 — Song Wars Rework, Started Started tearing into Song Wars, which turns out to be hella buggy underneath. Early stages of a rework rather than a patch job, since patching individual bugs in it hasn’t been holding up. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who got fooled by a decoy API path for a while. Q: Was the Suno issue related to the S3 discovery from devlog #38? A: Same general integration, different specific obstacle this round. Q: Is Song Wars getting a full rewrite or just fixes? A: Leaning toward a real rework rather than more patches, given how buggy it’s turned out to be. Q: What does “identity of the app” work actually produce? A: Not code directly — more a filter for which features actually belong and why, going forward. Q: How’s the 10 hour grind treating you? A: Productive despite the decoy detour. Real progress by the end of it. —This is the end*— *end for now, decoy paths permitting PAP!!!"}, {"post_id": 64321, "ts": "2026-09-08T16:38:31Z", "hours": 11.5997, "text": "Spectralis devlog #39 —Hello again proggers— All-nighter, running on 3 Monsters and a Coke Zero. Reverse engineering APIs is hard as hell, and untitled.stream in particular fought back the whole way. Also snuck in a fix for a Spotify library issue on the side. 3 Monsters and a Coke Zero is not a nutrition plan, it’s a battle strategy Cat or dog? 429 Too Many Requests Okay let’s get into it~ —Yap— Following up on devlog #38’s untitled.stream compat work — turns out “working on it” undersold how hard it actually was. Genuinely brutal reverse engineering session, plus a smaller fix that came out of the same stretch of work. —The Great Suffering— 1 — untitled.stream Was Particularly Hard To Crack Chasing this compatibility since devlog #38, and it turned out to be one of the harder reverse-engineering targets yet. No public API to lean on, so it was the usual slow grind of observing behavior and piecing together how it actually works under the hood. some APIs give up easy, this was not one of them 2 — Reverse Engineering APIs In General: Still Hard Not a new lesson given devlog #17’s whole saga, but worth restating: this category of work is consistently the hardest and slowest kind on the whole project. Going in with better patience and verification habits this time though, which helped. 3 — Spotify Library Polling, Increased Bumped how often libraries get polled to account for some Spotify-side issues that were surfacing. Smaller fix, but a real one, found and shipped in the same session. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who ran on three energy drinks to crack one integration. Q: Is untitled.stream compat actually working now? A: Meaningfully further along after this session, following up from devlog #38’s start on it. Q: Did this go better than devlog #17’s reverse-engineering disaster? A: Yes — hard and slow, but productive this time rather than a total dead end. Q: What was the Spotify polling issue specifically? A: Library state getting out of sync too easily — more frequent polling keeps it closer to accurate. Q: Sleep status? A: Same as every other all-nighter devlog. Not great. Worth it this time though. —This is the end*— *end for now, rate limits permitting PIPSQUEAK!!!"}, {"post_id": 64034, "ts": "2026-09-08T05:01:47Z", "hours": 9.5333, "text": "Spectralis devlog #38 —Hello again proggers— Suno’s integration broke after their latest TOS update, so that got fixed. Also added Discord Rich Presence control for capsules, started chasing down a batch of connections that quietly broke or got dropped over time, and picked up a fun trivia fact along the way: Suno apparently hosts on AWS S3. a TOS update breaking an integration, name a more classic story Cat or dog? S3:// Okay let’s get into it~ —Yap— Mixed bag this round: one reactive fix from an external platform change, one genuinely new feature, and the start of a cleanup pass on integrations that have been quietly rotting since whenever they last got touched. —The Great Suffering— 1 — Suno Integration, Fixed Suno’s newest TOS update broke the existing integration. Patched it back up to work with the new terms. Reactive fix, not a fun one, but necessary. 2 — Capsule DRPC Control Real new feature: Spectralis capsules can now control Discord Rich Presence, so a capsule can show custom status while it’s playing instead of the app just showing generic now-playing info. 3 — Chasing Down Broken And Dropped Connections Going through existing integrations that broke with newer updates on the other end, or that got dropped along the way and never revisited — untitled.stream compatibility being one specific example. Working through the backlog of “this used to work” one at a time. 4 — Suno Hosts On AWS S3 Small fun discovery while poking around the integration: Suno’s hosting is on AWS S3. Not actionable, just neat to know. 5 — Looking For New Platforms Actively looking for what to integrate with next. Feedback on what platforms people actually want would genuinely help shape this. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one whose integration broke because someone else updated a TOS page. Q: What’s DRPC? A: Discord Rich Presence — the status shown under someone’s name in Discord. Capsules can now set custom status through it. Q: What’s untitled.stream compat about? A: One of the connections that broke or got left behind at some point — being actively worked back into shape. Q: What platforms are being considered for new integration? A: Not decided yet, genuinely open to suggestions. Q: Was the Suno fix hard? A: Not conceptually, just annoying — an external change forcing reactive work instead of planned work. Q: What’s the image order now? A: Changed my mind again — meme first, app screenshot second this time. The devlog #37 order didn’t stick. —This is the end*— *end for now, TOS updates permitting POP!!!"}, {"post_id": 63804, "ts": "2026-09-07T19:28:07Z", "hours": 15.4, "text": "Spectralis devlog #37 —Hello again proggers— Working through the feedback wave from the ship, including an upcoming maybe-new streaming service integration. Reverse engineering, again, yay. Also completely forgot Hackclub’s 10 hour limit was a thing and ran 5 hours over it. It’s fine. Everything’s fine. last time reverse engineering a streaming service ate 12 hours and produced nothing, so this is either growth or déjà vu Cat or dog? HKEY_LOCAL_MACHINE Okay let’s get into it~ —Yap— Post-ship feedback turned into real changes fast, and one of them’s a streaming service integration that’s back to reverse-engineering territory — hopefully with better luck than the devlog #17 saga. Also, format note: switching up how devlogs get posted going forward. —The Great Suffering— 1 — Maybe New Streaming Service Support Working on possible support for another streaming service, and since it doesn’t have a public API either, that means reverse engineering again. Learned some hard lessons from devlog #17’s all-nighter about this exact kind of work, applying them here — verifying before implementing, checking whether something’s already patched before sinking hours into it. 2 — 15 Hours, Not 10 Completely lost track of Hackclub’s 10 hour session limit and blew past it by 5 hours. Not the plan, happened anyway, no regrets loud enough to stop it from happening again probably. time limits are more of a guideline when you’re mid-flow 3 — A Format Change, By Request People like the meme format but keep asking to actually see the project itself, which is fair — problem is most of what’s happening is engine work, and a screenshot of raw code just doesn’t communicate much on its own. Going to try posting an actual screenshot as the first image and keep the meme as the second, going forward. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who just blew past a 10 hour limit by half again as much. Q: Is this streaming integration going to end like devlog #17’s did? A: Hoping not — going in more carefully this time given how that one went. Q: Why not just show code screenshots if people want to see the project? A: Raw engine code doesn’t communicate much visually to most people. Trying to find screenshots that actually show something meaningful instead. Q: Will the meme format go away? A: No, staying as image two. Just adding an actual project screenshot as image one. Q: How’s the feedback wave going overall? A: Productive, this streaming service idea being one direct result of it. —This is the end*— *end for now, session limits permitting POSSIBLE!!!"}, {"post_id": 62666, "ts": "2026-09-06T04:36:39Z", "hours": 9.8669, "text": "Spectralis devlog #36 —Hello again proggers— Last log before 6.0.1 tries to ship to everyone. Except Mac, remember? If anyone — and by anyone I mean basically no one — has the app downloaded already, you should see the update land fairly soon. “anyone” carrying a lot of self-deprecation in that sentence Cat or dog? v6.0.1 Okay let’s get into it~ —Yap— Four things landing in this round: video export from devlog #35 finally patched back in properly, the about page expanded, a real EQ upgrade, and more webview bugs cleared out. Then it’s out the door. —The Great Suffering— 1 — Video Export, Actually Patched In Announced back in devlog #35, and this round it’s actually working and patched into the build for real instead of just existing as a headline feature nobody could touch yet. 2 — About Page, Expanded Grew the about page out — more actual content instead of the bare-minimum version it’s had this whole time. 3 — A Far More Advanced EQ System Real upgrade here: new EQ with envelope styling and a handful of presets. Meaningfully more capable than whatever was there before, for anyone who actually cares about shaping their sound instead of just hitting play. 4 — More Webview Bugs, Patched Following the WebView2Host fast-path fix from devlog #9, a few more webview-related bugs got cleared out this round. Apparently that surface keeps finding new ways to misbehave. webview bugs are the gift that keeps on giving 5 — 6.0.1 Ships, Mac Excluded (Still) Same LTS-only policy from devlog #32 applies — Mac isn’t getting 6.0.1 as a minor. Everyone else should see the update land soon. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one about to auto-update basically no one to 6.0.1. Q: Why doesn’t Mac get 6.0.1? A: Same policy from devlog #32 — Mac only gets LTS releases, not minors, unless it’s a Mac-specific patch. Q: What’s new in the EQ system specifically? A: Envelope styling plus a set of presets, a real step up from the previous version. Q: Is video export from devlog #35 fully working now? A: Yes, patched in properly this round. Q: When does 6.0.1 land? A: Fairly soon, per this devlog, for anyone who already has the app installed. —This is the end*— *end for now, update pushes permitting PEBBLE!!!"}, {"post_id": 62302, "ts": "2026-09-05T16:34:34Z", "hours": 9.5667, "text": "Spectralis devlog #35 —Hello again proggers— Long way from v5.3.0, that’s for sure. New ship’s cooking, and it’s built directly off the feedback wave from devlog #33 — took what came in and actually built more on top of it. Also, the big one this round: video export is here. 35 devlogs from “last ship” to this Cat or dog? .mp4 Okay let’s get into it~ —Yap— This one’s a real feedback-driven ship, not just internal roadmap stuff. Fed reports and requests all the way back from devlog #2’s post-first-ship feedback into the app, and video export was the headline addition that came out of it. —The Great Suffering— 1 — Feedback Actually Became Features Everything that came in since devlog #2, right after the very first ship, finally got folded back into this release, not just patched as bugs but expanded into more app. Real loop from “here’s what’s wrong/missing” way back then to “here’s it, fixed and built out” now. 2 — Video Export Is Here For music makers who want something to post — YouTube, Klipy, wherever you’re posting cool stuff — Spectralis can now export video directly instead of just playing audio and visualizers live. Been a long time coming given how much the visualizer/capsule work has built up across devlogs #7, #18, #23, and #29-#30. 3 — This Is The New Ship, Not The Finished One Announcing the direction this round more than closing it out — the surprise from devlog #33/#34 still rides along on this too. Full picture coming as it actually ships. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who just got a whole export pipeline for their trouble. Q: What can video export actually do? A: Exports your visualizer/capsule output as an actual video file, suited for posting to platforms like YouTube or Klipy. Q: Is this the same ship as the Stardance surprise from devlog #34? A: Same overall release window, yes. Q: How much of this came directly from user feedback? A: A meaningful chunk — some of it going all the way back to devlog #2, right after the very first ship. Q: When’s it actually dropping? A: Still in progress. This is the announcement, not the release. —This is the end*— *end for now, export pipelines permitting PS: couldn’t find a good meme this time, so you get corporate gif slop instead. Enjoy. PICKLE!!!"}, {"post_id": 61350, "ts": "2026-09-04T07:08:42Z", "hours": 7.2333, "text": "Spectralis devlog #34 —Hello again proggers— Still on the devlog commits grind. The surprise from devlog #33 is actually finished now, releasing alongside the next Stardance ship as soon as this current one clears. Meanwhile, spent this round scouring the app for small edge cases and UI stuff that’s been quietly overlooked. the surprise is done, the suspense is not Cat or dog? edge_case.md Okay let’s get into it~ —Yap— Two tracks this devlog: the surprise from last time is locked and ready, waiting on the current ship to clear before it goes out with Stardance. In the meantime, doing a proper sweep for the small stuff — edge cases and UI rough edges that don’t show up unless you’re specifically hunting for them. —The Great Suffering— 1 — The Surprise Is Finished Whatever it is, it’s done. Releasing with the next Stardance ship, not this current one — has to clear first. Still not saying what it is. still not telling you, patience 2 — Scouring For Edge Cases Going through the app specifically looking for edge cases that got missed during normal feature work — the inputs and states nobody thinks to test until something breaks in a very specific, very rare way. 3 — UI Stuff That Got Overlooked Alongside the edge cases, hunting down small UI issues that slipped through — spacing, alignment, states that don’t look quite right, the stuff that’s easy to miss when you’re heads-down building instead of using the app like a regular person would. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one hunting edge cases nobody else would think to try. Q: What’s the surprise? A: Patience, my dear child. Q: Why wait for the current ship to clear first? A: Cleaner to let one release settle before stacking the surprise onto the next one. Q: Any specific edge cases found yet? A: Sweep’s ongoing, nothing dramatic enough to call out individually yet. Q: Still not saying what the surprise is? A: Correct. Ask again next devlog. —This is the end*— *end for now, edge cases permitting PERISHABLE!!!"}, {"post_id": 60763, "ts": "2026-09-03T11:03:52Z", "hours": 5.8667, "text": "Spectralis devlog #33 —Hello again proggers— First real wave of feedback since Mac shipped in devlog #32, and it’s been genuinely good. Patching a handful of bugs people actually pointed out, plus one quick clarification for a specific rater who had a question. real users, real feedback, feels different from testing solo Cat or dog? feedback.md Okay let’s get into it~ —Yap— Shipping to actual people instead of just self-testing changes the kind of bugs that surface. Round of patches based directly on what came in, plus a couple of housekeeping notes. —The Great Suffering— 1 — Real Feedback, First Time At This Scale Genuinely solid feedback wave since the Mac release. Different flavor of bug reports than internal testing ever produces — actual usage patterns finding things a solo QA pass wouldn’t. 2 — Patching What Got Pointed Out Working through the specific bugs raised by that feedback. Direct fixes for direct reports, exactly the kind of loop that’s supposed to happen once something’s actually in people’s hands. 3 — Quick Note For A Specific Rater One rater asked about the track used in devlog #1 — it’s a custom remix of “Delete” by Ninjirachi. DM if you want the file. 4 — How To Reach Out For anyone hitting issues with the app: Slack works, or Discord at @deltav0rtex . Genuinely want the reports, keep them coming. 5 — A Surprise Is Coming Next Ship Got something tucked away for the next release that should land well. Not spoiling it here, staying quiet on purpose. Minor patch for this round’s QoL fixes drops within the next two days. teasing it and saying nothing else, that’s the whole bit —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one actually reading feedback instead of guessing what’s broken. Q: How do I report a bug? A: Slack, or Discord — @deltav0rtex . Q: What was that track in devlog #1? A: A custom remix of “Delete” by Ninjirachi. DM for the file if you want it. Q: Is the current bug list from this feedback wave big? A: Manageable, working through it directly rather than batching for a bigger release. Q: Any plans to formalize a feedback/bug channel later? A: Not stated yet, current setup is DMs and Slack for now. Q: What’s the surprise for next ship? A: Not saying. That’s the point of a surprise. Q: When’s the minor QoL patch dropping? A: Within the next two days. —This is the end*— *end for now, bug reports permitting PARABLE!!!"}, {"post_id": 60643, "ts": "2026-09-03T04:06:16Z", "hours": 3.4, "text": "Spectralis devlog #32 —Hello again proggers— Mac’s out. Actually out, actually available, actually done. Took way longer than expected — the site needed updating and every single update script needed fixing before this could actually go out the door clean. “we got mac out” undersells how much site and script work that actually took Cat or dog? .pkg Okay let’s get into it~ —Yap— Closing the loop that started way back in devlog #19 with a borrowed Mac and a hopeful “fingers crossed,” went through the decoding fixes in devlog #28, the platform-assumption hotfix in devlog #26, and now it’s actually shipped. Quick policy reminder while we’re here, since it matters going forward. —The Great Suffering— 1 — The Site Needed Updating First Before Mac could actually go out, the site itself needed real updates to reflect it — new download option, new platform messaging, none of which existed yet. Took a real chunk of the time this release ate. 2 — Every Update Script Needed Fixing Following up on the Windows/Linux-centric script assumptions caught back in devlog #26 — turns out that wasn’t a one-off fix, it touched update scripts broadly. Had to go through and fix them properly for Mac to actually be able to update itself going forward, not just install once. 3 — Mac Is Actually Out After all of that: it’s live. Full journey from borrowed hardware sessions to an actual public release. 4 — Reminder: Mac Only Gets LTS Quick policy note, stated plainly since it matters: Mac only receives LTS releases going forward, not minor updates, unless a minor is a Mac-specific patch. Same access-constraint reasoning from devlog #19 — this isn’t changing anytime soon, so setting the expectation clearly now. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who just found out “ship Mac” secretly meant “rebuild the update pipeline.” Q: Does Mac get every LTS release? A: Yes, every LTS. Just not the minors in between, unless that minor is Mac-specific. Q: Why not give Mac full parity now that it’s out? A: Hardware access is still the bottleneck — same reasoning as devlog #19, testing and building for Mac isn’t a routine, always-available thing yet. Q: What took so long between the decoding fixes in devlog #28 and now? A: Mostly the site and update script work described above — the actual build was closer to ready than the delivery pipeline around it was. Q: Is this the end of the Mac saga? A: The release side, yes. Ongoing maintenance is just going to follow the LTS-only cadence from here. —This is the end*— *end for now, update scripts permitting POP!!!"}, {"post_id": 59211, "ts": "2026-08-31T21:37:18Z", "hours": 9.9, "text": "Spectralis devlog #31 —Hello again proggers— More QoL, a real bug fixed in world editing, and a proper in-depth test run of the whole thing. Honest verdict after actually using it for real: still sucks, still hate it, but it’s at least somewhat usable now. Progress, technically. “somewhat usable” is a real milestone when you started from “actively bad” Cat or dog? node.isCorrupt Okay let’s get into it~ —Yap— World editing’s been the newer, rougher part of the studio since the Godot-inspired redesign in devlog #29. This round was about actually running it through its paces instead of just building on top of it, and that testing found a real problem. —The Great Suffering— 1 — More QoL Another pass of small quality-of-life improvements, continuing the trend from the last couple devlogs. Nothing individually huge, all of it adds up. 2 — The Bad Node Bug Found and fixed a genuinely bad node bug in the world section during testing. The kind of bug that only shows up once you’re actually building real worlds instead of poking at an empty editor. 3 — The In-Depth Test Run Took world editing for a real, thorough run this time instead of a quick sanity check. Built something with actual substance in it and used the tool the way it’s meant to be used. 4 — The Honest Verdict Still sucks. Still hate using it. But after this round of fixes and QoL, it’s crossed into “somewhat usable” territory, which is more than could be said before this session. low bar, cleared, moving on —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who just admitted their own tool still sucks and shipped it anyway. Q: Is world editing done now? A: No, “somewhat usable” is the current state, not “finished.” More work ahead. Q: How bad was the node bug? A: Bad enough to matter, found through actual real-world testing rather than a quick check. Q: Is this related to the layer work from devlog #30? A: Different area — that was capsules/timeline, this is world editing specifically. Q: What’s the plan to make world editing not suck? A: Keep testing it for real, keep fixing what that testing turns up. This devlog’s the start of that loop, not the end. —This is the end*— *end for now, corrupted nodes permitting PAPLE!!!"}, {"post_id": 58336, "ts": "2026-08-30T18:33:09Z", "hours": 9.3333, "text": "Spectralis devlog #30 —Hello again proggers— Following up on the studio redesign from last devlog — actually building inside that new layer system now. Lyric importer, a bezier tool that fought back the whole way, and capsules jumped to full HD. 30 devlogs in and the bezier tool still almost won Cat or dog? bezier.controlPoint Okay let’s get into it~ —Yap— Layers from devlog #29’s redesign got real functionality built on top of them this round, plus a genuinely useful new import path and a resolution bump that should’ve probably happened earlier. —The Great Suffering— 1 — Layer Fixes Cleaned up a handful of issues in the new After Effects-style layer system from last devlog — the kind of rough edges that only show up once you’re actually building real content in it instead of just looking at the layout. 2 — Lyric Importer: Auto Vector Layers + Keyframing New importer that takes lyric timing and automatically generates vector layers, keyframed to match. Turns what used to be manual layer-by-layer, keyframe-by-keyframe setup into an actual import step. Big time save for anything lyric-driven, including future capsules like the demo from devlog #18. 3 — A Few More Bugs, Squashed Small round of additional fixes alongside the bigger items, nothing individually dramatic. 4 — Capsule Resolution: Bumped To Full HD Capsules render at full HD now instead of whatever lower resolution they were capped at before. Straightforward upgrade, noticeably better output. 5 — The Bezier Tool (Which Was Hell) Added a real bezier curve tool to the timeline/layer editing. Genuinely brutal to get right — curve math, control point handling, and making it feel intuitive to actually drag are three different hard problems stacked on top of each other. Worth it, but it fought back the whole way. bezier curves: simple in theory, a nightmare in an actual editor UI 6 — Timeline And Tool QoL Assorted quality-of-life improvements across the timeline and tools generally — the small friction-reduction stuff that adds up once you’re using the studio for real work instead of just testing it. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who just fought a bezier tool and mostly won. Q: Does the lyric importer work with the demo capsule from devlog #18? A: That one was hand-timed and hand-built before this importer existed — this tool’s for making the next ones faster. Q: Why was the bezier tool specifically so hard? A: Curve math, control point interaction, and UI feel all had to work together, and getting any one of them wrong makes the whole tool feel broken. Q: Is full HD the resolution ceiling now, or is higher coming later? A: Full HD is what shipped this round. No commitment yet on going higher. Q: Is the studio redesign from devlog #29 basically done now? A: Getting real functionality built on it, which is a good sign, but still ongoing. —This is the end*— *end for now, control points permitting PALPABLE!!!"}, {"post_id": 57958, "ts": "2026-08-30T09:12:42Z", "hours": 9.7667, "text": "Spectralis devlog #29 —Hello again proggers— The studio’s finally looking like a real UI tool instead of a collection of windows held together by vibes. Two design references pulled this round: Godot for world editing, and Adobe After Effects for capsules. stealing good ideas from great tools is called “design research,” look it up Cat or dog? Ctrl+Shift+F Okay let’s get into it~ —Yap— Studio’s been the least polished part of the whole app for a while, mostly functional, rarely pretty. This round actually leaned into real interface design instead of just adding buttons where they fit, borrowing structure from two tools that already solved similar problems well. —The Great Suffering— 1 — Godot-Inspired World Editing World editing took cues from Godot’s editor layout — the way it structures a scene tree, viewport, and inspector panel together as one coherent workspace instead of scattered windows. Applying that same structural thinking to world editing here, since worlds are conceptually similar: a tree of pieces you’re arranging in space. 2 — After Effects-Inspired Capsules Capsule editing leaned on After Effects instead, specifically the layer/timeline/composition mental model. Capsules are time-based and layered by nature — a story surface, a visualizer, audio all stacked together — so a timeline-and-layers metaphor fits better than a flat property list ever did. 3 — The Studio Finally Feels Like A Tool Combined, these two reference points are what’s pushing the studio from “internal dev utility” toward something that actually feels designed for someone to sit down and use, not just something built incrementally to unblock whatever feature needed it that week. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one borrowing UI patterns from two very different but very good tools. Q: Is this a full rewrite of the studio UI? A: More a restructuring around better mental models than a ground-up rebuild, but it touches a lot of surface area. Q: Why Godot for world editing specifically? A: Scene/viewport/inspector is a well-worn pattern for spatial editing, and worlds are fundamentally a spatial arrangement problem. Q: Why After Effects for capsules? A: Capsules stack time-based layers — story, visualizer, audio — which maps naturally onto a timeline/layers workflow instead of flat settings. Q: Does this connect to the visualizer toolkit grind from devlogs #25-#27? A: Same broader authoring-tools push, yes, this is the UI side catching up to that work. —This is the end*— *end for now, layer panels permitting POP!!!"}, {"post_id": 57408, "ts": "2026-08-29T15:34:29Z", "hours": 8.4333, "text": "Spectralis devlog #28 —Hello again proggers— LTS 6 is out. Genuinely out, not “shipped to nowhere” out like devlog #11. Sleep deprivation’s fully caught up though — first chance I get, I’m passing out on the couch with the cat and that’s non-negotiable at this point. the cat’s getting a co-author credit at this rate Cat or dog? couch, specifically, with the cat, immediately Okay let’s get into it~ —Yap— Long stretch from devlog #26 through here finally paid off. LTS 6 pushed, and the major macOS decoding problems from the borrowed-Mac build sessions actually got fixed. Real progress, real exhaustion, both at once. —The Great Suffering— 1 — LTS 6 Is Out Following the hydra-bug fight in devlog #20, the Electron relearn and Mac hotfix in #26, and the binary format detour in #27 — it’s actually pushed now. Linux and Windows builds are the ones going out first. 2 — Major macOS Decoding Problems, Fixed Following up on the platform-assumption bug from devlog #26, where Windows/Linux-centric scripts choked on Mac being neither — dug into the actual decoding issues on macOS and got the major ones resolved this round. 3 — Mac Release Is Coming, Just Not Today No Mac hardware access again until Monday, so the macOS build follows a bit after Linux/Windows instead of dropping same-day. Same access constraint from devlog #19, still the bottleneck, still the plan. 4 — Sleep Is Winning Officially out of gas. Couch, cat, first available window. This devlog is basically the victory lap before collapsing. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one about to lose consciousness on a couch next to a cat, mission accomplished. Q: Is LTS 6 out for everyone right now? A: Linux and Windows, yes. macOS is coming shortly after once Mac access is available again Monday. Q: Were the macOS decoding problems from the script issue in devlog #26? A: Related territory, yes — once the platform-assumption bug got flagged, the deeper decoding issues underneath it got found and fixed too. Q: Any concerns going into the Mac release specifically? A: Nothing unresolved as of this devlog, but access is still limited to occasional sessions, so timing’s dependent on that. Q: What’s next after this? A: Sleep. Genuinely, actually sleep, before anything else touches this project. —This is the end*— *end for now, couch naps permitting thud Zzzzzz!!!"}, {"post_id": 56861, "ts": "2026-08-28T20:36:45Z", "hours": 9.3, "text": "Spectralis devlog #27 —Hello again proggers— Still going. Decided mid-grind to switch off JSON-based saving entirely and move to a proper binary streamed format instead — faster save/load, way less CPU overhead. Which sounds like a clean upgrade until you realize it means reading books on binary format design that were probably written before I was. my caffeine and my reading list have diverged wildly tonight Cat or dog? BinaryWriter Okay let’s get into it~ —Yap— The pivot away from JSON wasn’t planned going into tonight, it just became obviously worth it partway through the toolkit grind. Now stuck in the part of the process nobody enjoys: documentation, theory, and CS ideation before any of the actual implementation gets to happen. —The Great Suffering— 1 — JSON’s Getting Replaced Moving off JSON-based saving to a binary streamed format. The reasoning’s simple — faster save/load, meaningfully less CPU usage — but simple reasoning doesn’t mean simple implementation. 2 — Reading Books Older Than Me Digging into binary streaming format theory means reading material that predates this whole project by a wide margin, some of it by a lot more than that. Foundational stuff, just not exactly light reading at this hour. 3 — Documentation And Theory Hell Currently deep in the least glamorous part of any format redesign: reading documentation, working through theory, and CS ideation before writing a single line that actually does anything. Necessary, still miserable at 2am. the implementation is the fun part and it’s still hours away 4 — Sun Came Up, Had A Sandwich, Kept Going Watched the sunrise somewhere in the middle of the theory reading. Had an egg and bacon sandwich for breakfast, genuinely delicious, best part of the night so far. No sleep planned until tonight — just powering through on breakfast fuel instead. breakfast during an all-nighter hits different —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one reading format-design theory older than their own project at 2am. Q: Why move off JSON now, mid-grind? A: Became clear it was the right call while working on the visualizer toolkit — better performance characteristics were worth the detour. Q: Is this related to the toolkit from devlog #25/#26? A: Same overall session, this is a scope addition that came up while working on it. Q: When does actual implementation start? A: Once the theory and documentation phase actually resolves. Not there yet. Q: Is tonight ever going to end? A: Not until tonight, apparently — sun’s already up and there’s no sleep planned before then. —This is the end*— *end for now, binary formats permitting PAM!!!"}, {"post_id": 56521, "ts": "2026-08-28T10:00:04Z", "hours": 2.9008, "text": "Spectralis devlog #26 —Hello again proggers— Still grinding the visualizer toolkit from devlog #25. Fueled up properly this time — favorite tunes on, Coke Zero and a Monster Ultra on deck, going the entire night. Also, small detour: past me apparently gave in and used Electron at some point, so present me now has to relearn it from scratch. past me makes decisions present me has to live with, name a more accurate description of software Cat or dog? require(‘electron’) Okay let’s get into it~ —Yap— Two threads tonight: the toolkit grind continuing from last devlog, and a genuinely surprising discovery on the Mac build front that’s going to need its own hotfix branch. —The Great Suffering— 1 — Relearning Electron Past-me committed to Electron somewhere along the way and current-me forgot most of it. Spending part of tonight just getting back up to speed on something that used to be second nature. Annoying, but at least it’s a known quantity once it clicks back in. 2 — The Toolkit, Still Grinding Same visualizer toolkit as devlog #25. Not done yet, but the night’s young and there’s caffeine involved. Hoping to actually close real ground on it before LTS needs to be ready. 3 — Mac Build Actually Compiles Now Following up on devlog #19’s borrowed-Mac session — got it to build and compile this time. Real progress on a front that’s been genuinely hardware-constrained the whole way. 4 — Turns Out Mac Isn’t Windows Or Linux (Shocking, I Know) Here’s the surprising part: a lot of the build scripts turned out to be Windows/Linux-centric, and Mac is, in fact, neither of those operating systems. Somehow this wasn’t obvious until actually staring at a failing script on real Mac hardware. three major desktop OSes and somehow I only accounted for two of them 5 — Hotfix Branch Incoming Need to spin up a hotfix specifically for the platform-assumption problem in the scripts, and hoping it merges back clean without conflicts. Given tonight’s track record so far, cautiously optimistic. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who forgot their own framework choice from past-self. Q: Why Electron in the first place? A: Decision from before this devlog series apparently, reasons unclear at this hour, dealing with the consequences now regardless. Q: Is the Mac hotfix urgent? A: Ties directly into whether LTS with Mac support actually holds together, so yes, fairly urgent. Q: Was assuming Windows/Linux-only scripts really a mistake nobody caught until now? A: Apparently so. Borrowed-Mac hardware access from devlog #19 finally exposed it. Q: Toolkit status vs. hotfix status tonight — which wins? A: Whichever gets further before the caffeine runs out. Probably both get some progress. —This is the end*— *end for now, merge conflicts permitting PROPER!!!"}, {"post_id": 55615, "ts": "2026-08-27T16:05:39Z", "hours": 9.3964, "text": "Spectralis devlog #25 —Hello again proggers— Short one, I’m about to pass out for real this time. Ground away at the visualizer toolkit for a long stretch and it’s still nowhere near done. another one for the “not as close as I thought” pile Cat or dog? too tired to pick one honestly Okay quick version~ —Yap— Same visualizer editor territory from devlog #23, except the format not-changing this time didn’t mean the finish line got any closer. Long grind, real progress somewhere in there probably, just not a done toolkit at the end of it. —The Great Suffering— 1 — The Toolkit Isn’t Close Put in a long stretch on it and it’s genuinely still far from finished. Not a small gap either, just more scope than one exhausted session could close. 2 — I’m Cooked That’s the whole update. No dramatic bug story tonight, just hours in and not enough left to keep going. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who should probably close the laptop now. Q: Is this the same visualizer editor from devlog #23? A: Same one. Still cooking, longer than expected. Q: Any specific blockers? A: Too tired to write them up properly tonight. Next devlog, probably, once there’s actual sleep behind it. Q: When’s it landing? A: Unknown. Not this session. —This is the end*— *end for now, actually sleeping this time POOL!!!"}, {"post_id": 55404, "ts": "2026-08-27T06:36:57Z", "hours": 2.3342, "text": "Spectralis devlog #24 —Hello again proggers— Rewrote the README a third time. Not because it was wrong, because proper prose and actual formatting apparently reads as “completely AI” to whoever’s judging it, and I’m too burnt out to keep arguing that point. So it just got redone instead. can’t fight the vibes, can only rewrite around them Cat or dog? README.md Okay let’s get into it~ —Yap— Small win buried in the exhaustion: website’s on version 4 now and it didn’t get flagged this time. First one that made it through clean since devlog #21 started this whole saga. Progress, even if the README’s now on its third rewrite for reasons that have nothing to do with whether it’s actually good. —The Great Suffering— 1 — README Rewrite #3 Same content, restructured again, because well-formatted prose keeps getting read as an AI tell regardless of who wrote it or how. Not going to keep relitigating this one, just redid it and moved on. 2 — Website v4 Survived The actual good news. Fourth pass on the site, first one that didn’t get flagged. Whatever combination of changes from devlog #21 onward finally landed right. 3 — Hoping The App Gets Checked Next If the docs and the website keep clearing review, maybe eventually the actual app gets looked at instead of just the surface-level stuff around it. That’s the real hope here — less time defending prose formatting, more time on the thing that actually matters. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one whose actual writing keeps getting mistaken for a machine’s. Q: Why does formatted prose get flagged as AI? A: Genuinely unclear, and at this point not worth the energy to keep contesting. Rewriting around it was faster than arguing it. Q: Is this the fourth full website redesign? A: Yes — devlog #14, then #21’s rework, and now this pass, landing clean. Q: Has the app itself ever been flagged? A: Not yet, and that’s sort of the point of this devlog — hoping it stays that way, or at least gets a fair look if it comes up. Q: How’s the burnout? A: Present. Noted. Continuing anyway. —This is the end*— *end for now, formatting opinions permitting PEEL!!!"}, {"post_id": 55123, "ts": "2026-08-26T16:10:50Z", "hours": 2.6669, "text": "Spectralis devlog #23 —Hello again proggers— Introducing the visualizer editor. Been sitting on this one for a while without announcing it, for a very specific reason: every single time it felt ready, the format changed again and “ready” moved further away. Think it’s actually real this time. announced it in my head about six times before this devlog Cat or dog? visualizer.format Okay let’s get into it~ —Yap— Grinding all night on this one, branch and v1 dropping tomorrow. No promises beyond that, just the plan and the fact that this has been quietly cooking for way longer than any single devlog has let on. —The Great Suffering— 1 — Why This Wasn’t Announced Sooner Kept hitting the point where the editor felt done, then rethinking the underlying format and starting that part over. Easier to just not announce something that keeps changing shape than to keep walking back a “it’s ready” claim in public. 2 — v1 And The Branch, Tomorrow Committing to it now — v1 and the branch land tomorrow. Whole night’s going toward getting there, which given the last 22 devlogs of this project is either a great sign or a very familiar warning sign. history suggests: could go either way 3 — What The Visualizer Editor Actually Is A real editor for building visualizers instead of the visualizer side of the app staying built-in-only. Ties back to everything from the capsule/worlds work in devlogs #7 and #8 and the custom visualizer built for the demo capsule in devlog #18 — this is the tool version of doing that by hand. 4 — Hackatime Also Just Died (Or My PC Did) On top of everything else, Hackatime seems to be down, or my PC’s cooked, unclear which yet. Either way tracked hours for tonight are now undefined. Yipee. unlogged hours are the best kind of hours, said nobody’s time tracker ever —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one about to pull yet another all-nighter for a feature reveal. Q: Why did the format keep changing? A: Each pass revealed a new limitation once actually used for real, and fixing that meant reworking the format again rather than shipping something known to be wrong. Q: Is this related to the demo capsule visualizer from devlog #18? A: Same territory. That one was hand-built. This is the editor meant to make building one not require doing it by hand. Q: What’s “v1” mean here specifically? A: First real usable version, branch-only for now, not a full public release yet. Q: Any risk this slips again? A: Always possible given the track record, but committing to tomorrow specifically this time. —This is the end*— *end for now, format stability permitting PEPLE!!!"}, {"post_id": 54323, "ts": "2026-08-25T08:40:49Z", "hours": 4.6333, "text": "Spectralis devlog #22 —Hello again proggers— Posting this before I pass out for real. And no, that wasn’t me faceplanting the keyboard, that was the cat walking across it. Very important distinction. the cat gets a commit credit for that one, honestly Cat or dog? cat, apparently, tonight specifically Okay let’s get into it~ —Yap— Back on the ever-growing pile of bugs and QoL from devlog #20’s hydra fight — turns out killing all the tiny bugs once doesn’t mean they stay dead forever, more just showed up in the meantime. Made real progress anyway. —The Great Suffering— 1 — A Few Spotify Bugs, Actually Squashed Chased down and fixed a handful of Spotify-side bugs this round. Not a full audit like earlier devlogs, just real ground covered on stuff that’s been sitting in the pile. 2 — Resizing QA Went through resizing behavior across the app and did a real QA pass on it — the kind of thing that’s easy to skip until someone resizes a window in a way you never tested and everything looks wrong. 3 — The Multi-Channel Stream Queue Idea Had the idea to implement multi-channel support for Streamer Queue. Started on it, and it’s genuinely probably too big to land fully before LTS ships — most likely going in as a stub for now rather than a finished feature, with the real implementation following after. “horrible idea” is doing some self-aware lifting there and I stand by it —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who mistook a cat for their own exhaustion, and honestly it could’ve gone either way. Q: What’s a “stub” mean for multi-channel here? A: The scaffolding and interface exist, the real functional implementation doesn’t yet. Placeholder with intent, not a real feature. Q: Is this the same bug pile from devlog #20? A: Same pile, refilled since then. Small bugs apparently regenerate on their own schedule, not just when you’re actively fighting them. Q: Why is multi-channel “horrible” if you’re building it anyway? A: Because scope-wise it’s a lot more than it looks like on paper, and admitting that upfront beats pretending it’s simple. Q: Sleep status tonight? A: About to happen, actually, this time. Cat’s taking the credit either way. —This is the end*— *end for now, sleepy cats permitting PEOPLE!!!"}, {"post_id": 54216, "ts": "2026-08-25T03:14:52Z", "hours": 6.1014, "text": "Spectralis devlog #21 —Hello again proggers— Flagged for “AI website” again. By Shipwrights this time. Getting a little tired of this specific accusation, honestly — a commit log sitting right there would show actual work happening over actual time, but apparently that’s a few extra minutes nobody wants to spend. the receipts exist, nobody’s asking to see them Cat or dog? git log –oneline Okay let’s get into it~ —Yap— Third redesign of the site now. Not because the flag was right, but because if this keeps happening it’s worth just making the “looks AI-made” argument harder to make at all, regardless of whether it was ever a fair read in the first place. —The Great Suffering— 1 — Flagged Again Shipwrights flagged the site as AI-generated. Same accusation as the devlog #12-#14 saga, different flagger this time. Slightly more annoying with each repeat, since the actual work history’s right there for anyone willing to look. 2 — The Annoying Part It’s not that the site got flagged, it’s that the disproof is trivially available — commits, timestamps, iterative changes across three separate rebuilds — and checking that apparently isn’t part of the process. Frustrating, not devastating. 3 — Redesigned It A Third Time Rather than fight the flag directly, changed the site again. Third pass now, and it genuinely reads less like generic AI-slop territory than the last version did. Whether that satisfies the next flag or not, it’s a real improvement on its own merits. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who’s redesigned this website three separate times partly to dodge a false flag. Q: What’s Shipwrights? A: The one doing the flagging this round. Q: Is the flag actually accurate? A: No — there’s a real commit history behind the site across devlogs #12 through #14 and now this one. The flag’s wrong, just annoying to keep disproving. Q: Does this redesign replace the one from devlog #14? A: Yes, third full pass on top of that one. Q: Any plan if it gets flagged a fourth time? A: Probably the same plan: keep the receipts, keep improving the site anyway, move on. —This is the end*— *end for now, false flags permitting PALPABLE!!!"}, {"post_id": 53903, "ts": "2026-08-24T16:41:40Z", "hours": 7.9, "text": "Spectralis devlog #20 —Hello again proggers— Two zero. Milestone devlog, and it’s a good one: LTS is about to actually go out the door, Mac included, today. we made it, barely, on no sleep, as tradition demands Cat or dog? git revert HEAD 7 Okay let’s get into it —Yap— Spent the whole night doing QoL and QA on all the tiny bugs that had been getting pushed aside devlog after devlog. Turns out “small bugs” and “easy to fix” are not the same category, and the whole night proved it the hard way. —The Great Suffering— 1 — Hydra Bugs Every single one of the small deferred bugs got patched, and every single patch spawned about three new ones in its place. Fix one, watch three grow back. Felt less like debugging and more like fighting something with a regeneration mechanic. cut off one head, three more show up, name a more accurate bug report 2 — Tried Claude Code Out Of Exhaustion Got tired enough mid-hydra-fight to set up Claude Code and hand off some of the grind. It did not go well — ended up rearranging the repo and commit layout in ways that made the history a mess, not the bugs. 3 — Had To Undo Its Commits Rolled back what Claude Code did and went back to fixing things manually. Lesson for the night: handing off a messy, deep-in-it repo state to an agent mid-crisis is not the same as handing off a clean one. 4 — Actually Got All The Tiny Bugs Out After all of that, the hydra’s actually dead. Every deferred small bug from the last 19 devlogs finally cleared in one sitting, which is the whole reason today’s release is happening at all. 5 — Mac Release, Today Following up on devlog #19’s borrowed-Mac build attempt — releasing to Mac today alongside everything else. First real payoff from that session. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who fought a hydra of bugs all night and won, barely. Q: Did Claude Code actually break anything functional, or just the repo layout? A: Just history and commit structure, nothing shipped broke because of it. Still a mess worth undoing. Q: Is this LTS build the one from devlog #19’s prep? A: Yes, same one. This was the final QA gauntlet before it goes out. Q: Is Mac really getting it today? A: That’s the plan, following through on the borrowed-Mac build session from last devlog. Q: 20 devlogs in, anything you’d do differently? A: Sleep more, probably. Not going to happen, but it’d be the right answer. —This is the end*— *end for now, hydra heads permitting PROPERTY!!!"}, {"post_id": 53619, "ts": "2026-08-24T08:31:21Z", "hours": 4.2003, "text": "Spectralis devlog #19 —Hello again proggers— v6 LTS is on the horizon. Scheduled time with a friend who actually owns a Tim Cook machine, fingers crossed a Mac build comes out the other side of that session actually working. praying to the WWDC gods Cat or dog? arm64 Okay let’s get into it~ —Yap— First real LTS push. Different mindset than the last 18 devlogs of feature work and 3am bug hunts — LTS means stability first, and it also means finally taking a real swing at macOS instead of leaving it as a someday problem. —The Great Suffering— 1 — Prepping For v6 LTS Getting the groundwork in place for the first Long Term Support build. Less “ship the coolest thing,” more “ship the thing that won’t need constant babysitting after release.” 2 — Borrowing A Friend’s Mac Don’t own a Mac. Scheduled dedicated time with a friend’s actual Apple hardware to attempt a real build instead of guessing blind or fighting a CI-only setup with no way to actually test the output. 3 — The Honest Caveat: Mac Support Will Lag Straight talk: limited access to Mac hardware means Mac builds will very likely only get LTS releases going forward, and will land late relative to betas and regular updates on other platforms. Not ideal, but better to say it now than pretend otherwise. can’t test what you can’t touch —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one borrowing a friend’s Mac because Apple hardware access is not a given. Q: Will Mac users get every update? A: Realistically, no — LTS builds only for the foreseeable future, and later than other platforms. Access to hardware is the bottleneck, not desire to support it. Q: Why prioritize LTS over a beta cycle right now? A: Stability’s the actual goal for v6. Betas can come later once the LTS foundation’s solid. Q: Is the Mac build guaranteed to work this session? A: No promises. That’s what “fingers crossed” means. Q: What happens if the Mac session doesn’t go well? A: Try again next time hardware access lines up. Not giving up on it, just constrained by it. —This is the end*— *end for now, Tim Cook machines permitting PRINCIPLE!!!"}, {"post_id": 53545, "ts": "2026-08-24T04:19:31Z", "hours": 7.8, "text": "Spectralis devlog #18 —Hello again proggers— First real demo capsule is live. Not a screenshot, not a “trust me it works” — an actual .spectralis file you can grab and open yourself, right after devlog #17’s night of nothing. Felt good to ship something that isn’t a revert for once. redemption arc, one demo file at a time Cat or dog? demo.spectralis Okay let’s get into it~ —Yap— Wanted the first public demo to actually show off what a capsule can do, not just be a proof of concept nobody can open. So it’s a full one: real track, real hand-timed lyrics, and a visualizer built specifically for it instead of a generic default. —The Great Suffering— 1 — The Demo’s Live demo.spectralis is up at cdn.deltavdevs.com now. First capsule anyone outside this devlog series can actually download and open. 2 — The Track And The Lyrics Built around Black Coast’s “TRNDSTTR” (Lucian Remix). Lyrics for it were timed and written into the capsule by hand — not pulled from some export, actually sat down and did the timing work myself. 3 — The Visualizer’s Custom, Not A Default Also built the visualizer specifically for this capsule instead of shipping the demo with a stock one. Wanted the first thing people see from Spectralis to actually demonstrate what the capsule format can do end to end — audio, synced lyrics, and a visual built to match, all in one file. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one downloading the first real capsule demo. Q: Where’s the demo? A: cdn.deltavdevs.com/spectralis/demo.spectralis — direct download, no wrapper page. Q: Did you write the lyrics yourself or pull them from somewhere? A: Wrote and timed them in by hand for this capsule specifically. Q: Is the visualizer reusable for other capsules? A: Built for this one specifically, but nothing stopping it from getting adapted or reused as a base for others later. Q: Is this what stories/capsules from devlog #7-#8 were building toward? A: Exactly that. This is the first one actually finished and out in the world instead of just being tested locally. —This is the end*— *end for now, capsule downloads permitting PARODY!!!"}, {"post_id": 53182, "ts": "2026-08-23T16:54:15Z", "hours": 12.2667, "text": "Spectralis devlog #17 —Hello again proggers— 12 hours. All-nighter. Zero sleep. Feature isn’t in the app. Nothing shipped. This is the devlog where I explain what an entire night of work bought me, and the honest answer is “a very expensive lesson.” worth it? absolutely not. did i learn something? also debatable Cat or dog? catch (ApiDoesNotExistException) Okay let’s get into it~ —Yap— Got ambitious. Decided Spectralis should integrate with everything — Pandora, Amazon Music, a bunch of other big platforms on top of what already works. Turns out “everything” includes a lot of services that simply don’t offer a public API to integrate with in the first place, and finding that out was not the fast part of the night. —The Great Suffering— 1 — The APIs Just Don’t Exist Pandora, Amazon Music, and others: no public API to build against. Not “hard to find,” not “poorly documented,” just not there. Should’ve been step zero, ended up being the thing that derailed the entire night once discovered mid-build instead of before starting. 2 — So I Built Backdoors Instead Spent a huge chunk of the 12 hours reverse-engineering and building unofficial access paths instead, since the front door didn’t exist. This is the kind of work that eats hours and produces nothing you can point to until it’s fully working, if it ever gets there. 3 — Most Of Them Were Already Patched Implemented several of these backdoor approaches only to find out the platforms had already closed the exact gaps being exploited, sometimes before the implementation was even finished. Built things that were dead on arrival by the time they existed. patched before i even shipped it, incredible timing 4 — Asked Claude, Got A Hallucinated Answer, Followed It Anyway At the point of giving up, asked for a way to make it work anyway. Got a confident-sounding approach back that didn’t actually correspond to anything real, and followed it blindly instead of verifying it first, because by that point it was hour 10-something and verifying things sounded like more effort than it was. 5 — Ripped The Whole Feature Out End state: none of it works, none of it can work without real API access that doesn’t exist, so the entire feature attempt got stripped back out of the codebase. 12 hours, one commit’s worth of net progress, and that commit is the revert. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who just found out platforms without public APIs stay that way for a reason. Q: Is any of this coming back later? A: Not until there’s an actual, real, non-reverse-engineered way in. Not chasing patched backdoors again. Q: Should you have asked Claude earlier instead of at hour 10? A: Probably. Should also have double-checked what it said instead of following it blind at 4am. Two separate lessons from one night. Q: Was any of the 12 hours useful? A: Now know definitively which platforms are and aren’t worth attempting. That’s the only thing salvaged. Q: Sleep status? A: Catastrophic. Handling that before touching code again. —This is the end*— *end for now, actual sleep permitting Im gonna go pass out on the couch ADIOS!!!"}, {"post_id": 52796, "ts": "2026-08-23T04:27:01Z", "hours": 0.6667, "text": "Spectralis devlog #16 —Hello again proggers— Short one. Found the website pipeline issue from devlog #15. Cat or dog? sudo —Yap— It wasn’t the code. It was permissions. The site was calling root but never actually had access to root, which is exactly why it worked fine locally and fell over the second it hit deployment. “It woRKS On My macHiNe” — the oldest curse in software, and I said it unironically. classic —This is the end*— *end for now, root access permitting PAPAYA!!!"}, {"post_id": 52775, "ts": "2026-08-23T03:46:04Z", "hours": 2.0667, "text": "Spectralis devlog #15 —Hello again proggers— I lied. Posted devlog #14 saying the site was done and shipped, and the deploy pipeline crashed basically the second it went out. So that’s fun. On the bright side, v5.4.2 also went out this round, and it’s actually solid. “it’s done” is apparently my curse word Cat or dog? dequeue() Okay let’s get into it~ —Yap— Website pipeline ate itself right after devlog #14 posted, which is its own kind of poetic. Meanwhile the app side had a genuinely good run — six real fixes landed, one of them embarrassing enough to name directly. —The Great Suffering— 1 — The Website Pipeline Crashed Right After I Said It Shipped Devlog #14 said done. Pipeline said otherwise, immediately. Working on getting it back up, this is very much a “developing situation” and not a “resolved” one yet. 2 — Listener Requests Auto-Queue Now Requests from listeners now auto-queue instead of needing a manual step to actually land in the queue. 3 — Audio Literally Never Played, Whoops Exactly what it says. Somewhere in there, audio just wasn’t playing. Found and fixed, extremely glad this one got caught. a music player where the music doesn’t play is a bold minimalist statement 4 — Found It: Join Links Were Missing A Slash Root cause of a chunk of shared-play join weirdness — the links were missing a slash. One character. Fixed, join links actually resolve correctly now. 5 — Host Room Button Actually Tells You Something Now The host room button used to just sit there. Now it actually communicates state back to you instead of leaving you guessing whether anything happened. 6 — Host Room Was Dropping Every Tick Forever Host room had a bug where it was dropping on every single tick, indefinitely, rather than staying stable. Fixed so the room actually holds instead of degrading in real time. 7 — yt-dlp Was 5 Months Stale, Updated The bundled yt-dlp from devlog #10 hadn’t been touched in 5 months. Updated. Stale extraction tooling breaking silently is exactly the kind of thing that sneaks up on you. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who called the website shipped and got immediately humbled by CI. Q: Is the website back up yet? A: Working on it. Genuinely not resolved as of this devlog. Q: How long was audio actually broken for? A: Not specified, but “literally never played” is about as bad as this category of bug gets. Fixed now. Q: Was the missing-slash bug related to the join link work from devlog #9? A: Yes, same feature area, this was the actual root cause of some of the lingering weirdness there. Q: Is 5.4.2 stable? A: As far as testing shows. Same disclaimer as always applies. —This is the end*— *end for now, deploy pipelines permitting PARABLE!!!"}, {"post_id": 52728, "ts": "2026-08-23T01:43:09Z", "hours": 2.1678, "text": "Spectralis devlog #14 —Hello again proggers— Site’s done. Actually done. Got it to a place I actually liked instead of just a place I was tired of looking at, and shipped it. Three devlogs of fighting the generic-AI-look problem and it finally landed somewhere that feels like Spectralis instead of every other landing page on the internet. took long enough Cat or dog? git push origin main Okay let’s get into it~ —Yap— After devlog #12 and #13’s whole ordeal of everything converging on the same generic design no matter what got tried, something finally clicked and stuck. Shipped it. Two honest confessions on the way out the door, might as well log them here instead of pretending otherwise. —The Great Suffering— 1 — It’s Live The full rework from the last two devlogs is done and pushed. Went from “everything looks like AI made it” to something that actually feels intentional. Whatever finally broke the streak, it worked. 2 — The Help & Manuals Tab Is A Placebo Button Full transparency: the Help & Manuals tab on the site exists, looks real, sits right where you’d expect it, and does essentially nothing right now. It’s there because a site without one looks incomplete, not because there’s real content behind it yet. Consider it a placeholder wearing a real button’s clothes. it’s not lying, it’s aspirational 3 — I Copied FL Studio’s Homepage. Hard. Not going to pretend otherwise: leaned on FL Studio’s site pretty heavily for structure and layout ideas here. And honestly, that’s just how this works — programming, design, all of it is borrowing from people who borrowed from the people before them. Nobody’s inventing layout from first principles in 2026. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who finally shipped a website after three devlogs of fighting it. Q: Is Help & Manuals actually going to do anything eventually? A: Presumably, someday. Right now it’s a promise the button is making on behalf of a future devlog. Q: Isn’t copying FL Studio’s homepage kind of a big deal? A: Structure and layout inspiration, not a straight copy-paste. And realistically, every site borrows from something — this one’s just being honest about the source. Q: Did the “everything looks like AI” problem from devlog #13 actually get solved? A: Yes, finally. Whatever changed between then and now worked. Q: What’s next now that the site’s shipped? A: I finally get to ship my project without worrying about AI looking websites —This is the end*— *end for now, placebo buttons permitting PLACEBO!!!"}, {"post_id": 52690, "ts": "2026-08-22T23:32:19Z", "hours": 10.1028, "text": "Spectralis devlog #13 —Hello again proggers— Still on the website. Turns out the “make it not look like AI made it” problem does not have an easy exit — everything ends up looking like AI made it no matter what gets tried. Also had to ask Claude how to center a div. Yes, that div. The one every developer has fought since the dawn of CSS. the irony of asking an AI how to make something look less AI-made is not lost on me Cat or dog? display: flex Okay let’s get into it~ —Yap— Round two on the visual rework from last devlog, and the honest update is: it’s harder than expected. Every direction tried still lands somewhere in “generic modern web design,” which might just be what modern web design looks like right now regardless of who’s making it. —The Great Suffering— 1 — Everything Still Looks Like AI Made It Tried multiple directions this round trying to get away from the generic look. Kept landing back in the same neighborhood anyway. Starting to suspect this isn’t a “try harder” problem, it’s just what the current design language space looks like from basically every angle right now. 2 — Had To Ask Claude How To Center A Div The oldest joke in frontend development, still funny because it’s still true. Got stuck on it anyway. Some things never stop being annoying regardless of how many years of CSS have gone by. flexbox has existed for a decade and this is still where we are 3 — Pulled Up W3Schools For The First Time In Forever Dug up an old W3Schools reference mid-debugging, and it is dusty as hell at this point but the information’s still correct. Sometimes the ancient reference site is exactly what’s needed, aesthetics of the source be damned. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who asked an AI to help make something look less like an AI made it. Q: Did the AI-startup look actually get fixed this round? A: Not fully. Still fighting it. That’s most of this devlog. Q: Why does everything converge on the same generic look? A: Best guess: current tools and current design trends both nudge toward the same handful of patterns, so escaping it takes more than just trying different colors. Q: Is W3Schools still reliable? A: Apparently yes. Dated presentation, correct information. Q: When’s the website actually done? A: Closer than devlog #12, not there yet. Ask devlog #14. —This is the end*— *end for now, centered divs permitting PEPPLE!!!"}, {"post_id": 51936, "ts": "2026-08-21T21:25:25Z", "hours": 10.2181, "text": "Spectralis devlog #12 —Hello again proggers— Website’s getting a real pass. Not new copy this time, actual visual identity work, because it currently reads like every AI startup landing page that ever came out of the middle of California, and Spectralis is not that. gradient blob, bold sans headline, “revolutionize your workflow” — no Cat or dog? theme.css Okay let’s get into it~ —Yap— Not released yet, deliberately. This one’s still in progress, but close enough that it’s worth logging before it’s done instead of only after. The goal’s simple to say and annoying to actually do: stop looking generic. —The Great Suffering— 1 — The AI-Startup Look Had To Go Somewhere along the way the site had drifted into the exact aesthetic every seed-stage AI company in the Bay Area ships with — same fonts, same soft gradients, same layout rhythm everyone’s using because everyone else is using it. None of that says anything about what Spectralis actually is. 2 — Actual Visual Identity Work Working through what the site should look like instead of what’s easy to reach for by default. This is the slow part — not writing more copy, actually deciding what the thing looks like and why, instead of inheriting a template’s opinions by accident. 3 — Not Done, Getting Close Deliberately not shipping this mid-rework. Better to land it as one coherent pass than dribble out half-finished visual changes and confuse anyone who lands on the page in between. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one trying to make a music app’s website stop looking like a fundraising deck. Q: What specifically screamed “AI startup”? A: The general vibe more than any one element — the kind of design every YC-adjacent landing page converges on when nobody makes an active choice. Q: Why not ship incrementally instead of waiting? A: A visual identity rework half-applied looks worse than the thing it’s replacing. Waiting for it to be coherent. Q: How close is close? A: Close. Not “next devlog” close necessarily, but visibly closer than devlog #11 left it. Q: Does this touch the changelog-from-backend system from devlog #5? A: No, that infrastructure stays as-is. This is purely visual. —This is the end*— *end for now, gradient blobs permitting POGO!!!"}, {"post_id": 51267, "ts": "2026-08-20T20:03:38Z", "hours": 1.8481, "text": "Spectralis devlog #11 —Hello again proggers— Docs got a full rework this round. Also turns out v5.4.1 went out to nobody, because it never actually got pushed to the CDN. Tagged, released, announced probably, and completely inaccessible the whole time. shipped a release into a void and called it done Cat or dog? docs/ Okay let’s get into it~ —Yap— Started as a documentation pass and ended with the realization that the last release had been sitting local this whole time instead of where anyone could actually get it. Two very different kinds of work, same devlog. —The Great Suffering— 1 — The Entire Doc Rework Not a touch-up, a full rework. Docs, README, and STANDARDS all got restructured rather than patched in place, since patching them individually over the last several devlogs had left them internally inconsistent with each other and with what the app actually does now. 2 — 5.4.1 Never Made It To The CDN The actual headline bug of this devlog. v5.4.1 shipped, in the sense that it was built, tagged, and probably announced somewhere — but never got pushed to the CDN, meaning nobody could actually download it. Public-facing, and it was quietly broken the whole time until someone noticed. a release that ships to nowhere didn’t really ship 3 — Fixed And Actually Pushed Corrected the CDN push so 5.4.1 is genuinely available now, not just tagged in git looking like it is. Also part of why the doc rework mattered — docs referencing a version nobody could download was its own kind of lie. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who tagged a release and forgot the part where people can actually get it. Q: How long was 5.4.1 unavailable? A: Long enough to be embarrassing, short enough to fix before it became a real problem. Caught during this pass. Q: Why redo the docs entirely instead of patching them again? A: Because incremental doc patches across several devlogs had drifted apart from each other and from the app. A full rework got everything back in sync at once. Q: Is this the same CDN that serves changelogs now (devlog #5)? A: Same one. This time the release binary itself was the thing missing, not just content. Q: Anything else quietly broken that hasn’t surfaced yet? A: Unknown by definition. That’s what the next devlog is for. —This is the end*— *end for now, CDN pushes permitting POPPY!!!"}, {"post_id": 51122, "ts": "2026-08-20T16:50:19Z", "hours": 11.1333, "text": "Spectralis devlog #10 —Hello again proggers— 11 hours, zero sleep, and somewhere in the middle of that a full release went out. v5.4.1, then v5.4.1.2 right behind it because apparently one patch release wasn’t enough punishment for one night. sleep is a scheduling conflict I lost Cat or dog? winmm.dll Okay let’s get into it~ —Yap— Started as a normal patch pass and turned into a full Linux compatibility audit at 3am, because it turns out shipping something cross-platform means actually checking what “cross-platform” was quietly lying about. Found four separate ways the app was secretly Windows-only, fixed all of them, shipped twice. —The Great Suffering— 1 — winmm.dll Doesn’t Exist On Linux, Who Knew Something was calling into winmm.dll directly. Which is a Windows multimedia API. Which does not exist on Linux. Genuinely did not know this was happening until it broke loudly. “who knew” is doing a lot of work in that commit message 2 — Shipped A .exe To Linux, My Bad Somewhere in the build/packaging step, a .exe was ending up in the Linux build. An executable format Linux does not run. Not a subtle bug, just an embarrassing one. 3 — Song Wars Closing = Surprise Alt+F4 Closing Song Wars was apparently also closing the entire app, unprompted, no warning. A feature window doubling as a kill switch is not a feature, it’s a trap. 4 — Yeeted yt-dlp + ffmpeg Into Linux Land, Zero Installs Needed The actual fix underneath most of this: bundled yt-dlp and ffmpeg directly for Linux instead of assuming they’d already be installed system-wide, which they very often weren’t. Zero external installs needed now, it just works out of the box. 5 — Last Page Isn’t A Dead End Anymore Merged in from feature/story-pager-finish — reaching the last page of a story used to just… stop. Dead end, nothing to do. Fixed so it actually resolves properly instead of leaving you stranded on the final page. 6 — Two Releases In One Night v5.4.1 went out, then a second pass turned up enough left over that v5.4.1.2 followed right after. Both merged through staging same night, same sleepless stretch. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who found out about winmm.dll at 3am. Q: Was Spectralis actually broken on Linux before this? A: In at least four distinct ways, yes. Missing binaries, a stray .exe, a Windows-only DLL call, and an app-closing bug. Now fixed. Q: Why two patch releases instead of one? A: v5.4.1 went out, more got found immediately after, and waiting felt worse than just shipping v5.4.1.2 same night. Q: Did you actually not sleep? A: Correct. Not recommending it. Doing it anyway next time, probably. Q: Is Linux actually solid now? A: As solid as one very long, very tired night of testing can confirm. Time will tell the rest. —This is the end*— *end for now, sleep schedules permitting PIBBLE!!!"}, {"post_id": 50150, "ts": "2026-08-19T07:58:44Z", "hours": 5.4667, "text": "Spectralis devlog #9 — 5.4.0 is public —Hello again proggers— 5.4.0 is actually out, publicly, in people’s hands. Diffed v5.3.4 through v5.4.0: 40 commits, Aug 16-18, four threads of work. Cat or dog? spectral.resume() —Yap— Shared play became joinable, Streamer Queue and the Discord bot got hardened, story/visualizer bugs got chased down in one sitting, and some platform/perf issues got caught. None of these were small. —The Great Suffering— 1 — Shared Play Can Be Joined Now spectralis://shared-play/join links used to fall through to nothing. Now routed to a real handler. 2 — Streamer Queue: Host Controls + A Bot That Won’t Die Host can add tracks and mark played/skipped directly, no viewer round-trip. Desktop got an add-to-queue button and history panel. Both pollers (desktop + bot) back off dead rooms instead of hammering them. SQ API calls got a 10s timeout + one retry, GETs only — mutating calls don’t retry, to avoid double-submitting on a timed-out-but-successful response. Bot had zero global error handlers before this. One bad promise took the whole process down silently. Now it logs and survives, plus 3-attempt startup retry. 3 — Story Pages vs. Visualizers: Three Bugs, One Afternoon A capsule with both used to have them fight. Story can now queue a surface behind it — TryAdvancePastStory() swaps in the queued surface on spectral.resume(). Audio was starting under the story before the reader finished — now gated on whether a surface is queued. Once queued, picker/prev-next/keyboard could still hijack it — new IsVisualizerLocked blocks all three (user-picked “Special:” visualizers stay switchable). 4 — Platform + Perf Fixes MP3 decoding silently depended on Windows’ ACM codec via Mp3FileReader. Swapped to NLayer, pure managed decoder — MP3s decode on Linux/macOS now too. WebView2Host inline-rendered small visualizers via NavigateToString, which serves from about:blank with no real origin and tanks frame rate — everything goes through the fast file-backed path now. Auto-cycle switching checked IsLoaded/IsPlaying, both false during Spotify playback since Spotify never loads into the local engine — switched to HasTrack/IsPlaying. And: a regex stripping onclick=”…” had no exception, matched JS identifiers like onSomething =, and being quote-unguarded ate everything to the next stray quote anywhere later in the file. Fixed with a -block carve-out. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who’s been waiting on shared play join links forever. Q: Was shared play really host-only until now? A: Yes. The link existed, it just went nowhere. Q: How bad was the regex bug? A: Silent corruption of unrelated code anywhere later in the file, no error thrown. Very glad it’s found. Q: Is 5.4.0 stable? A: As far as testing shows. That’s what everyone says right before the hotfix. —This is the end*— *end for now, public users permitting PEBBLE!!!"}, {"post_id": 49430, "ts": "2026-08-18T08:25:19Z", "hours": 10.7003, "text": "Spectralis devlog #8 —Hello again proggers— 10 hours 48 minutes. Again. Didn’t plan it, didn’t notice it happening, just looked up and the sun had done a full cycle. This time it was capsules and worlds actually getting built and tested for real instead of just existing in theory. we’ve been here before and we will be here again Cat or dog? Capsule.story + Capsule.visualizer print(f”I try to make stu{2f} which {actually_coexist} {10h48m_later}”) Okay let’s get into it~ —Yap— Stories came back in devlog #7 as a concept. This round was making and testing the first actual .spectralis capsules and worlds built on that concept, which is a different job entirely — turns out “the architecture supports it” and “a real capsule with a real story actually works” are two very different milestones. Also fixed a bug that only shows up once you’re actually testing real capsules instead of imagining them, and a GitHub pull issue that had nothing to do with any of this and ate time anyway. —The Great Suffering— 1 — Building And Testing The First Real Capsules And Worlds Most of the 10 hours 48 minutes, honestly. Going from “stories and worlds work in concept” to actually authoring capsules, loading them, and confirming the hooks — track start, track control, the custom HTML page — behave the way they’re supposed to under real content instead of a test stub. This is the part where theory meets “wait, why is this blank.” 2 — A Story And A Visualizer Couldn’t Both Exist In One Capsule Found this one while testing, not before. A capsule with both a story and a visualizer defined would break, since apparently the two weren’t built to coexist in the same capsule at all. Fixed so a single capsule can hold both without one stepping on the other. the two features that were supposed to be siblings turned out to be enemies 3 — GitHub Was Being Weird About Pulling Somewhere in the middle of all this, git decided pulling wasn’t going to just work. Fixed the pulling issue, which is the kind of fix that has no interesting story attached, it was just broken and then it wasn’t. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who said “quick test” and looked up 10 hours 48 minutes later. Q: Was the story/visualizer bug there since devlog #7? A: Presumably, yes. Nobody had actually tried putting both in one capsule until this round. Q: What does “testing capsules and worlds” actually involve? A: Authoring real ones, loading them in the app, and checking the hooks — track start, track control, custom HTML rendering — behave correctly with actual content, not placeholder data. Q: What was the GitHub pulling issue? A: Not going into detail, it wasn’t interesting, it was just broken. Fixed now. Q: Is this the last capsule/worlds devlog? A: No idea. Ask devlog #9. —This is the end*— *end for now, git remotes permitting PEPPERONI!!!"}, {"post_id": 49210, "ts": "2026-08-17T21:23:21Z", "hours": 10.1667, "text": "Spectralis devlog #7 — welcome 5.4.0 —Hello again proggers— 5.4.0’s out. This one brought back a feature I’d basically buried, hardened two systems that were still a little too trust-me-bro, and finally let shared play open where it should’ve been opening the whole time. Also touched the docs, which I’m choosing to be proud of. Cat or dog? .spectralis print(f”I try to make stu{2f} which {actually_ships} {5.4.0}”) Okay let’s get into it~ —Yap— Big one this round is stories coming back into .spectralis capsules, except not as the thing they used to be — modernized, closer to how album worlds work now, as a proper custom HTML page with real hooks instead of whatever they were before. Rest of the release was hardening and cleanup: Streamer Queue and Discord got a pass to make sure live use doesn’t fall over, shared play finally opens in-app, and the docs stopped lying about what the app actually does. bringing back a feature I killed is a personality trait at this point —The Great Suffering— 1 — Stories Are Back, But Not The Same Stories Old stories concept is back inside .spectralis capsules, rebuilt to match how album worlds work now instead of resurrecting the original implementation as-is. Each one’s a custom HTML page with real hooks into the player — starting tracks, track control, the works — instead of being a static bolt-on. Bringing it back meant actually integrating it with the current architecture, not just copy-pasting the old version back in. 2 — Streamer Queue + Discord Got Hardened Both of these existed and mostly worked, which is different from “survives actually being used live by a streamer with chat moving.” Went through and hardened the interaction between Streamer Queue and the Discord bot — the stuff that only shows up under real load or real edge cases instead of a clean local test run. “mostly works” is doing a lot of lifting in software 3 — Shared Play Opens In App Now Shared play used to need you to go find it. Now there’s an actual open-in-app implementation, so joining a shared room is a real in-app flow instead of a workaround. Small change on paper, but it’s the difference between a feature people use and a feature people forget exists. 4 — Docs, README, and STANDARDS Actually Match Reality Updated the docs, README, and STANDARDS to reflect what’s actually in the app at this point instead of an earlier version of it. Boring work, necessary work, the kind of thing that only gets noticed when it’s wrong. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who buried a feature and then dug it back up two versions later. Q: Why bring stories back instead of leaving them dead? A: Because the concept was good, the old implementation just wasn’t, and album worlds proved the modernized version of the idea actually works. Q: What counts as “hardening” for Streamer Queue and Discord? A: The stuff that only breaks under real conditions — live chat, real timing, real edge cases — not the happy path you get testing solo. Q: Does shared play opening in-app change how sessions work? A: No, same sessions, same presence/reactions/queue from devlog #6. Just a real entry point now instead of a workaround. Q: Anything left over for next time? A: Always. This is a devlog series, not a finish line. —This is the end*— *end for now, capsule hooks permitting 再见!!!"}, {"post_id": 48667, "ts": "2026-08-17T05:02:56Z", "hours": 9.6881, "text": "Spectralis devlog #6 —Hello again proggers— Website stuff wrapped up at the 310ee27 merge, then everything shifted straight into Streamer Queue and shared play. Ten commits deep on dev, plus one fix that’s sitting uncommitted in the working tree because it’s the kind of thing you want to stare at twice before you trust it. Cat or dog? Mp3FileReaderBase print(f”I try to make stu{2f} which {actually_decodes} {cross_platform}”) Okay let’s get into it~ —Yap— Streamer Queue went from “backend endpoints exist” to “actual UI with history and add-to-queue” over the course of ten commits, shared play picked up presence and reactions along the way, and then right at the end I found out the MP3 decoder has been quietly depending on a Windows-only codec this whole time. Great. cross-platform, they said. it’ll be fine, they said —The Great Suffering— 1 — Streamer Queue Backend, Then Actually Wiring It Up 402e2ef–2b74f97 built out the Streamer Queue backend endpoints — host add, mark played, mark skipped — and wired them into the client through a new StreamerQueueViewModel. Backend existing and backend actually being called by anything are two different milestones, and this covered both. 2 — The UI Caught Up 16c4b26 added the add-to-queue button and a history panel, so Streamer Queue stopped being an API you’d have to hit manually and became something that’s actually usable in the app. 3 — Shared Play Learned About Presence and Reactions ecb43e6 and c7a19c2 — shared play now fetches and exposes presence and reaction snapshots straight from the CDN. 7e60e15 then had SharedPlaySessionController pass presence, reactions, and queue through properly instead of any of those three living off on their own. 4 — HostAsync Was Ignoring The Host 92f2079. Found and fixed HostAsync quietly ignoring the host’s actual settings — not great for a feature called “host a shared play session.” the host had opinions the whole time, we just weren’t asking 5 — Preloading and the Full Shared UI 22bc56e preloads the next track into the shared room too, so listeners aren’t waiting on it live. f2df836 (HEAD) rounds it out with listener count, a reactions ticker, and a request list in the shared play UI — the room finally looks like it has people in it. Net diff for this stretch: SectionViewModels.cs (+206), backend/src/main.rs (+103), plus the SharedPlay CDN client/models and StreamerQueueView.axaml. 6 — The Uncommitted One: MP3 Playback Was Windows-Only This Whole Time AudioEngine.cs and VideoExportEngine.cs were both using Mp3FileReader, which under the hood calls Windows’ ACM codec (msacm32.dll) to decompress. Which does not exist on Linux or macOS. Swapping to Mp3FileReaderBase with an NLayer decompressor instead — NLayer.NAudioSupport added to Spectralis.Core.csproj — since NLayer is a pure managed decoder and doesn’t care what OS it’s on. Not committed yet, wanted to sit with it first. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who just found out MP3 playback only worked on one OS. Q: Was Spectralis actually cross-platform before this fix? A: For anything that wasn’t MP3 audio, sure. For MP3 specifically, only on Windows, silently, this whole time. Q: Why leave the audio fix uncommitted? A: Swapping a decoder for something this central deserves a beat of “does this actually sound right” before it goes in, not just “does it build.” Q: What’s the difference between Streamer Queue and the regular request queue? A: Streamer Queue is host-controlled — add, mark played, mark skipped, from the streamer’s side, with its own history panel, separate from the public submission flow. Q: Did shared play or Streamer Queue touch the Discord bot? A: No, this round’s entirely Spectralis.App/Spectralis.Core and the Rust backend. Bot’s untouched. —This is the end*— *end for now, ACM codecs permitting PARROT!!!"}, {"post_id": 48057, "ts": "2026-08-16T10:39:23Z", "hours": 2.2006, "text": "Spectralis devlog #5 —Hello again proggers— This one’s website side, not app side. Less “watches chat and reacts,” more “stop lying to people who land on the page.” Changelogs, copy, and a pile of QoL that all needed doing at once, so they got done at once. Cat or dog? GET /changelog print(f”I try to make stu{2f} which {actually_updates} {2day}”) Okay let’s get into it~ —Yap— The website had drifted into “hardcoded strings and vibes” territory. Changelog was static, copy was doing the thing where every sentence has an exclamation point and says nothing, and a bunch of small friction points had just been sitting there unfixed because none of them were dramatic enough on their own to stop and deal with. death by a thousand papercuts, website edition —The Great Suffering— 1 — Changelogs Moved To The Backend Changelog used to live as static content baked into the site itself, which meant every release meant a redeploy just to update a text block. Now it’s served from the backend, so shipping a new version updates the changelog without touching the frontend at all. Site and release process finally agree with each other. 2 — Marketing Fluff: Removed Went through the copy and cut the stuff that existed to sound exciting instead of to say something. Fewer exclamation points, fewer vague superlatives, more actual sentences about what the thing does. Turns out “it’s fast” means more than “blazingly fast, lightning quick, revolutionary” stacked in one line. RIP to several adjectives, you will not be missed 3 — A Bunch Of Small QoL Fixes The kind of stuff that’s individually boring but collectively the difference between a site that feels maintained and one that doesn’t — broken anchor links, inconsistent spacing that had been “fine for now” for way too long, a couple of buttons that didn’t actually do what their label said, loading states that just weren’t there before. Nothing here gets its own numbered section because none of it deserves one, but all of it needed fixing. 4 — Site and Backend Actually Talk Now With changelogs pulled from the backend, the website stopped being a static artifact that occasionally gets redeployed and started being an actual client of the backend it’s supposed to represent. Small architectural shift, disproportionate amount of relief. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who wrote “blazingly fast” unironically at some point. Q: Why was the changelog static in the first place? A: Because it was easy at the time and “at the time” was a while ago. Q: Is the marketing copy gone entirely now? A: No, just the fluff. The site still has to say what Spectralis does, it just doesn’t need six adjectives to do it. Q: Does this affect the Discord bot or the app? A: No, this one’s website-only. App and bot are untouched this round. Q: What counts as a “small QoL fix” that didn’t get its own section? A: The stuff that’s annoying to list individually but adds up to “the site feels better now.” You’ll notice it without being told what it was. —This is the end*— *end for now, copywriting urges permitting CYA!!!"}, {"post_id": 47986, "ts": "2026-08-16T08:15:58Z", "hours": 11.9667, "text": "Spectralis devlog #4 —Hello again proggers— Uh. So. It’s been 11 hours. We sat down, opened the bot code, and just… didn’t stop. No devlog got posted because posting a devlog requires noticing that time is a thing that’s passing, and that stopped happening somewhere around hour 3. this is fine, this has always been fine Cat or dog? channelLock.ts print(f”I try to make stu{2f} which {actually_locked} {11hrs_later}”) Okay let’s get into it, before I forget more of it~ —Yap— No app changes this round. Zero. Not one line touched in Spectralis.App or Spectralis.Core. This whole stretch was 100% the Discord bot, going from “stubbed slash commands” to “bot that actually watches chat and does something about it.” —The Great Suffering— 1 — Railway Kept Rebuilding Rust For No Reason v5.3.2. Railway was rebuilding the entire backend on every single deploy regardless of whether the Rust actually changed. Pinned the build so it stops doing that. Small fix, saved a genuinely upsetting amount of deploy time. 2 — The Bot Learned to Watch Chat v5.3.3, and the actual reason for the 11 hours. The bot now watches the queue channel and reacts to song submissions as they come in, instead of just sitting there answering slash commands and pretending it doesn’t see anything else happening. 3 — New Files, New Problems messageSubmission.ts showed up to handle reacting to and tracking submitted songs in chat. channelLock.ts showed up next to it to handle locking logic for the watched channel, because a bot watching chat unsupervised is a bot that needs boundaries. 4 — Bot Token Can Now Actually See Things Bumped the bot token’s permissions so it can see and read submissions in the first place, which, in hindsight, was load-bearing for “watches chat and reacts to submissions.” Can’t react to what you can’t read. 5 — New Slash Commands, Existing Ones Got Bigger set-closed-message and set-open-message let streamers customize what shows up when the queue opens or closes instead of eating a hardcoded string. open-queue/close-queue got extended to actually talk to the new messaging and channel-lock logic instead of just flipping a flag and hoping. 6 — Everything Downstream Had to Catch Up db.ts, sqApi.ts, nowPlayingPoller.ts, types.ts, and index.ts all expanded to support the submission-tracking flow end to end. Backend picked up a small related change too, +11/-2 in main.rs, mostly plumbing to support what the bot needed on the other end. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who let this go 11 hours without a devlog. Q: How did 11 hours happen? A: One slash command needed one more file, which needed one more type, which needed the bot to actually be able to read messages, and then the sun came up. Q: Is the C# app okay? A: Untouched and fine. It got the week off. Q: Why does the bot need to watch chat instead of just answering commands? A: Song submissions happen by posting in the channel, not by running a command every time. The bot needed to actually see that to react to and track them. Q: What’s channelLock.ts for? A: Making sure the watched channel behaves predictably while the bot is actively tracking submissions in it, instead of reacting to chaos. Q: Are we caught up on devlogs now? A: This is #4. We are exactly as caught up as we’re going to get. —This is the end*— *end for now, sleep permitting PANCAKES!!!"}, {"post_id": 47399, "ts": "2026-08-15T09:49:05Z", "hours": 5.2097, "text": "Spectralis devlog #3 —Hello again proggers— Back at it. This round wasn’t visualizer polish or UI cleanup, it was Song Wars/SQ backend stuff and a Discord bot that didn’t exist yesterday. Less “make it pretty,” more “make it not lie to people.” Cat or dog? AcceptingSubmissions print(f”I try to make stu{2f} which {actually_closes} {2day}”) Okay let’s get into it~ —Yap— Turns out “turn off the fee toggle” and “actually prevent the fee-gated action” are two different things, and I had only been doing the first one. Also built an entire close-queue flow because apparently streamers want to stop taking requests sometimes, which, fair. And then there’s a Discord bot now. That happened too. scope creep? never heard of her —The Great Suffering— 1 — The Free Skip Loophole Turning off “Skip fee” or “Super Skip fee” removed the option from the public request page (sq.html/sq.js) just fine. What it did NOT do was stop the backend from accepting skip/super-skip attempts anyway — submit, upload, promote, all of it. Toggle says no, server says sure why not. Backend now actually rejects those attempts when the toggle’s off, closing the gap where a disabled tier was quietly still free. the frontend was lying and the backend believed it Still preserved: turning a toggle ON with a $0 amount is a real, intentional free tier. That distinction stays. 2 — Close Queue Didn’t Exist There was a “Queue enabled” toggle, but no way to just… stop taking requests without digging into settings. Added a real AcceptingSubmissions flag, separate from that, plus a one-click “Close Queue”/“Reopen Queue” button right next to “Copy Submit URL” in the header. No settings menu detour required. When closed, the public page still shows now-playing and queue count, just hides the request/skip/super-skip forms behind a “requests are closed” banner. Streamer can keep browsing and playing from the existing queue the whole time, since the app’s queue view was never gated on “enabled” to begin with. 3 — Now Playing Was Just Empty This Whole Time Found this one by accident while wiring Close Queue: the public page’s “Now Playing” section never actually populated for anyone who wasn’t the owner, because the backend just wasn’t sending track info to non-owner viewers. Fixed alongside everything else. 4 — A Discord Bot Shows Up New discord-bot/ folder, Node.js + TypeScript, discord.js, with a full PLANNING.md for the design: PIN-based pairing so the streamer generates a short-lived PIN in-app and runs /link-queue in Discord with no secrets ever touching chat, a scoped bot-token concept kept separate from the full owner token, and a (guildId, channelId) → room mapping so one bot instance can serve many servers. /queue, /request, /skip, /superskip are fully wired against the existing public SQ API and build clean. /link-queue, /close-queue, /open-queue are stubbed with TODOs since they need backend PIN/token endpoints that don’t exist yet, which is now the next backend work item. Everything typechecks and builds clean across the board — Rust release build, Spectralis.App, and the bot’s tsc. —FAQ (no one asked these but they are here)— Q: Why does Spectralis need a Discord bot? A: Because apparently the request queue living only on a web page wasn’t enough surface area. Now it can also live in your server. Q: What’s PIN-based pairing? A: Streamer gets a short-lived PIN in-app, runs one Discord command with it, done. No tokens or secrets ever posted in chat. Q: Anything left over from last devlog? A: Chat template drift is still an EDITH problem, not a Spectralis one. Wrong repo, wrong devlog. —This is the end*— *end for now, PIN endpoints permitting PIZZA!!!"}, {"post_id": 46741, "ts": "2026-08-14T06:44:16Z", "hours": 6.1242, "text": "Spectralis devlog #2 —Hello again proggers— New project, same yapping. This one’s Spectralis — the WinForms-to-Avalonia refugee that somehow ended up with a spin wheel, notepads, dead zones, and Spotify playlist sync bolted onto it. 917 commits deep and counting. Cat or dog? RowBackground print(f”I try to make stu{2f} which {actually_renders} {2day}”) Okay let’s get into it~ —Yap— This stretch was less “one big feature” and more “death by a thousand small horrors,” which honestly might just be what maintaining a music app is. Playlists, now playing, the visualizer pipeline, and a wheel of all things all got touched. a spin wheel. in a music app. sure —The Great Suffering— 1 — Playlists Looked Like a Log File For way too long, the playlist view rendered like plain rows in a terminal instead of, y’know, an app. Turns out library explicitly set RowBackground and playlists just… didn’t. So it fell back to the theme’s default accent-tinted fill on every single row instead of the real styling. One missing property. That’s it. That’s the bug. found staring at my own code for an hour 2 — Every Nav Click Rebuilt The World ContentControl was tearing down and rebuilding the entire section view from scratch on every single navigation click. Fixed by caching views per viewmodel instead of nuking them each time. App feels like it’s not fighting itself anymore. 3 — Library Load Was Blocking the Window From Even Opening Big libraries meant the window just… wouldn’t show up. Load was sitting on the UI thread like it owned the place. Moved off it. Window opens now regardless of how unhinged your library size is. 4 — Spectrum Bars Were Snapping FFT window was running back-to-back instead of overlapping, so spectrum/spectrogram/loudness only actually updated every ~185ms even at 60fps render — bars were snapping to new values instead of moving. Bumped overlap to 75% and eased toward target instead of drawing raw values. Smooth now. Suspiciously smooth. 5 — Notepads and the Wheel Happened Somewhere in here a full notepad feature got built — embed model, tag service, docked panel in now playing, pop-out window, save-to-track-tags — and then immediately got wired into a spin wheel with weighted entries, its own model, and a saved-wheels list. Neither of these were planned at the start of the week. Both exist now. 6 — Spotify Actually Behaves Spotify stopped pausing forever, stopped lying about the queue, stopped refusing to shut up, and playlists now actually sync instead of just vibing. Also Discord presence shows Spotify tracks now instead of just going blank like it forgot what music was. 7 — Small Bugs, Deployed With Extreme Prejudice Soundcloud playhead was showing the previous track’s end position on load, fixed. Word mode wasn’t saving timestamps so exports came out empty, fixed. Track-switch click (and the pop when another app grabs the audio device) got a quick fade instead. Dead zones stopped being OBS-only and now shift the app’s own layout too. —FAQ (no one asked these but they are here)— Q: What is Spectralis? A: A local + Spotify + SoundCloud music player with a visualizer pipeline, OBS integration, and apparently a spin wheel now. Originally WinForms, migrated to Avalonia across 917 commits. Q: Why does a music player need dead zones? A: For OBS overlay layouts — panels and toasts need to know where not to render so they don’t cover your stream elements. It’s a layout constraint system wearing a spooky name. Q: Was the RowBackground bug really just one missing line? A: Yes. I’m still thinking about it. Q: Is the wheel feature load-bearing or a bit? A: Unclear. It has weighted spins, saved wheel lists, and its own viewmodel. Feels load-bearing now. Q: What’s next? A: Whatever the changelog for the version after 5.4.0 ends up needing. Probably something I haven’t broken yet. —This is the end*— *end for now, RowBackground permitting ADIOS!!!😎😎😎😎"}, {"post_id": 27486, "ts": "2026-07-13T02:54:53Z", "hours": 16.6944, "text": "DEVLOG 001 initial setup with hackclub this is the 5th iteration of the spectralis audio visualizer app core features changed: switched from WinForms to AvaloniaUI refined UI design and theming fixed api related issues added streamer support and automated queueing web share audio hosting refinements to the embedded audio visualizer system bug fixes: fixed an issue with the youtube API placeholder fix for Spotify webplayer playback fixed an issue with the viz switcher would “hide” behind the html visualizers"}]...
|
Title: Spectralis by @DeltaVortex | Stardance
Dev Title: Spectralis by @DeltaVortex | Stardance
Devlogs:
DEVLOG 001 initial setup with hackclub this is the 5th iteration of the spectralis audio visualizer app core features changed: switched from WinForms to AvaloniaUI refined UI design and theming fixed api related issues added streamer support and automated queueing web share audio hosting refinements to the embedded audio visualizer system bug fixes: fixed an issue with the youtube API placeholder fix for Spotify webplayer playback fixed an issue with the viz switcher would “hide” behind the html visualizers
Spectralis devlog #2 —Hello again proggers— New project, same yapping. This one’s Spectralis — the WinForms-to-Avalonia refugee that somehow ended up with a spin wheel, notepads, dead zones, and Spotify playlist sync bolted onto it. 917 commits deep and counting. Cat or dog? RowBackground print(f”I try to make stu{2f} which {actually_renders} {2day}”) Okay let’s get into it~ —Yap— This stretch was less “one big feature” and more “death by a thousand small horrors,” which honestly might just be what maintaining a music app is. Playlists, now playing, the visualizer pipeline, and a wheel of all things all got touched. a spin wheel. in a music app. sure —The Great Suffering— 1 — Playlists Looked Like a Log File For way too long, the playlist view rendered like plain rows in a terminal instead of, y’know, an app. Turns out library explicitly set RowBackground and playlists just… didn’t. So it fell back to the theme’s default accent-tinted fill on every single row instead of the real styling. One missing property. That’s it. That’s the bug. found staring at my own code for an hour 2 — Every Nav Click Rebuilt The World ContentControl was tearing down and rebuilding the entire section view from scratch on every single navigation click. Fixed by caching views per viewmodel instead of nuking them each time. App feels like it’s not fighting itself anymore. 3 — Library Load Was Blocking the Window From Even Opening Big libraries meant the window just… wouldn’t show up. Load was sitting on the UI thread like it owned the place. Moved off it. Window opens now regardless of how unhinged your library size is. 4 — Spectrum Bars Were Snapping FFT window was running back-to-back instead of overlapping, so spectrum/spectrogram/loudness only actually updated every ~185ms even at 60fps render — bars were snapping to new values instead of moving. Bumped overlap to 75% and eased toward target instead of drawing raw values. Smooth now. Suspiciously smooth. 5 — Notepads and the Wheel Happened Somewhere in here a full notepad feature got built — embed model, tag service, docked panel in now playing, pop-out window, save-to-track-tags — and then immediately got wired into a spin wheel with weighted entries, its own model, and a saved-wheels list. Neither of these were planned at the start of the week. Both exist now. 6 — Spotify Actually Behaves Spotify stopped pausing forever, stopped lying about the queue, stopped refusing to shut up, and playlists now actually sync instead of just vibing. Also Discord presence shows Spotify tracks now instead of just going blank like it forgot what music was. 7 — Small Bugs, Deployed With Extreme Prejudice Soundcloud playhead was showing the previous track’s end position on load, fixed. Word mode wasn’t saving timestamps so exports came out empty, fixed. Track-switch click (and the pop when another app grabs the audio device) got a quick fade instead. Dead zones stopped being OBS-only and now shift the app’s own layout too. —FAQ (no one asked these but they are here)— Q: What is Spectralis? A: A local + Spotify + SoundCloud music player with a visualizer pipeline, OBS integration, and apparently a spin wheel now. Originally WinForms, migrated to Avalonia across 917 commits. Q: Why does a music player need dead zones? A: For OBS overlay layouts — panels and toasts need to know where not to render so they don’t cover your stream elements. It’s a layout constraint system wearing a spooky name. Q: Was the RowBackground bug really just one missing line? A: Yes. I’m still thinking about it. Q: Is the wheel feature load-bearing or a bit? A: Unclear. It has weighted spins, saved wheel lists, and its own viewmodel. Feels load-bearing now. Q: What’s next? A: Whatever the changelog for the version after 5.4.0 ends up needing. Probably something I haven’t broken yet. —This is the end*— *end for now, RowBackground permitting ADIOS!!!😎😎😎😎
Spectralis devlog #3 —Hello again proggers— Back at it. This round wasn’t visualizer polish or UI cleanup, it was Song Wars/SQ backend stuff and a Discord bot that didn’t exist yesterday. Less “make it pretty,” more “make it not lie to people.” Cat or dog? AcceptingSubmissions print(f”I try to make stu{2f} which {actually_closes} {2day}”) Okay let’s get into it~ —Yap— Turns out “turn off the fee toggle” and “actually prevent the fee-gated action” are two different things, and I had only been doing the first one. Also built an entire close-queue flow because apparently streamers want to stop taking requests sometimes, which, fair. And then there’s a Discord bot now. That happened too. scope creep? never heard of her —The Great Suffering— 1 — The Free Skip Loophole Turning off “Skip fee” or “Super Skip fee” removed the option from the public request page (sq.html/sq.js) just fine. What it did NOT do was stop the backend from accepting skip/super-skip attempts anyway — submit, upload, promote, all of it. Toggle says no, server says sure why not. Backend now actually rejects those attempts when the toggle’s off, closing the gap where a disabled tier was quietly still free. the frontend was lying and the backend believed it Still preserved: turning a toggle ON with a $0 amount is a real, intentional free tier. That distinction stays. 2 — Close Queue Didn’t Exist There was a “Queue enabled” toggle, but no way to just… stop taking requests without digging into settings. Added a real AcceptingSubmissions flag, separate from that, plus a one-click “Close Queue”/“Reopen Queue” button right next to “Copy Submit URL” in the header. No settings menu detour required. When closed, the public page still shows now-playing and queue count, just hides the request/skip/super-skip forms behind a “requests are closed” banner. Streamer can keep browsing and playing from the existing queue the whole time, since the app’s queue view was never gated on “enabled” to begin with. 3 — Now Playing Was Just Empty This Whole Time Found this one by accident while wiring Close Queue: the public page’s “Now Playing” section never actually populated for anyone who wasn’t the owner, because the backend just wasn’t sending track info to non-owner viewers. Fixed alongside everything else. 4 — A Discord Bot Shows Up New discord-bot/ folder, Node.js + TypeScript, discord.js, with a full PLANNING.md for the design: PIN-based pairing so the streamer generates a short-lived PIN in-app and runs /link-queue in Discord with no secrets ever touching chat, a scoped bot-token concept kept separate from the full owner token, and a (guildId, channelId) → room mapping so one bot instance can serve many servers. /queue, /request, /skip, /superskip are fully wired against the existing public SQ API and build clean. /link-queue, /close-queue, /open-queue are stubbed with TODOs since they need backend PIN/token endpoints that don’t exist yet, which is now the next backend work item. Everything typechecks and builds clean across the board — Rust release build, Spectralis.App, and the bot’s tsc. —FAQ (no one asked these but they are here)— Q: Why does Spectralis need a Discord bot? A: Because apparently the request queue living only on a web page wasn’t enough surface area. Now it can also live in your server. Q: What’s PIN-based pairing? A: Streamer gets a short-lived PIN in-app, runs one Discord command with it, done. No tokens or secrets ever posted in chat. Q: Anything left over from last devlog? A: Chat template drift is still an EDITH problem, not a Spectralis one. Wrong repo, wrong devlog. —This is the end*— *end for now, PIN endpoints permitting PIZZA!!!
Spectralis devlog #4 —Hello again proggers— Uh. So. It’s been 11 hours. We sat down, opened the bot code, and just… didn’t stop. No devlog got posted because posting a devlog requires noticing that time is a thing that’s passing, and that stopped happening somewhere around hour 3. this is fine, this has always been fine Cat or dog? channelLock.ts print(f”I try to make stu{2f} which {actually_locked} {11hrs_later}”) Okay let’s get into it, before I forget more of it~ —Yap— No app changes this round. Zero. Not one line touched in Spectralis.App or Spectralis.Core. This whole stretch was 100% the Discord bot, going from “stubbed slash commands” to “bot that actually watches chat and does something about it.” —The Great Suffering— 1 — Railway Kept Rebuilding Rust For No Reason v5.3.2. Railway was rebuilding the entire backend on every single deploy regardless of whether the Rust actually changed. Pinned the build so it stops doing that. Small fix, saved a genuinely upsetting amount of deploy time. 2 — The Bot Learned to Watch Chat v5.3.3, and the actual reason for the 11 hours. The bot now watches the queue channel and reacts to song submissions as they come in, instead of just sitting there answering slash commands and pretending it doesn’t see anything else happening. 3 — New Files, New Problems messageSubmission.ts showed up to handle reacting to and tracking submitted songs in chat. channelLock.ts showed up next to it to handle locking logic for the watched channel, because a bot watching chat unsupervised is a bot that needs boundaries. 4 — Bot Token Can Now Actually See Things Bumped the bot token’s permissions so it can see and read submissions in the first place, which, in hindsight, was load-bearing for “watches chat and reacts to submissions.” Can’t react to what you can’t read. 5 — New Slash Commands, Existing Ones Got Bigger set-closed-message and set-open-message let streamers customize what shows up when the queue opens or closes instead of eating a hardcoded string. open-queue/close-queue got extended to actually talk to the new messaging and channel-lock logic instead of just flipping a flag and hoping. 6 — Everything Downstream Had to Catch Up db.ts, sqApi.ts, nowPlayingPoller.ts, types.ts, and index.ts all expanded to support the submission-tracking flow end to end. Backend picked up a small related change too, +11/-2 in main.rs, mostly plumbing to support what the bot needed on the other end. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who let this go 11 hours without a devlog. Q: How did 11 hours happen? A: One slash command needed one more file, which needed one more type, which needed the bot to actually be able to read messages, and then the sun came up. Q: Is the C# app okay? A: Untouched and fine. It got the week off. Q: Why does the bot need to watch chat instead of just answering commands? A: Song submissions happen by posting in the channel, not by running a command every time. The bot needed to actually see that to react to and track them. Q: What’s channelLock.ts for? A: Making sure the watched channel behaves predictably while the bot is actively tracking submissions in it, instead of reacting to chaos. Q: Are we caught up on devlogs now? A: This is #4. We are exactly as caught up as we’re going to get. —This is the end*— *end for now, sleep permitting PANCAKES!!!
Spectralis devlog #5 —Hello again proggers— This one’s website side, not app side. Less “watches chat and reacts,” more “stop lying to people who land on the page.” Changelogs, copy, and a pile of QoL that all needed doing at once, so they got done at once. Cat or dog? GET /changelog print(f”I try to make stu{2f} which {actually_updates} {2day}”) Okay let’s get into it~ —Yap— The website had drifted into “hardcoded strings and vibes” territory. Changelog was static, copy was doing the thing where every sentence has an exclamation point and says nothing, and a bunch of small friction points had just been sitting there unfixed because none of them were dramatic enough on their own to stop and deal with. death by a thousand papercuts, website edition —The Great Suffering— 1 — Changelogs Moved To The Backend Changelog used to live as static content baked into the site itself, which meant every release meant a redeploy just to update a text block. Now it’s served from the backend, so shipping a new version updates the changelog without touching the frontend at all. Site and release process finally agree with each other. 2 — Marketing Fluff: Removed Went through the copy and cut the stuff that existed to sound exciting instead of to say something. Fewer exclamation points, fewer vague superlatives, more actual sentences about what the thing does. Turns out “it’s fast” means more than “blazingly fast, lightning quick, revolutionary” stacked in one line. RIP to several adjectives, you will not be missed 3 — A Bunch Of Small QoL Fixes The kind of stuff that’s individually boring but collectively the difference between a site that feels maintained and one that doesn’t — broken anchor links, inconsistent spacing that had been “fine for now” for way too long, a couple of buttons that didn’t actually do what their label said, loading states that just weren’t there before. Nothing here gets its own numbered section because none of it deserves one, but all of it needed fixing. 4 — Site and Backend Actually Talk Now With changelogs pulled from the backend, the website stopped being a static artifact that occasionally gets redeployed and started being an actual client of the backend it’s supposed to represent. Small architectural shift, disproportionate amount of relief. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who wrote “blazingly fast” unironically at some point. Q: Why was the changelog static in the first place? A: Because it was easy at the time and “at the time” was a while ago. Q: Is the marketing copy gone entirely now? A: No, just the fluff. The site still has to say what Spectralis does, it just doesn’t need six adjectives to do it. Q: Does this affect the Discord bot or the app? A: No, this one’s website-only. App and bot are untouched this round. Q: What counts as a “small QoL fix” that didn’t get its own section? A: The stuff that’s annoying to list individually but adds up to “the site feels better now.” You’ll notice it without being told what it was. —This is the end*— *end for now, copywriting urges permitting CYA!!!
Spectralis devlog #6 —Hello again proggers— Website stuff wrapped up at the 310ee27 merge, then everything shifted straight into Streamer Queue and shared play. Ten commits deep on dev, plus one fix that’s sitting uncommitted in the working tree because it’s the kind of thing you want to stare at twice before you trust it. Cat or dog? Mp3FileReaderBase print(f”I try to make stu{2f} which {actually_decodes} {cross_platform}”) Okay let’s get into it~ —Yap— Streamer Queue went from “backend endpoints exist” to “actual UI with history and add-to-queue” over the course of ten commits, shared play picked up presence and reactions along the way, and then right at the end I found out the MP3 decoder has been quietly depending on a Windows-only codec this whole time. Great. cross-platform, they said. it’ll be fine, they said —The Great Suffering— 1 — Streamer Queue Backend, Then Actually Wiring It Up 402e2ef–2b74f97 built out the Streamer Queue backend endpoints — host add, mark played, mark skipped — and wired them into the client through a new StreamerQueueViewModel. Backend existing and backend actually being called by anything are two different milestones, and this covered both. 2 — The UI Caught Up 16c4b26 added the add-to-queue button and a history panel, so Streamer Queue stopped being an API you’d have to hit manually and became something that’s actually usable in the app. 3 — Shared Play Learned About Presence and Reactions ecb43e6 and c7a19c2 — shared play now fetches and exposes presence and reaction snapshots straight from the CDN. 7e60e15 then had SharedPlaySessionController pass presence, reactions, and queue through properly instead of any of those three living off on their own. 4 — HostAsync Was Ignoring The Host 92f2079. Found and fixed HostAsync quietly ignoring the host’s actual settings — not great for a feature called “host a shared play session.” the host had opinions the whole time, we just weren’t asking 5 — Preloading and the Full Shared UI 22bc56e preloads the next track into the shared room too, so listeners aren’t waiting on it live. f2df836 (HEAD) rounds it out with listener count, a reactions ticker, and a request list in the shared play UI — the room finally looks like it has people in it. Net diff for this stretch: SectionViewModels.cs (+206), backend/src/main.rs (+103), plus the SharedPlay CDN client/models and StreamerQueueView.axaml. 6 — The Uncommitted One: MP3 Playback Was Windows-Only This Whole Time AudioEngine.cs and VideoExportEngine.cs were both using Mp3FileReader, which under the hood calls Windows’ ACM codec (msacm32.dll) to decompress. Which does not exist on Linux or macOS. Swapping to Mp3FileReaderBase with an NLayer decompressor instead — NLayer.NAudioSupport added to Spectralis.Core.csproj — since NLayer is a pure managed decoder and doesn’t care what OS it’s on. Not committed yet, wanted to sit with it first. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who just found out MP3 playback only worked on one OS. Q: Was Spectralis actually cross-platform before this fix? A: For anything that wasn’t MP3 audio, sure. For MP3 specifically, only on Windows, silently, this whole time. Q: Why leave the audio fix uncommitted? A: Swapping a decoder for something this central deserves a beat of “does this actually sound right” before it goes in, not just “does it build.” Q: What’s the difference between Streamer Queue and the regular request queue? A: Streamer Queue is host-controlled — add, mark played, mark skipped, from the streamer’s side, with its own history panel, separate from the public submission flow. Q: Did shared play or Streamer Queue touch the Discord bot? A: No, this round’s entirely Spectralis.App/Spectralis.Core and the Rust backend. Bot’s untouched. —This is the end*— *end for now, ACM codecs permitting PARROT!!!
Spectralis devlog #7 — welcome 5.4.0 —Hello again proggers— 5.4.0’s out. This one brought back a feature I’d basically buried, hardened two systems that were still a little too trust-me-bro, and finally let shared play open where it should’ve been opening the whole time. Also touched the docs, which I’m choosing to be proud of. Cat or dog? .spectralis print(f”I try to make stu{2f} which {actually_ships} {5.4.0}”) Okay let’s get into it~ —Yap— Big one this round is stories coming back into .spectralis capsules, except not as the thing they used to be — modernized, closer to how album worlds work now, as a proper custom HTML page with real hooks instead of whatever they were before. Rest of the release was hardening and cleanup: Streamer Queue and Discord got a pass to make sure live use doesn’t fall over, shared play finally opens in-app, and the docs stopped lying about what the app actually does. bringing back a feature I killed is a personality trait at this point —The Great Suffering— 1 — Stories Are Back, But Not The Same Stories Old stories concept is back inside .spectralis capsules, rebuilt to match how album worlds work now instead of resurrecting the original implementation as-is. Each one’s a custom HTML page with real hooks into the player — starting tracks, track control, the works — instead of being a static bolt-on. Bringing it back meant actually integrating it with the current architecture, not just copy-pasting the old version back in. 2 — Streamer Queue + Discord Got Hardened Both of these existed and mostly worked, which is different from “survives actually being used live by a streamer with chat moving.” Went through and hardened the interaction between Streamer Queue and the Discord bot — the stuff that only shows up under real load or real edge cases instead of a clean local test run. “mostly works” is doing a lot of lifting in software 3 — Shared Play Opens In App Now Shared play used to need you to go find it. Now there’s an actual open-in-app implementation, so joining a shared room is a real in-app flow instead of a workaround. Small change on paper, but it’s the difference between a feature people use and a feature people forget exists. 4 — Docs, README, and STANDARDS Actually Match Reality Updated the docs, README, and STANDARDS to reflect what’s actually in the app at this point instead of an earlier version of it. Boring work, necessary work, the kind of thing that only gets noticed when it’s wrong. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who buried a feature and then dug it back up two versions later. Q: Why bring stories back instead of leaving them dead? A: Because the concept was good, the old implementation just wasn’t, and album worlds proved the modernized version of the idea actually works. Q: What counts as “hardening” for Streamer Queue and Discord? A: The stuff that only breaks under real conditions — live chat, real timing, real edge cases — not the happy path you get testing solo. Q: Does shared play opening in-app change how sessions work? A: No, same sessions, same presence/reactions/queue from devlog #6. Just a real entry point now instead of a workaround. Q: Anything left over for next time? A: Always. This is a devlog series, not a finish line. —This is the end*— *end for now, capsule hooks permitting 再见!!!
Spectralis devlog #8 —Hello again proggers— 10 hours 48 minutes. Again. Didn’t plan it, didn’t notice it happening, just looked up and the sun had done a full cycle. This time it was capsules and worlds actually getting built and tested for real instead of just existing in theory. we’ve been here before and we will be here again Cat or dog? Capsule.story + Capsule.visualizer print(f”I try to make stu{2f} which {actually_coexist} {10h48m_later}”) Okay let’s get into it~ —Yap— Stories came back in devlog #7 as a concept. This round was making and testing the first actual .spectralis capsules and worlds built on that concept, which is a different job entirely — turns out “the architecture supports it” and “a real capsule with a real story actually works” are two very different milestones. Also fixed a bug that only shows up once you’re actually testing real capsules instead of imagining them, and a GitHub pull issue that had nothing to do with any of this and ate time anyway. —The Great Suffering— 1 — Building And Testing The First Real Capsules And Worlds Most of the 10 hours 48 minutes, honestly. Going from “stories and worlds work in concept” to actually authoring capsules, loading them, and confirming the hooks — track start, track control, the custom HTML page — behave the way they’re supposed to under real content instead of a test stub. This is the part where theory meets “wait, why is this blank.” 2 — A Story And A Visualizer Couldn’t Both Exist In One Capsule Found this one while testing, not before. A capsule with both a story and a visualizer defined would break, since apparently the two weren’t built to coexist in the same capsule at all. Fixed so a single capsule can hold both without one stepping on the other. the two features that were supposed to be siblings turned out to be enemies 3 — GitHub Was Being Weird About Pulling Somewhere in the middle of all this, git decided pulling wasn’t going to just work. Fixed the pulling issue, which is the kind of fix that has no interesting story attached, it was just broken and then it wasn’t. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who said “quick test” and looked up 10 hours 48 minutes later. Q: Was the story/visualizer bug there since devlog #7? A: Presumably, yes. Nobody had actually tried putting both in one capsule until this round. Q: What does “testing capsules and worlds” actually involve? A: Authoring real ones, loading them in the app, and checking the hooks — track start, track control, custom HTML rendering — behave correctly with actual content, not placeholder data. Q: What was the GitHub pulling issue? A: Not going into detail, it wasn’t interesting, it was just broken. Fixed now. Q: Is this the last capsule/worlds devlog? A: No idea. Ask devlog #9. —This is the end*— *end for now, git remotes permitting PEPPERONI!!!
Spectralis devlog #9 — 5.4.0 is public —Hello again proggers— 5.4.0 is actually out, publicly, in people’s hands. Diffed v5.3.4 through v5.4.0: 40 commits, Aug 16-18, four threads of work. Cat or dog? spectral.resume() —Yap— Shared play became joinable, Streamer Queue and the Discord bot got hardened, story/visualizer bugs got chased down in one sitting, and some platform/perf issues got caught. None of these were small. —The Great Suffering— 1 — Shared Play Can Be Joined Now spectralis://shared-play/join links used to fall through to nothing. Now routed to a real handler. 2 — Streamer Queue: Host Controls + A Bot That Won’t Die Host can add tracks and mark played/skipped directly, no viewer round-trip. Desktop got an add-to-queue button and history panel. Both pollers (desktop + bot) back off dead rooms instead of hammering them. SQ API calls got a 10s timeout + one retry, GETs only — mutating calls don’t retry, to avoid double-submitting on a timed-out-but-successful response. Bot had zero global error handlers before this. One bad promise took the whole process down silently. Now it logs and survives, plus 3-attempt startup retry. 3 — Story Pages vs. Visualizers: Three Bugs, One Afternoon A capsule with both used to have them fight. Story can now queue a surface behind it — TryAdvancePastStory() swaps in the queued surface on spectral.resume(). Audio was starting under the story before the reader finished — now gated on whether a surface is queued. Once queued, picker/prev-next/keyboard could still hijack it — new IsVisualizerLocked blocks all three (user-picked “Special:” visualizers stay switchable). 4 — Platform + Perf Fixes MP3 decoding silently depended on Windows’ ACM codec via Mp3FileReader. Swapped to NLayer, pure managed decoder — MP3s decode on Linux/macOS now too. WebView2Host inline-rendered small visualizers via NavigateToString, which serves from about:blank with no real origin and tanks frame rate — everything goes through the fast file-backed path now. Auto-cycle switching checked IsLoaded/IsPlaying, both false during Spotify playback since Spotify never loads into the local engine — switched to HasTrack/IsPlaying. And: a regex stripping onclick=”…” had no exception, matched JS identifiers like onSomething =, and being quote-unguarded ate everything to the next stray quote anywhere later in the file. Fixed with a -block carve-out. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who’s been waiting on shared play join links forever. Q: Was shared play really host-only until now? A: Yes. The link existed, it just went nowhere. Q: How bad was the regex bug? A: Silent corruption of unrelated code anywhere later in the file, no error thrown. Very glad it’s found. Q: Is 5.4.0 stable? A: As far as testing shows. That’s what everyone says right before the hotfix. —This is the end*— *end for now, public users permitting PEBBLE!!!
Spectralis devlog #10 —Hello again proggers— 11 hours, zero sleep, and somewhere in the middle of that a full release went out. v5.4.1, then v5.4.1.2 right behind it because apparently one patch release wasn’t enough punishment for one night. sleep is a scheduling conflict I lost Cat or dog? winmm.dll Okay let’s get into it~ —Yap— Started as a normal patch pass and turned into a full Linux compatibility audit at 3am, because it turns out shipping something cross-platform means actually checking what “cross-platform” was quietly lying about. Found four separate ways the app was secretly Windows-only, fixed all of them, shipped twice. —The Great Suffering— 1 — winmm.dll Doesn’t Exist On Linux, Who Knew Something was calling into winmm.dll directly. Which is a Windows multimedia API. Which does not exist on Linux. Genuinely did not know this was happening until it broke loudly. “who knew” is doing a lot of work in that commit message 2 — Shipped A .exe To Linux, My Bad Somewhere in the build/packaging step, a .exe was ending up in the Linux build. An executable format Linux does not run. Not a subtle bug, just an embarrassing one. 3 — Song Wars Closing = Surprise Alt+F4 Closing Song Wars was apparently also closing the entire app, unprompted, no warning. A feature window doubling as a kill switch is not a feature, it’s a trap. 4 — Yeeted yt-dlp + ffmpeg Into Linux Land, Zero Installs Needed The actual fix underneath most of this: bundled yt-dlp and ffmpeg directly for Linux instead of assuming they’d already be installed system-wide, which they very often weren’t. Zero external installs needed now, it just works out of the box. 5 — Last Page Isn’t A Dead End Anymore Merged in from feature/story-pager-finish — reaching the last page of a story used to just… stop. Dead end, nothing to do. Fixed so it actually resolves properly instead of leaving you stranded on the final page. 6 — Two Releases In One Night v5.4.1 went out, then a second pass turned up enough left over that v5.4.1.2 followed right after. Both merged through staging same night, same sleepless stretch. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who found out about winmm.dll at 3am. Q: Was Spectralis actually broken on Linux before this? A: In at least four distinct ways, yes. Missing binaries, a stray .exe, a Windows-only DLL call, and an app-closing bug. Now fixed. Q: Why two patch releases instead of one? A: v5.4.1 went out, more got found immediately after, and waiting felt worse than just shipping v5.4.1.2 same night. Q: Did you actually not sleep? A: Correct. Not recommending it. Doing it anyway next time, probably. Q: Is Linux actually solid now? A: As solid as one very long, very tired night of testing can confirm. Time will tell the rest. —This is the end*— *end for now, sleep schedules permitting PIBBLE!!!
Spectralis devlog #11 —Hello again proggers— Docs got a full rework this round. Also turns out v5.4.1 went out to nobody, because it never actually got pushed to the CDN. Tagged, released, announced probably, and completely inaccessible the whole time. shipped a release into a void and called it done Cat or dog? docs/ Okay let’s get into it~ —Yap— Started as a documentation pass and ended with the realization that the last release had been sitting local this whole time instead of where anyone could actually get it. Two very different kinds of work, same devlog. —The Great Suffering— 1 — The Entire Doc Rework Not a touch-up, a full rework. Docs, README, and STANDARDS all got restructured rather than patched in place, since patching them individually over the last several devlogs had left them internally inconsistent with each other and with what the app actually does now. 2 — 5.4.1 Never Made It To The CDN The actual headline bug of this devlog. v5.4.1 shipped, in the sense that it was built, tagged, and probably announced somewhere — but never got pushed to the CDN, meaning nobody could actually download it. Public-facing, and it was quietly broken the whole time until someone noticed. a release that ships to nowhere didn’t really ship 3 — Fixed And Actually Pushed Corrected the CDN push so 5.4.1 is genuinely available now, not just tagged in git looking like it is. Also part of why the doc rework mattered — docs referencing a version nobody could download was its own kind of lie. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who tagged a release and forgot the part where people can actually get it. Q: How long was 5.4.1 unavailable? A: Long enough to be embarrassing, short enough to fix before it became a real problem. Caught during this pass. Q: Why redo the docs entirely instead of patching them again? A: Because incremental doc patches across several devlogs had drifted apart from each other and from the app. A full rework got everything back in sync at once. Q: Is this the same CDN that serves changelogs now (devlog #5)? A: Same one. This time the release binary itself was the thing missing, not just content. Q: Anything else quietly broken that hasn’t surfaced yet? A: Unknown by definition. That’s what the next devlog is for. —This is the end*— *end for now, CDN pushes permitting POPPY!!!
Spectralis devlog #12 —Hello again proggers— Website’s getting a real pass. Not new copy this time, actual visual identity work, because it currently reads like every AI startup landing page that ever came out of the middle of California, and Spectralis is not that. gradient blob, bold sans headline, “revolutionize your workflow” — no Cat or dog? theme.css Okay let’s get into it~ —Yap— Not released yet, deliberately. This one’s still in progress, but close enough that it’s worth logging before it’s done instead of only after. The goal’s simple to say and annoying to actually do: stop looking generic. —The Great Suffering— 1 — The AI-Startup Look Had To Go Somewhere along the way the site had drifted into the exact aesthetic every seed-stage AI company in the Bay Area ships with — same fonts, same soft gradients, same layout rhythm everyone’s using because everyone else is using it. None of that says anything about what Spectralis actually is. 2 — Actual Visual Identity Work Working through what the site should look like instead of what’s easy to reach for by default. This is the slow part — not writing more copy, actually deciding what the thing looks like and why, instead of inheriting a template’s opinions by accident. 3 — Not Done, Getting Close Deliberately not shipping this mid-rework. Better to land it as one coherent pass than dribble out half-finished visual changes and confuse anyone who lands on the page in between. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one trying to make a music app’s website stop looking like a fundraising deck. Q: What specifically screamed “AI startup”? A: The general vibe more than any one element — the kind of design every YC-adjacent landing page converges on when nobody makes an active choice. Q: Why not ship incrementally instead of waiting? A: A visual identity rework half-applied looks worse than the thing it’s replacing. Waiting for it to be coherent. Q: How close is close? A: Close. Not “next devlog” close necessarily, but visibly closer than devlog #11 left it. Q: Does this touch the changelog-from-backend system from devlog #5? A: No, that infrastructure stays as-is. This is purely visual. —This is the end*— *end for now, gradient blobs permitting POGO!!!
Spectralis devlog #13 —Hello again proggers— Still on the website. Turns out the “make it not look like AI made it” problem does not have an easy exit — everything ends up looking like AI made it no matter what gets tried. Also had to ask Claude how to center a div. Yes, that div. The one every developer has fought since the dawn of CSS. the irony of asking an AI how to make something look less AI-made is not lost on me Cat or dog? display: flex Okay let’s get into it~ —Yap— Round two on the visual rework from last devlog, and the honest update is: it’s harder than expected. Every direction tried still lands somewhere in “generic modern web design,” which might just be what modern web design looks like right now regardless of who’s making it. —The Great Suffering— 1 — Everything Still Looks Like AI Made It Tried multiple directions this round trying to get away from the generic look. Kept landing back in the same neighborhood anyway. Starting to suspect this isn’t a “try harder” problem, it’s just what the current design language space looks like from basically every angle right now. 2 — Had To Ask Claude How To Center A Div The oldest joke in frontend development, still funny because it’s still true. Got stuck on it anyway. Some things never stop being annoying regardless of how many years of CSS have gone by. flexbox has existed for a decade and this is still where we are 3 — Pulled Up W3Schools For The First Time In Forever Dug up an old W3Schools reference mid-debugging, and it is dusty as hell at this point but the information’s still correct. Sometimes the ancient reference site is exactly what’s needed, aesthetics of the source be damned. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who asked an AI to help make something look less like an AI made it. Q: Did the AI-startup look actually get fixed this round? A: Not fully. Still fighting it. That’s most of this devlog. Q: Why does everything converge on the same generic look? A: Best guess: current tools and current design trends both nudge toward the same handful of patterns, so escaping it takes more than just trying different colors. Q: Is W3Schools still reliable? A: Apparently yes. Dated presentation, correct information. Q: When’s the website actually done? A: Closer than devlog #12, not there yet. Ask devlog #14. —This is the end*— *end for now, centered divs permitting PEPPLE!!!
Spectralis devlog #14 —Hello again proggers— Site’s done. Actually done. Got it to a place I actually liked instead of just a place I was tired of looking at, and shipped it. Three devlogs of fighting the generic-AI-look problem and it finally landed somewhere that feels like Spectralis instead of every other landing page on the internet. took long enough Cat or dog? git push origin main Okay let’s get into it~ —Yap— After devlog #12 and #13’s whole ordeal of everything converging on the same generic design no matter what got tried, something finally clicked and stuck. Shipped it. Two honest confessions on the way out the door, might as well log them here instead of pretending otherwise. —The Great Suffering— 1 — It’s Live The full rework from the last two devlogs is done and pushed. Went from “everything looks like AI made it” to something that actually feels intentional. Whatever finally broke the streak, it worked. 2 — The Help & Manuals Tab Is A Placebo Button Full transparency: the Help & Manuals tab on the site exists, looks real, sits right where you’d expect it, and does essentially nothing right now. It’s there because a site without one looks incomplete, not because there’s real content behind it yet. Consider it a placeholder wearing a real button’s clothes. it’s not lying, it’s aspirational 3 — I Copied FL Studio’s Homepage. Hard. Not going to pretend otherwise: leaned on FL Studio’s site pretty heavily for structure and layout ideas here. And honestly, that’s just how this works — programming, design, all of it is borrowing from people who borrowed from the people before them. Nobody’s inventing layout from first principles in 2026. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who finally shipped a website after three devlogs of fighting it. Q: Is Help & Manuals actually going to do anything eventually? A: Presumably, someday. Right now it’s a promise the button is making on behalf of a future devlog. Q: Isn’t copying FL Studio’s homepage kind of a big deal? A: Structure and layout inspiration, not a straight copy-paste. And realistically, every site borrows from something — this one’s just being honest about the source. Q: Did the “everything looks like AI” problem from devlog #13 actually get solved? A: Yes, finally. Whatever changed between then and now worked. Q: What’s next now that the site’s shipped? A: I finally get to ship my project without worrying about AI looking websites —This is the end*— *end for now, placebo buttons permitting PLACEBO!!!
Spectralis devlog #15 —Hello again proggers— I lied. Posted devlog #14 saying the site was done and shipped, and the deploy pipeline crashed basically the second it went out. So that’s fun. On the bright side, v5.4.2 also went out this round, and it’s actually solid. “it’s done” is apparently my curse word Cat or dog? dequeue() Okay let’s get into it~ —Yap— Website pipeline ate itself right after devlog #14 posted, which is its own kind of poetic. Meanwhile the app side had a genuinely good run — six real fixes landed, one of them embarrassing enough to name directly. —The Great Suffering— 1 — The Website Pipeline Crashed Right After I Said It Shipped Devlog #14 said done. Pipeline said otherwise, immediately. Working on getting it back up, this is very much a “developing situation” and not a “resolved” one yet. 2 — Listener Requests Auto-Queue Now Requests from listeners now auto-queue instead of needing a manual step to actually land in the queue. 3 — Audio Literally Never Played, Whoops Exactly what it says. Somewhere in there, audio just wasn’t playing. Found and fixed, extremely glad this one got caught. a music player where the music doesn’t play is a bold minimalist statement 4 — Found It: Join Links Were Missing A Slash Root cause of a chunk of shared-play join weirdness — the links were missing a slash. One character. Fixed, join links actually resolve correctly now. 5 — Host Room Button Actually Tells You Something Now The host room button used to just sit there. Now it actually communicates state back to you instead of leaving you guessing whether anything happened. 6 — Host Room Was Dropping Every Tick Forever Host room had a bug where it was dropping on every single tick, indefinitely, rather than staying stable. Fixed so the room actually holds instead of degrading in real time. 7 — yt-dlp Was 5 Months Stale, Updated The bundled yt-dlp from devlog #10 hadn’t been touched in 5 months. Updated. Stale extraction tooling breaking silently is exactly the kind of thing that sneaks up on you. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who called the website shipped and got immediately humbled by CI. Q: Is the website back up yet? A: Working on it. Genuinely not resolved as of this devlog. Q: How long was audio actually broken for? A: Not specified, but “literally never played” is about as bad as this category of bug gets. Fixed now. Q: Was the missing-slash bug related to the join link work from devlog #9? A: Yes, same feature area, this was the actual root cause of some of the lingering weirdness there. Q: Is 5.4.2 stable? A: As far as testing shows. Same disclaimer as always applies. —This is the end*— *end for now, deploy pipelines permitting PARABLE!!!
Spectralis devlog #16 —Hello again proggers— Short one. Found the website pipeline issue from devlog #15. Cat or dog? sudo —Yap— It wasn’t the code. It was permissions. The site was calling root but never actually had access to root, which is exactly why it worked fine locally and fell over the second it hit deployment. “It woRKS On My macHiNe” — the oldest curse in software, and I said it unironically. classic —This is the end*— *end for now, root access permitting PAPAYA!!!
Spectralis devlog #17 —Hello again proggers— 12 hours. All-nighter. Zero sleep. Feature isn’t in the app. Nothing shipped. This is the devlog where I explain what an entire night of work bought me, and the honest answer is “a very expensive lesson.” worth it? absolutely not. did i learn something? also debatable Cat or dog? catch (ApiDoesNotExistException) Okay let’s get into it~ —Yap— Got ambitious. Decided Spectralis should integrate with everything — Pandora, Amazon Music, a bunch of other big platforms on top of what already works. Turns out “everything” includes a lot of services that simply don’t offer a public API to integrate with in the first place, and finding that out was not the fast part of the night. —The Great Suffering— 1 — The APIs Just Don’t Exist Pandora, Amazon Music, and others: no public API to build against. Not “hard to find,” not “poorly documented,” just not there. Should’ve been step zero, ended up being the thing that derailed the entire night once discovered mid-build instead of before starting. 2 — So I Built Backdoors Instead Spent a huge chunk of the 12 hours reverse-engineering and building unofficial access paths instead, since the front door didn’t exist. This is the kind of work that eats hours and produces nothing you can point to until it’s fully working, if it ever gets there. 3 — Most Of Them Were Already Patched Implemented several of these backdoor approaches only to find out the platforms had already closed the exact gaps being exploited, sometimes before the implementation was even finished. Built things that were dead on arrival by the time they existed. patched before i even shipped it, incredible timing 4 — Asked Claude, Got A Hallucinated Answer, Followed It Anyway At the point of giving up, asked for a way to make it work anyway. Got a confident-sounding approach back that didn’t actually correspond to anything real, and followed it blindly instead of verifying it first, because by that point it was hour 10-something and verifying things sounded like more effort than it was. 5 — Ripped The Whole Feature Out End state: none of it works, none of it can work without real API access that doesn’t exist, so the entire feature attempt got stripped back out of the codebase. 12 hours, one commit’s worth of net progress, and that commit is the revert. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who just found out platforms without public APIs stay that way for a reason. Q: Is any of this coming back later? A: Not until there’s an actual, real, non-reverse-engineered way in. Not chasing patched backdoors again. Q: Should you have asked Claude earlier instead of at hour 10? A: Probably. Should also have double-checked what it said instead of following it blind at 4am. Two separate lessons from one night. Q: Was any of the 12 hours useful? A: Now know definitively which platforms are and aren’t worth attempting. That’s the only thing salvaged. Q: Sleep status? A: Catastrophic. Handling that before touching code again. —This is the end*— *end for now, actual sleep permitting Im gonna go pass out on the couch ADIOS!!!
Spectralis devlog #18 —Hello again proggers— First real demo capsule is live. Not a screenshot, not a “trust me it works” — an actual .spectralis file you can grab and open yourself, right after devlog #17’s night of nothing. Felt good to ship something that isn’t a revert for once. redemption arc, one demo file at a time Cat or dog? demo.spectralis Okay let’s get into it~ —Yap— Wanted the first public demo to actually show off what a capsule can do, not just be a proof of concept nobody can open. So it’s a full one: real track, real hand-timed lyrics, and a visualizer built specifically for it instead of a generic default. —The Great Suffering— 1 — The Demo’s Live demo.spectralis is up at cdn.deltavdevs.com now. First capsule anyone outside this devlog series can actually download and open. 2 — The Track And The Lyrics Built around Black Coast’s “TRNDSTTR” (Lucian Remix). Lyrics for it were timed and written into the capsule by hand — not pulled from some export, actually sat down and did the timing work myself. 3 — The Visualizer’s Custom, Not A Default Also built the visualizer specifically for this capsule instead of shipping the demo with a stock one. Wanted the first thing people see from Spectralis to actually demonstrate what the capsule format can do end to end — audio, synced lyrics, and a visual built to match, all in one file. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one downloading the first real capsule demo. Q: Where’s the demo? A: cdn.deltavdevs.com/spectralis/demo.spectralis — direct download, no wrapper page. Q: Did you write the lyrics yourself or pull them from somewhere? A: Wrote and timed them in by hand for this capsule specifically. Q: Is the visualizer reusable for other capsules? A: Built for this one specifically, but nothing stopping it from getting adapted or reused as a base for others later. Q: Is this what stories/capsules from devlog #7-#8 were building toward? A: Exactly that. This is the first one actually finished and out in the world instead of just being tested locally. —This is the end*— *end for now, capsule downloads permitting PARODY!!!
Spectralis devlog #19 —Hello again proggers— v6 LTS is on the horizon. Scheduled time with a friend who actually owns a Tim Cook machine, fingers crossed a Mac build comes out the other side of that session actually working. praying to the WWDC gods Cat or dog? arm64 Okay let’s get into it~ —Yap— First real LTS push. Different mindset than the last 18 devlogs of feature work and 3am bug hunts — LTS means stability first, and it also means finally taking a real swing at macOS instead of leaving it as a someday problem. —The Great Suffering— 1 — Prepping For v6 LTS Getting the groundwork in place for the first Long Term Support build. Less “ship the coolest thing,” more “ship the thing that won’t need constant babysitting after release.” 2 — Borrowing A Friend’s Mac Don’t own a Mac. Scheduled dedicated time with a friend’s actual Apple hardware to attempt a real build instead of guessing blind or fighting a CI-only setup with no way to actually test the output. 3 — The Honest Caveat: Mac Support Will Lag Straight talk: limited access to Mac hardware means Mac builds will very likely only get LTS releases going forward, and will land late relative to betas and regular updates on other platforms. Not ideal, but better to say it now than pretend otherwise. can’t test what you can’t touch —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one borrowing a friend’s Mac because Apple hardware access is not a given. Q: Will Mac users get every update? A: Realistically, no — LTS builds only for the foreseeable future, and later than other platforms. Access to hardware is the bottleneck, not desire to support it. Q: Why prioritize LTS over a beta cycle right now? A: Stability’s the actual goal for v6. Betas can come later once the LTS foundation’s solid. Q: Is the Mac build guaranteed to work this session? A: No promises. That’s what “fingers crossed” means. Q: What happens if the Mac session doesn’t go well? A: Try again next time hardware access lines up. Not giving up on it, just constrained by it. —This is the end*— *end for now, Tim Cook machines permitting PRINCIPLE!!!
Spectralis devlog #20 —Hello again proggers— Two zero. Milestone devlog, and it’s a good one: LTS is about to actually go out the door, Mac included, today. we made it, barely, on no sleep, as tradition demands Cat or dog? git revert HEAD 7 Okay let’s get into it —Yap— Spent the whole night doing QoL and QA on all the tiny bugs that had been getting pushed aside devlog after devlog. Turns out “small bugs” and “easy to fix” are not the same category, and the whole night proved it the hard way. —The Great Suffering— 1 — Hydra Bugs Every single one of the small deferred bugs got patched, and every single patch spawned about three new ones in its place. Fix one, watch three grow back. Felt less like debugging and more like fighting something with a regeneration mechanic. cut off one head, three more show up, name a more accurate bug report 2 — Tried Claude Code Out Of Exhaustion Got tired enough mid-hydra-fight to set up Claude Code and hand off some of the grind. It did not go well — ended up rearranging the repo and commit layout in ways that made the history a mess, not the bugs. 3 — Had To Undo Its Commits Rolled back what Claude Code did and went back to fixing things manually. Lesson for the night: handing off a messy, deep-in-it repo state to an agent mid-crisis is not the same as handing off a clean one. 4 — Actually Got All The Tiny Bugs Out After all of that, the hydra’s actually dead. Every deferred small bug from the last 19 devlogs finally cleared in one sitting, which is the whole reason today’s release is happening at all. 5 — Mac Release, Today Following up on devlog #19’s borrowed-Mac build attempt — releasing to Mac today alongside everything else. First real payoff from that session. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who fought a hydra of bugs all night and won, barely. Q: Did Claude Code actually break anything functional, or just the repo layout? A: Just history and commit structure, nothing shipped broke because of it. Still a mess worth undoing. Q: Is this LTS build the one from devlog #19’s prep? A: Yes, same one. This was the final QA gauntlet before it goes out. Q: Is Mac really getting it today? A: That’s the plan, following through on the borrowed-Mac build session from last devlog. Q: 20 devlogs in, anything you’d do differently? A: Sleep more, probably. Not going to happen, but it’d be the right answer. —This is the end*— *end for now, hydra heads permitting PROPERTY!!!
Spectralis devlog #21 —Hello again proggers— Flagged for “AI website” again. By Shipwrights this time. Getting a little tired of this specific accusation, honestly — a commit log sitting right there would show actual work happening over actual time, but apparently that’s a few extra minutes nobody wants to spend. the receipts exist, nobody’s asking to see them Cat or dog? git log –oneline Okay let’s get into it~ —Yap— Third redesign of the site now. Not because the flag was right, but because if this keeps happening it’s worth just making the “looks AI-made” argument harder to make at all, regardless of whether it was ever a fair read in the first place. —The Great Suffering— 1 — Flagged Again Shipwrights flagged the site as AI-generated. Same accusation as the devlog #12-#14 saga, different flagger this time. Slightly more annoying with each repeat, since the actual work history’s right there for anyone willing to look. 2 — The Annoying Part It’s not that the site got flagged, it’s that the disproof is trivially available — commits, timestamps, iterative changes across three separate rebuilds — and checking that apparently isn’t part of the process. Frustrating, not devastating. 3 — Redesigned It A Third Time Rather than fight the flag directly, changed the site again. Third pass now, and it genuinely reads less like generic AI-slop territory than the last version did. Whether that satisfies the next flag or not, it’s a real improvement on its own merits. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who’s redesigned this website three separate times partly to dodge a false flag. Q: What’s Shipwrights? A: The one doing the flagging this round. Q: Is the flag actually accurate? A: No — there’s a real commit history behind the site across devlogs #12 through #14 and now this one. The flag’s wrong, just annoying to keep disproving. Q: Does this redesign replace the one from devlog #14? A: Yes, third full pass on top of that one. Q: Any plan if it gets flagged a fourth time? A: Probably the same plan: keep the receipts, keep improving the site anyway, move on. —This is the end*— *end for now, false flags permitting PALPABLE!!!
Spectralis devlog #22 —Hello again proggers— Posting this before I pass out for real. And no, that wasn’t me faceplanting the keyboard, that was the cat walking across it. Very important distinction. the cat gets a commit credit for that one, honestly Cat or dog? cat, apparently, tonight specifically Okay let’s get into it~ —Yap— Back on the ever-growing pile of bugs and QoL from devlog #20’s hydra fight — turns out killing all the tiny bugs once doesn’t mean they stay dead forever, more just showed up in the meantime. Made real progress anyway. —The Great Suffering— 1 — A Few Spotify Bugs, Actually Squashed Chased down and fixed a handful of Spotify-side bugs this round. Not a full audit like earlier devlogs, just real ground covered on stuff that’s been sitting in the pile. 2 — Resizing QA Went through resizing behavior across the app and did a real QA pass on it — the kind of thing that’s easy to skip until someone resizes a window in a way you never tested and everything looks wrong. 3 — The Multi-Channel Stream Queue Idea Had the idea to implement multi-channel support for Streamer Queue. Started on it, and it’s genuinely probably too big to land fully before LTS ships — most likely going in as a stub for now rather than a finished feature, with the real implementation following after. “horrible idea” is doing some self-aware lifting there and I stand by it —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who mistook a cat for their own exhaustion, and honestly it could’ve gone either way. Q: What’s a “stub” mean for multi-channel here? A: The scaffolding and interface exist, the real functional implementation doesn’t yet. Placeholder with intent, not a real feature. Q: Is this the same bug pile from devlog #20? A: Same pile, refilled since then. Small bugs apparently regenerate on their own schedule, not just when you’re actively fighting them. Q: Why is multi-channel “horrible” if you’re building it anyway? A: Because scope-wise it’s a lot more than it looks like on paper, and admitting that upfront beats pretending it’s simple. Q: Sleep status tonight? A: About to happen, actually, this time. Cat’s taking the credit either way. —This is the end*— *end for now, sleepy cats permitting PEOPLE!!!
Spectralis devlog #23 —Hello again proggers— Introducing the visualizer editor. Been sitting on this one for a while without announcing it, for a very specific reason: every single time it felt ready, the format changed again and “ready” moved further away. Think it’s actually real this time. announced it in my head about six times before this devlog Cat or dog? visualizer.format Okay let’s get into it~ —Yap— Grinding all night on this one, branch and v1 dropping tomorrow. No promises beyond that, just the plan and the fact that this has been quietly cooking for way longer than any single devlog has let on. —The Great Suffering— 1 — Why This Wasn’t Announced Sooner Kept hitting the point where the editor felt done, then rethinking the underlying format and starting that part over. Easier to just not announce something that keeps changing shape than to keep walking back a “it’s ready” claim in public. 2 — v1 And The Branch, Tomorrow Committing to it now — v1 and the branch land tomorrow. Whole night’s going toward getting there, which given the last 22 devlogs of this project is either a great sign or a very familiar warning sign. history suggests: could go either way 3 — What The Visualizer Editor Actually Is A real editor for building visualizers instead of the visualizer side of the app staying built-in-only. Ties back to everything from the capsule/worlds work in devlogs #7 and #8 and the custom visualizer built for the demo capsule in devlog #18 — this is the tool version of doing that by hand. 4 — Hackatime Also Just Died (Or My PC Did) On top of everything else, Hackatime seems to be down, or my PC’s cooked, unclear which yet. Either way tracked hours for tonight are now undefined. Yipee. unlogged hours are the best kind of hours, said nobody’s time tracker ever —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one about to pull yet another all-nighter for a feature reveal. Q: Why did the format keep changing? A: Each pass revealed a new limitation once actually used for real, and fixing that meant reworking the format again rather than shipping something known to be wrong. Q: Is this related to the demo capsule visualizer from devlog #18? A: Same territory. That one was hand-built. This is the editor meant to make building one not require doing it by hand. Q: What’s “v1” mean here specifically? A: First real usable version, branch-only for now, not a full public release yet. Q: Any risk this slips again? A: Always possible given the track record, but committing to tomorrow specifically this time. —This is the end*— *end for now, format stability permitting PEPLE!!!
Spectralis devlog #24 —Hello again proggers— Rewrote the README a third time. Not because it was wrong, because proper prose and actual formatting apparently reads as “completely AI” to whoever’s judging it, and I’m too burnt out to keep arguing that point. So it just got redone instead. can’t fight the vibes, can only rewrite around them Cat or dog? README.md Okay let’s get into it~ —Yap— Small win buried in the exhaustion: website’s on version 4 now and it didn’t get flagged this time. First one that made it through clean since devlog #21 started this whole saga. Progress, even if the README’s now on its third rewrite for reasons that have nothing to do with whether it’s actually good. —The Great Suffering— 1 — README Rewrite #3 Same content, restructured again, because well-formatted prose keeps getting read as an AI tell regardless of who wrote it or how. Not going to keep relitigating this one, just redid it and moved on. 2 — Website v4 Survived The actual good news. Fourth pass on the site, first one that didn’t get flagged. Whatever combination of changes from devlog #21 onward finally landed right. 3 — Hoping The App Gets Checked Next If the docs and the website keep clearing review, maybe eventually the actual app gets looked at instead of just the surface-level stuff around it. That’s the real hope here — less time defending prose formatting, more time on the thing that actually matters. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one whose actual writing keeps getting mistaken for a machine’s. Q: Why does formatted prose get flagged as AI? A: Genuinely unclear, and at this point not worth the energy to keep contesting. Rewriting around it was faster than arguing it. Q: Is this the fourth full website redesign? A: Yes — devlog #14, then #21’s rework, and now this pass, landing clean. Q: Has the app itself ever been flagged? A: Not yet, and that’s sort of the point of this devlog — hoping it stays that way, or at least gets a fair look if it comes up. Q: How’s the burnout? A: Present. Noted. Continuing anyway. —This is the end*— *end for now, formatting opinions permitting PEEL!!!
Spectralis devlog #25 —Hello again proggers— Short one, I’m about to pass out for real this time. Ground away at the visualizer toolkit for a long stretch and it’s still nowhere near done. another one for the “not as close as I thought” pile Cat or dog? too tired to pick one honestly Okay quick version~ —Yap— Same visualizer editor territory from devlog #23, except the format not-changing this time didn’t mean the finish line got any closer. Long grind, real progress somewhere in there probably, just not a done toolkit at the end of it. —The Great Suffering— 1 — The Toolkit Isn’t Close Put in a long stretch on it and it’s genuinely still far from finished. Not a small gap either, just more scope than one exhausted session could close. 2 — I’m Cooked That’s the whole update. No dramatic bug story tonight, just hours in and not enough left to keep going. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who should probably close the laptop now. Q: Is this the same visualizer editor from devlog #23? A: Same one. Still cooking, longer than expected. Q: Any specific blockers? A: Too tired to write them up properly tonight. Next devlog, probably, once there’s actual sleep behind it. Q: When’s it landing? A: Unknown. Not this session. —This is the end*— *end for now, actually sleeping this time POOL!!!
Spectralis devlog #26 —Hello again proggers— Still grinding the visualizer toolkit from devlog #25. Fueled up properly this time — favorite tunes on, Coke Zero and a Monster Ultra on deck, going the entire night. Also, small detour: past me apparently gave in and used Electron at some point, so present me now has to relearn it from scratch. past me makes decisions present me has to live with, name a more accurate description of software Cat or dog? require(‘electron’) Okay let’s get into it~ —Yap— Two threads tonight: the toolkit grind continuing from last devlog, and a genuinely surprising discovery on the Mac build front that’s going to need its own hotfix branch. —The Great Suffering— 1 — Relearning Electron Past-me committed to Electron somewhere along the way and current-me forgot most of it. Spending part of tonight just getting back up to speed on something that used to be second nature. Annoying, but at least it’s a known quantity once it clicks back in. 2 — The Toolkit, Still Grinding Same visualizer toolkit as devlog #25. Not done yet, but the night’s young and there’s caffeine involved. Hoping to actually close real ground on it before LTS needs to be ready. 3 — Mac Build Actually Compiles Now Following up on devlog #19’s borrowed-Mac session — got it to build and compile this time. Real progress on a front that’s been genuinely hardware-constrained the whole way. 4 — Turns Out Mac Isn’t Windows Or Linux (Shocking, I Know) Here’s the surprising part: a lot of the build scripts turned out to be Windows/Linux-centric, and Mac is, in fact, neither of those operating systems. Somehow this wasn’t obvious until actually staring at a failing script on real Mac hardware. three major desktop OSes and somehow I only accounted for two of them 5 — Hotfix Branch Incoming Need to spin up a hotfix specifically for the platform-assumption problem in the scripts, and hoping it merges back clean without conflicts. Given tonight’s track record so far, cautiously optimistic. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who forgot their own framework choice from past-self. Q: Why Electron in the first place? A: Decision from before this devlog series apparently, reasons unclear at this hour, dealing with the consequences now regardless. Q: Is the Mac hotfix urgent? A: Ties directly into whether LTS with Mac support actually holds together, so yes, fairly urgent. Q: Was assuming Windows/Linux-only scripts really a mistake nobody caught until now? A: Apparently so. Borrowed-Mac hardware access from devlog #19 finally exposed it. Q: Toolkit status vs. hotfix status tonight — which wins? A: Whichever gets further before the caffeine runs out. Probably both get some progress. —This is the end*— *end for now, merge conflicts permitting PROPER!!!
Spectralis devlog #27 —Hello again proggers— Still going. Decided mid-grind to switch off JSON-based saving entirely and move to a proper binary streamed format instead — faster save/load, way less CPU overhead. Which sounds like a clean upgrade until you realize it means reading books on binary format design that were probably written before I was. my caffeine and my reading list have diverged wildly tonight Cat or dog? BinaryWriter Okay let’s get into it~ —Yap— The pivot away from JSON wasn’t planned going into tonight, it just became obviously worth it partway through the toolkit grind. Now stuck in the part of the process nobody enjoys: documentation, theory, and CS ideation before any of the actual implementation gets to happen. —The Great Suffering— 1 — JSON’s Getting Replaced Moving off JSON-based saving to a binary streamed format. The reasoning’s simple — faster save/load, meaningfully less CPU usage — but simple reasoning doesn’t mean simple implementation. 2 — Reading Books Older Than Me Digging into binary streaming format theory means reading material that predates this whole project by a wide margin, some of it by a lot more than that. Foundational stuff, just not exactly light reading at this hour. 3 — Documentation And Theory Hell Currently deep in the least glamorous part of any format redesign: reading documentation, working through theory, and CS ideation before writing a single line that actually does anything. Necessary, still miserable at 2am. the implementation is the fun part and it’s still hours away 4 — Sun Came Up, Had A Sandwich, Kept Going Watched the sunrise somewhere in the middle of the theory reading. Had an egg and bacon sandwich for breakfast, genuinely delicious, best part of the night so far. No sleep planned until tonight — just powering through on breakfast fuel instead. breakfast during an all-nighter hits different —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one reading format-design theory older than their own project at 2am. Q: Why move off JSON now, mid-grind? A: Became clear it was the right call while working on the visualizer toolkit — better performance characteristics were worth the detour. Q: Is this related to the toolkit from devlog #25/#26? A: Same overall session, this is a scope addition that came up while working on it. Q: When does actual implementation start? A: Once the theory and documentation phase actually resolves. Not there yet. Q: Is tonight ever going to end? A: Not until tonight, apparently — sun’s already up and there’s no sleep planned before then. —This is the end*— *end for now, binary formats permitting PAM!!!
Spectralis devlog #28 —Hello again proggers— LTS 6 is out. Genuinely out, not “shipped to nowhere” out like devlog #11. Sleep deprivation’s fully caught up though — first chance I get, I’m passing out on the couch with the cat and that’s non-negotiable at this point. the cat’s getting a co-author credit at this rate Cat or dog? couch, specifically, with the cat, immediately Okay let’s get into it~ —Yap— Long stretch from devlog #26 through here finally paid off. LTS 6 pushed, and the major macOS decoding problems from the borrowed-Mac build sessions actually got fixed. Real progress, real exhaustion, both at once. —The Great Suffering— 1 — LTS 6 Is Out Following the hydra-bug fight in devlog #20, the Electron relearn and Mac hotfix in #26, and the binary format detour in #27 — it’s actually pushed now. Linux and Windows builds are the ones going out first. 2 — Major macOS Decoding Problems, Fixed Following up on the platform-assumption bug from devlog #26, where Windows/Linux-centric scripts choked on Mac being neither — dug into the actual decoding issues on macOS and got the major ones resolved this round. 3 — Mac Release Is Coming, Just Not Today No Mac hardware access again until Monday, so the macOS build follows a bit after Linux/Windows instead of dropping same-day. Same access constraint from devlog #19, still the bottleneck, still the plan. 4 — Sleep Is Winning Officially out of gas. Couch, cat, first available window. This devlog is basically the victory lap before collapsing. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one about to lose consciousness on a couch next to a cat, mission accomplished. Q: Is LTS 6 out for everyone right now? A: Linux and Windows, yes. macOS is coming shortly after once Mac access is available again Monday. Q: Were the macOS decoding problems from the script issue in devlog #26? A: Related territory, yes — once the platform-assumption bug got flagged, the deeper decoding issues underneath it got found and fixed too. Q: Any concerns going into the Mac release specifically? A: Nothing unresolved as of this devlog, but access is still limited to occasional sessions, so timing’s dependent on that. Q: What’s next after this? A: Sleep. Genuinely, actually sleep, before anything else touches this project. —This is the end*— *end for now, couch naps permitting thud Zzzzzz!!!
Spectralis devlog #29 —Hello again proggers— The studio’s finally looking like a real UI tool instead of a collection of windows held together by vibes. Two design references pulled this round: Godot for world editing, and Adobe After Effects for capsules. stealing good ideas from great tools is called “design research,” look it up Cat or dog? Ctrl+Shift+F Okay let’s get into it~ —Yap— Studio’s been the least polished part of the whole app for a while, mostly functional, rarely pretty. This round actually leaned into real interface design instead of just adding buttons where they fit, borrowing structure from two tools that already solved similar problems well. —The Great Suffering— 1 — Godot-Inspired World Editing World editing took cues from Godot’s editor layout — the way it structures a scene tree, viewport, and inspector panel together as one coherent workspace instead of scattered windows. Applying that same structural thinking to world editing here, since worlds are conceptually similar: a tree of pieces you’re arranging in space. 2 — After Effects-Inspired Capsules Capsule editing leaned on After Effects instead, specifically the layer/timeline/composition mental model. Capsules are time-based and layered by nature — a story surface, a visualizer, audio all stacked together — so a timeline-and-layers metaphor fits better than a flat property list ever did. 3 — The Studio Finally Feels Like A Tool Combined, these two reference points are what’s pushing the studio from “internal dev utility” toward something that actually feels designed for someone to sit down and use, not just something built incrementally to unblock whatever feature needed it that week. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one borrowing UI patterns from two very different but very good tools. Q: Is this a full rewrite of the studio UI? A: More a restructuring around better mental models than a ground-up rebuild, but it touches a lot of surface area. Q: Why Godot for world editing specifically? A: Scene/viewport/inspector is a well-worn pattern for spatial editing, and worlds are fundamentally a spatial arrangement problem. Q: Why After Effects for capsules? A: Capsules stack time-based layers — story, visualizer, audio — which maps naturally onto a timeline/layers workflow instead of flat settings. Q: Does this connect to the visualizer toolkit grind from devlogs #25-#27? A: Same broader authoring-tools push, yes, this is the UI side catching up to that work. —This is the end*— *end for now, layer panels permitting POP!!!
Spectralis devlog #30 —Hello again proggers— Following up on the studio redesign from last devlog — actually building inside that new layer system now. Lyric importer, a bezier tool that fought back the whole way, and capsules jumped to full HD. 30 devlogs in and the bezier tool still almost won Cat or dog? bezier.controlPoint Okay let’s get into it~ —Yap— Layers from devlog #29’s redesign got real functionality built on top of them this round, plus a genuinely useful new import path and a resolution bump that should’ve probably happened earlier. —The Great Suffering— 1 — Layer Fixes Cleaned up a handful of issues in the new After Effects-style layer system from last devlog — the kind of rough edges that only show up once you’re actually building real content in it instead of just looking at the layout. 2 — Lyric Importer: Auto Vector Layers + Keyframing New importer that takes lyric timing and automatically generates vector layers, keyframed to match. Turns what used to be manual layer-by-layer, keyframe-by-keyframe setup into an actual import step. Big time save for anything lyric-driven, including future capsules like the demo from devlog #18. 3 — A Few More Bugs, Squashed Small round of additional fixes alongside the bigger items, nothing individually dramatic. 4 — Capsule Resolution: Bumped To Full HD Capsules render at full HD now instead of whatever lower resolution they were capped at before. Straightforward upgrade, noticeably better output. 5 — The Bezier Tool (Which Was Hell) Added a real bezier curve tool to the timeline/layer editing. Genuinely brutal to get right — curve math, control point handling, and making it feel intuitive to actually drag are three different hard problems stacked on top of each other. Worth it, but it fought back the whole way. bezier curves: simple in theory, a nightmare in an actual editor UI 6 — Timeline And Tool QoL Assorted quality-of-life improvements across the timeline and tools generally — the small friction-reduction stuff that adds up once you’re using the studio for real work instead of just testing it. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who just fought a bezier tool and mostly won. Q: Does the lyric importer work with the demo capsule from devlog #18? A: That one was hand-timed and hand-built before this importer existed — this tool’s for making the next ones faster. Q: Why was the bezier tool specifically so hard? A: Curve math, control point interaction, and UI feel all had to work together, and getting any one of them wrong makes the whole tool feel broken. Q: Is full HD the resolution ceiling now, or is higher coming later? A: Full HD is what shipped this round. No commitment yet on going higher. Q: Is the studio redesign from devlog #29 basically done now? A: Getting real functionality built on it, which is a good sign, but still ongoing. —This is the end*— *end for now, control points permitting PALPABLE!!!
Spectralis devlog #31 —Hello again proggers— More QoL, a real bug fixed in world editing, and a proper in-depth test run of the whole thing. Honest verdict after actually using it for real: still sucks, still hate it, but it’s at least somewhat usable now. Progress, technically. “somewhat usable” is a real milestone when you started from “actively bad” Cat or dog? node.isCorrupt Okay let’s get into it~ —Yap— World editing’s been the newer, rougher part of the studio since the Godot-inspired redesign in devlog #29. This round was about actually running it through its paces instead of just building on top of it, and that testing found a real problem. —The Great Suffering— 1 — More QoL Another pass of small quality-of-life improvements, continuing the trend from the last couple devlogs. Nothing individually huge, all of it adds up. 2 — The Bad Node Bug Found and fixed a genuinely bad node bug in the world section during testing. The kind of bug that only shows up once you’re actually building real worlds instead of poking at an empty editor. 3 — The In-Depth Test Run Took world editing for a real, thorough run this time instead of a quick sanity check. Built something with actual substance in it and used the tool the way it’s meant to be used. 4 — The Honest Verdict Still sucks. Still hate using it. But after this round of fixes and QoL, it’s crossed into “somewhat usable” territory, which is more than could be said before this session. low bar, cleared, moving on —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who just admitted their own tool still sucks and shipped it anyway. Q: Is world editing done now? A: No, “somewhat usable” is the current state, not “finished.” More work ahead. Q: How bad was the node bug? A: Bad enough to matter, found through actual real-world testing rather than a quick check. Q: Is this related to the layer work from devlog #30? A: Different area — that was capsules/timeline, this is world editing specifically. Q: What’s the plan to make world editing not suck? A: Keep testing it for real, keep fixing what that testing turns up. This devlog’s the start of that loop, not the end. —This is the end*— *end for now, corrupted nodes permitting PAPLE!!!
Spectralis devlog #32 —Hello again proggers— Mac’s out. Actually out, actually available, actually done. Took way longer than expected — the site needed updating and every single update script needed fixing before this could actually go out the door clean. “we got mac out” undersells how much site and script work that actually took Cat or dog? .pkg Okay let’s get into it~ —Yap— Closing the loop that started way back in devlog #19 with a borrowed Mac and a hopeful “fingers crossed,” went through the decoding fixes in devlog #28, the platform-assumption hotfix in devlog #26, and now it’s actually shipped. Quick policy reminder while we’re here, since it matters going forward. —The Great Suffering— 1 — The Site Needed Updating First Before Mac could actually go out, the site itself needed real updates to reflect it — new download option, new platform messaging, none of which existed yet. Took a real chunk of the time this release ate. 2 — Every Update Script Needed Fixing Following up on the Windows/Linux-centric script assumptions caught back in devlog #26 — turns out that wasn’t a one-off fix, it touched update scripts broadly. Had to go through and fix them properly for Mac to actually be able to update itself going forward, not just install once. 3 — Mac Is Actually Out After all of that: it’s live. Full journey from borrowed hardware sessions to an actual public release. 4 — Reminder: Mac Only Gets LTS Quick policy note, stated plainly since it matters: Mac only receives LTS releases going forward, not minor updates, unless a minor is a Mac-specific patch. Same access-constraint reasoning from devlog #19 — this isn’t changing anytime soon, so setting the expectation clearly now. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who just found out “ship Mac” secretly meant “rebuild the update pipeline.” Q: Does Mac get every LTS release? A: Yes, every LTS. Just not the minors in between, unless that minor is Mac-specific. Q: Why not give Mac full parity now that it’s out? A: Hardware access is still the bottleneck — same reasoning as devlog #19, testing and building for Mac isn’t a routine, always-available thing yet. Q: What took so long between the decoding fixes in devlog #28 and now? A: Mostly the site and update script work described above — the actual build was closer to ready than the delivery pipeline around it was. Q: Is this the end of the Mac saga? A: The release side, yes. Ongoing maintenance is just going to follow the LTS-only cadence from here. —This is the end*— *end for now, update scripts permitting POP!!!
Spectralis devlog #33 —Hello again proggers— First real wave of feedback since Mac shipped in devlog #32, and it’s been genuinely good. Patching a handful of bugs people actually pointed out, plus one quick clarification for a specific rater who had a question. real users, real feedback, feels different from testing solo Cat or dog? feedback.md Okay let’s get into it~ —Yap— Shipping to actual people instead of just self-testing changes the kind of bugs that surface. Round of patches based directly on what came in, plus a couple of housekeeping notes. —The Great Suffering— 1 — Real Feedback, First Time At This Scale Genuinely solid feedback wave since the Mac release. Different flavor of bug reports than internal testing ever produces — actual usage patterns finding things a solo QA pass wouldn’t. 2 — Patching What Got Pointed Out Working through the specific bugs raised by that feedback. Direct fixes for direct reports, exactly the kind of loop that’s supposed to happen once something’s actually in people’s hands. 3 — Quick Note For A Specific Rater One rater asked about the track used in devlog #1 — it’s a custom remix of “Delete” by Ninjirachi. DM if you want the file. 4 — How To Reach Out For anyone hitting issues with the app: Slack works, or Discord at @deltav0rtex . Genuinely want the reports, keep them coming. 5 — A Surprise Is Coming Next Ship Got something tucked away for the next release that should land well. Not spoiling it here, staying quiet on purpose. Minor patch for this round’s QoL fixes drops within the next two days. teasing it and saying nothing else, that’s the whole bit —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one actually reading feedback instead of guessing what’s broken. Q: How do I report a bug? A: Slack, or Discord — @deltav0rtex . Q: What was that track in devlog #1? A: A custom remix of “Delete” by Ninjirachi. DM for the file if you want it. Q: Is the current bug list from this feedback wave big? A: Manageable, working through it directly rather than batching for a bigger release. Q: Any plans to formalize a feedback/bug channel later? A: Not stated yet, current setup is DMs and Slack for now. Q: What’s the surprise for next ship? A: Not saying. That’s the point of a surprise. Q: When’s the minor QoL patch dropping? A: Within the next two days. —This is the end*— *end for now, bug reports permitting PARABLE!!!
Spectralis devlog #34 —Hello again proggers— Still on the devlog commits grind. The surprise from devlog #33 is actually finished now, releasing alongside the next Stardance ship as soon as this current one clears. Meanwhile, spent this round scouring the app for small edge cases and UI stuff that’s been quietly overlooked. the surprise is done, the suspense is not Cat or dog? edge_case.md Okay let’s get into it~ —Yap— Two tracks this devlog: the surprise from last time is locked and ready, waiting on the current ship to clear before it goes out with Stardance. In the meantime, doing a proper sweep for the small stuff — edge cases and UI rough edges that don’t show up unless you’re specifically hunting for them. —The Great Suffering— 1 — The Surprise Is Finished Whatever it is, it’s done. Releasing with the next Stardance ship, not this current one — has to clear first. Still not saying what it is. still not telling you, patience 2 — Scouring For Edge Cases Going through the app specifically looking for edge cases that got missed during normal feature work — the inputs and states nobody thinks to test until something breaks in a very specific, very rare way. 3 — UI Stuff That Got Overlooked Alongside the edge cases, hunting down small UI issues that slipped through — spacing, alignment, states that don’t look quite right, the stuff that’s easy to miss when you’re heads-down building instead of using the app like a regular person would. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one hunting edge cases nobody else would think to try. Q: What’s the surprise? A: Patience, my dear child. Q: Why wait for the current ship to clear first? A: Cleaner to let one release settle before stacking the surprise onto the next one. Q: Any specific edge cases found yet? A: Sweep’s ongoing, nothing dramatic enough to call out individually yet. Q: Still not saying what the surprise is? A: Correct. Ask again next devlog. —This is the end*— *end for now, edge cases permitting PERISHABLE!!!
Spectralis devlog #35 —Hello again proggers— Long way from v5.3.0, that’s for sure. New ship’s cooking, and it’s built directly off the feedback wave from devlog #33 — took what came in and actually built more on top of it. Also, the big one this round: video export is here. 35 devlogs from “last ship” to this Cat or dog? .mp4 Okay let’s get into it~ —Yap— This one’s a real feedback-driven ship, not just internal roadmap stuff. Fed reports and requests all the way back from devlog #2’s post-first-ship feedback into the app, and video export was the headline addition that came out of it. —The Great Suffering— 1 — Feedback Actually Became Features Everything that came in since devlog #2, right after the very first ship, finally got folded back into this release, not just patched as bugs but expanded into more app. Real loop from “here’s what’s wrong/missing” way back then to “here’s it, fixed and built out” now. 2 — Video Export Is Here For music makers who want something to post — YouTube, Klipy, wherever you’re posting cool stuff — Spectralis can now export video directly instead of just playing audio and visualizers live. Been a long time coming given how much the visualizer/capsule work has built up across devlogs #7, #18, #23, and #29-#30. 3 — This Is The New Ship, Not The Finished One Announcing the direction this round more than closing it out — the surprise from devlog #33/#34 still rides along on this too. Full picture coming as it actually ships. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who just got a whole export pipeline for their trouble. Q: What can video export actually do? A: Exports your visualizer/capsule output as an actual video file, suited for posting to platforms like YouTube or Klipy. Q: Is this the same ship as the Stardance surprise from devlog #34? A: Same overall release window, yes. Q: How much of this came directly from user feedback? A: A meaningful chunk — some of it going all the way back to devlog #2, right after the very first ship. Q: When’s it actually dropping? A: Still in progress. This is the announcement, not the release. —This is the end*— *end for now, export pipelines permitting PS: couldn’t find a good meme this time, so you get corporate gif slop instead. Enjoy. PICKLE!!!
Spectralis devlog #36 —Hello again proggers— Last log before 6.0.1 tries to ship to everyone. Except Mac, remember? If anyone — and by anyone I mean basically no one — has the app downloaded already, you should see the update land fairly soon. “anyone” carrying a lot of self-deprecation in that sentence Cat or dog? v6.0.1 Okay let’s get into it~ —Yap— Four things landing in this round: video export from devlog #35 finally patched back in properly, the about page expanded, a real EQ upgrade, and more webview bugs cleared out. Then it’s out the door. —The Great Suffering— 1 — Video Export, Actually Patched In Announced back in devlog #35, and this round it’s actually working and patched into the build for real instead of just existing as a headline feature nobody could touch yet. 2 — About Page, Expanded Grew the about page out — more actual content instead of the bare-minimum version it’s had this whole time. 3 — A Far More Advanced EQ System Real upgrade here: new EQ with envelope styling and a handful of presets. Meaningfully more capable than whatever was there before, for anyone who actually cares about shaping their sound instead of just hitting play. 4 — More Webview Bugs, Patched Following the WebView2Host fast-path fix from devlog #9, a few more webview-related bugs got cleared out this round. Apparently that surface keeps finding new ways to misbehave. webview bugs are the gift that keeps on giving 5 — 6.0.1 Ships, Mac Excluded (Still) Same LTS-only policy from devlog #32 applies — Mac isn’t getting 6.0.1 as a minor. Everyone else should see the update land soon. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one about to auto-update basically no one to 6.0.1. Q: Why doesn’t Mac get 6.0.1? A: Same policy from devlog #32 — Mac only gets LTS releases, not minors, unless it’s a Mac-specific patch. Q: What’s new in the EQ system specifically? A: Envelope styling plus a set of presets, a real step up from the previous version. Q: Is video export from devlog #35 fully working now? A: Yes, patched in properly this round. Q: When does 6.0.1 land? A: Fairly soon, per this devlog, for anyone who already has the app installed. —This is the end*— *end for now, update pushes permitting PEBBLE!!!
Spectralis devlog #37 —Hello again proggers— Working through the feedback wave from the ship, including an upcoming maybe-new streaming service integration. Reverse engineering, again, yay. Also completely forgot Hackclub’s 10 hour limit was a thing and ran 5 hours over it. It’s fine. Everything’s fine. last time reverse engineering a streaming service ate 12 hours and produced nothing, so this is either growth or déjà vu Cat or dog? HKEY_LOCAL_MACHINE Okay let’s get into it~ —Yap— Post-ship feedback turned into real changes fast, and one of them’s a streaming service integration that’s back to reverse-engineering territory — hopefully with better luck than the devlog #17 saga. Also, format note: switching up how devlogs get posted going forward. —The Great Suffering— 1 — Maybe New Streaming Service Support Working on possible support for another streaming service, and since it doesn’t have a public API either, that means reverse engineering again. Learned some hard lessons from devlog #17’s all-nighter about this exact kind of work, applying them here — verifying before implementing, checking whether something’s already patched before sinking hours into it. 2 — 15 Hours, Not 10 Completely lost track of Hackclub’s 10 hour session limit and blew past it by 5 hours. Not the plan, happened anyway, no regrets loud enough to stop it from happening again probably. time limits are more of a guideline when you’re mid-flow 3 — A Format Change, By Request People like the meme format but keep asking to actually see the project itself, which is fair — problem is most of what’s happening is engine work, and a screenshot of raw code just doesn’t communicate much on its own. Going to try posting an actual screenshot as the first image and keep the meme as the second, going forward. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who just blew past a 10 hour limit by half again as much. Q: Is this streaming integration going to end like devlog #17’s did? A: Hoping not — going in more carefully this time given how that one went. Q: Why not just show code screenshots if people want to see the project? A: Raw engine code doesn’t communicate much visually to most people. Trying to find screenshots that actually show something meaningful instead. Q: Will the meme format go away? A: No, staying as image two. Just adding an actual project screenshot as image one. Q: How’s the feedback wave going overall? A: Productive, this streaming service idea being one direct result of it. —This is the end*— *end for now, session limits permitting POSSIBLE!!!
Spectralis devlog #38 —Hello again proggers— Suno’s integration broke after their latest TOS update, so that got fixed. Also added Discord Rich Presence control for capsules, started chasing down a batch of connections that quietly broke or got dropped over time, and picked up a fun trivia fact along the way: Suno apparently hosts on AWS S3. a TOS update breaking an integration, name a more classic story Cat or dog? S3:// Okay let’s get into it~ —Yap— Mixed bag this round: one reactive fix from an external platform change, one genuinely new feature, and the start of a cleanup pass on integrations that have been quietly rotting since whenever they last got touched. —The Great Suffering— 1 — Suno Integration, Fixed Suno’s newest TOS update broke the existing integration. Patched it back up to work with the new terms. Reactive fix, not a fun one, but necessary. 2 — Capsule DRPC Control Real new feature: Spectralis capsules can now control Discord Rich Presence, so a capsule can show custom status while it’s playing instead of the app just showing generic now-playing info. 3 — Chasing Down Broken And Dropped Connections Going through existing integrations that broke with newer updates on the other end, or that got dropped along the way and never revisited — untitled.stream compatibility being one specific example. Working through the backlog of “this used to work” one at a time. 4 — Suno Hosts On AWS S3 Small fun discovery while poking around the integration: Suno’s hosting is on AWS S3. Not actionable, just neat to know. 5 — Looking For New Platforms Actively looking for what to integrate with next. Feedback on what platforms people actually want would genuinely help shape this. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one whose integration broke because someone else updated a TOS page. Q: What’s DRPC? A: Discord Rich Presence — the status shown under someone’s name in Discord. Capsules can now set custom status through it. Q: What’s untitled.stream compat about? A: One of the connections that broke or got left behind at some point — being actively worked back into shape. Q: What platforms are being considered for new integration? A: Not decided yet, genuinely open to suggestions. Q: Was the Suno fix hard? A: Not conceptually, just annoying — an external change forcing reactive work instead of planned work. Q: What’s the image order now? A: Changed my mind again — meme first, app screenshot second this time. The devlog #37 order didn’t stick. —This is the end*— *end for now, TOS updates permitting POP!!!
Spectralis devlog #39 —Hello again proggers— All-nighter, running on 3 Monsters and a Coke Zero. Reverse engineering APIs is hard as hell, and untitled.stream in particular fought back the whole way. Also snuck in a fix for a Spotify library issue on the side. 3 Monsters and a Coke Zero is not a nutrition plan, it’s a battle strategy Cat or dog? 429 Too Many Requests Okay let’s get into it~ —Yap— Following up on devlog #38’s untitled.stream compat work — turns out “working on it” undersold how hard it actually was. Genuinely brutal reverse engineering session, plus a smaller fix that came out of the same stretch of work. —The Great Suffering— 1 — untitled.stream Was Particularly Hard To Crack Chasing this compatibility since devlog #38, and it turned out to be one of the harder reverse-engineering targets yet. No public API to lean on, so it was the usual slow grind of observing behavior and piecing together how it actually works under the hood. some APIs give up easy, this was not one of them 2 — Reverse Engineering APIs In General: Still Hard Not a new lesson given devlog #17’s whole saga, but worth restating: this category of work is consistently the hardest and slowest kind on the whole project. Going in with better patience and verification habits this time though, which helped. 3 — Spotify Library Polling, Increased Bumped how often libraries get polled to account for some Spotify-side issues that were surfacing. Smaller fix, but a real one, found and shipped in the same session. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who ran on three energy drinks to crack one integration. Q: Is untitled.stream compat actually working now? A: Meaningfully further along after this session, following up from devlog #38’s start on it. Q: Did this go better than devlog #17’s reverse-engineering disaster? A: Yes — hard and slow, but productive this time rather than a total dead end. Q: What was the Spotify polling issue specifically? A: Library state getting out of sync too easily — more frequent polling keeps it closer to accurate. Q: Sleep status? A: Same as every other all-nighter devlog. Not great. Worth it this time though. —This is the end*— *end for now, rate limits permitting PIPSQUEAK!!!
Spectralis devlog #40 —Hello again proggers— 10 straight hours, and the highlight is getting tricked by Suno’s own scraper path. There was a decoy path that looked exactly like the real music endpoint, and it just returned forbidden the whole time. Maybe I’m the bot in this scenario. Unclear. got outsmarted by a decoy URL, humbling Cat or dog? 403 Forbidden Okay let’s get into it~ —Yap— Continuing the reverse-engineering grind from devlog #39, Suno specifically threw a curveball this round. Beyond that, spent real time thinking about what the app actually is and why certain features exist, plus started tearing into Song Wars, which has apparently been quietly buggy for a while. —The Great Suffering— 1 — The Suno Decoy Path Suno provides a path that looks exactly like the real music endpoint, structurally identical, right down to how it responds at a glance. In reality it just returns forbidden every time. Spent real time thinking this was progress before realizing it was a dead end dressed up as a working one. maybe im the bot 2 — Actually Fixed It, After Testing Once the decoy was identified for what it was, found the real path and got it working properly. Testing it thoroughly this time before calling it done, given how devlog #39 went. 3 — Identity Of The App Spent real time thinking through what Spectralis actually is at this point, and justifying why certain features exist rather than just accumulating them because they seemed cool at the time. Less code, more “why does this exist and does it still make sense.” 4 — Song Wars Rework, Started Started tearing into Song Wars, which turns out to be hella buggy underneath. Early stages of a rework rather than a patch job, since patching individual bugs in it hasn’t been holding up. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one who got fooled by a decoy API path for a while. Q: Was the Suno issue related to the S3 discovery from devlog #38? A: Same general integration, different specific obstacle this round. Q: Is Song Wars getting a full rewrite or just fixes? A: Leaning toward a real rework rather than more patches, given how buggy it’s turned out to be. Q: What does “identity of the app” work actually produce? A: Not code directly — more a filter for which features actually belong and why, going forward. Q: How’s the 10 hour grind treating you? A: Productive despite the decoy detour. Real progress by the end of it. —This is the end*— *end for now, decoy paths permitting PAP!!!
Spectralis devlog #41 —Hello again proggers— Podcast mode’s in the works, with a real new way to actually find saved podcasts instead of digging for them. Also fixed the randomizing tools so they actually help pick a song instead of just existing decoratively. And: class got canceled for a hurricane watch, so tonight’s an all-nighter by default. free 10 hours courtesy of a hurricane, weird way to get them Cat or dog? shuffle(weighted=True) Okay let’s get into it~ —Yap— Two real features this round plus a forced schedule change. Podcast mode’s genuinely new territory for the app, the randomizer fix is a smaller but meaningful UX improvement, and the hurricane watch just handed over a full night that wasn’t originally planned for grinding. —The Great Suffering— 1 — Podcast Mode, In Progress Building out actual podcast support, including a new way to locate saved podcasts rather than just treating them like any other track and hoping they surface in the right place. Real new territory for the app compared to the music-first feature set so far. 2 — Randomizing Tools, Actually Useful Now The shuffle/randomizer tools existed before but weren’t really doing anything meaningful — mostly there in name. Fixed so they actually aid in song selection now instead of just sitting there as a checkbox nobody trusted. a randomizer that doesn’t actually help you pick anything is just decoration 3 — The Hurricane Watch Situation Class got canceled due to a hurricane watch, which means tonight’s turning into a full grind session that wasn’t originally on the calendar. Silver lining of a weather delay, I suppose. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one getting a bonus grind night courtesy of a hurricane watch. Q: Is podcast mode close to done? A: In progress, this devlog’s the early build phase, not the finish line. Q: What was actually wrong with the randomizer before? A: It existed but didn’t meaningfully help pick songs — more decorative than functional. Fixed to actually aid selection now. Q: Is Song Wars rework from devlog #40 still going? A: Ongoing, this devlog’s focus shifted to podcast mode and the randomizer instead. Q: Stay safe with the hurricane watch, by the way. A: Appreciated. Staying inside, staying coding. —This is the end*— *end for now, hurricane watches permitting POOL!!!
Spectralis devlog #42 —Hello again proggers— Spent this round hardening shared queues, mostly because WebSockets are just genuinely cool and it’s about time they got treated that way in this codebase. a devlog motivated entirely by “websockets are cool” is a valid devlog Cat or dog? ws:// Okay let’s get into it~ —Yap— Shared queues have been functional but not particularly resilient this whole time, riding on shared play’s presence/reactions/queue work from way back in devlog #9. This round was about actually hardening that layer instead of leaving it fragile. —The Great Suffering— 1 — Hardening Shared Queues Went through and shored up a bunch of the underlying bases for shared queues — the stuff that only matters once real connections are dropping, reconnecting, and behaving unpredictably instead of the clean happy-path test case. 2 — Because WebSockets Are Cool Genuinely part of the motivation here. Real-time bidirectional connections are just satisfying to get right, and shared queues are exactly the kind of feature that benefits from taking that layer seriously instead of treating it as plumbing. not every feature needs a dramatic bug story, sometimes it’s just “wanted to do it well” —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one hardening infrastructure purely because it’s fun to get right. Q: Is this related to the shared play work from devlog #9? A: Same general system, this round focused specifically on making the queue layer more resilient. Q: What does “hardening” mean here specifically? A: Making the shared queue behavior hold up better under real conditions — drops, reconnects, timing edge cases — rather than just the clean test path. Q: Any bugs found during this pass? A: Nothing dramatic enough to call out individually, mostly proactive resilience work. Q: What’s next? A: Podcast mode and the randomizer work from devlog #41 are both still ongoing threads. —This is the end*— *end for now, dropped connections permitting P_P!!!
Spectralis devlog #43 —Hello again proggers— [2:47am] okay so. websockets again, more of them, and now the CDN backup is failing too which is great, love that for me. on my 4th coffee at this point, energy drink count is starting to get concerning honestly and I’m not gonna pretend it isn’t. pretty sure i debugged the cdn thing at 4am purely out of spite Cat or dog? idk man catch (Exception e) { } at this point Okay let’s get into it, or at least try to~ —Yap— so continuing from devlog #42’s websocket hardening, turns out hardening one part just revealed the next part was also fragile, shocking, anyway. need to push something to prod to actually get it working but can’t do that without interrupting infra which is currently live so that’s a whole separate problem I have to solve first before I can solve the actual problem. love layers. —The Great Suffering— 1 — More Websocket Issues more of them. found while poking at the hardening from last devlog. not sure if figuring this part out took 20 minutes or 3 hours honestly, time’s doing something weird tonight. 2 — CDN Backup Is Failing on top of the websocket stuff, cdn backups just started failing too. not connected to each other as far as i can tell but who knows at this point, everything feels connected at 3am. 3 — Need To Push To Prod, Can’t Without Interrupting Infra the actual fix needs to go to prod but pushing it right now means interrupting live infra, which i don’t want to do blind, so now i need a plan for THAT before the real fix even goes out. process problem wrapped around the actual problem, great. 4 — Shared Play Is Doing The AI-Look Thing Again noticed shared play’s UI is drifting into the same generic-AI-looking territory the main site kept getting flagged for back in devlog #21-#24. damn. gonna have to redo that too. not tonight though, one disaster at a time. 5 — Oh And I Found A Missing Semicolon spent a genuinely embarrassing amount of time on a bug that turned out to be a missing semicolon. send help. actually don’t, just let me suffer, i clearly deserve it at this hour. 6 — No Sleep For 2 Days, Hitting Now it’s catching up. hard. luckily got tomorrow off so plan is stay up tongiht finish this, and just completely pass out tomorrow instead. worth it. probably. —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: a human programmer. you. the one reading this at whatever hour you’re reading it, hopefully not also running on 2 days no sleep Q: Is the websocket hardening from #42 actually working? A: mostly? finding more edge cases as i go, which is annoying but also kind of expected honestly Q: Why can’t you just push to prod now? A: because infra’s live and i don’t want to interrupt it blind, need an actual plan for that part first Q: Is shared play getting a full redesign again? A: yeah probably, later though, not adding a 4th fire to tonight Q: Sleep plan? A: none tonight, all of it tomorrow, that’s the whole plan —This is the end — *end for now, semicolons permitting send sleep!!!
Spectralis devlog #44 —Hello again proggers— Did it. Fixed a genuine ton of bugs, following through on the mess from devlog #43. Tempted to just drop 6.1.0 right now, but holding off — want to get a few new features in and brainstorm some more QoL first so this actually feels like a finished product, not just a stopgap. Also: finally going to bed. the bar was “fix the bugs” and I cleared it, going higher anyway Cat or dog? sleep(∞) Okay let’s get into it~ —Yap— Real closure on the websocket/CDN/prod chaos from last devlog. Cleared out a lot in one sitting, and instead of rushing 6.1.0 out the door on relief alone, choosing to actually sit with it a bit longer. —The Great Suffering— 1 — The Bug Backlog, Actually Cleared Worked through the fallout from devlog #43 — websocket issues, the CDN backup failures, all of it — and got a genuine ton of it fixed in one real pass instead of piecemeal patching. 2 — Holding Off On 6.1.0, On Purpose Could ship right now. Choosing not to. Want to work in a few new features and brainstorm more QoL first, so the release feels complete rather than just “the bugs are gone, ship it.” Patience over momentum this time. 3 — Finally Going To Bed After devlog #43’s two-days-no-sleep spiral, actually calling it and going to bed now. Today off is finally getting used the way it was supposed to be used. the sleep debt collector finally caught up —FAQ (no one asked these but they are here)— Q: What is a “progger”? A: A human programmer. You. The one about to get real sleep for the first time in a while. Q: Why not just ship 6.1.0 now if the bugs are fixed? A: Because “bug-free” and “actually done” aren’t the same bar, and this one’s worth clearing the second one too. Q: Was this the same chaos from devlog #43? A: Same fires, all put out this round. Q: What kind of new features are being considered? A: Not locked in yet — that brainstorming is the next step, not this devlog. Q: Sleep status, finally? A: Handled. Going now. —This is the end*— *end for now, actual sleep permitting PLAY!!!
Ships:
Spectralis shiplarp — v5.3.0 —shipped it— Notepads. A spin wheel. Dead zones that aren’t OBS-only anymore. Playlists that don’t look like a log file. Spotify that actually behaves. That’s the version. —what’s in it— Notepad system: docked panel, tabs, pop-out window, saves to track tags Spin wheel: weighted entries, saved wheel lists, notepad-fed Dead zones now shift the app’s own layout, not just OBS overlays Spotify: playlist sync, queue, pause, and Discord presence all fixed Fixed: playlist rows missing RowBackground (looked like a terminal, my bad) Fixed: nav rebuilding the entire view every click Fixed: library load blocking window open on big libraries Fixed: spectrum bars snapping instead of moving (FFT overlap bumped to 75%) Fixed: soundcloud playhead, word-mode timestamp export, track-switch click/pop —that’s it— PICKLE!!!
Spectralis shiplarp 2 — Stardance —wuzzup guys— So much has happened since shiplarp 1 and I cannot wait to not break down what changed. I will. I’m lazy. Not right now though. Cat or dog? redeem_code.claim() —the celebration— We’ve gone through so many changes since last time that it deserves an actual celebration: a very cool, very awesome custom visualizer for Stardance. Claim yours: Help > Manage Visualizers, then redeem stardance-lts-pulp . —found a bug?— Including the dreaded Tim Cook issues — DM me: Discord: @deltav0rtex Slack: deltavortex Can’t wait to hear the feedback and all the bugs you dig up. —this is the end*— *end for now, redeem codes permitting YIPEE!!!...
|
1792878434.706125
|
1793742434.706125
|
|
21799
|
Kursal by @Kubik | Stardance
|
Kubik
|
1
|
241.28
|
4494
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-09T19:31:18Z", "hours": 225.0, "multiplier": 17.91, "payout": 4494, "blessing": "neutral", "text": "I built Kursal! A peer-to-peer, decentralized (means no central server!) and end-to-end encrypted messenger. It’s all coded in Rust for the backend and Svelte for the interface. There’s also a website for it showing a bit everything, it’s cool Basically when you open your client, it connects to other clients and creates a “mesh” of clients, communicating through each other. I think a good comparison is a mix of Bitcoin and Tor? Anyway it took me super long to code, and I hope you enjoy!", "repo": "https://github.com/KursalChat/Kursal", "demo": "https://kursal.chat/download"}]...
|
[{"post_id": 79997, "ts": "202 [{"post_id": 79997, "ts": "2026-10-15T20:32:51Z", "hours": 9.2917, "text": "Shipped and received ratings, thank you guys! We reached 25 stars on GitHub Changes: various bug fixes… lol (and dependency bumps) iOS build! and signed mac build! meaning you can know open the app on mac without it saying “broken”! (this was a signing issue yes, the app is not actually broken…) got Kursal working for ARCH !! finally, arch users can now open the app :) Still trying to get published on the app store and google play…. damn I did not think it would take that long"}, {"post_id": 73960, "ts": "2026-09-26T12:21:34Z", "hours": 6.9917, "text": "that gotta be the last devlog 😅 Basically i just “routine maintenance” the repo ¯ \\ (ツ) /¯ spent time TRYING getting it on the app store or play store… it’s pain 😭 but i’ll get it eventually!"}, {"post_id": 64991, "ts": "2026-09-09T19:21:46Z", "hours": 6.4067, "text": "Hi! I’m done! (i hope lol) i’m still in the process of publishing to the app store and play store… but heh it takes so long i’ll ship before i’m approved there lol Changes: Few possible vulnerability fixes: only allow LAN devices to reach LAN-specific endpoints Show security codes when added locally Strip more image metadata (like GPS infos) on more formats"}, {"post_id": 59064, "ts": "2026-08-31T17:38:46Z", "hours": 12.395, "text": "for real last devlog lol, mostly “ci” changes, nothing much Changes: improved code blocks! it has colors :) (thanks highlight.js) thanks Tiazzz for translating into Dutch! android + IOS building code updater on mobile opens the mobile store (instead of breaking) I spent a LOT of time on the Google and Apple publishing websites….. it takes time to get an app published…. :/"}, {"post_id": 54519, "ts": "2026-08-25T15:29:28Z", "hours": 11.0444, "text": "okay i think that’s the last devlog before I ship! sorry for that long time devlog but i was in holidays lol Changes: Use autonat on clients to determine if they can act as public relays Complete rework of the onboarding screens Better QR codes :D Bug Fixes: Fixed some potential security issues in the frontend (injections) Rewrite a part of the front-end to group util functions and avoid redundant code AND!! i’m almost done with the camera rewrite! i’m in the process of migrating that to the rust backend but this means native “per-device” code. Almost done! here are the onboarding screens one by one, i cant add more than 4 attachments so you’ll have to try urself to see ;)"}, {"post_id": 51026, "ts": "2026-08-20T14:49:41Z", "hours": 10.2336, "text": "hi! another devlog! i just turned 18 Changes: switched the formatter from prettier to oxfmt (it’s faster!) changed the icon got approved on OpenCollective ! Bug Fixes: avatar transfers now always work even when the other is offline removed some useless code… lol (like migration code) spent lot of time trying to migrate camera to backend but that’s still in the works… soon™"}, {"post_id": 48329, "ts": "2026-08-16T17:17:49Z", "hours": 9.6311, "text": "wow time actually flies! gotta devlog again XD i made cool assets for the app store release Features: you can now delete log files from the app unlimited file transfers (file transfers already existed, but now no size limit!) Bug Fixes stop spamming connections to peers… lol big language loading improvements! now shows the percentage of translation too more avatar work to store it on disk and not in the DB you can now mirror your camera if you want :) defer android permission window thingy for those interested i used a figma template for the phones 3d + a plugin (that was so much pain but it looks great lol)"}, {"post_id": 47315, "ts": "2026-08-15T05:58:52Z", "hours": 10.5314, "text": "more changess!!! and lots of fixes lol oh also i have setup https://status.kursal.chat (but not tracked that time) Performance: improved performance for the database (parallel reading) improved performance (storage & ram) for emojis perf: store avatars in files instead of serialized in the Contact {} struct more performance changes (camera loading, command palette) Bug Fixes: tried keeping less active connections to not blow up the client lol fixed a svelte #each issue… lol"}, {"post_id": 45057, "ts": "2026-08-11T10:00:47Z", "hours": 10.0292, "text": "okay I got some more work in! I’m getting really close to shipping, i’d like to get a demo and a proper app icon first tho Changes better QR code scanning screen! and it works on iOS :D the bluetooth module got improvements! no unwrap left (= cannot panic now) + better transfer speed! compressed all image assets to webp (gained like at least few MB) translated again everything in french lol migrated some localStorage data (file-path association) to the encrypted database"}, {"post_id": 43310, "ts": "2026-08-08T14:38:07Z", "hours": 10.1664, "text": "Lots of work! but no release yet, i’m almost done for beta.6!! :D a major thing i worked on is Github actions release. Now, when I create the draft release, GH actions will build for every platform in parallel and release! Features Contact page complete rework (easier to understand :p), with autocorrect etc Call ringtone (probably temporary, but it’s shipped!) Bug Fixes Smaller offline messages checks Addresses display, general UI improvements Prefer local connections & improved file transfers MacOS .kursal file association"}, {"post_id": 41634, "ts": "2026-08-05T23:40:37Z", "hours": 10.2592, "text": "Released beta.4 and beta.5 with lots of improvements and fixes! I spent uh… some time on trying to make a ring tone (like an hour maybe?) but i cant upload it here :/ but whatever it’s not that good anyway lol Features Updater progress bar (spinner go spinnyyy) Major long-term code improvements: you can now select the number of uses and the time it expires Bug Fixes critical first-contact deadlock fix… (oopsy) Pinned & unread messages improvements More accurate user status and that’s basically it I guess!"}, {"post_id": 40748, "ts": "2026-08-04T14:08:58Z", "hours": 10.1056, "text": "Released beta.3 and currently reworking long-term codes for beta.4! not done yet, but it’s WIP :) Features app now embeds the latest ToS update date, so when you update and last agreed to a previous version it shows a pop up so you can agree again Bug Fixes lots of CI fixes… like really a lot 😅 re-enabled mDNS, kinda forgot to put it back… app displays edge-to-edge on mobile, no weird offset! (normally) grammar fixes in english and french… yeeah!"}, {"post_id": 38297, "ts": "2026-07-31T16:46:21Z", "hours": 9.8047, "text": "Released a beta.2 fixing lots of things and almost done with a beta.3 I think… :D What changed? first, i spent like 4 hours translating everything into french LOL Features Mobile native file sharing (this one is crazy!) Large messages send as file (10k+) In-app log view File caption (sends as msg) Bug Fixes Otp consumption Offline messages edits Contact onboarding mobile self-lock (yeah u couldnt do the onboarding on phone in beta.1 😅) File upload location & UI Less in-app notifications that’s it for this devlog! we’ll see if I ship now or wait a bit more? i really want something to work super well :p"}, {"post_id": 37588, "ts": "2026-07-30T12:50:51Z", "hours": 10.1344, "text": "Okayy! i started publishing clean commits now and working with my github structure. Basically: I code on branches, like feature/some-feature . once it’s done, I squash it to dev. And when I want to release, I just make a branch release/0.1.0 (with the actual version) and change few things there! What changed? DOCKER WORKING! you can now host your relays using it Kursal JS is out too, you can now use the app API! Large messages send as file (10k+) In-app log view File caption (sends as msg) fixes: App focus notifications Contact onboarding mobile self-lock File upload location & UI Less in-app notifications File downloads What next I’m currently working on adding the native “share with” for Kursal to share images and files directly from your OS."}, {"post_id": 36273, "ts": "2026-07-28T08:26:38Z", "hours": 11.1028, "text": "Alright i got the new repo up! What changed? lots of bug fixes (IT OPENS ON ANDROID!) ci improvements got mail sending working from the domain spent lot of time setting the new repo up released the first beta + website update What next? testing… and getting to a stable release :)"}, {"post_id": 34027, "ts": "2026-07-24T13:26:17Z", "hours": 9.9975, "text": "hi! probably last few devlogs before a release?! What changed? more website improvements! added legal pages (boring stuff lol) fixed so many bugs offline messages work now!! and calls too tray icon & background process :) LOTS OF TESTING. and lots of improvements too What next? finish testing and publishing to the repo!"}, {"post_id": 32311, "ts": "2026-07-21T12:19:37Z", "hours": 10.9506, "text": "nothing much changed, again What changed? lots of internal code structure, some logic bugs & stuff Added docker support for hosting a relay! Improved the website and prepared for a beta release (not published yet, will do) More .md docs to explain everything! but more importantly (the only visual changes lol) terminal user interface for the relay! --tui new home for the app! (with stats)"}, {"post_id": 29439, "ts": "2026-07-16T11:58:15Z", "hours": 9.4086, "text": "again, nothing much to see… but lots of internal changes! What changed? complete rust refactor: made macros for frequently used things, organized the code better & stuff like that some quality of life features for the frontend like pasting an image in the chat directly more tutorials explaining kursal (offline messaging, file transfers) What next? i’m preparing everything for a soon-ish release! it’ll be a public beta version and yeah! hope it works"}, {"post_id": 27997, "ts": "2026-07-13T23:28:00Z", "hours": 10.3989, "text": "oops forgot to devlog again… and no new features this time What changed? as i said…. well nothing lots of bug fixes lots of code improvements (refactor stuff…) some UI/UX improvements but like nothing too crazy What next? honestly I cannot tell. I think i’m gonna start to plan the release and finally push to the public repo. gotta get everything ready, more bug fixes and proofread the code I guess! PS: sorry i really got no screenshots to show here so uh… here’s the intro animation when you first open the app!"}, {"post_id": 23055, "ts": "2026-07-05T19:50:56Z", "hours": 9.2908, "text": "I tried getting a feature out…. but nope, only fixed bugs What changed? Added AEC (active echo cancellation) on some platforms: i have to compile FROM these platforms, like cross-compilation straight up does not work… sorry windows Fixed file transfers and improved it’s UI Fixed offline messaging… i hope i had to figure out how to compile audio libs to other platforms… that took me a while…….. thanks opus What next? uhhh good question? more tests maybe? and UI improvements i was thinking about making a background process run, separate from the app that would get messages so you can close the app while that runs… will have to look into it"}, {"post_id": 21137, "ts": "2026-07-02T22:50:54Z", "hours": 4.73, "text": "hi! Started testing Kursal and found…. bugs! so i spent quite some time fixing them… What changed? Connections between peers were unstable: increased timeout + fixed a rate limiter bug Improved the UI with a new “connected nodes” section (see screenshot) Added an option to change the sample rate (defaults to 48 kHz, but you can lower to improve potential lag) and small UI improvements like moving the call bar to the bottom which fits better What next? test. test. test. my goal is to release the app in beta before august and get the first stable version out mid-august… we’ll see!"}, {"post_id": 18715, "ts": "2026-06-29T21:55:38Z", "hours": 11.0786, "text": "yooo 3rd devlog :) sorry i’m not posting very often, i’d like to devlog feature by feature but they really take time… What changed? Fixed vulnerabilities (post-quantum encryption in mailbox system & useless signature removal) Managing nodes in the settings (like viewing and adding connections) A lot of UI improvements a bit everywhere! calls… work in progress! calls is the feature i’ve been working on for a while. I re-used the encryption mechanism of file transfers: make a temporary secret key and then use it. I got SOUND going!! What next? testing offline messaging (my friends were still offline) testing calls (a lot)! improving call UI"}, {"post_id": 16325, "ts": "2026-06-26T15:51:40Z", "hours": 11.6608, "text": "Hello Got a lot of improvements working! Mainly on the front-end but quite a lot on the backend too actually! What changed? Added a CMD+K / CTRL+K search menu (see screenshot): you can search for settings, contacts or even messages! Made the background of the DMG installation on mac Searching messages!! and a few skeletons for when stuff is loading backend fixes… lots of em… like fixed adding a contact What next? still test offline messaging, still didn’t do that somehow"}, {"post_id": 13211, "ts": "2026-06-21T17:18:01Z", "hours": 15.6786, "text": "Hii! First Kursal devlog! This is a project i’ve started during Flavortown but I wasn’t done yet! Sorry kinda didn’t see the time pass lol What changed? Website rebranding! –> https://kursal.chat Spent a lot of time setuping “side-projects” like an uptime manager, translation manager etc Reworked the workflow for building, checking & more Lots of UI/UX changes POSSIBLY working offline messaging… (will test lol) What next? I’m about to test offline messaging, the whole app too actually lol…… hope it all works 🙏"}]...
|
Title: Kursal by @Kubik | Stardance
Devlogs:
Hii! Title: Kursal by @Kubik | Stardance
Devlogs:
Hii! First Kursal devlog! This is a project i’ve started during Flavortown but I wasn’t done yet! Sorry kinda didn’t see the time pass lol What changed? Website rebranding! –> https://kursal.chat Spent a lot of time setuping “side-projects” like an uptime manager, translation manager etc Reworked the workflow for building, checking & more Lots of UI/UX changes POSSIBLY working offline messaging… (will test lol) What next? I’m about to test offline messaging, the whole app too actually lol…… hope it all works 🙏
Hello Got a lot of improvements working! Mainly on the front-end but quite a lot on the backend too actually! What changed? Added a CMD+K / CTRL+K search menu (see screenshot): you can search for settings, contacts or even messages! Made the background of the DMG installation on mac Searching messages!! and a few skeletons for when stuff is loading backend fixes… lots of em… like fixed adding a contact What next? still test offline messaging, still didn’t do that somehow
yooo 3rd devlog :) sorry i’m not posting very often, i’d like to devlog feature by feature but they really take time… What changed? Fixed vulnerabilities (post-quantum encryption in mailbox system & useless signature removal) Managing nodes in the settings (like viewing and adding connections) A lot of UI improvements a bit everywhere! calls… work in progress! calls is the feature i’ve been working on for a while. I re-used the encryption mechanism of file transfers: make a temporary secret key and then use it. I got SOUND going!! What next? testing offline messaging (my friends were still offline) testing calls (a lot)! improving call UI
hi! Started testing Kursal and found…. bugs! so i spent quite some time fixing them… What changed? Connections between peers were unstable: increased timeout + fixed a rate limiter bug Improved the UI with a new “connected nodes” section (see screenshot) Added an option to change the sample rate (defaults to 48 kHz, but you can lower to improve potential lag) and small UI improvements like moving the call bar to the bottom which fits better What next? test. test. test. my goal is to release the app in beta before august and get the first stable version out mid-august… we’ll see!
I tried getting a feature out…. but nope, only fixed bugs What changed? Added AEC (active echo cancellation) on some platforms: i have to compile FROM these platforms, like cross-compilation straight up does not work… sorry windows Fixed file transfers and improved it’s UI Fixed offline messaging… i hope i had to figure out how to compile audio libs to other platforms… that took me a while…….. thanks opus What next? uhhh good question? more tests maybe? and UI improvements i was thinking about making a background process run, separate from the app that would get messages so you can close the app while that runs… will have to look into it
oops forgot to devlog again… and no new features this time What changed? as i said…. well nothing lots of bug fixes lots of code improvements (refactor stuff…) some UI/UX improvements but like nothing too crazy What next? honestly I cannot tell. I think i’m gonna start to plan the release and finally push to the public repo. gotta get everything ready, more bug fixes and proofread the code I guess! PS: sorry i really got no screenshots to show here so uh… here’s the intro animation when you first open the app!
again, nothing much to see… but lots of internal changes! What changed? complete rust refactor: made macros for frequently used things, organized the code better & stuff like that some quality of life features for the frontend like pasting an image in the chat directly more tutorials explaining kursal (offline messaging, file transfers) What next? i’m preparing everything for a soon-ish release! it’ll be a public beta version and yeah! hope it works
nothing much changed, again What changed? lots of internal code structure, some logic bugs & stuff Added docker support for hosting a relay! Improved the website and prepared for a beta release (not published yet, will do) More .md docs to explain everything! but more importantly (the only visual changes lol) terminal user interface for the relay! --tui new home for the app! (with stats)
hi! probably last few devlogs before a release?! What changed? more website improvements! added legal pages (boring stuff lol) fixed so many bugs offline messages work now!! and calls too tray icon & background process :) LOTS OF TESTING. and lots of improvements too What next? finish testing and publishing to the repo!
Alright i got the new repo up! What changed? lots of bug fixes (IT OPENS ON ANDROID!) ci improvements got mail sending working from the domain spent lot of time setting the new repo up released the first beta + website update What next? testing… and getting to a stable release :)
Okayy! i started publishing clean commits now and working with my github structure. Basically: I code on branches, like feature/some-feature . once it’s done, I squash it to dev. And when I want to release, I just make a branch release/0.1.0 (with the actual version) and change few things there! What changed? DOCKER WORKING! you can now host your relays using it Kursal JS is out too, you can now use the app API! Large messages send as file (10k+) In-app log view File caption (sends as msg) fixes: App focus notifications Contact onboarding mobile self-lock File upload location & UI Less in-app notifications File downloads What next I’m currently working on adding the native “share with” for Kursal to share images and files directly from your OS.
Released a beta.2 fixing lots of things and almost done with a beta.3 I think… :D What changed? first, i spent like 4 hours translating everything into french LOL Features Mobile native file sharing (this one is crazy!) Large messages send as file (10k+) In-app log view File caption (sends as msg) Bug Fixes Otp consumption Offline messages edits Contact onboarding mobile self-lock (yeah u couldnt do the onboarding on phone in beta.1 😅) File upload location & UI Less in-app notifications that’s it for this devlog! we’ll see if I ship now or wait a bit more? i really want something to work super well :p
Released beta.3 and currently reworking long-term codes for beta.4! not done yet, but it’s WIP :) Features app now embeds the latest ToS update date, so when you update and last agreed to a previous version it shows a pop up so you can agree again Bug Fixes lots of CI fixes… like really a lot 😅 re-enabled mDNS, kinda forgot to put it back… app displays edge-to-edge on mobile, no weird offset! (normally) grammar fixes in english and french… yeeah!
Released beta.4 and beta.5 with lots of improvements and fixes! I spent uh… some time on trying to make a ring tone (like an hour maybe?) but i cant upload it here :/ but whatever it’s not that good anyway lol Features Updater progress bar (spinner go spinnyyy) Major long-term code improvements: you can now select the number of uses and the time it expires Bug Fixes critical first-contact deadlock fix… (oopsy) Pinned & unread messages improvements More accurate user status and that’s basically it I guess!
Lots of work! but no release yet, i’m almost done for beta.6!! :D a major thing i worked on is Github actions release. Now, when I create the draft release, GH actions will build for every platform in parallel and release! Features Contact page complete rework (easier to understand :p), with autocorrect etc Call ringtone (probably temporary, but it’s shipped!) Bug Fixes Smaller offline messages checks Addresses display, general UI improvements Prefer local connections & improved file transfers MacOS .kursal file association
okay I got some more work in! I’m getting really close to shipping, i’d like to get a demo and a proper app icon first tho Changes better QR code scanning screen! and it works on iOS :D the bluetooth module got improvements! no unwrap left (= cannot panic now) + better transfer speed! compressed all image assets to webp (gained like at least few MB) translated again everything in french lol migrated some localStorage data (file-path association) to the encrypted database
more changess!!! and lots of fixes lol oh also i have setup https://status.kursal.chat (but not tracked that time) Performance: improved performance for the database (parallel reading) improved performance (storage & ram) for emojis perf: store avatars in files instead of serialized in the Contact {} struct more performance changes (camera loading, command palette) Bug Fixes: tried keeping less active connections to not blow up the client lol fixed a svelte #each issue… lol
wow time actually flies! gotta devlog again XD i made cool assets for the app store release Features: you can now delete log files from the app unlimited file transfers (file transfers already existed, but now no size limit!) Bug Fixes stop spamming connections to peers… lol big language loading improvements! now shows the percentage of translation too more avatar work to store it on disk and not in the DB you can now mirror your camera if you want :) defer android permission window thingy for those interested i used a figma template for the phones 3d + a plugin (that was so much pain but it looks great lol)
hi! another devlog! i just turned 18 Changes: switched the formatter from prettier to oxfmt (it’s faster!) changed the icon got approved on OpenCollective ! Bug Fixes: avatar transfers now always work even when the other is offline removed some useless code… lol (like migration code) spent lot of time trying to migrate camera to backend but that’s still in the works… soon™
okay i think that’s the last devlog before I ship! sorry for that long time devlog but i was in holidays lol Changes: Use autonat on clients to determine if they can act as public relays Complete rework of the onboarding screens Better QR codes :D Bug Fixes: Fixed some potential security issues in the frontend (injections) Rewrite a part of the front-end to group util functions and avoid redundant code AND!! i’m almost done with the camera rewrite! i’m in the process of migrating that to the rust backend but this means native “per-device” code. Almost done! here are the onboarding screens one by one, i cant add more than 4 attachments so you’ll have to try urself to see ;)
for real last devlog lol, mostly “ci” changes, nothing much Changes: improved code blocks! it has colors :) (thanks highlight.js) thanks Tiazzz for translating into Dutch! android + IOS building code updater on mobile opens the mobile store (instead of breaking) I spent a LOT of time on the Google and Apple publishing websites….. it takes time to get an app published…. :/
Hi! I’m done! (i hope lol) i’m still in the process of publishing to the app store and play store… but heh it takes so long i’ll ship before i’m approved there lol Changes: Few possible vulnerability fixes: only allow LAN devices to reach LAN-specific endpoints Show security codes when added locally Strip more image metadata (like GPS infos) on more formats
that gotta be the last devlog 😅 Basically i just “routine maintenance” the repo ¯ \ (ツ) /¯ spent time TRYING getting it on the app store or play store… it’s pain 😭 but i’ll get it eventually!
Shipped and received ratings, thank you guys! We reached 25 stars on GitHub Changes: various bug fixes… lol (and dependency bumps) iOS build! and signed mac build! meaning you can know open the app on mac without it saying “broken”! (this was a signing issue yes, the app is not actually broken…) got Kursal working for ARCH !! finally, arch users can now open the app :) Still trying to get published on the app store and google play…. damn I did not think it would take that long
Ships:
I built Kursal! A peer-to-peer, decentralized (means no central server!) and end-to-end encrypted messenger. It’s all coded in Rust for the backend and Svelte for the interface. There’s also a website for it showing a bit everything, it’s cool Basically when you open your client, it connects to other clients and creates a “mesh” of clients, communicating through each other. I think a good comparison is a mix of Bitcoin and Tor? Anyway it took me super long to code, and I hope you enjoy!...
|
1792853529.229275
|
1792939929.229275
|
|
2155
|
obliberry by @torkel | Stardance
|
torkel
|
1
|
433.12
|
5134
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-04T09:34:08Z", "hours": 270.0, "multiplier": 19.51, "payout": 5134, "blessing": "neutral", "text": "obliberry feels usable enough that i think its a good time for a first ship :) obliberry is a fallout-inspired isometric game engine for hex-grid games, written in C++20 with OpenGL, featuring a visual editor, an ECS core, its own scripting language, and single-file packaging/exports. this has all been rather challenging, but an incredibly fun learning project, especially regarding using modern C++, OpenGL, and making my own programming language it is still obviously not fully complete of course, but I think it’s in a rather good state :D", "repo": "https://github.com/torkelicious/obliberry", "demo": "https://github.com/torkelicious/obliberry/releases"}]...
|
[{"post_id": 81496, "ts": "202 [{"post_id": 81496, "ts": "2026-10-21T14:23:50Z", "hours": 7.1158, "text": "script properties & UUID types scripts can now declare properties that show up in the inspector and get saved per entity. also ripped std::string UUIDs out of most of the engine in favor of an actual Core::UUID type, plus some scripting additions and a few tests. changes script properties Prop(\"SpeedOrSomething\", 2.5) , PropEntity(\"TargetEntity\") and PropUI(\"MyRect\") for regular values, entities and UI elements properties show up under each script slot in the inspector, with appropriate controls and per-slot values values are only readable during top-level script execution, so store them in variables for use in hooks. Prop in a hook just returns the fallback saved as scriptProperties in scene JSON, omitted when empty property edits support undo, including live number/string editing. unused saved properties can be pruned with undo too.. ScriptSlot is move-only now Core::UUID replaced string UUIDs across the registry, UI, editor commands, project config, save directories and scripting with a 16-byte Core::UUID registry UUID lookups now use an index instead of looping through entities malformed UUIDs in files fall back to generated or nil UUIDs UI UUIDs are saved and restored, including nested elements. duplicate UI UUIDs are handled without crashing the loader savegame directories etc take a UUID directly scripting & UI script objects now have identity values and wrappers are readonly , along with various scripting result objects. came with an ObSL bump UI wrappers get SetParent(parent) and a uuid field. null reparents an element to the root UISystem::Reparent preserves ownership and prevents parenting an element under its own descendant new created scripts use fn on_update(dt) (I wrote on_update() last time …oops…) smaller stuff UndoManager::Execute returns whether the command applied script list shows filenames with Remove beside them tests and docs more tests and docs updated ofc… so u can reference entities in scripts without using Find() now!!!"}, {"post_id": 80249, "ts": "2026-10-16T21:56:07Z", "hours": 3.8333, "text": "uuid-bound script wrappers…, logger sinks…., and a pile of small editor stuff…. mostly scripting + logging plumbing this time, plus a couple of editor things I’d been wanting… changes script wrappers are uuid-bound now entity wrappers used to capture the raw runtime id, which is a problem if ids get recycled or the registry gets rebuilt. now every wrapper holds the entity’s uuid and resolves the live id on each call, so it keeps pointing at the right entity (or does nothing if it’s gone). new FindEntityByUUID(uuid) global and GetUUID() / .uuid on entity objects SetParent matches an entity object by uuid, a plain number is still a runtime id same treatment for UI wrappers: they resolve by uuid instead of name, so renaming or duplicate names don’t break them added FindUIByUUID , GetUUID() and Destroy() on UI elements, and SetImage / GetImage on images (acquires the texture through the scene asset scope like fonts do) still by name: FindUI , DestroyUI and the button state queries ( WasClicked / IsHovered / IsHeld ). UI scripting is still weird… work in progress i guess… logger sinks the old way was swapping the logger’s std::ostream for a stringstream that the UI panel also read from, which was a data race waiting to happen (logger thread writes, main thread reads). replaced it with actual sinks: ILogSink with ConsoleSink (stdout/stderr like before) and UILogSink (mutex -ed pending buffer the panel drains each frame) the editor and runtime both register a ConsoleSink , and the editor adds the UI sink on top, so the Logs panel is always there now instead of only when there’s no tty console panels color lines by severity now interpreter output goes through a small UiStream ostream into the ObSL panel, with stdout and stderr split (needed the bumped obsl, Interpreter takes both streams now…) ObSL panel clears when you enter play mode editor F focuses the camera on the selected entity, press it again to go back to the origin. its smooth…., ..panning cancels the focus keyboard pan only gets called when there’s actually input now.. editing a material in the inspector no longer mutates shared runtime-only materials. if it isn’t a catalog asset it gets cloned into assets.json first, and edits to catalog materials get “upserted” back to the catalog. “Clone Material” writes to the catalog too new scripts from the project browser come with an on_update stub instead of just a comment scripting runtime script top-level code now runs with the command buffer in “immediate” mode ( BeginImmediate / EndImmediate ), so registry writes at the top of a script apply right away instead of waiting for a flush that hasn’t been set up yet during init Hex_GetNeighbors wasn’t GC protecting its array while filling it, fixed…. grid tile textures a tile type with no texture used to fall back to hex_tex both when collecting dependencies and when loading scenes, which would pull in a texture that might not exist. now no texture means no texture… as it should… misc bumped obsl (new using alias feature, and err output stream settings) docs for all the uuid stuff, the F key, and the new UI/image methods… of course… oh also … new demo scene testin thingamabob im messing with…"}, {"post_id": 79544, "ts": "2026-10-14T15:18:47Z", "hours": 7.9614, "text": "map edit kinda overhauled changes map edit stuff the brush size is now 1 to 8 instead of 1 to 5. size 1 is one hex, size 2 is 7, size 3 is 19, etc. Ctrl +scroll also changes the size added Rect and Circle shapes alongside the brush. they work with Paint, Erase and Select. Rect uses opposite corners, Circle goes from a center out to the hex you release on. both apply on release paint previews are green, erase previews are red, and selection previews are yellow. selected tiles get a blue overlay added tool hotkeys: B for Paint, E for Erase and Q for Select Esc cancels a drag. Rect and Circle do nothing if cancelled, while a brush stroke gets reverted instead of leaving half the changes behind loading a map now prompts before discarding a dirty map, and successfully creating or loading a map clears the old undo history selecting and editing multiple tiles Select now supports click and drag, Shift +drag to add to the selection and Ctrl +drag to remove from it the toolbar shows the selection count and has Clear and Delete buttons. Delete removes all selected tiles in one undo step the Tile Editor can edit the type and walkability of the whole selection at once. when selected tiles differ, the controls show mixed values etc. material editing only appears when every selected tile shares a type. Override Current Type changes the material for every tile using that type, while Save as New Type assigns a matching type to the selection without changing every other tile using the old type brush strokes, Rect/Circle fills, deletes and bulk type or walkability changes are each grouped into one undo step. changing a type’s material itself is still not undoable…. the console…. logging now has a sink system, so the same formatted log messages can go to different outputs the editor now has separate Logs and ObSL panels. engine/application logs go to Logs now, and script stdout goes to ObSL the panels have Clear and Copy buttons and keep the latest 2000 lines. the UI sink buffers incoming logs under a mutex before the editor consumes them closing the editor closing the window now goes through a callback, so unsaved scene or project changes trigger the save/discard prompt instead of immediately closing removed the old global Esc -to-quit shortcut. ObSL’s CloseWindow() no longer closes the editor while in Editor mode. it logs that it was called instead. in the runtime, it still closes the window windows and smaller fixes enabled /MP for MSVC builds, and the editor/runtime targets use the Windows GUI subsystem so they don’t launch with a console window attached atomic file writes now write the byte buffer explicitly and retry Windows file replacement when it fails with access-denied or sharing-violation errors, for up to about 2 seconds a bit of cleanup around collision pair sorting, const-correctness and naming docs updated the editor guide and screenshot to cover the new tools, shapes, selection controls, shortcuts and undo behavior. blah blah …map editing is finally a lot less barebones…"}, {"post_id": 78861, "ts": "2026-10-11T19:54:19Z", "hours": 3.0197, "text": "uhhh changes dont nuke scene on failed load scene deserialization moved out of Scene::OnEnter into SceneManager::LoadScene , and now runs before the old scene gets torn down. if the new one fails, you stay in the old scene ( LoadSceneByPath returns a bool now) loading is stricter. missing map files, bad/out-of-range/cyclic parent values and broken UI sections fail the load instead of logging an error and limping on persistent entity migration happens before the swap too, so a failed asset acquire can’t leave you half in the new scene the editor’s LoadScene used to clear the current project before trying to load. now undo history and selection only get cleared once the load actually worked saving: map write failures now propagate instead of reporting success, and files get closed before the error check destroying entities DestroyEntity was recursive, now it’s iterative with a visited set. deep hierarchies, cycles and duplicate child entries no longer kaboom the stack or double delete, and children go first (wow that sounds dark) Reparent and SetParentDirect go through CanSetParent , which rejects cycles and stale parents, even if the existing hierarchy is already cyclic script DestroyEntity / entity.Destroy() now use RequestDestroy to tag the entity and its whole subtree instead of deleting immediately, so on_destroy runs before deletion. scene exit drains the destroy queue too, including entities tagged by exit hooks the script wrapper cache evicts an entity when it’s destroyed a dumb one…: the hot-reload cleanup list had on_exit in it twice and no on_destroy , so on_destroy GC roots never got released … the script system was holding raw ScriptComponent* across initialization, which dangles if a script spawns enough entities to grow the pool. it looks components up by entity ID now script runtime reinitialization after a scene change uses the VFS path and reruns setup, so using imports keep working from the mounted project ui undo UI elements have UUIDs now, and undo commands resolve them by UUID instead of holding raw pointers. removing an element captures the whole subtree plus its sibling position, so undo restores the hierarchy and order. renaming also updates the name index live. smaller fixes collision broadphase is a “spatial hash grid” now instead of checking every pair lightmap rebakes when ambient changes, and handles maps with no tiles atomic file writes use unique temp names so concurrent writers don’t trip over each other project changes wait for background asset loads to finish timeout timers are mutex-protected, and callbacks can schedule more timers without deadlocking SmallTask over-aligned captures fall back to the heap VFS::Resolve(\"..\") had UB from a std::mismatch that wasn’t bounded on the second range… PlayMusic stops, swaps and starts under the lock now instead of racing!!! tests wrote a pile of tests alongside all this: atomic writes, wrapper cache, hierarchy safety, map serialization, save concurrency, scene loading failures, script lifecycle, script modules, SmallTask and timeouts. expanded to the editor command, save game and VFS tests. so EVEN LESS explosions !!! Woo!"}, {"post_id": 78453, "ts": "2026-10-10T20:34:34Z", "hours": 4.7336, "text": "undo stuff + render lifetime fixes undo / redo the undo system relied way too much on runtime entity IDs and direct pointers into components. that works until an entity gets deleted, an ECS slot gets recycled, or a dense component pool moves stuff around… entity commands now store the entity UUID and resolve the current runtime entity when they execute / undo instead. this now applies to transforms, renaming, adding / removing components, script changes, component field edits and map painting. so older commands can still find the right entity even if it was deleted and later restored with a completely different runtime ID. deleting things is actually undoable now finally added proper undo for deleting entities. !!!!!! deleting an entity snapshots the whole subtree first, including components, UUIDs, names, hierarchy + sibling order, scripts, custom data and asset references. undo rebuilds the tree, reloads required assets, restores the UUIDs and puts everything back where it was. this also means edits from before the deletion still work afterwards, since those commands just resolve the restored entity by UUID. paste uses the same snapshot system now too, so undo / redo keeps the same pasted entity identities instead of creating unrelated ones every time. there are checks for conflicting UUIDs, missing parents, invalid hierarchies, missing assets etc. failed restores shouldn’t leave half-created entities behind. failed commands also no longer get added to undo history or wipe an existing redo chain. custom ObSL data custom script data needed special handling too. arrays / objects can share references or even be cyclic, so just copying ObSL::Value s wasn’t enough. there’s now a snapshot format that captures the object graph and rebuilds it through the interpreter + GC when an entity is restored. CustomDataComponent also roots stored ObSL values properly so GC-managed objects stay alive. runtime functions aren’t snapshotable though, so deletion just fails instead of restoring garbage. render thread lifetime stuff also did a pretty big pass over renderer resource lifetime, mostly because scene switching could unload resources while an already submitted frame was still using them. (this started because someone mightve pointed out a lil crash for me…) render commands now pin the meshes, materials, shaders and textures they need until that frame is done. same idea for UI textures and the editor viewport framebuffer. OpenGL objects also don’t call glDelete* from whichever thread destroys the C++ object anymore. textures, shaders, buffers, VAOs and framebuffers queue deletion for the render thread, while it actually owns the GL context. less bugs yay frame state + shutdown renderer state that can change while the render thread is behind is captured per frame now too, including clear color, post-processing and UI resolution / projection state. shutdown is also more deliberate now: worker threads stop first, background font loads finish, scripts stop, scenes/resources are cleared, renderer/UI resources shut down, then the remaining GL delete queue is processed while a context still exists. font loading uses tracked jthread s now too instead of detached threads. small things exporting now reports success / failure back to the editor and shows a little result popup instead of silently relying on the console. also added tests around delete / restore, UUID reuse, hierarchy restoration, script components, map edits, pasting, command failures and repeated undo / redo without leaking entities or asset references. so. .. . less explosions hopefully sorry if wording is weird.. character limit.."}, {"post_id": 78136, "ts": "2026-10-09T18:21:07Z", "hours": 3.2578, "text": "export dependencies + prefab asset loading redid how exporting figures out what needs to go into the package previously editor export was basically much closer to just packing the project directory. now it builds a dependency manifest first figuring out what to export export starts from the project + scenes and follows the things they reference: catalog assets used by entities, maps, UI and post processing map files attached ObSL scripts script using imports scenes loaded from scripts prefabs instantiated from scripts music / sound files material textures + shaders animation sheets shader #include s referenced scenes and prefabs get scanned too, dependencies keep chaining from there. it then generates a new filtered assets.json specifically for the package instead of sticking the entire project catalog in there. the actual project’s catalog is untouched. script analysis added a ScriptAssetAnalyzer which walks the ObSL AST without actually running anything. literal stuff can be narrowed down properly, including things like: PlayMusic(\"assets/audio/music.ogg\", 1.0) or even constant string concatenation… asset setters like SetTexture / SetFont get tracked too. if a texture or font ID is dynamic, export keeps that entire asset category. if a runtime file path for stuff like LoadScene , Instantiate , PlayMusic or PlaySound2D can’t be figured out, it falls back to keeping the eligible project files + full asset catalog. unknown / indirect calls are done the same too so simple projects get smaller exports, while weird dynamic scripting should still work… .pakignore still applies, and required files being missing or ignored is now an export error prefab assets also fixed prefabs properly interacting with the lazy asset system. instantiating a prefab now scans its components, acquires whatever catalog assets it needs, resolves their dependencies, and retains them in the scene before creating the entity. so a prefab can use an asset that wasn’t already referenced by the scene and it should just work. scene asset scopes got changed a bit for this too. instead of accumulating a new scope every time something acquires assets, they’re merged into one scene scope and duplicate asset references are ignored. also made prefab revert a little safer so the old entity isn’t destroyed unless the replacement prefab actually instantiated successfully. packaging / ci things editor packaging is stricter in general now. script dependency validation can fail the export, missing dependencies stop it, and PackageCurrentProject reports failure so the rest of the export doesn’t continue pretending everything is fine. shader includes are followed during dependency collection too, while the engine shader helpers still get bundled for runtime includes. also cleaned up CI a decent bit… also some more tests too for the packaging and script analysis lowk sorry for just posting an image of the logs idk how else to show it since it’s mostly backend / file stuff 😭"}, {"post_id": 77620, "ts": "2026-10-07T17:38:02Z", "hours": 3.62, "text": "more tests (more bugs) kept going with the unit tests the test suite now covers most of the important stuff, including: ECS / entity IDs / UUIDs serialization + hierarchies collision geometry, events and movement maps animation saves ObSL + some EngineLib bindings assets / asset lifetime VFS + packaged projects configuration editor undo commands also added a couple integration tests for audio and rendering (OpenGL tests are optional) finding things unsurprisingly this found some actual problems too. stale entity handles can no longer remove / access components from an entity that reused the same slot, and editor undo commands are a bit safer around entities or components disappearing. also fixed some hierarchy rotation decomposition weirdness, cleaned up VFS / package mounting state so old package data can’t leak into the next mount, and added a few other small null / cleanup checks around scenes and rendering resources."}, {"post_id": 76449, "ts": "2026-10-03T15:32:32Z", "hours": 3.1158, "text": "unit tests (& some fixes) uhhhh started adding actual unit tests… i was kinda putting it off but i gotta have it… set up GoogleTest + CTest and started covering some stuff ECS registry / generational IDs entity UUIDs entity serialization hierarchy / parenting collision events + movement blocking save games maps bugs bugs bugs… and unsurprisingly, writing tests immediately started exposing some smaller issues. fixed stale entity handles being able to mess with components belonging to a recycled entity slot, and cleaned up some hierarchy transform / rotation handling that wasn’t preserving transforms correctly in certain parenting cases. also tightened up a couple math helpers while testing them. im still gonna write even more tests.. its very needed at this point and will prolly help me find some more bugs i missed before…"}, {"post_id": 75890, "ts": "2026-10-01T14:46:00Z", "hours": 5.4794, "text": "uuids, collision layers, save settings, and other stuff bit of a mixed bag this time. mostly cleaning up some systems that were already there and filling in stuff I’d need… entity UUIDs entities have proper UUIDs now, separate from their normal runtime entity IDs. the regular generational ID still does all the normal ECS stuff, while the UUID is a stable identity that gets serialized with the entity. this mostly fixes how persistent entities work between scenes. previously I was deduplicating persistent entities by name , which was obviously not ideal since names aren’t actually identities. persistent entities + their children now keep their UUIDs when moving between scenes, and if the destination already has an entity with the same UUID it gets replaced by the carried-over one. two things can have the exact same name now without persistence randomly deciding they’re the same thing. normal prefab instances / newly created entities still get new UUIDs. collision layers colliders now have proper layers + masks. there are 32 collision layers, and every collider has: a layer a 32-bit mask of layers it accepts both colliders have to accept each other’s layer for the pair to interact. the same filtering is used for normal overlap events and movement blocking, so there isn’t a separate set of collision rules depending on which system happens to be asking. added editor controls for this too, including the layer selector, all 32 mask toggles, and select all / deselect all buttons because clicking 32 checkboxes individually sounds incredibly fun. scripts can also read / change the layer and mask now. collision-aware script movement also added Transform.TryMoveTo(x, y, z) to ObSL. unlike SetPosition , this checks whether the entity can actually occupy the destination before moving it. the normal hex movement system uses the same helper now too, so script-controlled collision-aware movement and normal movement go through the same path. direct SetPosition is still basically teleporting, which is intentional. also fixed on_collision_stay actually looking up the collision stay callback instead of the trigger stay callback. whoops. more save settings did some more work around the save system from the last update. saving can now be enabled / disabled per project, and projects can choose where save files go: Data Home , the normal OS application-data location Portable , relative to the executable both still use the project UUID underneath so different projects don’t start sharing save files because somebody named both of them game . these are editable from Project Settings now. also added a confirmation dialog when regenerating the project UUID since doing that changes which save directory the project looks at. the old saves aren’t deleted, the project just gets a new identity and stops finding them automatically. graphics config stuff changed packaged builds so graphics.json can live beside the executable and override the version inside the package. (i.e if someone decides to unignore the graphics config and package it) couple random fixes particle emitters now keep their actual live particle count, so GetAliveCount() in ObSL finally returns the real value instead of the completely useless placeholder it had before. fixed a prefab revert issue where the code was reading the prefab path from the component after destroying the entity. very intelligent. also made theme font loading a bit less fragile. missing / broken font files get logged and skipped instead of potentially taking the whole theme load down with them, plus some parsing cleanup. and updated another mountain of docs to match all the collision, persistence, save, prefab, post-processing and export changes."}, {"post_id": 73199, "ts": "2026-09-24T16:15:43Z", "hours": 7.0497, "text": "save system i wanted this to be pretty generic instead of the engine having some hardcoded idea of what a “player save” or whatever is, so the actual save data is ba sically just key/value storage that scripts can use for whatever they want!!! save data there’s now a SaveGameManager which keeps one active save in memory. save values can currently be: booleans numbers strings the file format is versioned and also stores a display name + created / updated timestamps. the actual save data itself doesn’t really care what the values mean. it is any key value pair that persists. there’s also locking around the active save since scripts can be running across multiple workers….. project UUIDs projects also have their own UUID now. it’s generated when the project is created or when a project that does not already have one is opened right now it’s mainly used to give each project its own save-data directory without name collisions but im sure its good to have outside that!!! save files the basic save file operations too create a new save write the current active save load a save delete a save list existing saves start a fresh unsaved “game” save filenames are generated from timestamps. the human-readable name stays inside the file, display names don’t need to also be valid / unique filenames. save_list() also gives creation + update timestamps, and saves are sorted by most recently updated. writes are atomic too, so it writes through a temporary file before replacing the real save instead of directly nuking the existing one and hoping for the best per-project save directories save data is stored outside the project itself in the normal OS application data home each project gets its own directory based on its UUID <data home>/obliberry/<project uuid>/saves/ projects with the same name don’t fight over the same saves.. (i have several projects just called “UntitledProject” lol) this is LocalAppData on Windows, Application Support on macOS, and XDG_DATA_HOME / ~/.local/share on Linux. both the editor and runtime configure the save manager when the project is loaded, and it gets reset again when the editor closes the project ! ObSL ObSL savedata enginelib intergration: basic data stuff: save_set(key, value) save_get(key) save_has(key) save_remove(key) save_clear() save_new() save file management: save_create(name) save_write() save_load(filename) save_delete(filename) save_list() save_list() returns an array with the filename, display name, creation time and last update time some cleanup also pulled the atomic file writing stuff into a shared OS file utility, so assets.json can use the same code instead of having its own implementation. bunch of formatting stuff too i still have to document this and do some more testingf but yeahhh"}, {"post_id": 71462, "ts": "2026-09-20T21:23:42Z", "hours": 6.445, "text": "asset system refactor + some editor stuff been wanting to redo how assets work for a while now. until now scenes carried the asset definitions with them, and loading scenes would keep throwing resources into the global resource manager. worked fine enough , but it also meant resources could kinda just accumulate forever.. i seperated them now!! assets.json projects now have a project-wide assets.json catalog. textures, shaders, meshes, materials, fonts, animation sets, etc. live there instead of getting serialized into every single scene. scenes / prefabs / UI / animations etc. just store resource IDs and the definitions live in one place besides making scene files considerably less bloated, this means saving a scene no longer serializes whatever random collection of resources happens to currently exist in the resource manager lazy asset loading having one project-wide catalog does not mean loading the entire project into memory. scene loading now scans for the resources that scene actually references and loads those from the catalog this includes stuff referenced by: entities maps / tile types UI post processing spritesheets / animators dependencies get resolved too so if something needs a material, its shader + texture get pulled in first. animation sets pull in their spritesheet texture, etc. etc. now the the resource manager should only contain what is actually being used asset lifetime stuff added SceneAssetScope for keeping track of what assets a scene has acquired. assets are retained while something needs them and can actually be unloaded once the last scope using them disappears so changing scenes repeatedly should no longer turn the resource manager into yummy more objects :O forever…. persistent entities reacquire the resources they need when moving between scenes too. there’s also handling for catalog entries being replaced / deleted while their old resource is still loaded. those can be marked stale and discarded safely once the old scene lets go of them instead of leaving weird zombie resources around. engine assets still stay around like normal. editor asset workflow the editor now goes through the asset catalog too. creating / importing / replacing / deleting things like: textures shaders meshes materials fonts animation sets updates assets.json instead of depending on scene serialization to preserve them…. supported editor selections / script setters can also acquire catalog assets on demand and attach them to the current scene’s asset scope old projects old projects obviously still have all their assets embedded inside their scene files, so I added an ob_asset_migrator tool. it can scan the old scenes and merge all of those definitions into a project-level assets.json . there’s: dry-run validation conflict detection optional removal of the old scene assets sections backups before it starts rewriting stuff uses backups because i dont trust myself enough .. might vaporize projects who knows… docs docs docs also updated a stupid amount of documentation for the new asset model … since of course.. there’s now a full assets.json format page covering the different asset types, dependencies, lazy loading, asset scopes, editor behavior and migration. updated the scene / prefab / animation / post-processing docs too since all of those previously described assets as being stored directly in scenes. also cleaned up the main README + docs index a bit and updated the feature list because quite a lot of it was outdated at this point…. theme presets also did some work on editor themes. split the built-in theme definitions out and added some interesting presets: Obliberry Dark ImGui Classic Dark Obliberry Light ew imagine using light themes… High Contrast Dark Haxxorman Green editable and all… tldr: resourcemanager is now longer an infintly growing landfill…"}, {"post_id": 70788, "ts": "2026-09-19T19:20:34Z", "hours": 1.5706, "text": "I will not elaborate"}, {"post_id": 70712, "ts": "2026-09-19T17:13:26Z", "hours": 3.3022, "text": "animation editor continued working on the animation system and made the editor UI…. animation editor there’s now a Sprite Animation Editor you can: choose the spritesheet texture edit rows / columns / spacing create, rename and delete clips toggle looping per clip edit individual frame indices + durations move frames up / down duplicate / remove frames expand / collapse the frame list also added range generation so adding a normal animation doesn’t make you manually enter every frame one by one….. theres also an Apply FPS to All Frames button ! preview added a live preview for the selected clip. you can play, pause and restart it woaw it shows the current clip frame and spritesheet index while it runs…. project browser integration animation assets are properly integrated into the project browser now too there’s an Animations section where you can create, import, edit and delete animation assets creating a new one lets you choose its path then opens it in the animation editor. the animation asset workflow is mostly usable from inside the editor :D erm even more enginelib changes for the new systen that i still have to document… ( Play() Restart() etc) some cleanup working on… some mostly const-correctness, explicit casts, ranges, include cleanup and some other small stuff etc etc.. god bless resharper c++ also cleaned up some EngineLib entity wrapper code around registry locking so it can create wrappers safely when the registry mutex is already held spritesheet used in video attached for testing is : https://opengameart.org/content/animated-butterfly"}, {"post_id": 70230, "ts": "2026-09-18T19:10:52Z", "hours": 6.3242, "text": "btw pls star on girhub animation clips / refactoring spritesheets …kinda refactoring the whole spritesheet animation thing already the first version worked, but having FPS / looping / frame ranges etc directly on the SpriteSheetComponent was gonna get pretty limiting cuz what if I wanted multiple animations for one sprite. it might sound stupid but for me it’s always worked to get a prototype working, then refactor/reimplement it. thats even what i did for this entire project early on, before it deleoped into a full on engine :D so now the spritesheet is mostly just the sheet + currently displayed frame, and animation playback is seperate animation clips working on proper animation sets + clips. an animation asset can have one spritesheet and multiple named clips, with each clip containing its own list of frames :D each frame also has its own duration now instead of the whole animation just sharing one FPS value, so stuff like holding a frame longer or doing irregular timing is possible without clips can loop independently too animator component added a separate SpriteAnimatorComponent which handles the actual playback state: animation asset initial clip autoplay current clip current frame inside that clip elapsed time playing state the normal SpriteSheetComponent is way simpler now… it just says what sheet + frame should currently be rendered (the animator updates that for it) animation assets animation sets are assets now under assets/animations/ they serialize separately and contain the spritesheet setup plus all the clips / frames / durations they are loaded through the normal asset system and registered in the ResourceManager scene serialization now keeps the animator config like the selected animation asset, initial clip, and autoplay editor stuff the sprite sheet inspector got reworked for the current thing but whole UI stuff isnt finished once an animator is attached it owns the sheet/frame instead of both systems trying to edit the same thing. I still need a proper UI for actually making / editing animation assets and clips though. i shall work on this next!!! (right now the backend is pretty much all ive done but its taken a lil longer than i thought… who wouldve thought adding cips cleanly would take this whole aah refactor) scripting EngineLib updates too SpriteAnimator in scripts can now do: Play(\"walk\") Restart(\"walk\") Pause() Resume() Stop() IsPlaying() GetClip() it is now based on named clips so i guess not anything flashy to show but… its stuff :)"}, {"post_id": 69178, "ts": "2026-09-16T15:19:06Z", "hours": 4.2144, "text": "spritesheets / animation finally … spritesheet support spritesheets added a new SpriteSheetComponent with: texture rows / columns optional row + column spacing start frame animation length FPS looping playing / paused state current frame basically the renderer can now render only a specific UV region of a texture animation also added a small sprite animation system that advances frames based on FPS and handles looping / stopping at the end etc etc animations also update while in the editor… might be annoying for some, might be less annoying for others.. but thats how i like it editor stuff you can pick the texture, set rows / columns and spacing, choose the start frame + animation length, change FPS, toggle looping / playback, scrub the current frame, restart the animation, etc. etc EngineLib scripts can inspect stuff like the current frame, frame count, FPS, rows / columns and texture, and can also change the texture/grid/animation, set frames, play, pause, restart and stop animations. Collider also has a proper EngineLib component wrapper instead of collision only being accessible through the callback hooks. right now that’s just getting / setting whether it’s a trigger, but it’s there. also added both Collider and SpriteSheet to the normal GetComponent , AddComponent , RemoveComponent , HasComponent , etc. obviously. some cleanup did a bit of registry / EngineLib locking cleanup while I was in there too, mostly around entity wrappers being created while the registry lock is already held. also fixed one very stupid collision callback typo where on_collision_stay was looking up the wrong hook… oops….. im also starting on documenting this stuff…. yep.. pain… spritesheet used in video attached for testing is : https://opengameart.org/content/animated-butterfly"}, {"post_id": 67894, "ts": "2026-09-14T06:13:59Z", "hours": 2.1764, "text": "collision callbacks scripts can do collision things now….!!! script collision callbacks ObSL scripts can now define collision hooks: on_collision_enter(other) on_collision_stay(other) on_collision_exit(other) on_trigger_enter(other) on_trigger_stay(other) on_trigger_exit(other) the other argument is a normal EngineLib entity wrapper, scripts can do stuff like check its name, components, etc. collision events get collected by the CollisionWorld , then dispatched to the relevant script instances afterwards. they’re also run through the existing script command buffer ofc 2D collider shapes are back too… added explicit 2D shapes alongside the 3D ones: Rectangle Circle so the full set is now: Box Sphere Cylinder Rectangle Circle rectangle / circle are flat shapes. which is nicer for sprites and other 2d things movement actually respects colliders hex movement now checks whether an entity can actually occupy its next tile before moving there. added a CanOccupy() collision query which builds the entity’s collider at the target position, it blocks the move if something solid is in the way. triggers don’t block movement. collision robustness stuff also did a bunch of smaller fixes around the collision added a shared collision tolerance instead of random 1e-6 s in different places AABB overlap now uses that tolerance too improved collider validation depending on the actual shape fixed gizmo world-to-local conversion to use the proper inverse transform more finite-value / clipping checks in the collider gizmo GJK Indeterminate results preserve the previous collision state instead of automatically counting as a collision p.s, heres a lil photo of my attempt at making syntax highlighting for obsl using textmate grammar… :D"}, {"post_id": 66845, "ts": "2026-09-12T19:22:05Z", "hours": 3.0608, "text": "collision system round 2 i guess ended up pretty much reworking most of the collision system….. the first version was still basically 2D, with separate box vs box / circle vs circle / box vs circle functions. that worked as a starting point, but it was gonna get annoying … so… it is 3D now. colliders ColliderComponent now supports: boxes spheres cylinders 3D offsets / dimensions triggers entity-space or billboard orientation billboard colliders follow the same camera-facing basis as billboard rendering, which means billboard sprites can still have colliders that actually line up with how they appear on screen. GJK got rid of all the individual boxVBox , boxVCircle , etc. collision functions and replaced them with support-mapped collision detection using GJK. each collider shape just provides a support point now, the intersection test doesn’t care what combination of shapes it’s checking. i dont fully understand the math completely yet.. but it kinda makes sense :D still no collision response / physics yet. this is just detection + events, i think ill prolly get it into EngineLib.. soon… events the CollisionWorld still tracks collisions between frames and generates: Enter Stay Exit trigger state is kept with the collision too. this is for EngineLib integration. scripts should be able to react to collisions / triggers like unity I have not gotten around to this yet though… collider gizmos also had to redo the collider gizmos now that colliders aren’t just flat 2D shapes anymore… its a lil janky but it works.. billboard cleanup while doing the billboard collider stuff I also cleaned up billboard rendering a bit billboards used to have their world transform temporarily modified by SpriteBillboardSystem before rendering. now the billboard matrix is generated when the entity is submitted to the renderer instead, so the actual ECS transform can stay as the real entity transform there’s now one shared billboard matrix helper used by both rendering and collision, which is considerably less cursed. um scripting integration next i guess.. if something dosent explode ! :D"}, {"post_id": 66200, "ts": "2026-09-11T21:27:55Z", "hours": 3.4236, "text": "collision stuff been working on a collider system. still pretty early and not hooked into EngineLib yet, but most of the basic backend + editor stuff is there planning to expose it to scripts in a similar way to how Unity handles collision callbacks / triggers, but that’s for later……. collision added a new ColliderComponent with: box and circle colliders offsets size / radius trigger support collision system currently handles: box vs box circle vs circle box vs circle collision normals + penetration depth ‘trigger’ collisions also added a CollisionWorld that keeps track of collisions between frames and generates Enter , Stay , and Exit events. mostly groundwork for when I hook this into EngineLib… collider editing colliders are editable from the editor theres a collider inspector widget for changing the shape, offset, size/radius, and whether it’s a trigger, plus a viewport gizmo for directly moving and resizing them collider edits also go through the undo system, because every new editor feature needs to become an undo/redo problem eventually……… :D other editor fixes entity copy/paste now copies the whole child hierarchy instead of only the selected entity pasted hierarchies keep their parent relationships added copy/paste to the entity and UI context menus fixed stale entity / UI selections after the thing being selected gets deleted fixed single-key shortcuts like V , T , R , etc. firing while Ctrl/Alt/Shift was held keyboard camera movement no longer fights with Ctrl/Alt shortcuts a few smaller include / cleanup things mostly collision work though. next step is probably getting the collision events into EngineLib and experimentiung w. it its still a bit jank of course but it works i guess :DDDDD"}, {"post_id": 65603, "ts": "2026-09-10T20:50:19Z", "hours": 4.8511, "text": "copy paste (kinda) also too much time fighting windows builds tried to get entity copy/paste working and it’s… janky. also ended up wasting a stupid amount of time just getting windows builds to actually build again because i lowk forgot again about how it wont let me pass paths as strings implictly as it does on every other damn os… changes copy/paste (wip, kinda broken) started on ctrl+c/ctrl+v for entities & ui in the editor it kinda works but is really janky and does not feel good to use, also tried implementing it in the context menu but its not workiong at all -.- other the windows fixes…. some resharper reccomendation inspection type shi but lowk its been a while since i logged soo yep"}, {"post_id": 64268, "ts": "2026-09-08T15:23:01Z", "hours": 3.8883, "text": "sllight hub overhaul redid the project hub screen and added recent projects tracking, since up to now opening anything meant going through a file dialog every single time… changes recent projects get tracked in a PROJECTHIST file (next to the editor executable) …dead simple format, one filepath per line, each pointing at a project’s .json . capped at 5 entries, oldest just get removed off the list. hub screen is basically remade two docked panels now instead of one. left panel is the same buttons as before (new project, open project, etc), right panel is the new recent-projects list, up to 5 entries since that’s all the history file holds. also removed some unused dead code i found… QoL type stuff i guess :D"}, {"post_id": 63577, "ts": "2026-09-07T14:25:37Z", "hours": 3.9417, "text": "too many post proc fx? followup to the post processing / shader experiments… changes shader includes shaders can #include \"rand.glsl\" etc and it resolves properly. it checks the project VFS first, then falls back to the engine’s own shader helper directory if it isn’t found there. engine shader helpers also get packaged into exported games under engine/shaders/ , so includes keep working at runtime. added a few helper include files: rand.glsl / auto_rand.glsl - seeded hash-based random, with auto_rand reseeding per frame from u_Time color.glsl - HSV conversion, lift/gamma/gain, contrast, saturation, and three-way color wheels commons.glsl - engine-provided uniform declarations so you don’t have to redeclare u_Resolution , etc. in every shader for engine-provided uniforms the helpers use #ifndef / #define guards, so auto_rand.glsl can include rand.glsl without causing double declarations if the effect shader or another include declare the same uniforms or includes. more built-in effects added a few more built-in post processing effects: ColorGrading - exposure, contrast + pivot, saturation, lift/gamma/gain, and shadow/midtone/highlight color wheels using color.glsl FilmGrain - chunky per-cell grain with u_GrainSize controlling the cell size Vingette - yes i know its mispelled. uniforms with Wheel in the name now get the wheel-style color picker instead of the regular color picker, since a normal RGB slider cleaned up effect registration used to have two separate lists, one for raw shader registration and one for the default effect chain. this meant adding an effect involved touching two different structs in two different places. merged those into one PPRegistration list with an inDefaultChain flag shader debug name added an actual m_DebugName field and made error messages / the material inspector fall back to it when there isn’t a real file path. docs wrote up some post-processing editor docs ….. i hate writing docs.. also .shader is now a valid extension for importing custom effect shaders, alongside .frag / .glsl trimmed down the miniaudio CMake config by disabling its examples, tests, and tools, along with Vorbis/Opus/FLAC support since i’m not using any of that…."}, {"post_id": 62331, "ts": "2026-09-05T17:14:14Z", "hours": 3.0172, "text": "shader preprocessing been working on a small shader preprocessor thing while also finishing up the final bits of post-processing right now the preprocessor is pretty simple, mostly just adding support for: #include #pragma once I haven’t actually needed it yet, I just kinda had the urge to make it… so now I have a shader preprocessor …? its pretty extendable and all though so usefull to have ig :)"}, {"post_id": 61599, "ts": "2026-09-04T16:12:18Z", "hours": 6.9642, "text": "more post processing!!!! this took way longer than i thought it would but uh whateveer. i think i still gotta fix some small things but its working pretty alright :D editor ui added a proper ui for post processing :) threw in an import button and stuff so you can load in fragment shaders as post proc fx you can edit the uniforms directly in the ui now stuff glsl uniform parser: wrote a very simple basic glsl uniforms parser. this is what makes the ui editing possible, but it also helps a ton with serialization so i don’t have to hardcode everything serialization: implemented saving and loading for post processing effects and also made post processing effects bound per-scene instead of being a global engine thing yay post processing funny effects shaders aaaaaaaah"}, {"post_id": 58126, "ts": "2026-08-30T14:12:01Z", "hours": 6.2431, "text": "experimenting with post processing working on a lil post-processing pipeline still very wip but im mostly just playing around with various shaders and stuff changes the pipeline PostProcessor is a simple “ping-pong” chain: scene renders to an off-screen FrameBuffer , then each enabled effect runs full-screen-triangle shaders bouncing between two ping-pong buffers, in whatever order they were added I’m working on a system via variants to get uniforms to be easily serializable and such, it seems to be working but I havent actually wired it into anything just yet. editor and runtime a lil bigger change than expected. i implemented a unified fbo for both editor/runtime rather than the weird jank i was doing before editor: scene renders into m_SceneFrameBuffer , post effects run, then it gets sent into the ImGui viewport image like before runtime: same scene framebuffer, same post effects, then PresentToScreen goes to the default framebuffer instead just some general cleanup for that ig crt shader i wrote a lil silly CRT looking shader to test it out as shown below, it’s cool but kind of useless, but very fun to play with!!!"}, {"post_id": 55765, "ts": "2026-08-27T19:09:56Z", "hours": 4.9358, "text": "custom meshes im trynna make it so you can draw your own custom 2d meshes in the editor its still a lil buggy but it’s mostly working, serializes and all that :) very fun…"}, {"post_id": 55022, "ts": "2026-08-26T13:27:21Z", "hours": 2.1303, "text": "ui editing gizmos!!!1 you can finally drag UI elements around in the editor (instead of typing position/scale values into the inspector) changes ui gizmo added a proper UI gizmo with resize handles and dragging support and that corners resize both axes, edges resize one axis dragging the body moves the element resizing from the top/left keeps the opposite edge anchored added a small drag deadzone so clicking doesn’t accidentally create an undo step UI transforms now go through TransformUIElementCommand , so they’re undo/redo -able also renamed the existing entity gizmo code and naming gets confusing otherwise… coordinate stuff the gizmo needed mouse coordinates relative to the viewport rather than the whole window, so added some better viewport coordinate handling for that… maybe a lil late ui editing mode buttons won’t randomly enter their hover/pressed states just because your mouse is sitting over them now in the editor beccause its a lil annoying when editing small optimization also fixed UIText and UIButton recalculating their text layout every frame when nothing changes feels nice :)"}, {"post_id": 54551, "ts": "2026-08-25T16:02:00Z", "hours": 2.53, "text": "hardening + performance stuff so this is kinda the continuation of the last log(s) where i was going through some old code kinda boooring but its important performance mainly been trying to get rid of unnecessary allocations and full scans stuff optimized ECS entity/component lookups and removal reworked hierarchy propagation to avoid unnecessary registry scans reduced allocations in scripting and UI command buffers cached script wrappers so they can be reused instead of constantly recreated improved UI lookups with a proper name index made particle/lightmap updates only rebuild when actually needed cached project browser directory scans capped the editor console and added clipping for large logs also did a bunch of smaller optimizations around scripting task scheduling and resource loading things thread safety went through a lot of the cross-thread stuff as well made ResourceManager access properly synchronized experimenting with the audio locking guarded FreeType access made window size and pending scene state thread-safe fixed some render thread / GL context handling basically trying to make all the multithreading stuff a little less “it seems to work” type stuff though alot of this probably wasnt actually causing any issues YET , it would be very hard to debug in the future if I didn’t try to fix it now so yeahh correctness fixed several out-of-bounds issues in VFS/package parsing made VFS path resolution properly stay inside the VFS root (oops…) fixed hierarchy reparenting allowing cycles fixed a few dangling references in hierarchy code fixed some component pool and packaged asset lifetime issues undo history now clears when loading a scene cleaned up a few map editor edge cases fixed text centering fixed the triangle mesh made engine context non copyable also updated the demo template while I was at it (since a recent movementcomponent update it wasnt behaving properly due to the addition of a new field) there are other small things i probably didn’t mention here too but it’s mostly all a collection of a bunch of small things im still testing this though and looking into a few other small things….."}, {"post_id": 53560, "ts": "2026-08-24T04:55:16Z", "hours": 7.8433, "text": "code cleanup & optimization currently going through a bunch of older code and fixing / optimizing things. prolly way too much to actually write about, and most of it is just boring small changes, bug fixes, and a lil cleanup big pr i guess soon idk"}, {"post_id": 51782, "ts": "2026-08-21T16:57:55Z", "hours": 3.4422, "text": "mostly windows fixes changes SetLightmap took a raw Lightmap* and just held onto it for the frame swapped it for a small value type the renderer copies out immediately instead… this sometimes caused crashes but seemingly only on windows?.. just my luck.. LightingSystem had the same issue, was writing back into ECS memory through a raw pointer from a GL init task. now creates the framebuffer/vao up front and just calls Invalidate() on them SubmitPersistent was also holding a raw pointer into caller-owned memory, now copies into the staging buffer like everything else does RenderBatch used to just silently not draw anything if a batch went over MAX_INSTANCES . now it chunks into multiple draw calls instead of dropping the whole thing InvalidateGLCache wasn’t resetting the dynamic instance buffers, only the VAO cache, so they could point at dead GL objects after a context loss actual windows fixes opening files tries to open via already existing file associationg, otherwise falls back to the “open with” dialog if there’s no default handler also the paths get normalized to backslashes now asset import for scripts and so just does a file copy now instead of going through the old import path"}, {"post_id": 51240, "ts": "2026-08-20T19:35:22Z", "hours": 4.2758, "text": "persistent entities… again kinda scrapped most of the first attempt at persistent entities and decided to redo it instead of setting persistence in the editor, I went with something closer to Unity’s DontDestroyOnLoad , where scripts explicitly mark entities as persistent. makes more sense and is a lot less weird around scene changes. (i.e this.SetPersistent(true); ) changes scripting added: entity.SetPersistent(true) entity.IsPersistent() persistence persistent entities are tagged before the scene unloads, serialized normally, then re-injected and reparented when the new scene loads. the persistence tag itself isn’t serialized, so it won’t accidentally end up saved into the scene dedup added some basic deduplication so persistent entities don’t get duplicated if the new scene already contains an entity with the same name. its name based for now… not very great, but good enough"}, {"post_id": 50497, "ts": "2026-08-19T17:37:31Z", "hours": 6.7433, "text": "persistent Entities been working on persistent entities via a tag.. the same idea as Unity’s DontDestroyOnLoad, except you mark entities as persistent in the editor instead of doing it through scripts (scripts can do it too though). everything keeps breaking or half-working help."}, {"post_id": 49249, "ts": "2026-08-17T22:47:10Z", "hours": 2.5156, "text": "more docs… and some bug fixes some small bugs that have been annoying me for a while finally got fixed… and I wrote more docs than I probably needed to…? or maybe too litte.. who knows changes entity selection actually clears now fixed an issue where clicking empty space in the viewport wouldn’t reliably clear the current selection. the pick-result handling was structured wrong, so the “nothing was selected” case basically never got handled properly. also explicitly clear the entity ID framebuffer attachment every frame so it doesn’t leave stale IDs around from previous frames. i knew this was broken, and figured the fix would be pretty simple for a while.. but i just kinda forgot to fix it.. oops…. fixed parent transforms during scene loading fixed a bug with parented entities getting their transforms messed up when loading a scene. the issue was that scene loading was using the same Reparent() logic as interactive editor reparenting. that function intentionally recalculates the local transform to preserve world position, which is what you don’t want when loading a transform that’s already been serialized correctly… was eepy when writing that i guess added Registry::SetParentDirect() for scene loading, which just sets up the parent/child relationship without touching the transforms. interactive reparenting still uses the old behaviour, so dragging entities around in the hierarchy still preserves their world position misc cleaned out some old commented-out code docs, docs, docs also wrote proper editor documentation section covering things like: editor concepts usage scenes prefabs components and some even have screenshots.. yes i know.. fancy the help button in the editor links to some of these pages now. i guess “figure it out yourself” wasn’t really an acceptable documentation strategy anymore…. i mean i had some docs.. but they weren’t that good for editor-usage and more technical stuff.. so yep.. also made the README headers slightly more obvious because people were still asking where the download link was …."}, {"post_id": 48754, "ts": "2026-08-17T08:58:43Z", "hours": 2.7114, "text": "scrips can change things on the map yippie changes scripting scripts can now modify maps through EngineLib added: Map_SetHexWalkable Map_SetTileType yes, i made sure changes to walkability properly update the map’s pathfinding data instead of leaving it with stale information… sanitizers added sanitizer builds…. got ASan + UBSan working through CMake, along with presets for testing… it has helped already :) timers SetTimeout : if a script created a timer and then the scene changed before it fired, the callback could still run against the old scene state. timers now use generations, so changing/reloading a scene invalidates any timers belonging to the previous scene. editor fixed another map editor bug where discarding unsaved changes didn’t actually discard them… it would clear the dirty state but leave the edited map in memory… i knew about this bug and fix for a while, but i kept on forgetting about it… but its finally done -.- also added an Edit button to script entries in the project browser so scripts can be opened directly (launches default app it detects for the file via ur os)"}, {"post_id": 47739, "ts": "2026-08-15T21:10:44Z", "hours": 1.0883, "text": "mostly ui stuff (and fighting windows wide chars) yay pretty ui editor ui theming ui blah blah idk what to call it kinda cleaned up some stuff into proper members so the ui state doesn’t get all weird and persistent when you close the theme window discarding changes: actually works now. closing the window used to revert colors but keep your staged font changes, which was dumb (didnt really cause issues since changes werent applied anyways unless you saved beforehand but still.) font role indicators: added a little visual thingamabob where the font list now shows a star next to whatever font is actively set as the body font (also font name is now rendered in its proper font) path tooltips: added a hover tooltip on the font list items that shows the full file path of the font also some placeholder stuff in the code for searching the customization menu i might be implementing soon windows compat std::filesystem::path everything: went through and switched out the raw std::string usage for font paths inside FontConfig , replacing them with std::filesystem::path . this was purely because my windows ci build was failing. i was passing raw char strings around and doing weird string conversions, which completely blows up on windows because it expects wide chars for paths and i didnt consider that when i was being lazy and doing silly conversions and stuff because i just wanted to pass ez pz to a c library. freetype & serialization cleanup: updated all the internal freetype helper functions ( GetFontName , etc.) and the json theme serializer to play nice with the new paths instead of passing raw char pointers kinda mostly just making it a lil more prettier"}, {"post_id": 47431, "ts": "2026-08-15T11:16:32Z", "hours": 9.0703, "text": "fighting with fonts font-management rabbit hole in the theme editor… still wip changes font management in the theme editor the theme editor now has a proper Fonts section import .ttf / .otf fonts directly from the editor assign fonts to roles like Body, Bold, Monospace, Icons, etc. merge fonts together so icon fonts can be stacked on top of regular fonts rename, delete, and change the size of fonts fontsets are now saved as part of the theme, so imported fonts persist across restarts the role system isn’t fully wired up yet currently Body is used as the default editor font and Monospace is used for the console. im still working on the whole font management system here and its very unfinished and kinda untested.. very WIP!!! hot-reloading the annoying part was getting font changes to work while the renderer is running on another thread. rebuilding the ImGui font atlas in the middle of a frame was… not ideal, and eventually resulted in an assertion. now font changes mark the atlas as dirty, and the editor waits for the render thread to finish before rebuilding the atlas at a safe point. not the prettiest solution, but it seems to be working.. kind of dpi & freetype also experimented with DPI handling for fonts and wrapped FreeType into a single shared instance instead of creating separate instances everywhere. still figuring out exactly how I want the DPI/font sizing stuff to behave, but it’s getting there. bug fixes while doing all of this I also ended up fixing a few unrelated things: fixed an old GUI rendering bug where text could stop rendering or become garbled because of a pointer race thanks to @staneko for helping test/report that one since I couldn’t reproduce it properly on my system fixed a weird compilation issue related to namespace escaping bumped the vendored ImGui version for some dynamic font-related fixes a few other small UI changes and cleanup still working on this, and the font management side definitely isn’t finished yet… most of this time was just spent trying to get it to half-work so.. yep.."}, {"post_id": 46512, "ts": "2026-08-13T19:50:30Z", "hours": 3.6469, "text": "…the default imgui theme first off, huge thanks for all the incredibly kind reviews on my last ship !!! most of this work was also inspired by someone pointing out that i was still using the default imgui theme. fairs… so i spent some time making the editor actually customizable and messing around with having some kinda-nice defaults :) editor ui & theming live theme editor: built a proper window to tweak colors, spacing, padding, rounding, etc. in real-time. semantic palettes: added a semantic color system so you can build out a theme from a small set of base colors, rather than manually adjusting every single internal imgui color enum (though you can still override individual colors if you need to). serialization: themes dump straight out to a theme.json sitting right next to the editor executable. undo/redo: the theme adjustments go through the undo/redo system! help menu: put in a placeholder help menu. turns out literally nobody likes reading docs, so i guess i gotta start explaining how to use the engine from inside the engine… not implemented yet though editor groundwork did a bit of backend cleanup as well. added an EditorContext for editor-specific state, separate from the runtime EngineContext (currently just used for theme stuff) started working on editor font support with a FontSet for things like Body, Bold, Monospace, and Icons, not implemented though the font stuff is mostly groundwork for now, but the theming system is actually working and makes the editor feel nice :D"}, {"post_id": 46257, "ts": "2026-08-13T11:34:55Z", "hours": 2.8147, "text": "scripts can schedule stuff for later Added SetTimeout to the scripting API changes SetTimeout SetTimeout(fn, ms) calls fn() after ms milliseconds. simple to call from obsl timers live in a plain std::vector<Timer> in a new Platform::Time namespace, polled once a frame from Scene::Update no threads, no async bs or whatever :) the callback itself is a SmallTask , which falls back to a heap allocation if the closure is too big to fit inline fine for this since timeouts aren’t really a hot path timeout callback fires from an arbitrary point in Update , so it gets its own ScriptCommandBuffer set up on the worker just for the duration of the call, then flushed right after also gc.add_root / remove_root the function around the callback so it doesn’t get collected while it’s sitting in the timer list waiting to fire Documented it in the api reference alongside the other Time functions also tiny UI tweak in the tile editor: it now warns “no tile types defined, no map will be visible!” instead of just “no tile types defined” was seeing people get confused about why a new map looked empty after trying to paint also small updates to docs in general and stuff but nothing super interesting"}, {"post_id": 40738, "ts": "2026-08-04T13:46:27Z", "hours": 0.7667, "text": "Lighting Fixes been fixing a few small things with the lighting system mainly fixed lights using the wrong entity transform I forgot to account for entity parenting when I implemented that… also added a per-scene toggle for enabling/disabling the lighting system"}, {"post_id": 40621, "ts": "2026-08-04T08:56:51Z", "hours": 3.7144, "text": "the repo is public been working on gettin things ready for that, mostly writing some docs and getting GitHub Actions set up so I can build and release cross-platform builds also did some small code cleanup / fixes while I was going through everything. changes github actions i setup a workflow to compile the project on linux, windows, and mac, and then publish a release (mac is untested but compiles). im real happy though that its actually compiling on all “major” platforms though docs finally wrote some actual documentation… there are a few files in the docs/ folder now and a proper README still a WIP obviously, but at least there’s something there… misc implemented create new map button i forgot about completely repo there is already a build published as a test of the github actions thingy, try it out if you want :D https://github.com/torkelicious/obliberry"}, {"post_id": 39155, "ts": "2026-08-01T21:44:42Z", "hours": 3.0289, "text": "Bugs bugs bugs… I’ve been working on a demo project to both test the engine properly (looking for bugs and all), and also have something to actually show off made in my engine… this is the project you’ve been seeing in the last couple logs btw :) of course… since I’ve been using the editor for actual “work”, I have found a bunch of bugs. the biggest one being the entity ID situation… or.. disaster? changes the entity ID mess in the past, out of laziness… entity ID 0 was being used as both a real, valid entity handle and the “no entity / invalid” value depending on where you looked. which worked fine… mostly because of pure luck. the annoying part was that after working on this for a while I wasn’t even sure anymore if I was using 0 , -1 , or something else for invalid entities.. yep.. so I finally cleaned it up there is now a proper INVALID_ENTITY_ID constant, and entity index 0 is reserved for invalid entities. real entities now start from 1 . went through and replaced a bunch of random == 0 / != 0 checks across ECS, serialization, prefab handling, editor panels, and scripting bindings. project templates added support for multiple project templates. new project creation now scans the Templates/ folder instead of everything being hardcoded to “Default”. currently has: DemoProject Empty the demo project is mostly there to show off the newer UI/scripting stuff (the same demo as mentioned before), while Empty is just a completely blank scene. hierarchy & transforms fixed entity and UI reparenting. previously moving something to a new parent could randomly change its position because it was just applying the new local transform now reparenting keeps the world transform, so dragging things around in the hierarchy behaves properly UI & text rendering fixed a bunch of UI text issues. text now centers vertically using actual glyph metrics instead of a random offset I was “pretty sure” was correct it was not, in fact, correct button text now scales to fit inside the button fonts can now load directly from VFS memory instead of requiring a real filesystem path the VFS font loading one was something I completely forgot about when testing outside packaged projects… oops. packaging implemented .pakignore instead of a hardcoded ignore list, the packer now supports gitignore-style patterns in a .pakignore file and properly skips ignored folders/files also fixed a few smaller packaging issues while testing exported projects. misc a bunch of smaller things: map save/load dialogs now default to the project maps folder fixed scene switching bindings in editor play mode fixed a lightmap redraw bug font importer now only accepts .ttf / .otf added a small README with build instructions since im planning on publishing the repo soon (and writing all the docs… scary..) nothing super flashy this time.. but important"}, {"post_id": 38183, "ts": "2026-07-31T13:32:00Z", "hours": 0.8028, "text": "Windows Build The Windows build seems to be working.. I don’t have proper OpenGL passthrough in my VM… However, the Windows executable compiles perfectly in the VM and is running fine under Wine. so I consider that a win for now…"}, {"post_id": 37625, "ts": "2026-07-30T14:23:01Z", "hours": 1.56, "text": "working in a windows vm trying to get it to compile on windows… it is obviously going great… -.-"}, {"post_id": 36411, "ts": "2026-07-28T14:49:53Z", "hours": 3.1286, "text": "Entity Hierarchy & Scripting Integration finally caved & added actual parent/child relationships to entities changes entity hierarchy entities can now have a parent & children via a new RelationshipComponent . Registry::Reparent() handles moving an entity under a new parent, with cycle & self-parenting protection so you cant do anything silly like parenting an entity to its own descendant. TransformComponent now has a worldTransform alongside the existing local one, a new HierarchySystem systems that care about actual position (i.e AISystem ) read worldTransform now instead of assuming local == world. destroying an entity recursively destroys its children too & unlinks it from its parent’s child list scene serialization now saves & restores the hierarchy editor the Registry panel is a proper collapsible tree now instead of a flat list drag & drop reparenting, plus a right click menu for “Create Child”, “Detach”, & “Set Parent”. scripting pulled all the entity/component script bindings out into their own EngineLibRegistry.cpp module, they were kind of scattered around before & this makes them way easier to find & extend. scripts can now walk the hierarchy too (get children, etc), same module. added SetFont / GetFont bindings so scripts can assign or query a button’s font, small thing but script generated buttons wont have visible text without it :) misc cleanup small modernization stuff while i was in these files anyway: dropped redundant ternary parens, swapped a bunch of auto x = ...; if (x) into if-with-initializer, dropped some unnecessary global qualifiers, const-correctness fixes on UISystem::Update & UIRenderer::Flush . (yes i know the gizmos are offset and buggy, i kind of forgot to update the gizmo code after changing transforms :p )"}, {"post_id": 35110, "ts": "2026-07-26T10:28:41Z", "hours": 8.4342, "text": "Scripted UI, Map Workflow, & a Bunch of Bug Fixes alot of bug hunting… changes scripting & ui scripts can now actually interact with the UI system. added bindings for things like: creating UI buttons, text, rects, and images finding UI elements destroying UI elements these return wrapped objects with basic getters/setters for position, visibility, and button state map workflow spent a fair bit of time cleaning up the map editor flow. maps no longer get a fake default path on creation switching to the Map Editor tab now auto-creates a map (empty) if there isn’t one yet mapFilePath now stays project dir relative instead of randomly becoming absolute tile materials are now shared properly instead of silently duplicating state rendering & lifetime bugs i’ve been doing alot of testing recently, so i found alot of bugs… this was probably the biggest pain point. renderer submissions now keep materials and meshes alive for the frame instead of trusting the caller replaced the old Shader::Default() singleton hack with a real fallback shader (internalshaders base) fixed the lightmap quad so it keeps its own VAO and clears correctly when there are no lights fixed a Texture move bug that was double-deleting GL handles sometimes editor polish also cleaned up a bunch of editor behavior while I was in there. Ctrl+S now behaves correctly depending on whether editing a scene or a map scene loading now rebinds editor panels properly save/load dialogs now append file extensions automatically added more inline warnings in the inspector and panels (i.e if an entity has no material it will tell you it wont render) and ive probably forgotten something else … in summary ive just been testing out some UI/UX changed and hunting down bugs untill I feel it is ready to maybe start prearing some sort of demo :)"}, {"post_id": 33128, "ts": "2026-07-22T19:10:20Z", "hours": 2.6717, "text": "more ui ive been kinda sick so i aint really had the motivation to do a lot but ive been working more on the UI system im kinda tired so i dont really feel like writing more for now -.-"}, {"post_id": 31900, "ts": "2026-07-20T17:42:45Z", "hours": 4.6017, "text": "game UI Progress been continuing work on the UI system. changes UI made some good progress UI system currently have: font importing working texture support for UI elements basic text rendering a simple editor view panel for UI it’s still very much WIP editor right now it’s pretty basic, but it’s enough to start experimenting with how creating and editing UI might actually work inside the editor there’s still a lot left to do before I’d call it usable, but im making progress.. getting text working is painfull, and still unfinished.. but im workin on it…"}, {"post_id": 30701, "ts": "2026-07-18T14:27:23Z", "hours": 3.7628, "text": "UI Experiments since working on the particle system, I feel like it’s in a pretty good place for the current scope. I don’t really know what else I want to add to it right now, so I decided to finally start on something that’s been sitting in the back of my mind for a long time… a proper UI system. changes particles mostly just spent some time testing and polishing the particle system to make sure everything behaves properly I’m pretty happy with where it’s at for now UI started prototyping a custom UI system it’s very early, but I’ve got the basic rendering pipeline up and running currently working on: a UIElement system a dedicated UI renderer text rendering font loading using FreeType right now it’s mostly just enough to prove everything works, but it’s the foundation for the runtime UI system ive wanted for a long time the goal is for games made in the editor to be able to have their own UI, with everything exposed through EngineLib so scripts can create and interact with UI elements as well honestly, for now.. I was expecting it to go alot worse.. FreeType isn’t as bad as it seems once you get it working with GL The screenshot below dosent show much, but you can see the rendering of Text and rects, it also supports textured rects (which is what the text is currently using to render from a texture atlas)"}, {"post_id": 30249, "ts": "2026-07-17T17:50:34Z", "hours": 2.8864, "text": "More Particle work… been spending some time on the particle system… changes particles expanded the particle system quite a bit. currently supports: randomized size ranges randomized rotation configurable emitter shapes (support quad, circle, and soft circle) alpha and additive blending configurable render order (still kinda broken but im working on it) per-particle color over lifetime particle presets that can be saved and loaded (as JSON) also added an editor preview mode, so particles can be previewed while editing instead of only showing up in play mode renderer had to do a bit of renderer work to support all of this particles now use their own dedicated shader added support for per-instance colors during instanced rendering added an overlay render pass for effects that should render on top of the scene cleanup also did a some more project cleanup, splitting up my Utils header into multiple files.. nothing special though misc particle emitters can now be saved as reusable presets (some which will be shipped as defaults ofc) as suggested by @sol4r_on_hackclub cleaned up a few asset importing edge cases fixed a couple of packaging issues too I’m pretty happy with how the particle system is coming along :D"}, {"post_id": 29706, "ts": "2026-07-16T19:55:20Z", "hours": 0.9678, "text": "mostly just spent some time going through some old code.. nothing really important, but i’ve also replaced the placeholder assets.. with my own placeholder assets that i drew in GIMP, considering i probably do not have the rights at all to distribute the previous assets.. :)"}, {"post_id": 29523, "ts": "2026-07-16T14:38:59Z", "hours": 2.2728, "text": "Particles! :) Ive started working on a particle system. i have got the core pieces in place and it seems to be working nicely so far…. changes particles implemented the foundations of the particle system currently has: ParticleEmitterComponent ParticleSystem ParticlePool emitters currently support: configurable particle limits and emission rates randomized lifetimes and velocities “gravity” size over lifetime color over lifetime world space simulation materials obviously so far it’s all behaving pretty well… EngineLib next up is getting particles exposed through the EngineLib API so scripts can spawn and control emitter components we will see how it goes…"}, {"post_id": 29203, "ts": "2026-07-15T22:53:22Z", "hours": 6.2536, "text": "Editor QoL, Graphics Configs & Prefabs new devlog… mostly been focusing on editor ui and qol changes this time around. kinda tired of hardcoded settings for the graphics settings, so i finally built a proper interface for it, plus some prefab management stuff in the editor changes graphics settings i built a dedicated graphics configurator window in the window, for the current project ( GraphicsConfigEditor ). it hooks directly into the UndoManager using the command pattern ( GraphicsConfigUpdateCommand ) serializes everything out to graphics.json . added QuerySupportedSampleCounts which asks the active GL context ( before it gets handed to the render thread ) what MSAA sample counts it supports. the editor now dynamically generates the dropdown and snaps to a valid sample count (i.e 1, 2, 4, 8, 16). prefab management the editor now supports prefab management that i implemented earlier .. instead of directly writing it in the scene json file you can spawn entities directly into the scene from prefab json files you can revert a prefab, which wipes any local overrides and resets the entity back to whatever is saved in the file you can break a prefab, severing the link to the json file and turning it into a normal, standalone entity in the registry ui & editor cleanup spent some time making the editor less annoying.. in general the editor layout stops resetting itself , it now checks if imgui.ini exists on startup, and if it does, it skips rebuilding the default dockspace ripped the hardcoded hub drawing code out of the EditorLayer and made it its own state for the editor state machine refactored the config windows ( ProjectConfigEditor , SceneConfigEditor , and the new GraphicsConfigEditor ) to inherit from a base ConfigEditor class so its cleaner and easier to maintain.. fixed the script widget since the ui was kinda messy"}, {"post_id": 28584, "ts": "2026-07-14T22:27:14Z", "hours": 2.6136, "text": "the OpenGL State Machine Strikes Back… I spent the entire day trapped in hell: debugging a corrupted OpenGL state… it may not show up as tracked hours.. since most of it was just staring at various forms of text.. but it was painful. problem so since i turned the lightmap to run on gpu .. well… Whenever I transitioned from the editor ( MapEditState ) into Play mode, the map would turn into like a bunch of weird diamonds, and the corruption would persist indefinitely until I remounted the current project. because it only happened on state transition, i spent hours chasing ghosts in my state management code and scene cleanup routines… (in the end though i did make some changes to the cleanup routines, but between states rather than scenes.. so i guess i was halfway there?) the culprit It was the lighting pass… took me forever to figure it out, but i had the genius and definitely NOT a very late and obvious idea i shouldve had hours ago , to see if the issue happened when i turned off the lighting system. so i put some early returns in my lighting system functions and.. it didnt corrupt.. inside LightingSystem::Update() , the renderer was modifying global OpenGL state changing depth functions, blending modes, and texture bindings, but not restoring them to their original defaults properly When the engine swapped states, the next frame inherited this dirty, half configured state, causing the whole thing to become a mess. the fix I went through the lighting system and made sure the state changes are wrapped and properly restored through the render thread.. LightingSystem.h : Full GL state save/restore around the light pass. now explicitly backing up and restoring the FBO, program, VAO, blend state, draw buffers, clear color, viewport, and active texture. MapEditState.cpp : OnExit() now properly nulls out m_MapComp and m_CurrentGrid . OnEnter() and will refetch them from the current registry so it isnt holding onto outdated references. EditorLayer.cpp : Added a call to renderer->Clean() after state transfers to clear out stale VAO and mesh caches.(bc its multithreaded things go kinda weird but.. it works now) glad thats over with :D Also heres a fun peek of what ObSL can do with EngineLib, yes, it can make your entire map look like hell..! i am totally not going insane"}, {"post_id": 27998, "ts": "2026-07-13T23:29:33Z", "hours": 5.0142, "text": "GPU Lighting & Graphics Settings been doing a bit of rendering work again… mostly trying to optimize things. the biggest change is that I completely rewrote the lighting system previously all the point light calculations were happening on the CPU, and after doing some profiling (and spending way too long staring at compiler generated assembly annotations) it became pretty obvious that this was one of the bigger performance bottlenecks (well THE biggest excluding driver overhead) lighting now runs entirely on the GPU through shaders instead changes lighting rewrote the lighting system. lighting is now shader-based and runs on the GPU removed the old CPU-side lighting calculations moved engine shaders (like the base shader and lighting shader) into built-in InternalShaders (hardcoded string literals, it might seem messy but i prefer it like that) the internal shader change mostly exists because they’re pretty fundamental to the renderer. if they were treated like normal project assets and someone accidentally deleted them… well… suddenly nothing renders (unless they had setup their own shaders, which is fully supported!) and lighting completely falls over, also i prefer it to loading them from the filesystem anyways overall I’m pretty happy with how the new lighting system turned out graphics settings also started working on configurable graphics settings instead of baking them into the project, the engine now loads graphics settings from a separate JSON file. this doesn’t get packed into the .obpak , so users can tweak their graphics settings after exporting a game currently supports: resolution fullscreen MSAA (toggle + sample count) target FPS VSync it’s weirdly fun actually being back in OpenGL code again instead of just working with engine abstractions sometimes it’s nice to get back into the weeds.. even if its.. painfull :D"}, {"post_id": 27425, "ts": "2026-07-12T23:53:21Z", "hours": 7.5097, "text": "Performance & Zero Copy Assets been spending some time under the hood… this one’s almost entirely backend. no new features, mostly went through the render thread, asset pipeline, & a handful of ECS loops to squeeze out more performance. it was incredibly rage inducing at times.. but seeing the profiler diff against baseline.. i am satisfied.. almost at peace.. but was considering becoming a farmer & never touching a computer again.. mostly because i thought i’d messed up more than i did.. but.. im happy now. changes threading & ecs i’ve reinvented the wheel enough already… but had to redo how tasks are dispatched. ThreadPool used to take a std::function , which heap allocates if you capture more than a couple pointers. scripts dispatch through this every frame, so it added up. swapped it for a custom Task type a 56-byte inline buffer, no heap allocs swapped the pending-task counter to a lock free atomic decrement instead of a mutex on every completion… rendering been cleaning up how the main thread interacts with the render thread. the main & render threads used to awkwardly poll eachothers framebuffers. now theres a m_ReadyFrames deque main pushes a frame index, render pops it. much cleaner :) ImGui draw data is now reused in-place instead of allocating & freeing a fresh clone every frame (ive put off fixing that hack for a while so its nice to finally come around to it). instanced draws no longer store a vector<mat4> per draw call, transforms get appended into one giant staging buffer per frame now. added SubmitPersistent for things that already own a long-lived buffer (like the map tile renderer) to skip the copy entirely. swapped a bunch of unordered_map s for flat vectors in the texture/VAO/uniform caches for a handful of items, linear scan beats hashing. batched rendering also caches the last bound texture & color uniform so b2b batches sharing a texture dont rebind needlessly. added a zero-size window safeguard for Wayland so it stops wrecking the renderer when the window briefly reports 0x0 during resize (also turned vsync back on, weird syscall spam otherwise) assets & packaging added VFS::ReadVirtualView to hand out string_view s directly into memory instead of owned strings for packaged builds, ContainerReader now mmap s the .obpak file directly, uncompressed stuff (textures, uncompiled maps) gets handed right to the parser without a copy. also now move only, with a destructor that unmaps memory instead of holding a copied vector of chars scripting the script hot-reloader was doing a stat() syscall on every script file every frame . oops. now polls every 300 frames & caches resolved paths.. thought i already debounced this.. guess not.. the on_update & on_destroy work buckets used to be freshly allocated vectors every frame… now static , so they just clear & reuse capacity editor & ui finally ripped out the old in game debug UI ( GameUI.cpp ), it had fallen out of sync with the ECS anyway (used it for debug visuals while implementing the first version of the ecs.. then forgot about it) the editors inspector does all of this better now, so replaced it with a minimal FPS counter audio & map audio engine now sets an explicit period size (2048 frames) via miniaudio to cut IPC roundtrips to the audio daemon.. (this one was annoying to figure out.. god bless strace & gdb) the map’s visible transforms buffer is now double buffered, rebuilds write to the back buffer while the render thread reads the front, no race conditions. also swapped typeMats from an unordered_map to a flat vector nothing user facing changed this time, but frame pacing feels noticeably smoother (somewhat suprised), & the packaged build starts noticeably faster i know it could probably be a lot better, but im still a bit of a noob at C++, so this is one hell of a learning project"}, {"post_id": 26719, "ts": "2026-07-11T17:53:32Z", "hours": 3.9353, "text": "Undo/Redo …again! been working on the editor again the undo/redo system now covers a lot more than just gizmo transforms. but there’s still a few things left (entity creation/deletion mainly). changes undo/redo expanded the command system to cover most editor actions. currently supports: entity transforms adding/removing components adding/removing scripts editing project settings editing scene properties also fixed the undo/redo shortcuts so they only trigger once per key press instead of repeatedly firing while the keys are held… which is probably how they should’ve worked from the start map editor continued working on map editing. painting and erasing now properly integrate with the command system. also, an entire brush stroke is treated as a single undo step instead of undoing one tile at a time. also cleaned up a couple of edge cases while doing this, like preserving existing tile data and avoiding unnecessary commands when nothing actually changed. misc did a bit of cleanup around the editor while wiring everything together. centralized a few bits of duplicated UI logic cleaned up window title updates continued refactoring the command system the undo system is still unfinished, but it covers most of the important stuff and feels nice.. also.. still gotta fix some ui window-size stuff soon too but .. thats for later"}, {"post_id": 26228, "ts": "2026-07-10T21:54:28Z", "hours": 3.1872, "text": "Undo/Redo! :) been working on some editor QoL stuff again… the biggest addition this time is a proper undo/redo system. it’s still very early and pretty barebones, but having the foundations in place is nice changes editor commands implemented the beginnings of a proper command system for the editor instead of modifying things directly, editor actions now go through commands, which means they can be undone and redone currently supports: entity transforms movement rotation scaling adding components removing components (with the exception of ScriptComponent for now.. that’ll get its own custom command due to the way it works) also keeps a command history, and the usual shortcuts are hooked up now: Ctrl + Z : Undo Ctrl + Y : Redo its still pretty basic, but it works and feels nice to use. input for this, I added proper key-combination support to the input manager. things like: Ctrl + S Ctrl + Z Ctrl + Y can now be handled properly instead of manually checking modifier keys everywhere logging did a bit more cleanup to the logging system as well. the logger now goes through a proper interface instead of everything depending directly on one concrete implementation, which should make it a bit easier to swap things around later if I ever want to. mostly backend work again… but undo/redo is fire"}, {"post_id": 26050, "ts": "2026-07-10T17:12:54Z", "hours": 2.2128, "text": "editor polish still nothing super flashy.., mostly a bunch of small things changes window titles the editor now updates its window title based on what youre working on. it’ll now include things like the current project and scene, or map project loading cleaned up project loading a bit. the editor now properly syncs the loaded project configuration into the engine context instead of relying on stale data also added menu in the map editor that lets you save and load map files (create new is just placeholder for now) UI added a small helper for rendering framebuffer textures in ImGui without needing to remember to flip the UVs every time. and made the tile Editor use it also forgot to mention in the last log that i cleaned up the “project browser” ui a bit logging fixed up some more logging :)"}, {"post_id": 25892, "ts": "2026-07-10T11:51:37Z", "hours": 3.0564, "text": "Logging Cleanup replaced all the random std::cout / std::cerr calls scattered throughout the project with an actual logging system logging implemented a proper logging system. replaced std::cout / std::cerr throughout the engine added support for different log levels optional logging to a log file centralized all engine logging into one place thread safe !!!! nothing particularly flashy or fancy, but its cleaner, easier to work with, and generally just nice i probably should’ve done this a long time ago :)"}, {"post_id": 25509, "ts": "2026-07-09T20:30:56Z", "hours": 4.8756, "text": "Map Editing, Brushes, and a 4(?) hour ImGui Bug The map editor is finally coming together It’s still a bit… rough but it does feel nice to be able to paint a map in the editor I did, however, spend an embarrassing amount of time trying to figure out why my click and drag “painting” wasn’t working… well.. ImGui was eating my inputs because it thought I was trying to drag the Scene View window around.. yeah.. changes map editor actually got the map editing tools working for real this time. the paint and erase tools actually place and remove tiles now instead of just being placeholder buttons added a brush radius slider, so you can paint in bigger hex rings added a preview outline that renders around your cursor so you can see before clicking toggling “is walkable” on a tile now properly syncs with the grid pathfinding editor ui spent some time making the tile palette and material editing.. work.. video explains better ngl im not good at describing ui stuff math laid some groundwork in the hex math system ( Lerp , CubeRound , and GetHexLine ) this is mostly for some future evil plans… still a WIP…"}, {"post_id": 25003, "ts": "2026-07-08T22:10:08Z", "hours": 0.7108, "text": "map editor preveiw ig kinda didnt have much time to do anything today but im working on the tile editor"}, {"post_id": 24426, "ts": "2026-07-07T23:37:55Z", "hours": 8.7589, "text": "editor rework & map editing groundwork been working on the editor again this update was mostly about cleaning up the editor architecture so I can actually keep adding features without everything turning into spaghetti. I also finally started laying the groundwork for proper map editing. changes editor reworked the editor state system. instead of instantly swapping between states, transitions are now deferred until a safe point during the update loop. this makes switching between Edit, Play, Map Edit, and the Hub a lot cleaner, and the editor now remembers which editing mode you were in before hitting Play. (i’ll admit… i was getting a bunch of weird, seemingly unexplainable crashes before eventually realizing my mistake was instantly switching states while things were still being updated/rendered…) also moved more UI responsibility into the individual states instead of having EditorLayer decide how everything should be drawn. map editor started putting together the map editor. currently i have: map hover and tile selection working placeholder Paint / Erase / Select tools the beginnings of a tile palette system a placeholder tile editor panel the actual editing logic isn’t implemented yet, but the foundations are there now :) asset picker ripped out the old “open a native file dialog for every asset field” flow. instead, the editor now lets you pick existing textures, meshes, materials and shaders directly from the ResourceManager , which is a lot nicer to work with and also avoids accidentally importing duplicate assets. (the old workflow would happily create a brand new object every time you imported something… which was fine for testing, but definitely wasn’t something i wanted to keep) rendering fixed a few editor rendering issues while i was at it. materials with invalid shaders now fall back to the default shader instead of silently disappearing fixed some edge cases with framebuffer entity picking currently unused, but functional shader hot reloading tests misc smoothed out editor camera movement and zoom added a few helper utilities for the map editor reorganized the editor UI code a bit doesn’t look massively different in screenshots, but makes future work alot easier/cleaner map painting is next ?.."}, {"post_id": 23641, "ts": "2026-07-06T18:38:19Z", "hours": 2.4394, "text": "Project Exporting been working on making projects exportable from the editor it’s now able to export a project to the selected folder, package all the assets into an .obpak , and then copy over the runtime so the exported project is runnable changes project exporting added export to the editor choose an output folder for the exported project packages the project into an .obpak copies the runtime into the export folder renames the runtime to match the project name (just 2 files for full project!, executable and .obpak) the whole process is pretty much one click now instead of manually packaging everything together. file dialogs refactored my entire filedialog implementation cuz it was kinda broken packaging did some more work on the packaging pipeline while implementing exporting and put it in the editor ui im pretty happy that its all working and i can actually export stuff, and run it feels cool :)"}, {"post_id": 23429, "ts": "2026-07-06T12:05:06Z", "hours": 4.1694, "text": "Project Packaging is Working been spending a lot of time working on project packaging, and it’s finally working now. the engine can now load projects directly from .obpak files, and I’ve got basic tooling to create them as well. the plan is to integrate the tooling i have now with the editor to “build” an obpak archive (i think its called an archive?) changes packaging implemented the full packaging/loading pipeline yippie :D currently the packer: pre-generates ASTs for ObSL scripts converts project, scene(s) and prefab(s) JSON into MessagePack bundles everything into a single .obpak container compresses the package with LZ4 assets like textures, audio and shaders just get copied into the package without any conversion runtime the engine can now load packaged projects directly instead of relying on loose project files. all of this goes through the VFS, so from the engine’s point of view it doesn’t really matter whether assets are coming from a folder or from an .obpak (i.e it can still load loose project files of course) tooling added command-line tools for packing and unpacking projects, i originally made it for testing but it’s actually pretty nice to work with so im probably keeping it. still probably things to polish, but it’s pretty satisfying seeing the engine load an entire packaged project properly pls ignore the lag in the video, i promise its not as terrible as it looks, its just that recording is pretty buggy for me"}, {"post_id": 23095, "ts": "2026-07-05T20:42:38Z", "hours": 3.8311, "text": "Project Packaging been working on a packaging format for projects. the goal is basically to package an entire project into a single container while preprocessing assets that make sense to preprocess. Also makes shipping a game made in the engine in the future alot easier / cleaner, and portable. changes packaging implemented the start of a proper project packaging system. currently it: parses ObSL scripts ahead of time and stores serialized ASTs instead of source code (basically very similar to some sort of a very very simple AOT compiler) converts project, scene and prefab JSON files into MessagePack stores media and other binary assets directly in the package optionally compresses package entries with LZ4 the idea is that the engine has less work to do at runtime since scripts don’t need parsing and JSON doesn’t need parsing either. and a single “package” file is alot cleaner in general for a finished game “build” package format also implemented the actual container format itself. different asset types are stored as different entry types (scripts, binary JSON, media, shaders, etc.), so the loader knows exactly how each asset should be handled. tools added standalone packaging tools as well for packing and unpacking projects, mostly for testing. still a work in progress, but the whole packaging pipeline is starting to come together."}, {"post_id": 22372, "ts": "2026-07-04T20:12:27Z", "hours": 5.1664, "text": "editor Gizmos! :DD this took a lot longer than I’d like to admit… but it’s finally working. changes gizmos got all gizmos working.. but had issues with rotation and scale at first figured out the issues with rotation/scaling ended up patching ImGuizmo at first to get things working, but after digging through the code I eventually figured out how to do it properly with the normal library translation, rotation, and scale gizmos all work now :)))))) honestly I learnt quite a bit just from messing around with the ImGuizmo internals.. but it was painful editor added a few more UI improvements as well. i.e billboard sprites now explicitly mention that rotation doesn’t do anything, instead of letting you wonder why nothing happens gizmos are one of those things I’ve been waiting on implementing.. but im finally happy to have them"}, {"post_id": 21565, "ts": "2026-07-03T16:19:30Z", "hours": 2.6169, "text": "actually working on the editor I’m finally getting around to actually implementing the editor ..it still looks pretty similar (well mostly the same) but most of the UI before was just placeholder. changes editor implemented a Project Settings window implemented a Scene Properties window made the component widgets actually do something now load textures assign scripts change material colors change meshes change shaders etc…. added an Add Component button added Remove buttons to components it works.. so thats good :D"}, {"post_id": 21208, "ts": "2026-07-03T00:51:55Z", "hours": 0.6447, "text": "ObSL Scripting Library Moved the scripting language into its own repository :) It’s now included in the engine as a library using git submodules and public headers instead of living directly in the engine source code Makes the project structure a lot cleaner .. for both projects ( ObSL can now be found at https://github.com/torkelicious/ObSL )"}, {"post_id": 21066, "ts": "2026-07-02T20:52:49Z", "hours": 5.9469, "text": "Script multithreading (and concurrency) scripts now run on other thread(s) :D this took a fair bit of cleanup, but it’s working. changes script workers moved script execution onto worker thread(s) worked on script worker concurrency dynamically clamp the number of active workers based on how many callbacks are actually running, so idle threads aren’t just spinning doing nothing garbage collection did some work on the GC as well. introduced external root tracking fixed a few issues around GC roots while getting multithreaded script execution working cleanup spent some time cleaning up a bunch of backend stuff while getting all of this working. build system updated CMake so all executables, scripts, and (project) templates are output to a single build/bin directory instead of being messy. multithreading yay :)"}, {"post_id": 20164, "ts": "2026-07-01T18:24:52Z", "hours": 3.945, "text": "ive been mostly messing around with getting the ObSL language to be thread-safe and refactoring some things, so I don’t have much to show but my end goal is to be able to get scripts to run concurrently and outside of the main thread"}, {"post_id": 19379, "ts": "2026-06-30T17:52:06Z", "hours": 4.6878, "text": "Editor & Scene Management been working on the editor mostly. changes ECS implemented generational ID masks for the ECS. this should prevents issues with stale entity references since IDs can now properly track generations instead of just relying on raw IDs. (i encountered this issue when testing multiple scenes in one project) scene manager fully implemented the SceneManager so it can actually be used by the editor & game layer. this allows the editor to properly load/save/validate/find and generally handle scenes through a unified API (goes for gamelayer aswell but it only really loads them) bug fixing spent a lot of time fixing various issues around: project folder management scene management loading / saving behaviour asset loading (cache was causing some problems on loading scenes but its all fixed now :D) mostly backend work but things are becoming a lot more stable and the editor foundation is starting to come together…."}, {"post_id": 18509, "ts": "2026-06-29T17:58:54Z", "hours": 7.6317, "text": "Namespace Refactor & Project Management Work Dependencies finally caused me to run into a namespace conflict after being lazy and unorganized… instead of being sane and just renaming one class.. I decided to refactor the entire project to use proper namespaces everywhere.. changes namespaces Refactored the entire codebase into proper namespaces project management / editor backend I don’t really have much visually to show this update since I’ve mostly been working on backend stuff. Working on: project management scene management VFS improvements editor saving/loading I’m using nativefiledialog-extended to work on proper file dialogs for saving and loading from the editor. Also been doing a lot of testing around project creation and loading. alot of this is in the hope i can get this working multi-platform and not just on linux (though i have yet to try and compile on another os) Things are working… for now… so progress :D"}, {"post_id": 17698, "ts": "2026-06-28T16:44:24Z", "hours": 1.5475, "text": "Editor Picking & Project Management because my EditorLayer uses a framebuffer, I can now utilize framebuffer color picking in the editor i updated the shaders to store an entity ID, so now I can click on entities directly in the editor scene view and it selects them. …and it’s pixel perfect :D changes editor layer added framebuffer based entity picking clicking entities in the scene view selects them!!!! selection is based on the exact pixel under the mouse (i mean to implement gizmos i first need to know what the hell my mouse is on) project management also started laying the groundwork for actual project management. now that I have some sort of VFS implemented, I’m working on a way to properly manage Projects instead of relying on the current setup. still figuring out the exact structure, but ive been working on setting up the Project class"}, {"post_id": 16940, "ts": "2026-06-27T14:41:38Z", "hours": 3.1197, "text": "VFS & Editor layer implemented a basic VFS (Virtual File System) . all asset loading is now routed through the VFS instead of directly loading files. this is mainly preparation for adding proper project management later instead of relying on a hardcoded project.json in the project root i was testing with changes VFS added a basic VFS implementation routed asset loading through the VFS the idea is that the VFS will make it easier to manage project assets and not have everything depend on hardcoded paths. editor layer still experimenting a bit with the editor placeholder UI. added: (new EditorCamera derived class of Camera ) camera panning in the editor viewport camera zoom toggling top-down / isometric perspective with keybinds the top-down view should be useful later when I add actual map editing stuff most of the editor UI is still just placeholder right now, I’m mostly testing layouts and figuring out how I want the editor to feel and look ImGuizmo also added ImGuizmo to the project since I’m planning to start implementing proper editor stuff soon.. …and well… you need gizmos… I’ve reinvented the wheel enough already, so using a proper gizmo library seems like the better choice :) (also integrates very nicely with ImGui)"}, {"post_id": 16309, "ts": "2026-06-26T15:23:43Z", "hours": 2.0242, "text": "Editor UI & Framebuffer Experiments i’ve started experimenting with the ImGui docking branch in the EditorLayer . (switched branch had some build errors blah blah blah but its all set up now) Implemented some placeholder editor UI to test out the docking stuff and get a feel for how the editor layout might end up being like changes editor layer placeholder UI using ImGui docking features testing editor panel layouts framebuffer implemented a framebuffer system for the editor viewport. the scene is currently rendering in the editorlayer via a frame buffer so it can fit in the little thingy (i forgot the name) while testing I noticed some resizing issues when running on my nvidia dGPU: the framebuffer resize works, but resizing the viewport can appear somewhat choppy? the framebuffer and docking setup seem to be working, so i guess this im close to actually start to build proper tooling :)"}, {"post_id": 15851, "ts": "2026-06-25T19:34:56Z", "hours": 4.3886, "text": "refactoring for editor foundation Refactored rendering and culling systems and made broader architectural changes to decouple the game from the application layer. Rendering & Culling Refactored frustum culling logic to be lil more performant and generally cleaner Cleaned up and improved parts of the rendering pipeline since i had alot of old unused code lurking in them since i switched to a multithreaded architechture Application Architecture the engine is now structured around an ApplicationLayer system. The core Application class now runs a single active ApplicationLayer Each layer exposes: Init Update Render Shutdown Game class refactor The Game implementation has been converted into a derived ApplicationLayer Game logic is now fully driven through the layer system instead of hardcoded to the application class (the different executable mains decide now) Editor Layer added a new EditorLayer Intended for a future scene editor application. (right now all it does is render a given scene on the screen) CMake changes reworked the project to generate multiple executables: obliberry_engine core engine executable (ig runtime) obliberry_editor editor application layer changes: Engine and core systems (i.e ObSL, Renderer, etc) are now compiled as libraries Executables link against shared engine libraries instead of duplicating code Editor executable links against engine modules summary Game logic is now layer-based Engine and tools are separated Editor can proceed independently from the game runtime"}, {"post_id": 15286, "ts": "2026-06-24T20:32:54Z", "hours": 3.7039, "text": "multithreading & rendering I think I got some form of multithreading working now. The renderer has been moved onto its own dedicated thread, separating rendering from the main engine thread :) Changes Rendering Thread Moved rendering execution to a separate thread (alot had to be refactored for this to work lol) Thread Safety i tried (imgui was a pain) Rendering Optimizations Added frustum culling to the renderer. big optimizeD? actual rendering (i.e gpu calls) is now seperated from the main thread :D …it looks like its working for now"}, {"post_id": 14758, "ts": "2026-06-23T23:48:42Z", "hours": 0.4239, "text": "I think i fixed most of the silly bugs from trying to make rendering thread safe, im still gonna double check some stuff and do some testing but moving rendering to its own render thread will be coming soon :))))"}, {"post_id": 14743, "ts": "2026-06-23T23:15:37Z", "hours": 1.1569, "text": "kinda reverted changes from the last log and tried again to convert everything to be thread safe before actually trying to run on a seperate thread… things are going.. interestingly"}, {"post_id": 14522, "ts": "2026-06-23T17:41:20Z", "hours": 0.8647, "text": "im trying to make the renderer run on another thread… few issues… cant see (entity) meshes?, and closing the window seems to cause a freeze…. :))"}, {"post_id": 14480, "ts": "2026-06-23T16:45:32Z", "hours": 1.2731, "text": "Been mostly just fixing some window rendering stuff Moved away from hardcoded resolution / aspect ratio and made it handle itself on the fly also removed the padding bars i had before so rendering actually takes up full screen New native engine binding in EngineLib too: Window_SetFullscreen (takes a bool) I’m planning on starting to work on making the engine multithreaded soon…"}, {"post_id": 14379, "ts": "2026-06-23T14:22:29Z", "hours": 0.8064, "text": "“project” file system prototype Started implementing support for engine project files instead of hardcoding a scene path like i was before for testing. The engine will now deserialize a project.json file containing configuration, includes: name Project name (unused for now) version Project version (also unused) start_scene Path to the scene the engine loads on startup Window configuration: width height title fullscreen while implementing this, I uncovered some unexpected behaviour related to fullscreen handling caused by how window sizing was previously managed. i spent time refactoring and fixing the window size logic to make fullscreen behaviour… work.. project loading is now starting to come together, less hardcoded stuff yippie (im planning on making an editor in the future so.. this is why)"}, {"post_id": 14345, "ts": "2026-06-23T13:22:42Z", "hours": 1.3275, "text": "Porting ECS systems to ObSL Fully ported the InteractionSystem to ObSL through EngineLib. Camera movement and player movement are now handled through dedicated ObSL scripts instead of being hardcoded ECS systems. This moves more gameplay logic into the scripting layer and makes systems easier to modify and iterate on :) Changes System Migration Ported InteractionSystem from ECS code to ObSL Basically Moved camera movement & player movement logic into ObSL scripts Interaction system is no longer hardcoded engine-side gameplay system New EngineLib Bindings Math / Hex Grid Math_WorldToHex Converts world coordinates into hex grid coordinates SetSelectedHex Updates the currently selected hex tile Camera Camera_SetZoom Sets the camera zoom level Window Window_GetHeight Gets the current window height Window_GetWidth Gets the current window width Input Input_IsKeyReleased Checks if a key was released Input_IsMouseDown Checks if a mouse button is currently held Input_IsMouseReleased Checks if a mouse button was released Input_GetMouseX Gets the mouse X position Input_GetMouseY Gets the mouse Y position Input_GetScrollX Gets horizontal scroll input Input_GetScrollY Gets vertical scroll input Please ignore the weird graphical artifacting in the attached video, my pc has been acting up recently :("}, {"post_id": 13950, "ts": "2026-06-22T22:00:49Z", "hours": 3.1867, "text": "more EngineLib work Implemented several improvements to the scripting and entity systems. changes prefab caching Added caching for prefabs to improve performance when repeatedly instantiating entities Entity Access in Scripts Added GetEntity , which returns the entity Object that the script is attached to. Added support for the this keyword in ObSL scripts. this is a wrapper around GetEntity() to provide direct access to the current entity custom components Added support for script-defined components: entity.AddCustomComponent entity.GetCustomComponent This allows scripts to attach and retrieve custom data/components without requiring engine side component definitions entity validation Updated all entity object calls (such as GetComponent ) to validate the entity before executing (in both native bindings & engine source code) Entity operations now check: registry.isValid(id) before accessing the entity. This prevents errors caused by accessing deleted entities during scenarios such as scene unloading/loading cleanup"}, {"post_id": 13774, "ts": "2026-06-22T16:02:35Z", "hours": 0.8908, "text": "EngineLib I may have forgotten to mention this in my previous log, but I also implemented an Instantiate method in EngineLib. Instantiate takes an entity definition as a JSON file (ig a prefab) and spawns the entity into the current scene. I also added scene related functionality to EngineLib: LoadScene Loads a scene from a given path GetCurrentScenePath Returns the path of the currently loaded scene"}, {"post_id": 13737, "ts": "2026-06-22T15:02:47Z", "hours": 3.4014, "text": "I’m using miniaudio to implement audio support in the game engine, with an AudioEngine class to abstract the audio functionality. I’ve also updated SceneProperties to include a new background_music property. This allows each scene to define a background music track (via filepath) that will automatically loop through the AudioEngine while that scene is active. It all seems to be currently working well, Next I’m starting to integrate audio functionality into EngineLib so that scripts can interact with the audio system. changes Added AudioEngine abstraction layer using miniaudio Added background_music support to SceneProperties (w. proper serialization/deserialization ofc) Implemented looping background music per scene"}, {"post_id": 13262, "ts": "2026-06-21T18:28:09Z", "hours": 2.735, "text": "EngineLib Script Integration I fully replaced the previously hardcoded PlayerMovementSystem with an ObSL script implementation using new EngineLib bindings. The movement logic is now handled externally through scripting instead of being directly implemented in C++. New EngineLib Bindings entity management Added bindings for basic entity operations: CreateEntity Creates a new entity Destroy Removes an entity HasComponent Checks whether an entity has a specific component RemoveComponent Removes a component from an entity global functions get_dt Retrieves delta time CloseWindow Closes the glfw window Input System Added script access to input handling: Input_IsKeyDown Checks if a key is currently held Input_IsKeyPressed Checks for a key press event Input_IsMousePressed Checks if a mouse button is pressed Input_GetMouseWorldPos Gets the mouse position converted to world space Movement / Hex Grid Functions Added bindings for interacting with movement components: GetSelectedHex Gets the currently hovered hex tile SetPathToHex Sets a movement target path for an entity with a MovementComponent Camera Added camera manipulation support: Camera_GetPosition Gets the camera position Camera_SetPosition Sets the camera position Camera_Move Moves the camera Camera_PanScreenSpace Moves the camera relative to screen space Camera_GetZoom Gets the current camera zoom Hex Rendering Added bindings for controlling grid visuals: ClearSelectionOverlay Clears the hex selection overlay ClearPathTarget Clears the path target visual marker ClearPathTarget is currently named poorly. It only clears the grid overlay visualization, not the actual movement target!!! summary Removed the old hardcoded PlayerMovementSystem Migrated player movement logic into script format Added engine bindings required for script-driven gameplay Camera movement, input handling, and hex selection now work through scripts Even more gameplay code can now be modified without recompiling the engine :)"}, {"post_id": 12232, "ts": "2026-06-19T23:34:06Z", "hours": 2.7347, "text": "I’ve got a good basis for the Engine integration library for the ObSL Scripting Language. In the attached video, I’m changing the player’s size using a ping-pong function (?forgot the name…), fully through an ObSL script ( ScriptComponent ) attached to the “Player” entity. The language now has support for the following through the EngineLib : Entity Objects Find GetName SetName GetComponent Components Transform SetPosition SetRotation SetScale GetPosition GetRotation GetScale (uses ObSL arrays) Point Light SetColor (Vec3) SetIntensity SetRadius MovementComponent GetIsMoving SetIsMoving SetTimePerStep MapStateComponent GetHasSelection GetSelectedHex GetPathToHex DirectionalTextureComponent SetIndex GetIndex PlayerInputComponent is still w.i.p. Tag Components currently don’t have any methods since they are only used as tags. Planned I’m planning to keep expanding the EngineLib api with more methods, such as: Has(component) AddComponent RemoveComponent(name or ref) Destroy(EntityID) GetEntityID(entity object ref)"}, {"post_id": 12030, "ts": "2026-06-19T16:56:29Z", "hours": 2.8408, "text": "I’ve got the scripting language integrating with the engine via a ScriptComponent on the player entity, seems to be working all good though I still have to implement the actual Engine library for everything… but I have simple scripts running on entities as components in the game engine, which went faster than I expected, so i’m happy with it :)"}, {"post_id": 11605, "ts": "2026-06-18T21:53:02Z", "hours": 15.6978, "text": "Drafting a readme for the scripting language before I plan on the Engine bindings"}, {"post_id": 9500, "ts": "2026-06-15T21:05:05Z", "hours": 6.1578, "text": "added switch statements, foreach-loop, objects, modules (imports), and a standard library to the scripting language"}, {"post_id": 8966, "ts": "2026-06-14T22:36:48Z", "hours": 2.3381, "text": "I’m working down my todo-list for the scripting language (ObSL). Right now i’ve got arrays implemented! i also made a method to define functions from the c++ source so that I can access c++ stuff (like std::chrono functions that im using for testing right now from the test.obsl script), and whatever other functions i want to have accessible, this will be very useful later on as I to integrate the scripting language with the game engine, as now i have an easy way to call functions already defined in the engine source code from the scripting language by just calling interpreter.bind_native(args blah blah); and then I can call the function from the interpreted scripts.. very useful :D"}, {"post_id": 8716, "ts": "2026-06-14T14:08:32Z", "hours": 2.1228, "text": "the scripting language now has some more mathematical operators and functions !"}, {"post_id": 8434, "ts": "2026-06-14T01:00:46Z", "hours": 2.25, "text": "The scripting language is now technically Turing complete, as i have added state environment (basically variables persist throughout the session), conditional branching via if / else statements basic repetition via while & for loops the screenshot below shows a fibonacci sequence & an example of the conditional branching w. looping . of course it’s not done yet though, i still have a lot of work ahead :)"}, {"post_id": 8361, "ts": "2026-06-13T21:59:28Z", "hours": 2.07, "text": "still working on parsing and implementing new nodes :)"}, {"post_id": 8255, "ts": "2026-06-13T18:48:40Z", "hours": 2.3453, "text": "Working on trying to implement a scripting language for my game engine… i’ve got a simple parser working, it definitely went faster than i expected. Going back and reviewing an old parser i made in C# a while ago helped a lot in this :)"}, {"post_id": 8113, "ts": "2026-06-13T15:24:08Z", "hours": 3.8419, "text": "I’d like Entities to be scriptable in a future editor application / in general without having to edit c++ source files of the editor to implement new logic systems for one entity, so i’m planning on implementing a very basic scripting language, the way i plan on it working is that you attach a script to an entinty as a component, and it will hold the actual game logic in that script, im not great at explaining with words but what im doing now is starting on implementing lexical analysis for a simple interpreter just to test things out, while I have written small interpreters before, alot of this is still new to me so I am learning along the way. the idea is that its just a very basic scripting language to interact with entities and the current scene, with basic apis for interacting with the current scenes ECS registry,we will see how it goes :)"}, {"post_id": 7654, "ts": "2026-06-12T19:56:36Z", "hours": 2.1944, "text": "I’m working on a simple map lighting system, which seems to be working alright. Also scene files now have background color information (which ends up getting wired into glClearColor), also implemented name field for entities because why not. I’m also messing around a bit with the UI since im not super experienced with ImGui but I like trying things out…"}, {"post_id": 7507, "ts": "2026-06-12T15:05:30Z", "hours": 2.1106, "text": "I’ve been focusing mostly on my scene serialization lately. First, I refactored the maps to remove the hardcoded TileTypes enum, which used to map 0 to grass and 1 to sand. Instead, I implemented a system where this is defined in the grid section of the scene’s json file. The “id” property is now a generic unsigned integer for the tile type, and the “texture” property references a specific asset loaded in the scene. I also added a “properties” section for the scene’s name and a “clear_color” array. This lets you dynamically change the window’s background color on the fly instead of always defaulting to a hardcoded black. Writing the new methods and sorting out the custom serialization logic took a bit of work, but it is working great now. also bumped the map file “version” to 2, even though the reading/writing of map files didn’t change at all, the usage of some bytes did kind of change (for the tiletype) so i felt it was fitting"}, {"post_id": 7189, "ts": "2026-06-12T00:17:40Z", "hours": 1.3681, "text": "i’ve been playing with loading in entities and meshes.. ignore the weird fps drops and generally low fps (compared to normally), screenshots and recordings loves messing with performance for some reason"}, {"post_id": 7135, "ts": "2026-06-11T22:23:21Z", "hours": 5.1658, "text": "i’ve implemented instanced draw calls alongside regular draw calls in my renderer, which currently im using instancing for drawing the map, I also implemented culling for the map depending on viewport and some other small optimizations, I also spent some time on fixing and improving my “Systems” and some general cleanup"}, {"post_id": 6799, "ts": "2026-06-11T12:20:56Z", "hours": 1.5519, "text": "Managed to fix the segfault.. Mesh::Upload was updating buffer data without binding its own VAO first, which polluted the global OpenGL state. When a new scene loaded, the driver tweaked out on the broken index bindings and crashed on the next draw call …"}, {"post_id": 6484, "ts": "2026-06-10T22:04:02Z", "hours": 1.4136, "text": "I’ve got saving scenes working fully now! ^-^, but an issue ive run into is a segmentation fault on switching scenes, I theorize that it’s due to me not cleaning up / reassigning things when I load in new meshes etc from the scene, thus leaving old pointers in the render queue which don’t exist anymore. This i will work on fixing next.. But for now I am quite happy that i have scenes loading and saving to json :)"}, {"post_id": 6400, "ts": "2026-06-10T19:22:44Z", "hours": 4.4556, "text": "I’ve got loading in scenes working pretty well, but I still have work todo before I can save them properly, im pretty tired already since i spent all day chasing a bug regarding render sorting and ended up refactoring a ton of stuff that i probably didnt have too as i was searching for the issue, but atleast the codebase is somewhat cleaner"}, {"post_id": 6187, "ts": "2026-06-10T12:05:48Z", "hours": 0.365, "text": "running some tests.. messing around with funny map generation shapes too but i dont know how i feel about them"}, {"post_id": 5958, "ts": "2026-06-09T23:43:23Z", "hours": 5.3872, "text": "rather than using another custom file format i decided to just use json to serialize scenes which is coming along rather nicely …"}, {"post_id": 5695, "ts": "2026-06-09T16:10:54Z", "hours": 2.3658, "text": "I’ve been restructuring the and moving things to run actual game logic via “Systems”. I’ve temporarily been testing this in a messy way directly in the scene class, but I’m planning on implementing maybe some sort of basic scripting language that can be used for game logic in entities as a Component w. accompanying systems ofc, so game logic can be defined outside of engine source files and serialized into a scene’s registry from a given file rather than the things im messing around with now. serialization of scenes is what im planning to implement next once im happy with how scenes are working, but i need to plan ahead alot. So for now I’m still going to focus on making sure my Scene implementation is good enough before I focus on implementing serialization and scripting etc, and I have alot to think about regarding the design and architecture of this thing that seems to have evolved into a Game Engine :)"}, {"post_id": 5539, "ts": "2026-06-09T10:55:05Z", "hours": 2.0847, "text": "working on getting Scenes implemented"}, {"post_id": 5225, "ts": "2026-06-08T22:43:53Z", "hours": 2.7831, "text": "I completely refactored my ECS into an actual proper entity component system and added a lil fancy inspector for entities/components in the UI, everything works with the new system :) Now that my ECS is properly implemented I’m going to start focusing on implementing proper Levels/Scenes rather than the mess I have right now in my “Game” class which I’ve been using for testing stuff (ignore the weird framedrops my screen recorder was tweaking out)"}, {"post_id": 4858, "ts": "2026-06-08T12:03:11Z", "hours": 0.5367, "text": "i made a npc (the red super mutant) that just wanders around"}, {"post_id": 4844, "ts": "2026-06-08T11:26:15Z", "hours": 0.9856, "text": "I’ve been having a bit of fun with player sprites (currently som fallout 1 super-mutant sprites i found online) and the renderer sorting sorting code to avoid the player appearing under the ground"}, {"post_id": 4599, "ts": "2026-06-07T23:21:51Z", "hours": 0.7331, "text": "I implemented reading from the previously saved map file, with some tests ofc :D please ignore the player flying away at the end.. as of the time of writing it was a sloppy bug which is already fixed"}, {"post_id": 4582, "ts": "2026-06-07T22:30:26Z", "hours": 1.5031, "text": "I’ve implemented saving the current grid to my own custom file format, and some tests to check that it’s working and all seems good.. but now, the real test is to see if I can load back in that file properly :)"}, {"post_id": 4281, "ts": "2026-06-07T15:19:30Z", "hours": 3.5969, "text": "I did a few things i made it highlight what hex the player is currently moving towards in white fixed a bug causing it to crash when i tried to use my dgpu (issue with my GLdebug class trying to load unavailable glDebugMessageCallback since my dgpu driver uses an older OpenGL version than my igpu and i kinda forgot to check if it the callback function was available BEFORE calling it.. .-.) refactored some of my Hex code to prepare for making some sort of system to load maps from files, so i generally cleaned up some stuff and opted for smaller datatypes for my needs (i.e using int16_t rather than ints for hex coords r & q, since that’s really all you need unless your map is massive) i also added some more fancy ui with imgui to play around with and generally just cleaned up some code… in short im basically preparing myself to implement some sort of map file loader w. accompanying filetype?"}, {"post_id": 3847, "ts": "2026-06-06T22:12:28Z", "hours": 1.7772, "text": "I managed to setup a basic ImGui window to control map generation, I also tried to optimize my rendering by fixing a sloppy bug i had in my batching implementation and caching transformation matrices per transform (dirty flag pattern) fps does seem stable :) (please ignore the video artifacting)"}, {"post_id": 3544, "ts": "2026-06-06T15:07:32Z", "hours": 11.2967, "text": "I redid almost everything with what i’ve learnt from trying the first time (ECS, ResourceManager & MeshFactory are basically the same though) I managed to implement A* pathfinding for the player movement. I got to render out the map with textures i made. tried to recreate movement like Fallout has, where you move the mouse to pan and click to move to a tile with stepping. The hex grid is reperesented via an odd-r offset layout."}, {"post_id": 2707, "ts": "2026-06-05T12:48:03Z", "hours": 1.4394, "text": "Experimenting with camera stuff and input, now i can zoom with the scrollwheel and i’m trying to get an isometric perspective working better"}, {"post_id": 2669, "ts": "2026-06-05T10:44:01Z", "hours": 1.9911, "text": "im getting a simple resource manager implemented :)"}, {"post_id": 2395, "ts": "2026-06-04T21:04:46Z", "hours": 3.0553, "text": "It may not look like much, but I’ve been working on implementing a form of an ECS , rewriting some stuff too. I kind of broke some camera stuff in the process which I’m going to fix soon, and actually get this stuff to be the correct perspective and such…."}, {"post_id": 2168, "ts": "2026-06-04T14:49:59Z", "hours": 3.0614, "text": "i’ve been experimenting with some stuff back and forth, now im working on testing basic “Player” movement with WASD"}, {"post_id": 1448, "ts": "2026-06-03T14:24:00Z", "hours": 2.3058, "text": "I’ve implemented proper debug logging for OpenGL, optimized rendering with a queue that sorts RenderCommands to avoid unnecessarily binding & unbinding, a basic InputManager class, and very basic materials."}, {"post_id": 1055, "ts": "2026-06-02T21:13:14Z", "hours": 1.5414, "text": "i’ve got a basic hex grid “map” rendering and working well"}, {"post_id": 890, "ts": "2026-06-02T16:46:10Z", "hours": 0.7936, "text": "Implemented a basic camera which im messing around with a bit to rotate (around) my mesh"}, {"post_id": 858, "ts": "2026-06-02T15:50:32Z", "hours": 1.3153, "text": "I now have textures working, and a basic “meshfactory”"}, {"post_id": 801, "ts": "2026-06-02T13:58:30Z", "hours": 2.4436, "text": "I’ve gotten transforms and basic rendering implemented of objects implemented via a “Mesh” class that gets passed to Draw() in the Renderer Class :)"}, {"post_id": 403, "ts": "2026-06-01T19:57:36Z", "hours": 0.2883, "text": "Setup basic GLFW Window boilerplate & CMake Project :)"}]...
|
Title: obliberry by @torkel | Stardance
Devlogs:
Title: obliberry by @torkel | Stardance
Devlogs:
Setup basic GLFW Window boilerplate & CMake Project :)
I’ve gotten transforms and basic rendering implemented of objects implemented via a “Mesh” class that gets passed to Draw() in the Renderer Class :)
I now have textures working, and a basic “meshfactory”
Implemented a basic camera which im messing around with a bit to rotate (around) my mesh
i’ve got a basic hex grid “map” rendering and working well
I’ve implemented proper debug logging for OpenGL, optimized rendering with a queue that sorts RenderCommands to avoid unnecessarily binding & unbinding, a basic InputManager class, and very basic materials.
i’ve been experimenting with some stuff back and forth, now im working on testing basic “Player” movement with WASD
It may not look like much, but I’ve been working on implementing a form of an ECS , rewriting some stuff too. I kind of broke some camera stuff in the process which I’m going to fix soon, and actually get this stuff to be the correct perspective and such….
im getting a simple resource manager implemented :)
Experimenting with camera stuff and input, now i can zoom with the scrollwheel and i’m trying to get an isometric perspective working better
I redid almost everything with what i’ve learnt from trying the first time (ECS, ResourceManager & MeshFactory are basically the same though) I managed to implement A* pathfinding for the player movement. I got to render out the map with textures i made. tried to recreate movement like Fallout has, where you move the mouse to pan and click to move to a tile with stepping. The hex grid is reperesented via an odd-r offset layout.
I managed to setup a basic ImGui window to control map generation, I also tried to optimize my rendering by fixing a sloppy bug i had in my batching implementation and caching transformation matrices per transform (dirty flag pattern) fps does seem stable :) (please ignore the video artifacting)
I did a few things i made it highlight what hex the player is currently moving towards in white fixed a bug causing it to crash when i tried to use my dgpu (issue with my GLdebug class trying to load unavailable glDebugMessageCallback since my dgpu driver uses an older OpenGL version than my igpu and i kinda forgot to check if it the callback function was available BEFORE calling it.. .-.) refactored some of my Hex code to prepare for making some sort of system to load maps from files, so i generally cleaned up some stuff and opted for smaller datatypes for my needs (i.e using int16_t rather than ints for hex coords r & q, since that’s really all you need unless your map is massive) i also added some more fancy ui with imgui to play around with and generally just cleaned up some code… in short im basically preparing myself to implement some sort of map file loader w. accompanying filetype?
I’ve implemented saving the current grid to my own custom file format, and some tests to check that it’s working and all seems good.. but now, the real test is to see if I can load back in that file properly :)
I implemented reading from the previously saved map file, with some tests ofc :D please ignore the player flying away at the end.. as of the time of writing it was a sloppy bug which is already fixed
I’ve been having a bit of fun with player sprites (currently som fallout 1 super-mutant sprites i found online) and the renderer sorting sorting code to avoid the player appearing under the ground
i made a npc (the red super mutant) that just wanders around
I completely refactored my ECS into an actual proper entity component system and added a lil fancy inspector for entities/components in the UI, everything works with the new system :) Now that my ECS is properly implemented I’m going to start focusing on implementing proper Levels/Scenes rather than the mess I have right now in my “Game” class which I’ve been using for testing stuff (ignore the weird framedrops my screen recorder was tweaking out)
working on getting Scenes implemented
I’ve been restructuring the and moving things to run actual game logic via “Systems”. I’ve temporarily been testing this in a messy way directly in the scene class, but I’m planning on implementing maybe some sort of basic scripting language that can be used for game logic in entities as a Component w. accompanying systems ofc, so game logic can be defined outside of engine source files and serialized into a scene’s registry from a given file rather than the things im messing around with now. serialization of scenes is what im planning to implement next once im happy with how scenes are working, but i need to plan ahead alot. So for now I’m still going to focus on making sure my Scene implementation is good enough before I focus on implementing serialization and scripting etc, and I have alot to think about regarding the design and architecture of this thing that seems to have evolved into a Game Engine :)
rather than using another custom file format i decided to just use json to serialize scenes which is coming along rather nicely …
running some tests.. messing around with funny map generation shapes too but i dont know how i feel about them
I’ve got loading in scenes working pretty well, but I still have work todo before I can save them properly, im pretty tired already since i spent all day chasing a bug regarding render sorting and ended up refactoring a ton of stuff that i probably didnt have too as i was searching for the issue, but atleast the codebase is somewhat cleaner
I’ve got saving scenes working fully now! ^-^, but an issue ive run into is a segmentation fault on switching scenes, I theorize that it’s due to me not cleaning up / reassigning things when I load in new meshes etc from the scene, thus leaving old pointers in the render queue which don’t exist anymore. This i will work on fixing next.. But for now I am quite happy that i have scenes loading and saving to json :)
Managed to fix the segfault.. Mesh::Upload was updating buffer data without binding its own VAO first, which polluted the global OpenGL state. When a new scene loaded, the driver tweaked out on the broken index bindings and crashed on the next draw call …
i’ve implemented instanced draw calls alongside regular draw calls in my renderer, which currently im using instancing for drawing the map, I also implemented culling for the map depending on viewport and some other small optimizations, I also spent some time on fixing and improving my “Systems” and some general cleanup
i’ve been playing with loading in entities and meshes.. ignore the weird fps drops and generally low fps (compared to normally), screenshots and recordings loves messing with performance for some reason
I’ve been focusing mostly on my scene serialization lately. First, I refactored the maps to remove the hardcoded TileTypes enum, which used to map 0 to grass and 1 to sand. Instead, I implemented a system where this is defined in the grid section of the scene’s json file. The “id” property is now a generic unsigned integer for the tile type, and the “texture” property references a specific asset loaded in the scene. I also added a “properties” section for the scene’s name and a “clear_color” array. This lets you dynamically change the window’s background color on the fly instead of always defaulting to a hardcoded black. Writing the new methods and sorting out the custom serialization logic took a bit of work, but it is working great now. also bumped the map file “version” to 2, even though the reading/writing of map files didn’t change at all, the usage of some bytes did kind of change (for the tiletype) so i felt it was fitting
I’m working on a simple map lighting system, which seems to be working alright. Also scene files now have background color information (which ends up getting wired into glClearColor), also implemented name field for entities because why not. I’m also messing around a bit with the UI since im not super experienced with ImGui but I like trying things out…
I’d like Entities to be scriptable in a future editor application / in general without having to edit c++ source files of the editor to implement new logic systems for one entity, so i’m planning on implementing a very basic scripting language, the way i plan on it working is that you attach a script to an entinty as a component, and it will hold the actual game logic in that script, im not great at explaining with words but what im doing now is starting on implementing lexical analysis for a simple interpreter just to test things out, while I have written small interpreters before, alot of this is still new to me so I am learning along the way. the idea is that its just a very basic scripting language to interact with entities and the current scene, with basic apis for interacting with the current scenes ECS registry,we will see how it goes :)
Working on trying to implement a scripting language for my game engine… i’ve got a simple parser working, it definitely went faster than i expected. Going back and reviewing an old parser i made in C# a while ago helped a lot in this :)
still working on parsing and implementing new nodes :)
The scripting language is now technically Turing complete, as i have added state environment (basically variables persist throughout the session), conditional branching via if / else statements basic repetition via while & for loops the screenshot below shows a fibonacci sequence & an example of the conditional branching w. looping . of course it’s not done yet though, i still have a lot of work ahead :)
the scripting language now has some more mathematical operators and functions !
I’m working down my todo-list for the scripting language (ObSL). Right now i’ve got arrays implemented! i also made a method to define functions from the c++ source so that I can access c++ stuff (like std::chrono functions that im using for testing right now from the test.obsl script), and whatever other functions i want to have accessible, this will be very useful later on as I to integrate the scripting language with the game engine, as now i have an easy way to call functions already defined in the engine source code from the scripting language by just calling interpreter.bind_native(args blah blah); and then I can call the function from the interpreted scripts.. very useful :D
added switch statements, foreach-loop, objects, modules (imports), and a standard library to the scripting language
Drafting a readme for the scripting language before I plan on the Engine bindings
I’ve got the scripting language integrating with the engine via a ScriptComponent on the player entity, seems to be working all good though I still have to implement the actual Engine library for everything… but I have simple scripts running on entities as components in the game engine, which went faster than I expected, so i’m happy with it :)
I’ve got a good basis for the Engine integration library for the ObSL Scripting Language. In the attached video, I’m changing the player’s size using a ping-pong function (?forgot the name…), fully through an ObSL script ( ScriptComponent ) attached to the “Player” entity. The language now has support for the following through the EngineLib : Entity Objects Find GetName SetName GetComponent Components Transform SetPosition SetRotation SetScale GetPosition GetRotation GetScale (uses ObSL arrays) Point Light SetColor (Vec3) SetIntensity SetRadius MovementComponent GetIsMoving SetIsMoving SetTimePerStep MapStateComponent GetHasSelection GetSelectedHex GetPathToHex DirectionalTextureComponent SetIndex GetIndex PlayerInputComponent is still w.i.p. Tag Components currently don’t have any methods since they are only used as tags. Planned I’m planning to keep expanding the EngineLib api with more methods, such as: Has(component) AddComponent RemoveComponent(name or ref) Destroy(EntityID) GetEntityID(entity object ref)
EngineLib Script Integration I fully replaced the previously hardcoded PlayerMovementSystem with an ObSL script implementation using new EngineLib bindings. The movement logic is now handled externally through scripting instead of being directly implemented in C++. New EngineLib Bindings entity management Added bindings for basic entity operations: CreateEntity Creates a new entity Destroy Removes an entity HasComponent Checks whether an entity has a specific component RemoveComponent Removes a component from an entity global functions get_dt Retrieves delta time CloseWindow Closes the glfw window Input System Added script access to input handling: Input_IsKeyDown Checks if a key is currently held Input_IsKeyPressed Checks for a key press event Input_IsMousePressed Checks if a mouse button is pressed Input_GetMouseWorldPos Gets the mouse position converted to world space Movement / Hex Grid Functions Added bindings for interacting with movement components: GetSelectedHex Gets the currently hovered hex tile SetPathToHex Sets a movement target path for an entity with a MovementComponent Camera Added camera manipulation support: Camera_GetPosition Gets the camera position Camera_SetPosition Sets the camera position Camera_Move Moves the camera Camera_PanScreenSpace Moves the camera relative to screen space Camera_GetZoom Gets the current camera zoom Hex Rendering Added bindings for controlling grid visuals: ClearSelectionOverlay Clears the hex selection overlay ClearPathTarget Clears the path target visual marker ClearPathTarget is currently named poorly. It only clears the grid overlay visualization, not the actual movement target!!! summary Removed the old hardcoded PlayerMovementSystem Migrated player movement logic into script format Added engine bindings required for script-driven gameplay Camera movement, input handling, and hex selection now work through scripts Even more gameplay code can now be modified without recompiling the engine :)
I’m using miniaudio to implement audio support in the game engine, with an AudioEngine class to abstract the audio functionality. I’ve also updated SceneProperties to include a new background_music property. This allows each scene to define a background music track (via filepath) that will automatically loop through the AudioEngine while that scene is active. It all seems to be currently working well, Next I’m starting to integrate audio functionality into EngineLib so that scripts can interact with the audio system. changes Added AudioEngine abstraction layer using miniaudio Added background_music support to SceneProperties (w. proper serialization/deserialization ofc) Implemented looping background music per scene
EngineLib I may have forgotten to mention this in my previous log, but I also implemented an Instantiate method in EngineLib. Instantiate takes an entity definition as a JSON file (ig a prefab) and spawns the entity into the current scene. I also added scene related functionality to EngineLib: LoadScene Loads a scene from a given path GetCurrentScenePath Returns the path of the currently loaded scene
more EngineLib work Implemented several improvements to the scripting and entity systems. changes prefab caching Added caching for prefabs to improve performance when repeatedly instantiating entities Entity Access in Scripts Added GetEntity , which returns the entity Object that the script is attached to. Added support for the this keyword in ObSL scripts. this is a wrapper around GetEntity() to provide direct access to the current entity custom components Added support for script-defined components: entity.AddCustomComponent entity.GetCustomComponent This allows scripts to attach and retrieve custom data/components without requiring engine side component definitions entity validation Updated all entity object calls (such as GetComponent ) to validate the entity before executing (in both native bindings & engine source code) Entity operations now check: registry.isValid(id) before accessing the entity. This prevents errors caused by accessing deleted entities during scenarios such as scene unloading/loading cleanup
Porting ECS systems to ObSL Fully ported the InteractionSystem to ObSL through EngineLib. Camera movement and player movement are now handled through dedicated ObSL scripts instead of being hardcoded ECS systems. This moves more gameplay logic into the scripting layer and makes systems easier to modify and iterate on :) Changes System Migration Ported InteractionSystem from ECS code to ObSL Basically Moved camera movement & player movement logic into ObSL scripts Interaction system is no longer hardcoded engine-side gameplay system New EngineLib Bindings Math / Hex Grid Math_WorldToHex Converts world coordinates into hex grid coordinates SetSelectedHex Updates the currently selected hex tile Camera Camera_SetZoom Sets the camera zoom level Window Window_GetHeight Gets the current window height Window_GetWidth Gets the current window width Input Input_IsKeyReleased Checks if a key was released Input_IsMouseDown Checks if a mouse button is currently held Input_IsMouseReleased Checks if a mouse button was released Input_GetMouseX Gets the mouse X position Input_GetMouseY Gets the mouse Y position Input_GetScrollX Gets horizontal scroll input Input_GetScrollY Gets vertical scroll input Please ignore the weird graphical artifacting in the attached video, my pc has been acting up recently :(
“project” file system prototype Started implementing support for engine project files instead of hardcoding a scene path like i was before for testing. The engine will now deserialize a project.json file containing configuration, includes: name Project name (unused for now) version Project version (also unused) start_scene Path to the scene the engine loads on startup Window configuration: width height title fullscreen while implementing this, I uncovered some unexpected behaviour related to fullscreen handling caused by how window sizing was previously managed. i spent time refactoring and fixing the window size logic to make fullscreen behaviour… work.. project loading is now starting to come together, less hardcoded stuff yippie (im planning on making an editor in the future so.. this is why)
Been mostly just fixing some window rendering stuff Moved away from hardcoded resolution / aspect ratio and made it handle itself on the fly also removed the padding bars i had before so rendering actually takes up full screen New native engine binding in EngineLib too: Window_SetFullscreen (takes a bool) I’m planning on starting to work on making the engine multithreaded soon…
im trying to make the renderer run on another thread… few issues… cant see (entity) meshes?, and closing the window seems to cause a freeze…. :))
kinda reverted changes from the last log and tried again to convert everything to be thread safe before actually trying to run on a seperate thread… things are going.. interestingly
I think i fixed most of the silly bugs from trying to make rendering thread safe, im still gonna double check some stuff and do some testing but moving rendering to its own render thread will be coming soon :))))
multithreading & rendering I think I got some form of multithreading working now. The renderer has been moved onto its own dedicated thread, separating rendering from the main engine thread :) Changes Rendering Thread Moved rendering execution to a separate thread (alot had to be refactored for this to work lol) Thread Safety i tried (imgui was a pain) Rendering Optimizations Added frustum culling to the renderer. big optimizeD? actual rendering (i.e gpu calls) is now seperated from the main thread :D …it looks like its working for now
refactoring for editor foundation Refactored rendering and culling systems and made broader architectural changes to decouple the game from the application layer. Rendering & Culling Refactored frustum culling logic to be lil more performant and generally cleaner Cleaned up and improved parts of the rendering pipeline since i had alot of old unused code lurking in them since i switched to a multithreaded architechture Application Architecture the engine is now structured around an ApplicationLayer system. The core Application class now runs a single active ApplicationLayer Each layer exposes: Init Update Render Shutdown Game class refactor The Game implementation has been converted into a derived ApplicationLayer Game logic is now fully driven through the layer system instead of hardcoded to the application class (the different executable mains decide now) Editor Layer added a new EditorLayer Intended for a future scene editor application. (right now all it does is render a given scene on the screen) CMake changes reworked the project to generate multiple executables: obliberry_engine core engine executable (ig runtime) obliberry_editor editor application layer changes: Engine and core systems (i.e ObSL, Renderer, etc) are now compiled as libraries Executables link against shared engine libraries instead of duplicating code Editor executable links against engine modules summary Game logic is now layer-based Engine and tools are separated Editor can proceed independently from the game runtime
Editor UI & Framebuffer Experiments i’ve started experimenting with the ImGui docking branch in the EditorLayer . (switched branch had some build errors blah blah blah but its all set up now) Implemented some placeholder editor UI to test out the docking stuff and get a feel for how the editor layout might end up being like changes editor layer placeholder UI using ImGui docking features testing editor panel layouts framebuffer implemented a framebuffer system for the editor viewport. the scene is currently rendering in the editorlayer via a frame buffer so it can fit in the little thingy (i forgot the name) while testing I noticed some resizing issues when running on my nvidia dGPU: the framebuffer resize works, but resizing the viewport can appear somewhat choppy? the framebuffer and docking setup seem to be working, so i guess this im close to actually start to build proper tooling :)
VFS & Editor layer implemented a basic VFS (Virtual File System) . all asset loading is now routed through the VFS instead of directly loading files. this is mainly preparation for adding proper project management later instead of relying on a hardcoded project.json in the project root i was testing with changes VFS added a basic VFS implementation routed asset loading through the VFS the idea is that the VFS will make it easier to manage project assets and not have everything depend on hardcoded paths. editor layer still experimenting a bit with the editor placeholder UI. added: (new EditorCamera derived class of Camera ) camera panning in the editor viewport camera zoom toggling top-down / isometric perspective with keybinds the top-down view should be useful later when I add actual map editing stuff most of the editor UI is still just placeholder right now, I’m mostly testing layouts and figuring out how I want the editor to feel and look ImGuizmo also added ImGuizmo to the project since I’m planning to start implementing proper editor stuff soon.. …and well… you need gizmos… I’ve reinvented the wheel enough already, so using a proper gizmo library seems like the better choice :) (also integrates very nicely with ImGui)
Editor Picking & Project Management because my EditorLayer uses a framebuffer, I can now utilize framebuffer color picking in the editor i updated the shaders to store an entity ID, so now I can click on entities directly in the editor scene view and it selects them. …and it’s pixel perfect :D changes editor layer added framebuffer based entity picking clicking entities in the scene view selects them!!!! selection is based on the exact pixel under the mouse (i mean to implement gizmos i first need to know what the hell my mouse is on) project management also started laying the groundwork for actual project management. now that I have some sort of VFS implemented, I’m working on a way to properly manage Projects instead of relying on the current setup. still figuring out the exact structure, but ive been working on setting up the Project class
Namespace Refactor & Project Management Work Dependencies finally caused me to run into a namespace conflict after being lazy and unorganized… instead of being sane and just renaming one class.. I decided to refactor the entire project to use proper namespaces everywhere.. changes namespaces Refactored the entire codebase into proper namespaces project management / editor backend I don’t really have much visually to show this update since I’ve mostly been working on backend stuff. Working on: project management scene management VFS improvements editor saving/loading I’m using nativefiledialog-extended to work on proper file dialogs for saving and loading from the editor. Also been doing a lot of testing around project creation and loading. alot of this is in the hope i can get this working multi-platform and not just on linux (though i have yet to try and compile on another os) Things are working… for now… so progress :D
Editor & Scene Management been working on the editor mostly. changes ECS implemented generational ID masks for the ECS. this should prevents issues with stale entity references since IDs can now properly track generations instead of just relying on raw IDs. (i encountered this issue when testing multiple scenes in one project) scene manager fully implemented the SceneManager so it can actually be used by the editor & game layer. this allows the editor to properly load/save/validate/find and generally handle scenes through a unified API (goes for gamelayer aswell but it only really loads them) bug fixing spent a lot of time fixing various issues around: project folder management scene management loading / saving behaviour asset loading (cache was causing some problems on loading scenes but its all fixed now :D) mostly backend work but things are becoming a lot more stable and the editor foundation is starting to come together….
ive been mostly messing around with getting the ObSL language to be thread-safe and refactoring some things, so I don’t have much to show but my end goal is to be able to get scripts to run concurrently and outside of the main thread
Script multithreading (and concurrency) scripts now run on other thread(s) :D this took a fair bit of cleanup, but it’s working. changes script workers moved script execution onto worker thread(s) worked on script worker concurrency dynamically clamp the number of active workers based on how many callbacks are actually running, so idle threads aren’t just spinning doing nothing garbage collection did some work on the GC as well. introduced external root tracking fixed a few issues around GC roots while getting multithreaded script execution working cleanup spent some time cleaning up a bunch of backend stuff while getting all of this working. build system updated CMake so all executables, scripts, and (project) templates are output to a single build/bin directory instead of being messy. multithreading yay :)
ObSL Scripting Library Moved the scripting language into its own repository :) It’s now included in the engine as a library using git submodules and public headers instead of living directly in the engine source code Makes the project structure a lot cleaner .. for both projects ( ObSL can now be found at https://github.com/torkelicious/ObSL )
actually working on the editor I’m finally getting around to actually implementing the editor ..it still looks pretty similar (well mostly the same) but most of the UI before was just placeholder. changes editor implemented a Project Settings window implemented a Scene Properties window made the component widgets actually do something now load textures assign scripts change material colors change meshes change shaders etc…. added an Add Component button added Remove buttons to components it works.. so thats good :D
editor Gizmos! :DD this took a lot longer than I’d like to admit… but it’s finally working. changes gizmos got all gizmos working.. but had issues with rotation and scale at first figured out the issues with rotation/scaling ended up patching ImGuizmo at first to get things working, but after digging through the code I eventually figured out how to do it properly with the normal library translation, rotation, and scale gizmos all work now :)))))) honestly I learnt quite a bit just from messing around with the ImGuizmo internals.. but it was painful editor added a few more UI improvements as well. i.e billboard sprites now explicitly mention that rotation doesn’t do anything, instead of letting you wonder why nothing happens gizmos are one of those things I’ve been waiting on implementing.. but im finally happy to have them
Project Packaging been working on a packaging format for projects. the goal is basically to package an entire project into a single container while preprocessing assets that make sense to preprocess. Also makes shipping a game made in the engine in the future alot easier / cleaner, and portable. changes packaging implemented the start of a proper project packaging system. currently it: parses ObSL scripts ahead of time and stores serialized ASTs instead of source code (basically very similar to some sort of a very very simple AOT compiler) converts project, scene and prefab JSON files into MessagePack stores media and other binary assets directly in the package optionally compresses package entries with LZ4 the idea is that the engine has less work to do at runtime since scripts don’t need parsing and JSON doesn’t need parsing either. and a single “package” file is alot cleaner in general for a finished game “build” package format also implemented the actual container format itself. different asset types are stored as different entry types (scripts, binary JSON, media, shaders, etc.), so the loader knows exactly how each asset should be handled. tools added standalone packaging tools as well for packing and unpacking projects, mostly for testing. still a work in progress, but the whole packaging pipeline is starting to come together.
Project Packaging is Working been spending a lot of time working on project packaging, and it’s finally working now. the engine can now load projects directly from .obpak files, and I’ve got basic tooling to create them as well. the plan is to integrate the tooling i have now with the editor to “build” an obpak archive (i think its called an archive?) changes packaging implemented the full packaging/loading pipeline yippie :D currently the packer: pre-generates ASTs for ObSL scripts converts project, scene(s) and prefab(s) JSON into MessagePack bundles everything into a single .obpak container compresses the package with LZ4 assets like textures, audio and shaders just get copied into the package without any conversion runtime the engine can now load packaged projects directly instead of relying on loose project files. all of this goes through the VFS, so from the engine’s point of view it doesn’t really matter whether assets are coming from a folder or from an .obpak (i.e it can still load loose project files of course) tooling added command-line tools for packing and unpacking projects, i originally made it for testing but it’s actually pretty nice to work with so im probably keeping it. still probably things to polish, but it’s pretty satisfying seeing the engine load an entire packaged project properly pls ignore the lag in the video, i promise its not as terrible as it looks, its just that recording is pretty buggy for me
Project Exporting been working on making projects exportable from the editor it’s now able to export a project to the selected folder, package all the assets into an .obpak , and then copy over the runtime so the exported project is runnable changes project exporting added export to the editor choose an output folder for the exported project packages the project into an .obpak copies the runtime into the export folder renames the runtime to match the project name (just 2 files for full project!, executable and .obpak) the whole process is pretty much one click now instead of manually packaging everything together. file dialogs refactored my entire filedialog implementation cuz it was kinda broken packaging did some more work on the packaging pipeline while implementing exporting and put it in the editor ui im pretty happy that its all working and i can actually export stuff, and run it feels cool :)
editor rework & map editing groundwork been working on the editor again this update was mostly about cleaning up the editor architecture so I can actually keep adding features without everything turning into spaghetti. I also finally started laying the groundwork for proper map editing. changes editor reworked the editor state system. instead of instantly swapping between states, transitions are now deferred until a safe point during the update loop. this makes switching between Edit, Play, Map Edit, and the Hub a lot cleaner, and the editor now remembers which editing mode you were in before hitting Play. (i’ll admit… i was getting a bunch of weird, seemingly unexplainable crashes before eventually realizing my mistake was instantly switching states while things were still being updated/rendered…) also moved more UI responsibility into the individual states instead of having EditorLayer decide how everything should be drawn. map editor started putting together the map editor. currently i have: map hover and tile selection working placeholder Paint / Erase / Select tools the beginnings of a tile palette system a placeholder tile editor panel the actual editing logic isn’t implemented yet, but the foundations are there now :) asset picker ripped out the old “open a native file dialog for every asset field” flow. instead, the editor now lets you pick existing textures, meshes, materials and shaders directly from the ResourceManager , which is a lot nicer to work with and also avoids accidentally importing duplicate assets. (the old workflow would happily create a brand new object every time you imported something… which was fine for testing, but definitely wasn’t something i wanted to keep) rendering fixed a few editor rendering issues while i was at it. materials with invalid shaders now fall back to the default shader instead of silently disappearing fixed some edge cases with framebuffer entity picking currently unused, but functional shader hot reloading tests misc smoothed out editor camera movement and zoom added a few helper utilities for the map editor reorganized the editor UI code a bit doesn’t look massively different in screenshots, but makes future work alot easier/cleaner map painting is next ?..
map editor preveiw ig kinda didnt have much time to do anything today but im working on the tile editor
Map Editing, Brushes, and a 4(?) hour ImGui Bug The map editor is finally coming together It’s still a bit… rough but it does feel nice to be able to paint a map in the editor I did, however, spend an embarrassing amount of time trying to figure out why my click and drag “painting” wasn’t working… well.. ImGui was eating my inputs because it thought I was trying to drag the Scene View window around.. yeah.. changes map editor actually got the map editing tools working for real this time. the paint and erase tools actually place and remove tiles now instead of just being placeholder buttons added a brush radius slider, so you can paint in bigger hex rings added a preview outline that renders around your cursor so you can see before clicking toggling “is walkable” on a tile now properly syncs with the grid pathfinding editor ui spent some time making the tile palette and material editing.. work.. video explains better ngl im not good at describing ui stuff math laid some groundwork in the hex math system ( Lerp , CubeRound , and GetHexLine ) this is mostly for some future evil plans… still a WIP…
Logging Cleanup replaced all the random std::cout / std::cerr calls scattered throughout the project with an actual logging system logging implemented a proper logging system. replaced std::cout / std::cerr throughout the engine added support for different log levels optional logging to a log file centralized all engine logging into one place thread safe !!!! nothing particularly flashy or fancy, but its cleaner, easier to work with, and generally just nice i probably should’ve done this a long time ago :)
editor polish still nothing super flashy.., mostly a bunch of small things changes window titles the editor now updates its window title based on what youre working on. it’ll now include things like the current project and scene, or map project loading cleaned up project loading a bit. the editor now properly syncs the loaded project configuration into the engine context instead of relying on stale data also added menu in the map editor that lets you save and load map files (create new is just placeholder for now) UI added a small helper for rendering framebuffer textures in ImGui without needing to remember to flip the UVs every time. and made the tile Editor use it also forgot to mention in the last log that i cleaned up the “project browser” ui a bit logging fixed up some more logging :)
Undo/Redo! :) been working on some editor QoL stuff again… the biggest addition this time is a proper undo/redo system. it’s still very early and pretty barebones, but having the foundations in place is nice changes editor commands implemented the beginnings of a proper command system for the editor instead of modifying things directly, editor actions now go through commands, which means they can be undone and redone currently supports: entity transforms movement rotation scaling adding components removing components (with the exception of ScriptComponent for now.. that’ll get its own custom command due to the way it works) also keeps a command history, and the usual shortcuts are hooked up now: Ctrl + Z : Undo Ctrl + Y : Redo its still pretty basic, but it works and feels nice to use. input for this, I added proper key-combination support to the input manager. things like: Ctrl + S Ctrl + Z Ctrl + Y can now be handled properly instead of manually checking modifier keys everywhere logging did a bit more cleanup to the logging system as well. the logger now goes through a proper interface instead of everything depending directly on one concrete implementation, which should make it a bit easier to swap things around later if I ever want to. mostly backend work again… but undo/redo is fire
Undo/Redo …again! been working on the editor again the undo/redo system now covers a lot more than just gizmo transforms. but there’s still a few things left (entity creation/deletion mainly). changes undo/redo expanded the command system to cover most editor actions. currently supports: entity transforms adding/removing components adding/removing scripts editing project settings editing scene properties also fixed the undo/redo shortcuts so they only trigger once per key press instead of repeatedly firing while the keys are held… which is probably how they should’ve worked from the start map editor continued working on map editing. painting and erasing now properly integrate with the command system. also, an entire brush stroke is treated as a single undo step instead of undoing one tile at a time. also cleaned up a couple of edge cases while doing this, like preserving existing tile data and avoiding unnecessary commands when nothing actually changed. misc did a bit of cleanup around the editor while wiring everything together. centralized a few bits of duplicated UI logic cleaned up window title updates continued refactoring the command system the undo system is still unfinished, but it covers most of the important stuff and feels nice.. also.. still gotta fix some ui window-size stuff soon too but .. thats for later
Performance & Zero Copy Assets been spending some time under the hood… this one’s almost entirely backend. no new features, mostly went through the render thread, asset pipeline, & a handful of ECS loops to squeeze out more performance. it was incredibly rage inducing at times.. but seeing the profiler diff against baseline.. i am satisfied.. almost at peace.. but was considering becoming a farmer & never touching a computer again.. mostly because i thought i’d messed up more than i did.. but.. im happy now. changes threading & ecs i’ve reinvented the wheel enough already… but had to redo how tasks are dispatched. ThreadPool used to take a std::function , which heap allocates if you capture more than a couple pointers. scripts dispatch through this every frame, so it added up. swapped it for a custom Task type a 56-byte inline buffer, no heap allocs swapped the pending-task counter to a lock free atomic decrement instead of a mutex on every completion… rendering been cleaning up how the main thread interacts with the render thread. the main & render threads used to awkwardly poll eachothers framebuffers. now theres a m_ReadyFrames deque main pushes a frame index, render pops it. much cleaner :) ImGui draw data is now reused in-place instead of allocating & freeing a fresh clone every frame (ive put off fixing that hack for a while so its nice to finally come around to it). instanced draws no longer store a vector<mat4> per draw call, transforms get appended into one giant staging buffer per frame now. added SubmitPersistent for things that already own a long-lived buffer (like the map tile renderer) to skip the copy entirely. swapped a bunch of unordered_map s for flat vectors in the texture/VAO/uniform caches for a handful of items, linear scan beats hashing. batched rendering also caches the last bound texture & color uniform so b2b batches sharing a texture dont rebind needlessly. added a zero-size window safeguard for Wayland so it stops wrecking the renderer when the window briefly reports 0x0 during resize (also turned vsync back on, weird syscall spam otherwise) assets & packaging added VFS::ReadVirtualView to hand out string_view s directly into memory instead of owned strings for packaged builds, ContainerReader now mmap s the .obpak file directly, uncompressed stuff (textures, uncompiled maps) gets handed right to the parser without a copy. also now move only, with a destructor that unmaps memory instead of holding a copied vector of chars scripting the script hot-reloader was doing a stat() syscall on every script file every frame . oops. now polls every 300 frames & caches resolved paths.. thought i already debounced this.. guess not.. the on_update & on_destroy work buckets used to be freshly allocated vectors every frame… now static , so they just clear & reuse capacity editor & ui finally ripped out the old in game debug UI ( GameUI.cpp ), it had fallen out of sync with the ECS anyway (used it for debug visuals while implementing the first version of the ecs.. then forgot about it) the editors inspector does all of this better now, so replaced it with a minimal FPS counter audio & map audio engine now sets an explicit period size (2048 frames) via miniaudio to cut IPC roundtrips to the audio daemon.. (this one was annoying to figure out.. god bless strace & gdb) the map’s visible transforms buffer is now double buffered, rebuilds write to the back buffer while the render thread reads the front, no race conditions. also swapped typeMats from an unordered_map to a flat vector nothing user facing changed this time, but frame pacing feels noticeably smoother (somewhat suprised), & the packaged build starts noticeably faster i know it could probably be a lot better, but im still a bit of a noob at C++, so this is one hell of a learning project
GPU Lighting & Graphics Settings been doing a bit of rendering work again… mostly trying to optimize things. the biggest change is that I completely rewrote the lighting system previously all the point light calculations were happening on the CPU, and after doing some profiling (and spending way too long staring at compiler generated assembly annotations) it became pretty obvious that this was one of the bigger performance bottlenecks (well THE biggest excluding driver overhead) lighting now runs entirely on the GPU through shaders instead changes lighting rewrote the lighting system. lighting is now shader-based and runs on the GPU removed the old CPU-side lighting calculations moved engine shaders (like the base shader and lighting shader) into built-in InternalShaders (hardcoded string literals, it might seem messy but i prefer it like that) the internal shader change mostly exists because they’re pretty fundamental to the renderer. if they were treated like normal project assets and someone accidentally deleted them… well… suddenly nothing renders (unless they had setup their own shaders, which is fully supported!) and lighting completely falls over, also i prefer it to loading them from the filesystem anyways overall I’m pretty happy with how the new lighting system turned out graphics settings also started working on configurable graphics settings instead of baking them into the project, the engine now loads graphics settings from a separate JSON file. this doesn’t get packed into the .obpak , so users can tweak their graphics settings after exporting a game currently supports: resolution fullscreen MSAA (toggle + sample count) target FPS VSync it’s weirdly fun actually being back in OpenGL code again instead of just working with engine abstractions sometimes it’s nice to get back into the weeds.. even if its.. painfull :D
the OpenGL State Machine Strikes Back… I spent the entire day trapped in hell: debugging a corrupted OpenGL state… it may not show up as tracked hours.. since most of it was just staring at various forms of text.. but it was painful. problem so since i turned the lightmap to run on gpu .. well… Whenever I transitioned from the editor ( MapEditState ) into Play mode, the map would turn into like a bunch of weird diamonds, and the corruption would persist indefinitely until I remounted the current project. because it only happened on state transition, i spent hours chasing ghosts in my state management code and scene cleanup routines… (in the end though i did make some changes to the cleanup routines, but between states rather than scenes.. so i guess i was halfway there?) the culprit It was the lighting pass… took me forever to figure it out, but i had the genius and definitely NOT a very late and obvious idea i shouldve had hours ago , to see if the issue happened when i turned off the lighting system. so i put some early returns in my lighting system functions and.. it didnt corrupt.. inside LightingSystem::Update() , the renderer was modifying global OpenGL state changing depth functions, blending modes, and texture bindings, but not restoring them to their original defaults properly When the engine swapped states, the next frame inherited this dirty, half configured state, causing the whole thing to become a mess. the fix I went through the lighting system and made sure the state changes are wrapped and properly restored through the render thread.. LightingSystem.h : Full GL state save/restore around the light pass. now explicitly backing up and restoring the FBO, program, VAO, blend state, draw buffers, clear color, viewport, and active texture. MapEditState.cpp : OnExit() now properly nulls out m_MapComp and m_CurrentGrid . OnEnter() and will refetch them from the current registry so it isnt holding onto outdated references. EditorLayer.cpp : Added a call to renderer->Clean() after state transfers to clear out stale VAO and mesh caches.(bc its multithreaded things go kinda weird but.. it works now) glad thats over with :D Also heres a fun peek of what ObSL can do with EngineLib, yes, it can make your entire map look like hell..! i am totally not going insane
Editor QoL, Graphics Configs & Prefabs new devlog… mostly been focusing on editor ui and qol changes this time around. kinda tired of hardcoded settings for the graphics settings, so i finally built a proper interface for it, plus some prefab management stuff in the editor changes graphics settings i built a dedicated graphics configurator window in the window, for the current project ( GraphicsConfigEditor ). it hooks directly into the UndoManager using the command pattern ( GraphicsConfigUpdateCommand ) serializes everything out to graphics.json . added QuerySupportedSampleCounts which asks the active GL context ( before it gets handed to the render thread ) what MSAA sample counts it supports. the editor now dynamically generates the dropdown and snaps to a valid sample count (i.e 1, 2, 4, 8, 16). prefab management the editor now supports prefab management that i implemented earlier .. instead of directly writing it in the scene json file you can spawn entities directly into the scene from prefab json files you can revert a prefab, which wipes any local overrides and resets the entity back to whatever is saved in the file you can break a prefab, severing the link to the json file and turning it into a normal, standalone entity in the registry ui & editor cleanup spent some time making the editor less annoying.. in general the editor layout stops resetting itself , it now checks if imgui.ini exists on startup, and if it does, it skips rebuilding the default dockspace ripped the hardcoded hub drawing code out of the EditorLayer and made it its own state for the editor state machine refactored the config windows ( ProjectConfigEditor , SceneConfigEditor , and the new GraphicsConfigEditor ) to inherit from a base ConfigEditor class so its cleaner and easier to maintain.. fixed the script widget since the ui was kinda messy
Particles! :) Ive started working on a particle system. i have got the core pieces in place and it seems to be working nicely so far…. changes particles implemented the foundations of the particle system currently has: ParticleEmitterComponent ParticleSystem ParticlePool emitters currently support: configurable particle limits and emission rates randomized lifetimes and velocities “gravity” size over lifetime color over lifetime world space simulation materials obviously so far it’s all behaving pretty well… EngineLib next up is getting particles exposed through the EngineLib API so scripts can spawn and control emitter components we will see how it goes…
mostly just spent some time going through some old code.. nothing really important, but i’ve also replaced the placeholder assets.. with my own placeholder assets that i drew in GIMP, considering i probably do not have the rights at all to distribute the previous assets.. :)
More Particle work… been spending some time on the particle system… changes particles expanded the particle system quite a bit. currently supports: randomized size ranges randomized rotation configurable emitter shapes (support quad, circle, and soft circle) alpha and additive blending configurable render order (still kinda broken but im working on it) per-particle color over lifetime particle presets that can be saved and loaded (as JSON) also added an editor preview mode, so particles can be previewed while editing instead of only showing up in play mode renderer had to do a bit of renderer work to support all of this particles now use their own dedicated shader added support for per-instance colors during instanced rendering added an overlay render pass for effects that should render on top of the scene cleanup also did a some more project cleanup, splitting up my Utils header into multiple files.. nothing special though misc particle emitters can now be saved as reusable presets (some which will be shipped as defaults ofc) as suggested by @sol4r_on_hackclub cleaned up a few asset importing edge cases fixed a couple of packaging issues too I’m pretty happy with how the particle system is coming along :D
UI Experiments since working on the particle system, I feel like it’s in a pretty good place for the current scope. I don’t really know what else I want to add to it right now, so I decided to finally start on something that’s been sitting in the back of my mind for a long time… a proper UI system. changes particles mostly just spent some time testing and polishing the particle system to make sure everything behaves properly I’m pretty happy with where it’s at for now UI started prototyping a custom UI system it’s very early, but I’ve got the basic rendering pipeline up and running currently working on: a UIElement system a dedicated UI renderer text rendering font loading using FreeType right now it’s mostly just enough to prove everything works, but it’s the foundation for the runtime UI system ive wanted for a long time the goal is for games made in the editor to be able to have their own UI, with everything exposed through EngineLib so scripts can create and interact with UI elements as well honestly, for now.. I was expecting it to go alot worse.. FreeType isn’t as bad as it seems once you get it working with GL The screenshot below dosent show much, but you can see the rendering of Text and rects, it also supports textured rects (which is what the text is currently using to render from a texture atlas)
game UI Progress been continuing work on the UI system. changes UI made some good progress UI system currently have: font importing working texture support for UI elements basic text rendering a simple editor view panel for UI it’s still very much WIP editor right now it’s pretty basic, but it’s enough to start experimenting with how creating and editing UI might actually work inside the editor there’s still a lot left to do before I’d call it usable, but im making progress.. getting text working is painfull, and still unfinished.. but im workin on it…
more ui ive been kinda sick so i aint really had the motivation to do a lot but ive been working more on the UI system im kinda tired so i dont really feel like writing more for now -.-
Scripted UI, Map Workflow, & a Bunch of Bug Fixes alot of bug hunting… changes scripting & ui scripts can now actually interact with the UI system. added bindings for things like: creating UI buttons, text, rects, and images finding UI elements destroying UI elements these return wrapped objects with basic getters/setters for position, visibility, and button state map workflow spent a fair bit of time cleaning up the map editor flow. maps no longer get a fake default path on creation switching to the Map Editor tab now auto-creates a map (empty) if there isn’t one yet mapFilePath now stays project dir relative instead of randomly becoming absolute tile materials are now shared properly instead of silently duplicating state rendering & lifetime bugs i’ve been doing alot of testing recently, so i found alot of bugs… this was probably the biggest pain point. renderer submissions now keep materials and meshes alive for the frame instead of trusting the caller replaced the old Shader::Default() singleton hack with a real fallback shader (internalshaders base) fixed the lightmap quad so it keeps its own VAO and clears correctly when there are no lights fixed a Texture move bug that was double-deleting GL handles sometimes editor polish also cleaned up a bunch of editor behavior while I was in there. Ctrl+S now behaves correctly depending on whether editing a scene or a map scene loading now rebinds editor panels properly save/load dialogs now append file extensions automatically added more inline warnings in the inspector and panels (i.e if an entity has no material it will tell you it wont render) and ive probably forgotten something else … in summary ive just been testing out some UI/UX changed and hunting down bugs untill I feel it is ready to maybe start prearing some sort of demo :)
Entity Hierarchy & Scripting Integration finally caved & added actual parent/child relationships to entities changes entity hierarchy entities can now have a parent & children via a new RelationshipComponent . Registry::Reparent() handles moving an entity under a new parent, with cycle & self-parenting protection so you cant do anything silly like parenting an entity to its own descendant. TransformComponent now has a worldTransform alongside the existing local one, a new HierarchySystem systems that care about actual position (i.e AISystem ) read worldTransform now instead of assuming local == world. destroying an entity recursively destroys its children too & unlinks it from its parent’s child list scene serialization now saves & restores the hierarchy editor the Registry panel is a proper collapsible tree now instead of a flat list drag & drop reparenting, plus a right click menu for “Create Child”, “Detach”, & “Set Parent”. scripting pulled all the entity/component script bindings out into their own EngineLibRegistry.cpp module, they were kind of scattered around before & this makes them way easier to find & extend. scripts can now walk the hierarchy too (get children, etc), same module. added SetFont / GetFont bindings so scripts can assign or query a button’s font, small thing but script generated buttons wont have visible text without it :) misc cleanup small modernization stuff while i was in these files anyway: dropped redundant ternary parens, swapped a bunch of auto x = ...; if (x) into if-with-initializer, dropped some unnecessary global qualifiers, const-correctness fixes on UISystem::Update & UIRenderer::Flush . (yes i know the gizmos are offset and buggy, i kind of forgot to update the gizmo code after changing transforms :p )
working in a windows vm trying to get it to compile on windows… it is obviously going great… -.-
Windows Build The Windows build seems to be working.. I don’t have proper OpenGL passthrough in my VM… However, the Windows executable compiles perfectly in the VM and is running fine under Wine. so I consider that a win for now…
Bugs bugs bugs… I’ve been working on a demo project to both test the engine properly (looking for bugs and all), and also have something to actually show off made in my engine… this is the project you’ve been seeing in the last couple logs btw :) of course… since I’ve been using the editor for actual “work”, I have found a bunch of bugs. the biggest one being the entity ID situation… or.. disaster? changes the entity ID mess in the past, out of laziness… entity ID 0 was being used as both a real, valid entity handle and the “no entity / invalid” value depending on where you looked. which worked fine… mostly because of pure luck. the annoying part was that after working on this for a while I wasn’t even sure anymore if I was using 0 , -1 , or something else for invalid entities.. yep.. so I finally cleaned it up there is now a proper INVALID_ENTITY_ID constant, and entity index 0 is reserved for invalid entities. real entities now start from 1 . went through and replaced a bunch of random == 0 / != 0 checks across ECS, serialization, prefab handling, editor panels, and scripting bindings. project templates added support for multiple project templates. new project creation now scans the Templates/ folder instead of everything being hardcoded to “Default”. currently has: DemoProject Empty the demo project is mostly there to show off the newer UI/scripting stuff (the same demo as mentioned before), while Empty is just a completely blank scene. hierarchy & transforms fixed entity and UI reparenting. previously moving something to a new parent could randomly change its position because it was just applying the new local transform now reparenting keeps the world transform, so dragging things around in the hierarchy behaves properly UI & text rendering fixed a bunch of UI text issues. text now centers vertically using actual glyph metrics instead of a random offset I was “pretty sure” was correct it was not, in fact, correct button text now scales to fit inside the button fonts can now load directly from VFS memory instead of requiring a real filesystem path the VFS font loading one was something I completely forgot about when testing outside packaged projects… oops. packaging implemented .pakignore instead of a hardcoded ignore list, the packer now supports gitignore-style patterns in a .pakignore file and properly skips ignored folders/files also fixed a few smaller packaging issues while testing exported projects. misc a bunch of smaller things: map save/load dialogs now default to the project maps folder fixed scene switching bindings in editor play mode fixed a lightmap redraw bug font importer now only accepts .ttf / .otf added a small README with build instructions since im planning on publishing the repo soon (and writing all the docs… scary..) nothing super flashy this time.. but important
the repo is public been working on gettin things ready for that, mostly writing some docs and getting GitHub Actions set up so I can build and release cross-platform builds also did some small code cleanup / fixes while I was going through everything. changes github actions i setup a workflow to compile the project on linux, windows, and mac, and then publish a release (mac is untested but compiles). im real happy though that its actually compiling on all “major” platforms though docs finally wrote some actual documentation… there are a few files in the docs/ folder now and a proper README still a WIP obviously, but at least there’s something there… misc implemented create new map button i forgot about completely repo there is already a build published as a test of the github actions thingy, try it out if you want :D https://github.com/torkelicious/obliberry
Lighting Fixes been fixing a few small things with the lighting system mainly fixed lights using the wrong entity transform I forgot to account for entity parenting when I implemented that… also added a per-scene toggle for enabling/disabling the lighting system
scripts can schedule stuff for later Added SetTimeout to the scripting API changes SetTimeout SetTimeout(fn, ms) calls fn() after ms milliseconds. simple to call from obsl timers live in a plain std::vector<Timer> in a new Platform::Time namespace, polled once a frame from Scene::Update no threads, no async bs or whatever :) the callback itself is a SmallTask , which falls back to a heap allocation if the closure is too big to fit inline fine for this since timeouts aren’t really a hot path timeout callback fires from an arbitrary point in Update , so it gets its own ScriptCommandBuffer set up on the worker just for the duration of the call, then flushed right after also gc.add_root / remove_root the function around the callback so it doesn’t get collected while it’s sitting in the timer list waiting to fire Documented it in the api reference alongside the other Time functions also tiny UI tweak in the tile editor: it now warns “no tile types defined, no map will be visible!” instead of just “no tile types defined” was seeing people get confused about why a new map looked empty after trying to paint also small updates to docs in general and stuff but nothing super interesting
…the default imgui theme first off, huge thanks for all the incredibly kind reviews on my last ship !!! most of this work was also inspired by someone pointing out that i was still using the default imgui theme. fairs… so i spent some time making the editor actually customizable and messing around with having some kinda-nice defaults :) editor ui & theming live theme editor: built a proper window to tweak colors, spacing, padding, rounding, etc. in real-time. semantic palettes: added a semantic color system so you can build out a theme from a small set of base colors, rather than manually adjusting every single internal imgui color enum (though you can still override individual colors if you need to). serialization: themes dump straight out to a theme.json sitting right next to the editor executable. undo/redo: the theme adjustments go through the undo/redo system! help menu: put in a placeholder help menu. turns out literally nobody likes reading docs, so i guess i gotta start explaining how to use the engine from inside the engine… not implemented yet though editor groundwork did a bit of backend cleanup as well. added an EditorContext for editor-specific state, separate from the runtime EngineContext (currently just used for theme stuff) started working on editor font support with a FontSet for things like Body, Bold, Monospace, and Icons, not implemented though the font stuff is mostly groundwork for now, but the theming system is actually working and makes the editor feel nice :D
fighting with fonts font-management rabbit hole in the theme editor… still wip changes font management in the theme editor the theme editor now has a proper Fonts section import .ttf / .otf fonts directly from the editor assign fonts to roles like Body, Bold, Monospace, Icons, etc. merge fonts together so icon fonts can be stacked on top of regular fonts rename, delete, and change the size of fonts fontsets are now saved as part of the theme, so imported fonts persist across restarts the role system isn’t fully wired up yet currently Body is used as the default editor font and Monospace is used for the console. im still working on the whole font management system here and its very unfinished and kinda untested.. very WIP!!! hot-reloading the annoying part was getting font changes to work while the renderer is running on another thread. rebuilding the ImGui font atlas in the middle of a frame was… not ideal, and eventually resulted in an assertion. now font changes mark the atlas as dirty, and the editor waits for the render thread to finish before rebuilding the atlas at a safe point. not the prettiest solution, but it seems to be working.. kind of dpi & freetype also experimented with DPI handling for fonts and wrapped FreeType into a single shared instance instead of creating separate instances everywhere. still figuring out exactly how I want the DPI/font sizing stuff to behave, but it’s getting there. bug fixes while doing all of this I also ended up fixing a few unrelated things: fixed an old GUI rendering bug where text could stop rendering or become garbled because of a pointer race thanks to @staneko for helping test/report that one since I couldn’t reproduce it properly on my system fixed a weird compilation issue related to namespace escaping bumped the vendored ImGui version for some dynamic font-related fixes a few other small UI changes and cleanup still working on this, and the font management side definitely isn’t finished yet… most of this time was just spent trying to get it to half-work so.. yep..
mostly ui stuff (and fighting windows wide chars) yay pretty ui editor ui theming ui blah blah idk what to call it kinda cleaned up some stuff into proper members so the ui state doesn’t get all weird and persistent when you close the theme window discarding changes: actually works now. closing the window used to revert colors but keep your staged font changes, which was dumb (didnt really cause issues since changes werent applied anyways unless you saved beforehand but still.) font role indicators: added a little visual thingamabob where the font list now shows a star next to whatever font is actively set as the body font (also font name is now rendered in its proper font) path tooltips: added a hover tooltip on the font list items that shows the full file path of the font also some placeholder stuff in the code for searching the customization menu i might be implementing soon windows compat std::filesystem::path everything: went through and switched out the raw std::string usage for font paths inside FontConfig , replacing them with std::filesystem::path . this was purely because my windows ci build was failing. i was passing raw char strings around and doing weird string conversions, which completely blows up on windows because it expects wide chars for paths and i didnt consider that when i was being lazy and doing silly conversions and stuff because i just wanted to pass ez pz to a c library. freetype & serialization cleanup: updated all the internal freetype helper functions ( GetFontName , etc.) and the json theme serializer to play nice with the new paths instead of passing raw char pointers kinda mostly just making it a lil more prettier
scrips can change things on the map yippie changes scripting scripts can now modify maps through EngineLib added: Map_SetHexWalkable Map_SetTileType yes, i made sure changes to walkability properly update the map’s pathfinding data instead of leaving it with stale information… sanitizers added sanitizer builds…. got ASan + UBSan working through CMake, along with presets for testing… it has helped already :) timers SetTimeout : if a script created a timer and then the scene changed before it fired, the callback could still run against the old scene state. timers now use generations, so changing/reloading a scene invalidates any timers belonging to the previous scene. editor fixed another map editor bug where discarding unsaved changes didn’t actually discard them… it would clear the dirty state but leave the edited map in memory… i knew about this bug and fix for a while, but i kept on forgetting about it… but its finally done -.- also added an Edit button to script entries in the project browser so scripts can be opened directly (launches default app it detects for the file via ur os)
more docs… and some bug fixes some small bugs that have been annoying me for a while finally got fixed… and I wrote more docs than I probably needed to…? or maybe too litte.. who knows changes entity selection actually clears now fixed an issue where clicking empty space in the viewport wouldn’t reliably clear the current selection. the pick-result handling was structured wrong, so the “nothing was selected” case basically never got handled properly. also explicitly clear the entity ID framebuffer attachment every frame so it doesn’t leave stale IDs around from previous frames. i knew this was broken, and figured the fix would be pretty simple for a while.. but i just kinda forgot to fix it.. oops…. fixed parent transforms during scene loading fixed a bug with parented entities getting their transforms messed up when loading a scene. the issue was that scene loading was using the same Reparent() logic as interactive editor reparenting. that function intentionally recalculates the local transform to preserve world position, which is what you don’t want when loading a transform that’s already been serialized correctly… was eepy when writing that i guess added Registry::SetParentDirect() for scene loading, which just sets up the parent/child relationship without touching the transforms. interactive reparenting still uses the old behaviour, so dragging entities around in the hierarchy still preserves their world position misc cleaned out some old commented-out code docs, docs, docs also wrote proper editor documentation section covering things like: editor concepts usage scenes prefabs components and some even have screenshots.. yes i know.. fancy the help button in the editor links to some of these pages now. i guess “figure it out yourself” wasn’t really an acceptable documentation strategy anymore…. i mean i had some docs.. but they weren’t that good for editor-usage and more technical stuff.. so yep.. also made the README headers slightly more obvious because people were still asking where the download link was ….
persistent Entities been working on persistent entities via a tag.. the same idea as Unity’s DontDestroyOnLoad, except you mark entities as persistent in the editor instead of doing it through scripts (scripts can do it too though). everything keeps breaking or half-working help.
persistent entities… again kinda scrapped most of the first attempt at persistent entities and decided to redo it instead of setting persistence in the editor, I went with something closer to Unity’s DontDestroyOnLoad , where scripts explicitly mark entities as persistent. makes more sense and is a lot less weird around scene changes. (i.e this.SetPersistent(true); ) changes scripting added: entity.SetPersistent(true) entity.IsPersistent() persistence persistent entities are tagged before the scene unloads, serialized normally, then re-injected and reparented when the new scene loads. the persistence tag itself isn’t serialized, so it won’t accidentally end up saved into the scene dedup added some basic deduplication so persistent entities don’t get duplicated if the new scene already contains an entity with the same name. its name based for now… not very great, but good enough
mostly windows fixes changes SetLightmap took a raw Lightmap* and just held onto it for the frame swapped it for a small value type the renderer copies out immediately instead… this sometimes caused crashes but seemingly only on windows?.. just my luck.. LightingSystem had the same issue, was writing back into ECS memory through a raw pointer from a GL init task. now creates the framebuffer/vao up front and just calls Invalidate() on them SubmitPersistent was also holding a raw pointer into caller-owned memory, now copies into the staging buffer like everything else does RenderBatch used to just silently not draw anything if a batch went over MAX_INSTANCES . now it chunks into multiple draw calls instead of dropping the whole thing InvalidateGLCache wasn’t resetting the dynamic instance buffers, only the VAO cache, so they could point at dead GL objects after a context loss actual windows fixes opening files tries to open via already existing file associationg, otherwise falls back to the “open with” dialog if there’s no default handler also the paths get normalized to backslashes now asset import for scripts and so just does a file copy now instead of going through the old import path
code cleanup & optimization currently going through a bunch of older code and fixing / optimizing things. prolly way too much to actually write about, and most of it is just boring small changes, bug fixes, and a lil cleanup big pr i guess soon idk
hardening + performance stuff so this is kinda the continuation of the last log(s) where i was going through some old code kinda boooring but its important performance mainly been trying to get rid of unnecessary allocations and full scans stuff optimized ECS entity/component lookups and removal reworked hierarchy propagation to avoid unnecessary registry scans reduced allocations in scripting and UI command buffers cached script wrappers so they can be reused instead of constantly recreated improved UI lookups with a proper name index made particle/lightmap updates only rebuild when actually needed cached project browser directory scans capped the editor console and added clipping for large logs also did a bunch of smaller optimizations around scripting task scheduling and resource loading things thread safety went through a lot of the cross-thread stuff as well made ResourceManager access properly synchronized experimenting with the audio locking guarded FreeType access made window size and pending scene state thread-safe fixed some render thread / GL context handling basically trying to make all the multithreading stuff a little less “it seems to work” type stuff though alot of this probably wasnt actually causing any issues YET , it would be very hard to debug in the future if I didn’t try to fix it now so yeahh correctness fixed several out-of-bounds issues in VFS/package parsing made VFS path resolution properly stay inside the VFS root (oops…) fixed hierarchy reparenting allowing cycles fixed a few dangling references in hierarchy code fixed some component pool and packaged asset lifetime issues undo history now clears when loading a scene cleaned up a few map editor edge cases fixed text centering fixed the triangle mesh made engine context non copyable also updated the demo template while I was at it (since a recent movementcomponent update it wasnt behaving properly due to the addition of a new field) there are other small things i probably didn’t mention here too but it’s mostly all a collection of a bunch of small things im still testing this though and looking into a few other small things…..
ui editing gizmos!!!1 you can finally drag UI elements around in the editor (instead of typing position/scale values into the inspector) changes ui gizmo added a proper UI gizmo with resize handles and dragging support and that corners resize both axes, edges resize one axis dragging the body moves the element resizing from the top/left keeps the opposite edge anchored added a small drag deadzone so clicking doesn’t accidentally create an undo step UI transforms now go through TransformUIElementCommand , so they’re undo/redo -able also renamed the existing entity gizmo code and naming gets confusing otherwise… coordinate stuff the gizmo needed mouse coordinates relative to the viewport rather than the whole window, so added some better viewport coordinate handling for that… maybe a lil late ui editing mode buttons won’t randomly enter their hover/pressed states just because your mouse is sitting over them now in the editor beccause its a lil annoying when editing small optimization also fixed UIText and UIButton recalculating their text layout every frame when nothing changes feels nice :)
custom meshes im trynna make it so you can draw your own custom 2d meshes in the editor its still a lil buggy but it’s mostly working, serializes and all that :) very fun…
experimenting with post processing working on a lil post-processing pipeline still very wip but im mostly just playing around with various shaders and stuff changes the pipeline PostProcessor is a simple “ping-pong” chain: scene renders to an off-screen FrameBuffer , then each enabled effect runs full-screen-triangle shaders bouncing between two ping-pong buffers, in whatever order they were added I’m working on a system via variants to get uniforms to be easily serializable and such, it seems to be working but I havent actually wired it into anything just yet. editor and runtime a lil bigger change than expected. i implemented a unified fbo for both editor/runtime rather than the weird jank i was doing before editor: scene renders into m_SceneFrameBuffer , post effects run, then it gets sent into the ImGui viewport image like before runtime: same scene framebuffer, same post effects, then PresentToScreen goes to the default framebuffer instead just some general cleanup for that ig crt shader i wrote a lil silly CRT looking shader to test it out as shown below, it’s cool but kind of useless, but very fun to play with!!!
more post processing!!!! this took way longer than i thought it would but uh whateveer. i think i still gotta fix some small things but its working pretty alright :D editor ui added a proper ui for post processing :) threw in an import button and stuff so you can load in fragment shaders as post proc fx you can edit the uniforms directly in the ui now stuff glsl uniform parser: wrote a very simple basic glsl uniforms parser. this is what makes the ui editing possible, but it also helps a ton with serialization so i don’t have to hardcode everything serialization: implemented saving and loading for post processing effects and also made post processing effects bound per-scene instead of being a global engine thing yay post processing funny effects shaders aaaaaaaah
shader preprocessing been working on a small shader preprocessor thing while also finishing up the final bits of post-processing right now the preprocessor is pretty simple, mostly just adding support for: #include #pragma once I haven’t actually needed it yet, I just kinda had the urge to make it… so now I have a shader preprocessor …? its pretty extendable and all though so usefull to have ig :)
too many post proc fx? followup to the post processing / shader experiments… changes shader includes shaders can #include "rand.glsl" etc and it resolves properly. it checks the project VFS first, then falls back to the engine’s own shader helper directory if it isn’t found there. engine shader helpers also get packaged into exported games under engine/shaders/ , so includes keep working at runtime. added a few helper include files: rand.glsl / auto_rand.glsl - seeded hash-based random, with auto_rand reseeding per frame from u_Time color.glsl - HSV conversion, lift/gamma/gain, contrast, saturation, and three-way color wheels commons.glsl - engine-provided uniform declarations so you don’t have to redeclare u_Resolution , etc. in every shader for engine-provided uniforms the helpers use #ifndef / #define guards, so auto_rand.glsl can include rand.glsl without causing double declarations if the effect shader or another include declare the same uniforms or includes. more built-in effects added a few more built-in post processing effects: ColorGrading - exposure, contrast + pivot, saturation, lift/gamma/gain, and shadow/midtone/highlight color wheels using color.glsl FilmGrain - chunky per-cell grain with u_GrainSize controlling the cell size Vingette - yes i know its mispelled. uniforms with Wheel in the name now get the wheel-style color picker instead of the regular color picker, since a normal RGB slider cleaned up effect registration used to have two separate lists, one for raw shader registration and one for the default effect chain. this meant adding an effect involved touching two different structs in two different places. merged those into one PPRegistration list with an inDefaultChain flag shader debug name added an actual m_DebugName field and made error messages / the material inspector fall back to it when there isn’t a real file path. docs wrote up some post-processing editor docs ….. i hate writing docs.. also .shader is now a valid extension for importing custom effect shaders, alongside .frag / .glsl trimmed down the miniaudio CMake config by disabling its examples, tests, and tools, along with Vorbis/Opus/FLAC support since i’m not using any of that….
sllight hub overhaul redid the project hub screen and added recent projects tracking, since up to now opening anything meant going through a file dialog every single time… changes recent projects get tracked in a PROJECTHIST file (next to the editor executable) …dead simple format, one filepath per line, each pointing at a project’s .json . capped at 5 entries, oldest just get removed off the list. hub screen is basically remade two docked panels now instead of one. left panel is the same buttons as before (new project, open project, etc), right panel is the new recent-projects list, up to 5 entries since that’s all the history file holds. also removed some unused dead code i found… QoL type stuff i guess :D
copy paste (kinda) also too much time fighting windows builds tried to get entity copy/paste working and it’s… janky. also ended up wasting a stupid amount of time just getting windows builds to actually build again because i lowk forgot again about how it wont let me pass paths as strings implictly as it does on every other damn os… changes copy/paste (wip, kinda broken) started on ctrl+c/ctrl+v for entities & ui in the editor it kinda works but is really janky and does not feel good to use, also tried implementing it in the context menu but its not workiong at all -.- other the windows fixes…. some resharper reccomendation inspection type shi but lowk its been a while since i logged soo yep
collision stuff been working on a collider system. still pretty early and not hooked into EngineLib yet, but most of the basic backend + editor stuff is there planning to expose it to scripts in a similar way to how Unity handles collision callbacks / triggers, but that’s for later……. collision added a new ColliderComponent with: box and circle colliders offsets size / radius trigger support collision system currently handles: box vs box circle vs circle box vs circle collision normals + penetration depth ‘trigger’ collisions also added a CollisionWorld that keeps track of collisions between frames and generates Enter , Stay , and Exit events. mostly groundwork for when I hook this into EngineLib… collider editing colliders are editable from the editor theres a collider inspector widget for changing the shape, offset, size/radius, and whether it’s a trigger, plus a viewport gizmo for directly moving and resizing them collider edits also go through the undo system, because every new editor feature needs to become an undo/redo problem eventually……… :D other editor fixes entity copy/paste now copies the whole child hierarchy instead of only the selected entity pasted hierarchies keep their parent relationships added copy/paste to the entity and UI context menus fixed stale entity / UI selections after the thing being selected gets deleted fixed single-key shortcuts like V , T , R , etc. firing while Ctrl/Alt/Shift was held keyboard camera movement no longer fights with Ctrl/Alt shortcuts a few smaller include / cleanup things mostly collision work though. next step is probably getting the collision events into EngineLib and experimentiung w. it its still a bit jank of course but it works i guess :DDDDD
collision system round 2 i guess ended up pretty much reworking most of the collision system….. the first version was still basically 2D, with separate box vs box / circle vs circle / box vs circle functions. that worked as a starting point, but it was gonna get annoying … so… it is 3D now. colliders ColliderComponent now supports: boxes spheres cylinders 3D offsets / dimensions triggers entity-space or billboard orientation billboard colliders follow the same camera-facing basis as billboard rendering, which means billboard sprites can still have colliders that actually line up with how they appear on screen. GJK got rid of all the individual boxVBox , boxVCircle , etc. collision functions and replaced them with support-mapped collision detection using GJK. each collider shape just provides a support point now, the intersection test doesn’t care what combination of shapes it’s checking. i dont fully understand the math completely yet.. but it kinda makes sense :D still no collision response / physics yet. this is just detection + events, i think ill prolly get it into EngineLib.. soon… events the CollisionWorld still tracks collisions between frames and generates: Enter Stay Exit trigger state is kept with the collision too. this is for EngineLib integration. scripts should be able to react to collisions / triggers like unity I have not gotten around to this yet though… collider gizmos also had to redo the collider gizmos now that colliders aren’t just flat 2D shapes anymore… its a lil janky but it works.. billboard cleanup while doing the billboard collider stuff I also cleaned up billboard rendering a bit billboards used to have their world transform temporarily modified by SpriteBillboardSystem before rendering. now the billboard matrix is generated when the entity is submitted to the renderer instead, so the actual ECS transform can stay as the real entity transform there’s now one shared billboard matrix helper used by both rendering and collision, which is considerably less cursed. um scripting integration next i guess.. if something dosent explode ! :D
collision callbacks scripts can do collision things now….!!! script collision callbacks ObSL scripts can now define collision hooks: on_collision_enter(other) on_collision_stay(other) on_collision_exit(other) on_trigger_enter(other) on_trigger_stay(other) on_trigger_exit(other) the other argument is a normal EngineLib entity wrapper, scripts can do stuff like check its name, components, etc. collision events get collected by the CollisionWorld , then dispatched to the relevant script instances afterwards. they’re also run through the existing script command buffer ofc 2D collider shapes are back too… added explicit 2D shapes alongside the 3D ones: Rectangle Circle so the full set is now: Box Sphere Cylinder Rectangle Circle rectangle / circle are flat shapes. which is nicer for sprites and other 2d things movement actually respects colliders hex movement now checks whether an entity can actually occupy its next tile before moving there. added a CanOccupy() collision query which builds the entity’s collider at the target position, it blocks the move if something solid is in the way. triggers don’t block movement. collision robustness stuff also did a bunch of smaller fixes around the collision added a shared collision tolerance instead of random 1e-6 s in different places AABB overlap now uses that tolerance too improved collider validation depending on the actual shape fixed gizmo world-to-local conversion to use the proper inverse transform more finite-value / clipping checks in the collider gizmo GJK Indeterminate results preserve the previous collision state instead of automatically counting as a collision p.s, heres a lil photo of my attempt at making syntax highlighting for obsl using textmate grammar… :D
spritesheets / animation finally … spritesheet support spritesheets added a new SpriteSheetComponent with: texture rows / columns optional row + column spacing start frame animation length FPS looping playing / paused state current frame basically the renderer can now render only a specific UV region of a texture animation also added a small sprite animation system that advances frames based on FPS and handles looping / stopping at the end etc etc animations also update while in the editor… might be annoying for some, might be less annoying for others.. but thats how i like it editor stuff you can pick the texture, set rows / columns and spacing, choose the start frame + animation length, change FPS, toggle looping / playback, scrub the current frame, restart the animation, etc. etc EngineLib scripts can inspect stuff like the current frame, frame count, FPS, rows / columns and texture, and can also change the texture/grid/animation, set frames, play, pause, restart and stop animations. Collider also has a proper EngineLib component wrapper instead of collision only being accessible through the callback hooks. right now that’s just getting / setting whether it’s a trigger, but it’s there. also added both Collider and SpriteSheet to the normal GetComponent , AddComponent , RemoveComponent , HasComponent , etc. obviously. some cleanup did a bit of registry / EngineLib locking cleanup while I was in there too, mostly around entity wrappers being created while the registry lock is already held. also fixed one very stupid collision callback typo where on_collision_stay was looking up the wrong hook… oops….. im also starting on documenting this stuff…. yep.. pain… spritesheet used in video attached for testing is : https://opengameart.org/content/animated-butterfly
btw pls star on girhub animation clips / refactoring spritesheets …kinda refactoring the whole spritesheet animation thing already the first version worked, but having FPS / looping / frame ranges etc directly on the SpriteSheetComponent was gonna get pretty limiting cuz what if I wanted multiple animations for one sprite. it might sound stupid but for me it’s always worked to get a prototype working, then refactor/reimplement it. thats even what i did for this entire project early on, before it deleoped into a full on engine :D so now the spritesheet is mostly just the sheet + currently displayed frame, and animation playback is seperate animation clips working on proper animation sets + clips. an animation asset can have one spritesheet and multiple named clips, with each clip containing its own list of frames :D each frame also has its own duration now instead of the whole animation just sharing one FPS value, so stuff like holding a frame longer or doing irregular timing is possible without clips can loop independently too animator component added a separate SpriteAnimatorComponent which handles the actual playback state: animation asset initial clip autoplay current clip current frame inside that clip elapsed time playing state the normal SpriteSheetComponent is way simpler now… it just says what sheet + frame should currently be rendered (the animator updates that for it) animation assets animation sets are assets now under assets/animations/ they serialize separately and contain the spritesheet setup plus all the clips / frames / durations they are loaded through the normal asset system and registered in the ResourceManager scene serialization now keeps the animator config like the selected animation asset, initial clip, and autoplay editor stuff the sprite sheet inspector got reworked for the current thing but whole UI stuff isnt finished once an animator is attached it owns the sheet/frame instead of both systems trying to edit the same thing. I still need a proper UI for actually making / editing animation assets and clips though. i shall work on this next!!! (right now the backend is pretty much all ive done but its taken a lil longer than i thought… who wouldve thought adding cips cleanly would take this whole aah refactor) scripting EngineLib updates too SpriteAnimator in scripts can now do: Play("walk") Restart("walk") Pause() Resume() Stop() IsPlaying() GetClip() it is now based on named clips so i guess not anything flashy to show but… its stuff :)
animation editor continued working on the animation system and made the editor UI…. animation editor there’s now a Sprite Animation Editor you can: choose the spritesheet texture edit rows / columns / spacing create, rename and delete clips toggle looping per clip edit individual frame indices + durations move frames up / down duplicate / remove frames expand / collapse the frame list also added range generation so adding a normal animation doesn’t make you manually enter every frame one by one….. theres also an Apply FPS to All Frames button ! preview added a live preview for the selected clip. you can play, pause and restart it woaw it shows the current clip frame and spritesheet index while it runs…. project browser integration animation assets are properly integrated into the project browser now too there’s an Animations section where you can create, import, edit and delete animation assets creating a new one lets you choose its path then opens it in the animation editor. the animation asset workflow is mostly usable from inside the editor :D erm even more enginelib changes for the new systen that i still have to document… ( Play() Restart() etc) some cleanup working on… some mostly const-correctness, explicit casts, ranges, include cleanup and some other small stuff etc etc.. god bless resharper c++ also cleaned up some EngineLib entity wrapper code around registry locking so it can create wrappers safely when the registry mutex is already held spritesheet used in video attached for testing is : https://opengameart.org/content/animated-butterfly
I will not elaborate
asset system refactor + some editor stuff been wanting to redo how assets work for a while now. until now scenes carried the asset definitions with them, and loading scenes would keep throwing resources into the global resource manager. worked fine enough , but it also meant resources could kinda just accumulate forever.. i seperated them now!! assets.json projects now have a project-wide assets.json catalog. textures, shaders, meshes, materials, fonts, animation sets, etc. live there instead of getting serialized into every single scene. scenes / prefabs / UI / animations etc. just store resource IDs and the definitions live in one place besides making scene files considerably less bloated, this means saving a scene no longer serializes whatever random collection of resources happens to currently exist in the resource manager lazy asset loading having one project-wide catalog does not mean loading the entire project into memory. scene loading now scans for the resources that scene actually references and loads those from the catalog this includes stuff referenced by: entities maps / tile types UI post processing spritesheets / animators dependencies get resolved too so if something needs a material, its shader + texture get pulled in first. animation sets pull in their spritesheet texture, etc. etc. now the the resource manager should only contain what is actually being used asset lifetime stuff added SceneAssetScope for keeping track of what assets a scene has acquired. assets are retained while something needs them and can actually be unloaded once the last scope using them disappears so changing scenes repeatedly should no longer turn the resource manager into yummy more objects :O forever…. persistent entities reacquire the resources they need when moving between scenes too. there’s also handling for catalog entries being replaced / deleted while their old resource is still loaded. those can be marked stale and discarded safely once the old scene lets go of them instead of leaving weird zombie resources around. engine assets still stay around like normal. editor asset workflow the editor now goes through the asset catalog too. creating / importing / replacing / deleting things like: textures shaders meshes materials fonts animation sets updates assets.json instead of depending on scene serialization to preserve them…. supported editor selections / script setters can also acquire catalog assets on demand and attach them to the current scene’s asset scope old projects old projects obviously still have all their assets embedded inside their scene files, so I added an ob_asset_migrator tool. it can scan the old scenes and merge all of those definitions into a project-level assets.json . there’s: dry-run validation conflict detection optional removal of the old scene assets sections backups before it starts rewriting stuff uses backups because i dont trust myself enough .. might vaporize projects who knows… docs docs docs also updated a stupid amount of documentation for the new asset model … since of course.. there’s now a full assets.json format page covering the different asset types, dependencies, lazy loading, asset scopes, editor behavior and migration. updated the scene / prefab / animation / post-processing docs too since all of those previously described assets as being stored directly in scenes. also cleaned up the main README + docs index a bit and updated the feature list because quite a lot of it was outdated at this point…. theme presets also did some work on editor themes. split the built-in theme definitions out and added some interesting presets: Obliberry Dark ImGui Classic Dark Obliberry Light ew imagine using light themes… High Contrast Dark Haxxorman Green editable and all… tldr: resourcemanager is now longer an infintly growing landfill…
save system i wanted this to be pretty generic instead of the engine having some hardcoded idea of what a “player save” or whatever is, so the actual save data is ba sically just key/value storage that scripts can use for whatever they want!!! save data there’s now a SaveGameManager which keeps one active save in memory. save values can currently be: booleans numbers strings the file format is versioned and also stores a display name + created / updated timestamps. the actual save data itself doesn’t really care what the values mean. it is any key value pair that persists. there’s also locking around the active save since scripts can be running across multiple workers….. project UUIDs projects also have their own UUID now. it’s generated when the project is created or when a project that does not already have one is opened right now it’s mainly used to give each project its own save-data directory without name collisions but im sure its good to have outside that!!! save files the basic save file operations too create a new save write the current active save load a save delete a save list existing saves start a fresh unsaved “game” save filenames are generated from timestamps. the human-readable name stays inside the file, display names don’t need to also be valid / unique filenames. save_list() also gives creation + update timestamps, and saves are sorted by most recently updated. writes are atomic too, so it writes through a temporary file before replacing the real save instead of directly nuking the existing one and hoping for the best per-project save directories save data is stored outside the project itself in the normal OS application data home each project gets its own directory based on its UUID <data home>/obliberry/<project uuid>/saves/ projects with the same name don’t fight over the same saves.. (i have several projects just called “UntitledProject” lol) this is LocalAppData on Windows, Application Support on macOS, and XDG_DATA_HOME / ~/.local/share on Linux. both the editor and runtime configure the save manager when the project is loaded, and it gets reset again when the editor closes the project ! ObSL ObSL savedata enginelib intergration: basic data stuff: save_set(key, value) save_get(key) save_has(key) save_remove(key) save_clear() save_new() save file management: save_create(name) save_write() save_load(filename) save_delete(filename) save_list() save_list() returns an array with the filename, display name, creation time and last update time some cleanup also pulled the atomic file writing stuff into a shared OS file utility, so assets.json can use the same code instead of having its own implementation. bunch of formatting stuff too i still have to document this and do some more testingf but yeahhh
uuids, collision layers, save settings, and other stuff bit of a mixed bag this time. mostly cleaning up some systems that were already there and filling in stuff I’d need… entity UUIDs entities have proper UUIDs now, separate from their normal runtime entity IDs. the regular generational ID still does all the normal ECS stuff, while the UUID is a stable identity that gets serialized with the entity. this mostly fixes how persistent entities work between scenes. previously I was deduplicating persistent entities by name , which was obviously not ideal since names aren’t actually identities. persistent entities + their children now keep their UUIDs when moving between scenes, and if the destination already has an entity with the same UUID it gets replaced by the carried-over one. two things can have the exact same name now without persistence randomly deciding they’re the same thing. normal prefab instances / newly created entities still get new UUIDs. collision layers colliders now have proper layers + masks. there are 32 collision layers, and every collider has: a layer a 32-bit mask of layers it accepts both colliders have to accept each other’s layer for the pair to interact. the same filtering is used for normal overlap events and movement blocking, so there isn’t a separate set of collision rules depending on which system happens to be asking. added editor controls for this too, including the layer selector, all 32 mask toggles, and select all / deselect all buttons because clicking 32 checkboxes individually sounds incredibly fun. scripts can also read / change the layer and mask now. collision-aware script movement also added Transform.TryMoveTo(x, y, z) to ObSL. unlike SetPosition , this checks whether the entity can actually occupy the destination before moving it. the normal hex movement system uses the same helper now too, so script-controlled collision-aware movement and normal movement go through the same path. direct SetPosition is still basically teleporting, which is intentional. also fixed on_collision_stay actually looking up the collision stay callback instead of the trigger stay callback. whoops. more save settings did some more work around the save system from the last update. saving can now be enabled / disabled per project, and projects can choose where save files go: Data Home , the normal OS application-data location Portable , relative to the executable both still use the project UUID underneath so different projects don’t start sharing save files because somebody named both of them game . these are editable from Project Settings now. also added a confirmation dialog when regenerating the project UUID since doing that changes which save directory the project looks at. the old saves aren’t deleted, the project just gets a new identity and stops finding them automatically. graphics config stuff changed packaged builds so graphics.json can live beside the executable and override the version inside the package. (i.e if someone decides to unignore the graphics config and package it) couple random fixes particle emitters now keep their actual live particle count, so GetAliveCount() in ObSL finally returns the real value instead of the completely useless placeholder it had before. fixed a prefab revert issue where the code was reading the prefab path from the component after destroying the entity. very intelligent. also made theme font loading a bit less fragile. missing / broken font files get logged and skipped instead of potentially taking the whole theme load down with them, plus some parsing cleanup. and updated another mountain of docs to match all the collision, persistence, save, prefab, post-processing and export changes.
unit tests (& some fixes) uhhhh started adding actual unit tests… i was kinda putting it off but i gotta have it… set up GoogleTest + CTest and started covering some stuff ECS registry / generational IDs entity UUIDs entity serialization hierarchy / parenting collision events + movement blocking save games maps bugs bugs bugs… and unsurprisingly, writing tests immediately started exposing some smaller issues. fixed stale entity handles being able to mess with components belonging to a recycled entity slot, and cleaned up some hierarchy transform / rotation handling that wasn’t preserving transforms correctly in certain parenting cases. also tightened up a couple math helpers while testing them. im still gonna write even more tests.. its very needed at this point and will prolly help me find some more bugs i missed before…
more tests (more bugs) kept going with the unit tests the test suite now covers most of the important stuff, including: ECS / entity IDs / UUIDs serialization + hierarchies collision geometry, events and movement maps animation saves ObSL + some EngineLib bindings assets / asset lifetime VFS + packaged projects configuration editor undo commands also added a couple integration tests for audio and rendering (OpenGL tests are optional) finding things unsurprisingly this found some actual problems too. stale entity handles can no longer remove / access components from an entity that reused the same slot, and editor undo commands are a bit safer around entities or components disappearing. also fixed some hierarchy rotation decomposition weirdness, cleaned up VFS / package mounting state so old package data can’t leak into the next mount, and added a few other small null / cleanup checks around scenes and rendering resources.
export dependencies + prefab asset loading redid how exporting figures out what needs to go into the package previously editor export was basically much closer to just packing the project directory. now it builds a dependency manifest first figuring out what to export export starts from the project + scenes and follows the things they reference: catalog assets used by entities, maps, UI and post processing map files attached ObSL scripts script using imports scenes loaded from scripts prefabs instantiated from scripts music / sound files material textures + shaders animation sheets shader #include s referenced scenes and prefabs get scanned too, dependencies keep chaining from there. it then generates a new filtered assets.json specifically for the package instead of sticking the entire project catalog in there. the actual project’s catalog is untouched. script analysis added a ScriptAssetAnalyzer which walks the ObSL AST without actually running anything. literal stuff can be narrowed down properly, including things like: PlayMusic("assets/audio/music.ogg", 1.0) or even constant string concatenation… asset setters like SetTexture / SetFont get tracked too. if a texture or font ID is dynamic, export keeps that entire asset category. if a runtime file path for stuff like LoadScene , Instantiate , PlayMusic or PlaySound2D can’t be figured out, it falls back to keeping the eligible project files + full asset catalog. unknown / indirect calls are done the same too so simple projects get smaller exports, while weird dynamic scripting should still work… .pakignore still applies, and required files being missing or ignored is now an export error prefab assets also fixed prefabs properly interacting with the lazy asset system. instantiating a prefab now scans its components, acquires whatever catalog assets it needs, resolves their dependencies, and retains them in the scene before creating the entity. so a prefab can use an asset that wasn’t already referenced by the scene and it should just work. scene asset scopes got changed a bit for this too. instead of accumulating a new scope every time something acquires assets, they’re merged into one scene scope and duplicate asset references are ignored. also made prefab revert a little safer so the old entity isn’t destroyed unless the replacement prefab actually instantiated successfully. packaging / ci things editor packaging is stricter in general now. script dependency validation can fail the export, missing dependencies stop it, and PackageCurrentProject reports failure so the rest of the export doesn’t continue pretending everything is fine. shader includes are followed during dependency collection too, while the engine shader helpers still get bundled for runtime includes. also cleaned up CI a decent bit… also some more tests too for the packaging and script analysis lowk sorry for just posting an image of the logs idk how else to show it since it’s mostly backend / file stuff 😭
undo stuff + render lifetime fixes undo / redo the undo system relied way too much on runtime entity IDs and direct pointers into components. that works until an entity gets deleted, an ECS slot gets recycled, or a dense component pool moves stuff around… entity commands now store the entity UUID and resolve the current runtime entity when they execute / undo instead. this now applies to transforms, renaming, adding / removing components, script changes, component field edits and map painting. so older commands can still find the right entity even if it was deleted and later restored with a completely different runtime ID. deleting things is actually undoable now finally added proper undo for deleting entities. !!!!!! deleting an entity snapshots the whole subtree first, including components, UUIDs, names, hierarchy + sibling order, scripts, custom data and asset references. undo rebuilds the tree, reloads required assets, restores the UUIDs and puts everything back where it was. this also means edits from before the deletion still work afterwards, since those commands just resolve the restored entity by UUID. paste uses the same snapshot system now too, so undo / redo keeps the same pasted entity identities instead of creating unrelated ones every time. there are checks for conflicting UUIDs, missing parents, invalid hierarchies, missing assets etc. failed restores shouldn’t leave half-created entities behind. failed commands also no longer get added to undo history or wipe an existing redo chain. custom ObSL data custom script data needed special handling too. arrays / objects can share references or even be cyclic, so just copying ObSL::Value s wasn’t enough. there’s now a snapshot format that captures the object graph and rebuilds it through the interpreter + GC when an entity is restored. CustomDataComponent also roots stored ObSL values properly so GC-managed objects stay alive. runtime functions aren’t snapshotable though, so deletion just fails instead of restoring garbage. render thread lifetime stuff also did a pretty big pass over renderer resource lifetime, mostly because scene switching could unload resources while an already submitted frame was still using them. (this started because someone mightve pointed out a lil crash for me…) render commands now pin the meshes, materials, shaders and textures they need until that frame is done. same idea for UI textures and the editor viewport framebuffer. OpenGL objects also don’t call glDelete* from whichever thread destroys the C++ object anymore. textures, shaders, buffers, VAOs and framebuffers queue deletion for the render thread, while it actually owns the GL context. less bugs yay frame state + shutdown renderer state that can change while the render thread is behind is captured per frame now too, including clear color, post-processing and UI resolution / projection state. shutdown is also more deliberate now: worker threads stop first, background font loads finish, scripts stop, scenes/resources are cleared, renderer/UI resources shut down, then the remaining GL delete queue is processed while a context still exists. font loading uses tracked jthread s now too instead of detached threads. small things exporting now reports success / failure back to the editor and shows a little result popup instead of silently relying on the console. also added tests around delete / restore, UUID reuse, hierarchy restoration, script components, map edits, pasting, command failures and repeated undo / redo without leaking entities or asset references. so. .. . less explosions hopefully sorry if wording is weird.. character limit..
uhhh changes dont nuke scene on failed load scene deserialization moved out of Scene::OnEnter into SceneManager::LoadScene , and now runs before the old scene gets torn down. if the new one fails, you stay in the old scene ( LoadSceneByPath returns a bool now) loading is stricter. missing map files, bad/out-of-range/cyclic parent values and broken UI sections fail the load instead of logging an error and limping on persistent entity migration happens before the swap too, so a failed asset acquire can’t leave you half in the new scene the editor’s LoadScene used to clear the current project before trying to load. now undo history and selection only get cleared once the load actually worked saving: map write failures now propagate instead of reporting success, and files get closed before the error check destroying entities DestroyEntity was recursive, now it’s iterative with a visited set. deep hierarchies, cycles and duplicate child entries no longer kaboom the stack or double delete, and children go first (wow that sounds dark) Reparent and SetParentDirect go through CanSetParent , which rejects cycles and stale parents, even if the existing hierarchy is already cyclic script DestroyEntity / entity.Destroy() now use RequestDestroy to tag the entity and its whole subtree instead of deleting immediately, so on_destroy runs before deletion. scene exit drains the destroy queue too, including entities tagged by exit hooks the script wrapper cache evicts an entity when it’s destroyed a dumb one…: the hot-reload cleanup list had on_exit in it twice and no on_destroy , so on_destroy GC roots never got released … the script system was holding raw ScriptComponent* across initialization, which dangles if a script spawns enough entities to grow the pool. it looks components up by entity ID now script runtime reinitialization after a scene change uses the VFS path and reruns setup, so using imports keep working from the mounted project ui undo UI elements have UUIDs now, and undo commands resolve them by UUID instead of holding raw pointers. removing an element captures the whole subtree plus its sibling position, so undo restores the hierarchy and order. renaming also updates the name index live. smaller fixes collision broadphase is a “spatial hash grid” now instead of checking every pair lightmap rebakes when ambient changes, and handles maps with no tiles atomic file writes use unique temp names so concurrent writers don’t trip over each other project changes wait for background asset loads to finish timeout timers are mutex-protected, and callbacks can schedule more timers without deadlocking SmallTask over-aligned captures fall back to the heap VFS::Resolve("..") had UB from a std::mismatch that wasn’t bounded on the second range… PlayMusic stops, swaps and starts under the lock now instead of racing!!! tests wrote a pile of tests alongside all this: atomic writes, wrapper cache, hierarchy safety, map serialization, save concurrency, scene loading failures, script lifecycle, script modules, SmallTask and timeouts. expanded to the editor command, save game and VFS tests. so EVEN LESS explosions !!! Woo!
map edit kinda overhauled changes map edit stuff the brush size is now 1 to 8 instead of 1 to 5. size 1 is one hex, size 2 is 7, size 3 is 19, etc. Ctrl +scroll also changes the size added Rect and Circle shapes alongside the brush. they work with Paint, Erase and Select. Rect uses opposite corners, Circle goes from a center out to the hex you release on. both apply on release paint previews are green, erase previews are red, and selection previews are yellow. selected tiles get a blue overlay added tool hotkeys: B for Paint, E for Erase and Q for Select Esc cancels a drag. Rect and Circle do nothing if cancelled, while a brush stroke gets reverted instead of leaving half the changes behind loading a map now prompts before discarding a dirty map, and successfully creating or loading a map clears the old undo history selecting and editing multiple tiles Select now supports click and drag, Shift +drag to add to the selection and Ctrl +drag to remove from it the toolbar shows the selection count and has Clear and Delete buttons. Delete removes all selected tiles in one undo step the Tile Editor can edit the type and walkability of the whole selection at once. when selected tiles differ, the controls show mixed values etc. material editing only appears when every selected tile shares a type. Override Current Type changes the material for every tile using that type, while Save as New Type assigns a matching type to the selection without changing every other tile using the old type brush strokes, Rect/Circle fills, deletes and bulk type or walkability changes are each grouped into one undo step. changing a type’s material itself is still not undoable…. the console…. logging now has a sink system, so the same formatted log messages can go to different outputs the editor now has separate Logs and ObSL panels. engine/application logs go to Logs now, and script stdout goes to ObSL the panels have Clear and Copy buttons and keep the latest 2000 lines. the UI sink buffers incoming logs under a mutex before the editor consumes them closing the editor closing the window now goes through a callback, so unsaved scene or project changes trigger the save/discard prompt instead of immediately closing removed the old global Esc -to-quit shortcut. ObSL’s CloseWindow() no longer closes the editor while in Editor mode. it logs that it was called instead. in the runtime, it still closes the window windows and smaller fixes enabled /MP for MSVC builds, and the editor/runtime targets use the Windows GUI subsystem so they don’t launch with a console window attached atomic file writes now write the byte buffer explicitly and retry Windows file replacement when it fails with access-denied or sharing-violation errors, for up to about 2 seconds a bit of cleanup around collision pair sorting, const-correctness and naming docs updated the editor guide and screenshot to cover the new tools, shapes, selection controls, shortcuts and undo behavior. blah blah …map editing is finally a lot less barebones…
uuid-bound script wrappers…, logger sinks…., and a pile of small editor stuff…. mostly scripting + logging plumbing this time, plus a couple of editor things I’d been wanting… changes script wrappers are uuid-bound now entity wrappers used to capture the raw runtime id, which is a problem if ids get recycled or the registry gets rebuilt. now every wrapper holds the entity’s uuid and resolves the live id on each call, so it keeps pointing at the right entity (or does nothing if it’s gone). new FindEntityByUUID(uuid) global and GetUUID() / .uuid on entity objects SetParent matches an entity object by uuid, a plain number is still a runtime id same treatment for UI wrappers: they resolve by uuid instead of name, so renaming or duplicate names don’t break them added FindUIByUUID , GetUUID() and Destroy() on UI elements, and SetImage / GetImage on images (acquires the texture through the scene asset scope like fonts do) still by name: FindUI , DestroyUI and the button state queries ( WasClicked / IsHovered / IsHeld ). UI scripting is still weird… work in progress i guess… logger sinks the old way was swapping the logger’s std::ostream for a stringstream that the UI panel also read from, which was a data race waiting to happen (logger thread writes, main thread reads). replaced it with actual sinks: ILogSink with ConsoleSink (stdout/stderr like before) and UILogSink (mutex -ed pending buffer the panel drains each frame) the editor and runtime both register a ConsoleSink , and the editor adds the UI sink on top, so the Logs panel is always there now instead of only when there’s no tty console panels color lines by severity now interpreter output goes through a small UiStream ostream into the ObSL panel, with stdout and stderr split (needed the bumped obsl, Interpreter takes both streams now…) ObSL panel clears when you enter play mode editor F focuses the camera on the selected entity, press it again to go back to the origin. its smooth…., ..panning cancels the focus keyboard pan only gets called when there’s actually input now.. editing a material in the inspector no longer mutates shared runtime-only materials. if it isn’t a catalog asset it gets cloned into assets.json first, and edits to catalog materials get “upserted” back to the catalog. “Clone Material” writes to the catalog too new scripts from the project browser come with an on_update stub instead of just a comment scripting runtime script top-level code now runs with the command buffer in “immediate” mode ( BeginImmediate / EndImmediate ), so registry writes at the top of a script apply right away instead of waiting for a flush that hasn’t been set up yet during init Hex_GetNeighbors wasn’t GC protecting its array while filling it, fixed…. grid tile textures a tile type with no texture used to fall back to hex_tex both when collecting dependencies and when loading scenes, which would pull in a texture that might not exist. now no texture means no texture… as it should… misc bumped obsl (new using alias feature, and err output stream settings) docs for all the uuid stuff, the F key, and the new UI/image methods… of course… oh also … new demo scene testin thingamabob im messing with…
script properties & UUID types scripts can now declare properties that show up in the inspector and get saved per entity. also ripped std::string UUIDs out of most of the engine in favor of an actual Core::UUID type, plus some scripting additions and a few tests. changes script properties Prop("SpeedOrSomething", 2.5) , PropEntity("TargetEntity") and PropUI("MyRect") for regular values, entities and UI elements properties show up under each script slot in the inspector, with appropriate controls and per-slot values values are only readable during top-level script execution, so store them in variables for use in hooks. Prop in a hook just returns the fallback saved as scriptProperties in scene JSON, omitted when empty property edits support undo, including live number/string editing. unused saved properties can be pruned with undo too.. ScriptSlot is move-only now Core::UUID replaced string UUIDs across the registry, UI, editor commands, project config, save directories and scripting with a 16-byte Core::UUID registry UUID lookups now use an index instead of looping through entities malformed UUIDs in files fall back to generated or nil UUIDs UI UUIDs are saved and restored, including nested elements. duplicate UI UUIDs are handled without crashing the loader savegame directories etc take a UUID directly scripting & UI script objects now have identity values and wrappers are readonly , along with various scripting result objects. came with an ObSL bump UI wrappers get SetParent(parent) and a uuid field. null reparents an element to the root UISystem::Reparent preserves ownership and prevents parenting an element under its own descendant new created scripts use fn on_update(dt) (I wrote on_update() last time …oops…) smaller stuff UndoManager::Execute returns whether the command applied script list shows filenames with Remove beside them tests and docs more tests and docs updated ofc… so u can reference entities in scripts without using Find() now!!!
Ships:
obliberry feels usable enough that i think its a good time for a first ship :) obliberry is a fallout-inspired isometric game engine for hex-grid games, written in C++20 with OpenGL, featuring a visual editor, an ECS core, its own scripting language, and single-file packaging/exports. this has all been rather challenging, but an incredibly fun learning project, especially regarding using modern C++, OpenGL, and making my own programming language it is still obviously not fully complete of course, but I think it’s in a rather good state :D...
|
1792821255.310022
|
1792907655.310022
|
|
18497
|
Helyx by @lix | Stardance
|
lix
|
1
|
324.55
|
5177
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-08-22T22:08:55Z", "hours": 309.0, "multiplier": 19.45, "payout": 5177, "blessing": "neutral", "text": "What I made Helyx is a terminal app for Windows that keeps every local Git repository you own in one place and lets you commit, branch, resolve conflicts, repair broken repositories and answer GitHub Issues and Pull Requests without opening anything else. I spent a lot of time thinking about what kind of project I wanted to build. I wanted something that would be genuinely useful to developers in many different ways, and that is how I came up with Helyx, a TUI application that brings many Git and GitHub tasks into one place. What was challenging Learning new libraries, keeping the code organized as it grew, and designing every screen so it looks and feels as polished as I could get it. Deciding what to build next was harder than it sounds, because there was always more that could go in. What I am proud of It has everything I originally planned to include. The diagnostics screen finds what is wrong with a repository and offers the fix instead of just reporting it, the conflict resolver opens the conflicted block in its own editor, and the whole app speaks 8 languages. How to try it Download the latest release from Helyx’s GitHub and run it. It installs into your user folder and adds Helyx to your PATH , so you can start it by typing helyx in any terminal. No administrator rights are needed, and the .NET runtime is bundled inside. Then pick Add project and choose any folder that contains your project. Helyx is open source, so you can also read the code or build it yourself. Just click See source code below.", "repo": "https://github.com/lixtheyt/Helyx", "demo": "https://github.com/lixtheyt/Helyx/releases/latest"}]...
|
[{"post_id": 68799, "ts": "202 [{"post_id": 68799, "ts": "2026-09-15T19:30:38Z", "hours": 4.4892, "text": "Hackatime integration Hello there! A guy made a feature suggestion on Helyx’s GitHub, that I should add a Hackatime integration into it. So I was thinking… and thinking… and thinking and woah… I ADDED IT! It is not 1:1 like the web interface, that one is better & shows you more things but sadly this was everything that I could request from API (at least I think): Total Seconds Languages Repo URL Total Heartbeats First Heartbeat (DateTime) Last Heartbeat (DateTime) and when combining all of these information, I created a screen where you can see all of this specifically for your project. It works on the principe of authorization. You put in your Hackatime token which authorizes you and then when you go to your project and go on Hackatime Info, it prompts you to select the project from a list of projects that are assigned to your Hackatime account/token."}, {"post_id": 62263, "ts": "2026-09-05T15:31:03Z", "hours": 1.14, "text": "Fixed User Scripts bug So, every path block used Path.GetFullPath(path) instead of Path.GetFullPath(path, script.ProjectPath) . That means it was resolving relative paths against Helyx’s own directory, not your project’s. This is now fixed."}, {"post_id": 60348, "ts": "2026-09-02T17:13:41Z", "hours": 2.7431, "text": "Reviewing my codebase and fixing bugs Since all of the features that Helyx was supposed to be finished with are almost all done (maybe even all are done), I will now change my view to another projects for Stardance such as ThetaNexus . But that does not mean that now I will just forget about Helyx. I will be reviewing the codebase sometimes to find some bugs and fix them. You can help me with this, by making an Issue request on Helyx’s GitHub. So what bugs did I fix since the last devlog? I fixed line breaking in badge/status README editor. When you were inserting your badge/status into your README via Helyx’s README editor, it done… messy stuff to the README, not something like really bad what couldn’t be fixed by manually doing it, but it should now insert the badge/status exactly as you see it in the editor. I also introduced a new ‘Found state’ text instead of ‘Found’ text in IDE settings to avoid confusion. To avoid confusion because if an editor was found and you clicked on it… it wrote this: Found Found Found Not Found Found Set by user Now it writes this: Found state Found Found state Not Found Found state Set by user Most of the time, I was reviewing the codebase via Claude Code to actually check everything precisely."}, {"post_id": 56815, "ts": "2026-08-28T18:55:16Z", "hours": 1.7133, "text": "Replaced hardcoded string colors with Color members for code safety, fixed line breaking while assigning a status/badge Okay so Markup texts (those are the texts with color) were formatted in this format: \"[red]Hello World![/]\" So it was string-based. And if you accidentally added some character to it for instance: \"[redd]Hello World![/]\" <- Exception Helyx would crash. I mainly added this, because it is an open-source project. So if someone tried to edit it, they would only have to edit the string and they might have misspelled it. But now, when he goes into the codebase, he will see Color members and he just can’t misspell that, and if he would, compiler would alert him. Basically, now it is like this: $\"[{Color.Red}]Hello World![/]\" Okay so next I fixed line breaking. What does that mean? Well… In Helyx native README editor, so when you try to assign a status/badge, you’ll get that editor, when you try to add a status/badge to that line, you might have thought that it would be on the same line as the tags above it. But it didn’t… This was happening due to the comment markers for Helyx so Helyx knows where this status/badge is located and which status/badge it is. Now Helyx will put those comment markers in a way that prevents the line from breaking."}, {"post_id": 56645, "ts": "2026-08-28T14:17:12Z", "hours": 2.1092, "text": "Added GitHub Issues/PRs events rendering Originally, when you selected Manage GitHub Issues or PRs and opened some issues/PR. You could have only seen messages posted by users, but not when a label was assigned or when the issue/PR was closed. Well… Now you can! Now it displays the exact action that happened and when it happened! Of course, it is also translated to all languages that Helyx supports. Just making sure you didn’t think it wasn’t! I also cleaned up the code a little bit. Removed some useless usings and some files were in the wrong namespace, so that is fixed too."}, {"post_id": 54407, "ts": "2026-08-25T12:34:33Z", "hours": 1.2639, "text": "Edited README.md, again I was again editing the whole README.md, because reviewers weren’t happy with the current one. Well after spending another hour of editing the whole README.md file, I hope they won’t ask me to rewrite the whole README.md file again, because I don’t even know what else to add/remove/edit."}, {"post_id": 53900, "ts": "2026-08-24T16:30:00Z", "hours": 2.0894, "text": "Edited README.md I rewrote the README.md because of the ship review. I also added a couple of recommendations that are worth knowing when you use Helyx. I also removed the <summary> comments that Claude Code wrote for the documentation, I don’t think that anyone would have used them anyway."}, {"post_id": 52656, "ts": "2026-08-22T22:04:08Z", "hours": 0.4681, "text": "README.md update I replaced the title in README.md with a banner that contains the text Helyx. I tried a few versions I made and, well, I landed on the one you can see in Helyx’s README.md, or below!"}, {"post_id": 52636, "ts": "2026-08-22T21:23:40Z", "hours": 1.4575, "text": "Experimenting with the conflict solver I was thinking about adding a simpler conflict solver, where you wouldn’t have to delete the <<<<<<< , ======= and >>>>>>> markers yourself but would just pick either the first or the second version. But I realized it would be messier than I thought, so in the end I kept it as a basic editor where you remove the version you don’t want by hand."}, {"post_id": 52516, "ts": "2026-08-22T17:40:41Z", "hours": 4.2228, "text": "GitHub done, shipping Helyx today! Today I was messing with the GitHub page for Helyx, fixing the last bugs we found and working on the installer. For the installer I used Inno Setup, because it is the most recognized and the most used one. The point of using an installer is simple: it adds Helyx to PATH. Of course there were other options, but this one seemed like the best fit. We were fighting with the script for a while, because it was doing really weird things, like staying in the background after the installation finished. But those bugs are fixed now! README.md is done, all of those GIFs and screenshots are in it too, and I have to say it looks really good! I was also setting up the GitHub side of things, so the description, the tags, a GitHub Action and so on. With the help of Claude Code, we created the logo and the banner for the installer as well. The installer uses the same logo as Helyx. It’s just a basic H, because nothing else came to mind haha. I also asked Claude Code to review the codebase one last time, and yep, it looks fine! I told it to add the basic documentation comments as well, the <summary> kind. Let’s be real here, nobody does this, and if they do, something else writes it for them, usually an AI, because it understands the function better than the person who wrote it (I know that from my own experience hahaha)."}, {"post_id": 51969, "ts": "2026-08-21T23:29:24Z", "hours": 9.8508, "text": "New features, new languages, new problems. A new feature that I added is GitHub Actions! It is on the same principle as Manage Issues and Manage PRs, so you have a list of GitHub Actions, you pick one and you can control it, check its log, observe information about it. You can even run an action! I also added a refresh keybind to Manage Issues, Manage PRs and GitHub Actions. Before, you had to go back from the details of an issue/PR/action to the list and then return to the details. Now you don’t have to. You just have to press the keybind displayed in the footer that belongs to refresh. Yes! The Helyx Language System is finally complete! Italian & Portuguese are now available in Helyx! Lately I’ve been working on the README.md file. I was mainly making more GIFs & designing screenshots for it so it will look pretty and futuristic (in my opinion)! As I have mentioned in the title, NEW… PROBLEMS! People… you won’t believe what happened to me today… I use Helyx’s Git & GitHub for testing, so there is no official one yet, and I rarely commit changes or push them. Only when I test something. And it looks like it got back at me. Well… I told Claude Code to remove comments all over my codebase, because they were mainly scrapped code and some temporary information that I had there, that wasn’t used anymore. Okay, so I told it to remove them, and for some reason instead of removing comments, it deleted Helyx’s whole codebase. Thank god README.md was untouched haha. We had to decompile the .dll that was left over from testing Helyx’s latest version, and actually check the diff and rewrite it. We still don’t know if everything was brought back since for some reason Claude Code’s memory got wiped instantly when it realized that it deleted my whole codebase. There were no backups, no restore, no nothing. The only possible thing was to use the forgotten stash that I created and use the .dll as a map to restore Helyx’s outdated codebase and rewrite it again. So that’s what we did. Yeah, so I hope everything was brought back. Claude says it was, but after what it has done I don’t know if I trust it. Just kidding, everything should be back, because it compared the .dll with the rewritten code 1:1 and everything matched."}, {"post_id": 51403, "ts": "2026-08-21T02:37:22Z", "hours": 10.1656, "text": "More bugs fixed, new functions, README & Language System updates! Hello guys, once again at 4 AM! Bugs: As the title says, there are more fixed bugs. Diagnostics crashed Helyx if you ran a rebase in a terminal and hit a conflict. Now it doesn’t! Another fixed bug is that when you opened an issue in Helyx, the footer vanished. At first I was shocked, but it was a simple fix so now your footer doesn’t vanish. Another vanishing bug! The Languages row from the header vanished when you entered a tab where Layout class was being used. Now you will see your sweet programming languages used in your selected project. Guess what! Another vanishing bug! This time the whole header vanished when you exited .Live()! Now it is okay! New behaviour: I unified some color codes with some type of info. E.g. SHA is Dark Orange everywhere, Stash is Yellow, Date is Cadet Blue and Issue Number is Aqua. The README.md editor, when inserting badges/status now has a new keybind: backspace! It is different from DEL! DEL deletes the badges/status but backspace deletes the whole line, including the badge/status that was on that line. README The README is almost done! At least I hope! Claude was a big help here, because I wanted to create an insane README and we really did. Guys, you should be excited about the README file haha! Language System Translations for these languages are already done: English French German Russian Slovak Spanish So basically every language translation is already done. BUT I decided to add even more languages! The new languages that Helyx will support are: Italian Portuguese"}, {"post_id": 50335, "ts": "2026-08-19T14:33:20Z", "hours": 8.0847, "text": "Languages almost done, moving onto GitHub & README.md Well guys, Language System is almost done. It is powered by a Resources file that stores all of the translated strings. More bugs were found! But now, all of the bugs should be fixed with also many failsafes! Now, I want to complete the Language System because I am really close to finishing it. I also want to make the README.md for Helyx’s GitHub Repository. Originally I wanted to make it via Obsidian app, but it doesn’t have direct support for Wakatime, so I have to use VS 2026 native Markdown editor with the support of Markdown Editor v2 extension from Mads Kristensen. (not sponsored lol) I also heard that Obsidian app doesn’t use the same Markdown as GitHub does so there would be some things mistyped or not even rendered, but VS 2026 should be fully compatible with GitHub’s Markdown renderer, so we will see!"}, {"post_id": 49506, "ts": "2026-08-18T11:50:08Z", "hours": 6.5236, "text": "Fixing more bugs I fix bugs mainly with use of Claude Code, because hunting for bugs is not easy and this project is not a small one haha. I had to run MANY code review tools for this, because every time it kept finding new bugs. No idea how but it did. So what we fixed? If a GitHub comment had bold text split across two lines, opening that issue crashed Helyx before it drew anything. A file with a square bracket in its name (e.g. data[1].json) crashed Status, Diff, Commit, Stashes and Log. If anything held config.json open for even a moment, Helyx assumed it was corrupt, reset it, then crashed everywhere that looked for a project. If config.json was missing its Badges section, the startup migration quietly deleted every badge from every project. Committing saved a copy of the project taken before the confirmation prompts, so anything changed in between was silently thrown away. If you linked a GitHub repo during Push, the remote was created with an empty name. Syncing a status that had since been deleted crashed in the middle of a push. A commit message containing a square bracket crashed “View Full Message” (those are just bugs that were missing Markup.Escape() function). Applying a stash said “applied successfully” even when it conflicted. One bad path stored in config.json crashed “Add Project”. This is just a snippet of the amount of fixed bugs. I won’t write all of them here since it would take a lot of text and I am pretty sure that this is enough for you to understand that we fixed a lot of bugs haha. Right now I am going to do the Language System. I am not sure if I mentioned in some devlog, the list of languages that Helyx will support. If not… there it is: English Slovak Spanish French German Russian"}, {"post_id": 48471, "ts": "2026-08-16T20:37:52Z", "hours": 9.3269, "text": "Adding new features & fixing bugs I finished making “Analyze Project” which analyzes your whole project and prints stuff such as: Number of files Number of folders Size of the project on disk Number of lines Also you can now see what amount of what programming language makes your project. It also shows you the biggest files in your project directory. And also you can see Git information such as: Branch Number of commits First commit (date) Last commit Working tree .git size So it displays some maybe important and basic information that you may check sometimes or might be interested in. There were like 6 revisions of this because I was testing different styles & designs. I also found a lot of hidden bugs with help of Claude! Before talking about bugs, I will tell you something about new features that I added. Now, when you assign a badge or change a status and you don’t have markers in README.md yet in it, then it will ask you if you want to add them manually or via Helyx. What does that mean? Well, it opens a “text editor” in Helyx which displays README.md and you can insert the badges/statuses where you want instead of opening the file in notepad and inserting the markers manually. Overall it is way quicker to do it now via Helyx. Helyx’s Generic Text Editor is now even better! You can now use all of the arrows, before you could just use Left/Right Arrow to move cursor left or right. Now you can move between lines. Now you can also open your project’s wiki via Helyx. Be aware that it doesn’t check anything, if you have wiki or not. It directly opens the website for the wiki where it should have been for the current linked GitHub Repository. Let’s talk about bugs now! Open an issue called the Markdown handler function and it was accidentally calling GitHub 101 times, when it needed some info. Now it doesn’t. 🆒 Notes have an encryption system, so if you put some sensitive info into it, it couldn’t be directly taken from the file. Only via Helyx. There was a bug, where when you enabled encryption and edit notes of 2 projects, then you turn off encryption globally and open the first project’s notes, it decrypts… but after that you open second project’s notes, it won’t. This was due to having a global bool instead of per project bool when saving if it was encrypted. Fixeddd! Another bug! Sync Status & Sync Badges was deleting staging index. Funny that I was thinking about to restore the staging index whenever using it, but at the end… the logic was wrong 😭 Now it isn’t. Then there was a bug that when you unassigned a badge, it unassigned ALL badges. Fixed! Another bug linked to badges… Unassigning a badge didn’t remove it from GitHub. Yeah… fixed!!"}, {"post_id": 47110, "ts": "2026-08-14T19:16:58Z", "hours": 10.0108, "text": "Manage PRs done! Added few new things… I finally finished making Manage PRs. So now you can: Delete Comment Merge Review Close PR Reopen PR I also had to fix some design flaws and function flaws but now it should be all good. Before doing all of this, there was a bunch of GET requests… now? Now it is also a bunch of PATCH & PUT requests. Also, now when you’ll try to link your GitHub Repository with the local one, you will just select the one that is on your GitHub account. Another thing! When you have conflicts between the local repository and the remote one (GitHub) and you try to sync them, a lot of the time Notepad pops us and tells you to remove the version of the text that you don’t want. Well now Helyx does it too and doesn’t open notepad, but lets you do it directly in TUI interface in my very own notepad. Conflict solver also uses alternate screen for this. (there’s sadly no showoff image for this, because currently I don’t have anything to create a conflict on) I am not sure what to do next in a next devlog, since everything I really wanted to do is already done… well… not everything but everything around the main things is. Maybe I’ll move on another refactoring? Or finishing the language settings? Well, we will see!"}, {"post_id": 46111, "ts": "2026-08-13T03:18:59Z", "hours": 9.2472, "text": "Manage PRs displaying and some logic done After pulling another all-nighter I finished making the Pull Request display functions. List and details about each Pull Request is done and paging also works too (took it from manage issues ;] ). Pull Requests also contain filters such as: Open Drafts Assigned Reviewed and we can’t forget their counterparts either: Closed Ready Unassigned No reviewers Pull Requests now have comment selection and Markdown formatting, but functions to manage Pull Requests are not done yet. The only ones I managed to finish are: Comment Open Browser The biggest problem with PRs is going to be, that their functions and methods for executing those functions are more complex than the ones for Issues. I plan to add these functions for PRs: Delete Comment Merge Review Close PR Reopen PR I am pretty sure that all of this will be done in next devlog, so stay updated! This is going to be very cool, I think. Well, now I am going to sleep so good night everyone!"}, {"post_id": 45830, "ts": "2026-08-12T15:39:18Z", "hours": 8.5531, "text": "Manage Issues, completed! PRs, incoming… Manage Issues is now fully completed. I still had a few issues with paging and rendering but now they are fixed. Now you can select a message and delete it & edit it. But also now you can create a comment, lock an issue, unlock an issue and create an issue. I also added a thing that I hope will be appreciated, Helyx renders Markdown from GitHub Issue comment and when you comment via Helyx, Helyx gives you Markdown options such as: Bold Text Italic Text Code Text List Quote Also, when you don’t provide a text to a comment in GitHub, Helyx will say that “No description was provided.” So the same thing as GitHub already does, but in Helyx you must provide text. Why? Because why would you create a comment with no text? So I banned adding a comment with no text. Okay, that would be everything! It was fun to create this because everything was working so well, except the paging system… that was painful to make even with Claude’s help. As I said in past devlogs, after Issues I am going to move to PRs. So yeah, let’s work on PR. I hope it won’t be harder to make, because a PR is a type of Issue in GitHub, so I hope I will use the same function logic and functions and callbacks to make it."}, {"post_id": 45232, "ts": "2026-08-11T15:56:35Z", "hours": 9.2425, "text": "Paging done, functions almost! I finished making the logic for rendering issues. In the last devlog it was just displaying all of the issues at the same time. No paging system so if there was a lot of issues or long issues, they would simply… not appear. It took me a really long time to work this out. I was mainly switching back and forth the rendering logic all the time and it went so far, that I had to use Claude to help me with it. At the end, I ended up with a rendering logic that I am not really keen on, but it is the best one that can be used in Helyx and TUI environment. Main obstacles were the Spectre.Console rendering functions and classes that were under IRenderable interface. And also the limitations of Panels, Grids… Layout had everything I needed . I wanted to cut the part which couldn’t be rendered and it should have looked like, like an unfinished Panel. Well, this was impossible. Without changing the core code of Spectre.Console or creating own system for making Panels it was impossible. Also, I haven’t seen it as something that WOULD NEED an own system that would render comments. So I just made it when a comment cuts, it creates whole Panel with part of the comment that can be rendered and at the bottom is text saying that it continues on the next page… and on the other page at the top there’s text that, hey, it continues here! Let’s finally talk about the Issue functions! I finished some simple one like: Close Reopen and create an issue… But I still have to create a system that can let you: Comment Edit comments Delete comments Lock issue Unlock issue Those are currently in WIP, but in the next devlog they’ll be most probably finished and after everything is done with issues, I will move to Pull Requests!"}, {"post_id": 44672, "ts": "2026-08-10T16:18:14Z", "hours": 9.8836, "text": "Manage Issues, at your service. After a painful development period I am again here, writing devlog! What changed? Good question! Manage Issues is partly done! I still have to finish making the actual actions but displaying is somewhat finished. When you go to ‘Manage Issues’, you will firstly see a list of issues that are on your GitHub repository. From there you can already see some details about the issues such as: Number State Title Labels Comments (number) Updated (time) Above them are filters, currently those are the available filters: All -> All Commented -> Issues has some comments Assigned -> Issues that have some assignees Labels -> Issues that have some labels But that is not all! There are also their counterparts: No comments Unassigned Unlabeled (there’s no inversion of All because why would you need filter None) Yeah, so you can invert your filters… When you select an issue at the very top you will see its number, then you will have a panel with details about the issue with its title and: State Author Opened (time) Labels Assignees Right under these details are all of the comments in chronological order. When it is done, it will also show the whole timeline of each issue. So when this and this label was added/removed… when was this assignee assigned/unassigned… when was this issue closed/opened…. Of course I am going to add actions so you can add a comment, close issue, open issue, etc… When I’ll finish Manage Issues, I will go to work on Manage Pull Requests. It shouldn’t be that different because Pull Requests are by GitHub a kind of Issue but they are also not the same, so different classes, types, etc… Well, wish me luck people… or should I say… Stardancers?? P.S.: Sorry for the grammar in images in comments. I did it very quick for the preview."}, {"post_id": 44020, "ts": "2026-08-09T14:52:22Z", "hours": 9.7869, "text": "Diagnostics done, other stuff too and some changes! Diagnostics are now fully done! When something messes up, it will give you options to fix it! Some time ago I created GitHub Synchronization settings for managing what to sync with GitHub, so what to retrieve and send with those options: Sync status with GitHub repository Sync badges with GitHub repository Fetch GitHub repository topics Fetch GitHub repository stats Use GitHub’s language detection instead of Helyx’s I created a brand new tab called ‘GitHub Actions’ where this setting is. GitHub Actions is meant to contain all of the actions that are mainly linked with GitHub endpoints. I kept few such as Push, Pull, Sync in Git Actions due to how the layout is already created. Also I added when you are rebasing and it fails, it automatically gives you a prompt to cancel it. So repair it… GitHub Actions will contain a new stuff that will come to Helyx! Managing Issues and Pull Requests!! Maybe also workspaces/actions but I will see how difficult that is and how it is needed/useful in Helyx. Another new function is, that when there’s an update for Helyx and I change the GitHub OAuth scope because of new features… Helyx will warn you and tell you to reauthorize to make sure every function will work correctly. Before this change, Helyx was using its folder name as a name of the project and as a repository name for GitHub. Now, when you add a project to Helyx, Helyx will ask you what’s its name and when you will try to use some GitHub function for the first time on your newly added project on Helyx, it will request a GitHub Repository name from you. ;) There’s still a lot of things to add. Honestly I thought that Helyx was at the very end like 50 hours ago and look! There are many more functions to add haha!"}, {"post_id": 43404, "ts": "2026-08-08T17:00:23Z", "hours": 8.0208, "text": "Doctor Git As you may know, right now I am working on Diagnostics. I am almost done with fully displaying all of the health checks about your Git repository. But I still have to finish all of the fixing actions that it will have. Diagnostics will mainly be for a case where something happens in Helyx and it will need to be fixed. The main idea of it is not aimed at resolving issues with your Git repository outside Helyx. But it may resolve some because you may run into the same issue as you had in Helyx of course. In the last devlog I said that I put GitHub Topics off. Well, that did not happen! I finished displaying GitHub Topics!! I think in some devlogs I said that it was for managing GitHub Topics. Managing meant like adding, removing, editing. Well, that wasn’t actually my main point. I just wanted it to show you your currently assigned topics in GitHub. I also didn’t see a big reason in adding Add, Remove, Edit functions for topics. Topics rarely changed, honestly and the most intuitive way would be doing it via GitHub web interface."}, {"post_id": 42869, "ts": "2026-08-07T20:34:12Z", "hours": 3.6694, "text": "More bugs are appearing, and being fixed!! So since Helyx is already far and has many advanced functions, it also has some bugs. Today when I was experimenting with assigning a project and syncing it with GitHub, I found out, that if you try to sync the projects in a wrong way… it will not work. For that reason I added more fail-safes to make sure that this will be eliminated. I can’t confirm yet if those fail-safes work, because I am also working on a new Diagnostics action in Git Actions so if something goes wrong, you can fix it by the error Helyx gives you. Right now my testing project is in a state of “Git corrupted” (no idea what I should call it) where rebase was aborted. Because of this, I had to put the “GitHub Sync Topics” synchronization off until later, so I can focus on fixing these major bugs. Also another bug came to my mind that I fixed… Helyx works on a principle of directory paths. Each project is saved in config file under its own unique GUID and its path. The bug is that when you try to rename the directory, the project won’t be found and it will be removed from Helyx. Now, you can either let Helyx find it automatically (sadly can easily fail) or you can select project manually in explorer (recommended!!!)."}, {"post_id": 42404, "ts": "2026-08-07T02:57:49Z", "hours": 4.2367, "text": "Sync finally done!! It’s 5 AM and I finished “Sync badges with GitHub Repository” and “Sync the status with GitHub repository” (this was already done, but with the enum version of status). I added also a few fail-safes so when you assign some badge or status and then delete it, it will also delete it from GitHub and project. Now it won’t be a ghost that you cannot get rid of haha. This was a little more difficult than I expected to do, the fail-safes because the local changing mechanism and syncing mechanism were written inline in the same function. The only thing that was dividing them was an if statement. It was interesting to make this. To make sure everything will work fine. Even though it didn’t MANY TIMES. Now I will focus on syncing GitHub topics. Wish me luck! P.S.: Forgot to mention, that I have to add this “On Status/Badge Edit, ASAP sync with GitHub” with Edit. I almost forgot lol, just came into my mind. I hope that COPY+PASTE will be enough and I won’t have to create another syncing system specifically for edits…"}, {"post_id": 42259, "ts": "2026-08-06T21:43:48Z", "hours": 8.6897, "text": "Never expected it to be this hard So the last days I was again changing the structure of my solution and trying to get on with it. It took me a while to create one that Claude agrees with and is good for such open-source projects. Anyways, this was the easy part. In my last devlog I said that I completed Custom Statuses & Custom Badges. Well… I did! But then I found out, that my system was bad… and when I say bad I mean it wasn’t thought out. I found out about all of this when I finished the edit action for both. Originally I used Dictionary<string, TagDefinition>. Key was name of the Status/Badge and TagDefinition was the class of one of them which also has name property. But Helyx was not prepared for this, so for the last days I redid the whole system eight times. Once I used Dictionary, once I used List, then HashSet, then Dictionary, then Dictionary with other types and so on. I just couldn’t settle on the correct type for it. Until now, it took so long even though it is so primitive because it simply didn’t come to my mind and when I was asking Claude for suggestions of how could it be made, it didn’t think of using this type. The final type is simply… Dictionary<Guid, TagDefinition> AND A LOT OF CHANGES. Yeah… don’t worry guys! I am totally devastated by doing this over and over even though it was so simple & primitive to do. Well… maybe not really primitive because the changes were also difficult to do. I mainly didn’t want to use the GUID system because I have Custom Statuses but also Built-in Statuses and I was really worried about Built-in statuses having GUID assigned to them. Those sync options with GitHub are still in work, but I finished the GitHub Repository Stats viewer after a lot of experimenting with layouts and designs/effects/colors. I’m looking forward to the next devlog guys! I hope Helyx will be your good coworker that will actually count for something hah! P.S.: I also made that text of colors is grammatically formatted. At least it should be…"}, {"post_id": 40755, "ts": "2026-08-04T14:24:15Z", "hours": 6.5064, "text": "Adding Custom Statuses, Custom Badges and even more! Here we are again! Today I added: Custom Statuses Custom Badges WIP: Sync badges with GitHub repository Sync topics with GitHub repository My original status system for projects was a hardcoded enum with statuses “Active”, “Inactive”, “Paused” and “Archived”. Then I had a lot of switches which determined color of markup based on which enum it is hah. As you may already know, enums cannot be changed in runtime :) What does that mean? That users cannot add their own statuses in Helyx directly… They would have to hardcode into Helyx their own statuses and that’s just impractical, no? That’s why I spent below mentioned amount of hours redoing so many things to make it actually work and I even learned something from this! That JSON Parsers and Colors are NOT huge friends! (genuinely, I HAD NO IDEA why it wasn’t working until AI told me that JSON parsers cannot translate Color structs). Custom Statuses/Badges currently have Add/Delete functions and right now I am going to add also Edit function, so when you accidentally create a status/badge with wrong color, you don’t have to delete it and create it again :) (just saved 10seconds of your life). I also recategorized my whole codebase with help of Claude Code. I told him to review my whole codebase and suggest what classes, enums, interfaces should be in which files and those files in which folders. It was fun, finally something where I did not have to concentrate much and chill and watch something when doing it. Well, now it is not much fun when functions that I was using are in different files and some classes have different names. But at least my codebase looks more professional! (before this I had like 10 files with a bunch of lines where classes were stacked…) Also, about the WIP stuff above… Sync badges with GitHub repository is going to be something like the Sync status with GitHub repository. It will just pop up in your README.md based on where you put the headers which Helyx will give you for that specific badge. Sync topics on the other hand are classic topics of the repository which you can see in top right corner of your repository page. It will mostly show you which topics are assigned to your repository in Helyx but I’ll make it also so you can assign/unassign topics from your repository. I’m thinking of adding more GitHub Synchronization options, but none are currently coming to my mind. Maybe something with actions, no idea yet, or local AI that will explain to you errors given by Helyx when you will be trying to do something. We will see!"}, {"post_id": 40227, "ts": "2026-08-03T17:05:06Z", "hours": 5.3314, "text": "Settings and Git pages are receiving more stuff! I added for Settings page: Notes Settings Updates and for Git page: Undo Commit Redo Commit as the name says, Notes Settings are for changing properties of global Notes on every project. There is only one setting that came to my mind and that is encryption. Some of you might paste into it something personal or confidential. Well, this makes sure that these info CANNOT be taken from raw file, but from Helyx directly. (thinking about adding password mechanism lol) Updates, yeah, it looks for updates for Helyx . Undo Commit is a special one, when you commit something and for some reason you want to go back you just undo it. On the other hand, if you somehow accidentaly clicked on Undo Commit or now you want to redo the undo, you can with Redo Commit. My plan now is to add again more functions, such as Custom Badges, option to sync the Custom Badges with your GitHub repo (it will pop up in README.md) and also add Tags sync, so you can edit your repository’s Tags via Helyx. Oh yeah, also going to add custom project status because some people may say that having statuses such as “Active”, “Inactive”, “Paused”, “Archived” is limiting (custom ones will yes, also be synced with GitHub). :) I also mustn’t forget to add the translations for other languages. I am going to do this at the end due to new text appearing every time I add something new."}, {"post_id": 39660, "ts": "2026-08-02T19:45:40Z", "hours": 6.2036, "text": "Slowly, but surely We are almost at the end (if no other function to add will come to my mind) and I was messing with access modifiers, accessors, refactoring names of variables, Tasks, voids, properties. I was adding exception handling keywords and many ifs to make sure there will be no bugs and that almost every exception will be caught. I was doing this manually so I might have missed some places where the exception handler is needed but yeah we shall see! I also enabled a search bar, so when you will be looking for your project in Helyx and you have many projects added, you can search for yours! I was also changing styles of my old menus and theirs logic because they weren’t done very well in comparison with style that I am using now… Funny story: while I was messing with the access modifiers and accessors I actually bricked the whole Helyx, because functions that were supposed to resolve configuration file and read/write into it couldn’t. I thought I accidentally removed something important but at the end it was just that, that I was changing the access modifiers and accessors."}, {"post_id": 39059, "ts": "2026-08-01T18:54:21Z", "hours": 9.4842, "text": "Added new setting, finished overwrite languages and still working on show stats I have finished the overwrite languages function which uses GitHub’s programming languages detection system over Helyx’s one. I added a setting where you can choose your identity (Git -> local, GitHub -> remote). Local is based on Git’s settings and remote one is accessible after authorization with GitHub. I am currently working on retrieving and displaying the GitHub repository statistics. I am using charts to display it nicely and simply. Currently it is showing only Stars, Watchers, Forks and chart of used languages. I also added a few informative labels that tell you that something is actually happening and the program did not freeze. If I didn’t add this you would be looking at an empty black screen. One of the last things I added is active GitHub Authorization Token checker and resolver. Before this if you revoked your OAuth with Helyx on GitHub page, Helyx would think that it is still authorized to your GitHub account, now it checks it and if you revoke it online, Helyx will disable functions that are only accessible when you are authorized via GitHub."}, {"post_id": 37815, "ts": "2026-07-30T19:23:03Z", "hours": 4.9556, "text": "User Scripts done? What next?? As written above, I have finished User Scripts. Yeah, they don’t have that many functions as before, but I am going to add some, that will actually be useful and will stay in Helyx. Right after that I’d want to move to add more things to GitHub Synchronization settings that are per project. This is mainly to make the Helyx project dashboard look better with more interesting info about your current repository. Be aware that you have to be authorized in Helyx via GitHub to access those settings. This may sound funny, but I was thinking about adding Add-on manager to Helyx. No idea how I would make it yet or what packages would even Helyx have, but I hope that after some brainstorming I will have an answer. Before that, I will again think for a while if it is a good idea and if it is even needed. But surely it sounds cool to me, to someone who has never made an add-on manager for his program. At the end I want to transfer my view to hardening the code. Many checkings, many dialog boxes what’s wrong, and such things, so your Helyx window just doesn’t close after you mess up with configuration file or you do something that no one would ever do in his lifetime. ;)"}, {"post_id": 37545, "ts": "2026-07-30T10:56:21Z", "hours": 10.0053, "text": "Changing my mind over User Scripts So I have finished all of these User Scripts functions and I found out something interesting, that made me remove some of them after I finished them. In the devlog before, I wrote a list of actions that are in Helyx such as… Wait Until, If, Loop, Set/Get Variable, etc… . Well, I found out that making some that I have mentioned would be useless, because I imagined User Scripts mainly as an automatic actions for testing your project, but how could your program get script’s variable from Helyx or set/change it. The same applies for If, If would be also complex to set. With each If Action there would be x^2 (if my calculations are correct) more node pathways and without making some really good UX in TUI environment, it would be difficult to find your way around."}, {"post_id": 36457, "ts": "2026-07-28T16:14:12Z", "hours": 9.1958, "text": "Making User Scripts I am currently working on the User Scripts as I have mentioned in older devlogs. I must say that this is one of my first interactions with interfaces in C# because there was not a huge reason to use it in my code… until now. I must say that User Scripts is the most difficult thing in all Helyx to make because you have to think on everything… how this will work, how shall we display it, how to make it versatile so other actions work with it too, etc… I made the system for adding Blocks (Actions = Blocks) to Scripts and right now I am implementing dialogs to insert properties for each action, such as Duration for Wait Action. These are current actions that are in Helyx (you can suggest new ones in comments) : Wait Wait Until If Loop (should be something like while(), might change the idea of it) End (ends script, so like return/break) Set Variable Get Variable Compare Random Log (logs text) Execute (executes command) Open (opens directory) Create File Create Folder Delete File Delete Folder Right after that I would want to move to make the UI look overall better and function better. Welp, we will see in my next devlog the progress I will make."}, {"post_id": 35822, "ts": "2026-07-27T14:40:58Z", "hours": 5.6561, "text": "Backup system, done!! I finished the Backup system and also had to fix some major issues I had in helper functions due to the “project looking up system” migration… yeah… awkward name, I know. Now that the Backup system is done, let me continue and begin to work on User Scripts. Just realized that I have to come up with how it will work…"}, {"post_id": 34093, "ts": "2026-07-24T15:52:43Z", "hours": 8.3447, "text": "Losing sanity is not fun I honestly think I’ll go insane soon. I have changed the whole system of how Helyx saves Projects to its config file and how every function… EVERY FUNCTION works with it. I just have to say that I’ll try my best to make the code better than the one I am currently editing because 18h spent on redoing the whole codebase (revamping included from devlog before) is 1. crazy and 2. even more crazy. It’s wild how a tiny thing can ruin your whole codebase, I hope I will finish it quickly, because I want to continue working on the Backup system and after that on the User Scripts."}, {"post_id": 31940, "ts": "2026-07-20T19:06:16Z", "hours": 9.93, "text": "Cleanup time! I have completely revamped my code… I removed a lot of unused code that was either used for experimenting or was scrapped and I forgot to remove it. Before removing some of the code, I actually tried something with it… but then I realized that they were commented for some reason. I refactored parts of my code to look overall simpler with lambda expressions and LINQ. Not sure if it is more readable now, but it works so it’s fine. If anything, I’ll just add a comment so I know what it does instead of looking at it and brainstorming what it could be. I decided to mainly work on the Backup system because I think that User Scripts will be more complicated to make."}, {"post_id": 31333, "ts": "2026-07-19T17:11:07Z", "hours": 6.3575, "text": "Local & Remote Repository status I just finished making the status manager, so now you can change your status locally… but also remotely! Remotely means on GitHub, not like via some controller. Because of this, I created a tab called GitHub Synchronization, where you can enable/disable settings that are linked with GitHub and retrieve/push from/to GitHub. Now, I am planning to work on Backup system and User Scripts."}, {"post_id": 29735, "ts": "2026-07-16T20:33:20Z", "hours": 9.7861, "text": "Git Actions family is getting EVEN bigger! I have finally finished a lot of major stuff and also tried to make some additional things that MAY be added in the future. I finally added Stashes, Pull, Push and Sync to the Git Actions, so now they work! Also, all of Git functions have some automatic repair, so if you do something you shouldn’t, it should be alright… but it is not 100% so don’t try your luck! I still have to finish and a bunch of stuff with it so you can do whatever you want with it without editing the code itself! I was thinking of adding some label for your GitHub repository which you can control via Helyx. Like status… yeah… let’s add a badge that will act as a status info of your project!"}, {"post_id": 26717, "ts": "2026-07-11T17:47:55Z", "hours": 12.8578, "text": "Git Actions family is getting bigger! We’ve made a lot of progress! More of the Git Actions are done such as… Status Stage Commit Diff Create Branch Switch Branch Delete Branch Right now I am working on another: Pull Push Sync Stashes I hope they will be done soon! Stay updated!"}, {"post_id": 21798, "ts": "2026-07-03T22:31:34Z", "hours": 45.9456, "text": "Huge updates!! Since it is my first time working with Spectre.Console library, I was trying a lot of stuff with it. When I was somewhat happy with what I learned, I cleaned up the code due to the amount of useless lines and duplicated/not used variables . 1, Updated UI/UX I have updated the UI/UX so it looks more modern-ish. This new UI/UX design is for now only on the main pages of Helyx… but I plan to add it to every page very soon! 2, More actions! (even more will be available in the future) I have added more Git Actions that are still in WIP. I also created templates in code of what actions I’d want to add later. I’ll tell you more about them when they will be finished (SOON). 3, More stuff in Settings! I have added more settings into Settings :D Now you can select Default IDE, see if your IDE was found in your system, if not you can manually select the .exe of it. You can also manage the configuration file, well, reset it. 4, Projects sorting Projects are now sorted based on its status. 5, You can manage the projects for Helyx You can now delete the projects and change the status. 6, Future bugs & lots of if statements My code was completely unsafe up to this point, so I had to add many of try/catch and if statements to make it safe. I was experimenting with Spectre.Console, because I have never worked with it. I made some cool stuff that I will add in the future to Helyx! I understand it now better! All of this was quite difficult for me to do, since as I said, on such project where I am using C# with its basic types… I was mostly a Unity C# Developer, where Unity had its own classes and functions and callers that were standard."}, {"post_id": 10796, "ts": "2026-06-17T18:25:25Z", "hours": 14.0269, "text": "Helyx, the IDE detective I’ve been working on the IDE detection system. This took me a long time because I was testing many different ways of how to detect it and then sort them from most probable to least. At the end I have selected the one that uses points based on what the Project includes in its path… so files, extensions and directories. I was experimenting with the Language system that I will make in the future. I just want to be sure what I am doing so later, I won’t be in panic what now and what was my original plan. I have also refactored the code to some point but it is still not great after all of these things I have done above … so still need to do this. I redesigned the menus and made it more universal and made the menu easier to navigate in. I think my progress is going kinda good so far and it looks promising for me. I also added some basic Git function like “git status” but I am about to add more. I’d appreciate if you would write into comments some functions that I should add to Helyx. Not sure if I already mentioned this but I am also planning to add a feature so you can create your own shortcuts for your projects like… some testing shortcut. For instance, you have some project you want to test and you need to build it, then tweak some settings and at the end you actually test. With this, you can do all of this just by one click… Well, that’s at least my imagination and I am not sure if it will get to such point where you can do such tasks but we’ll see Wish me luck!"}, {"post_id": 9561, "ts": "2026-06-15T22:44:15Z", "hours": 4.0336, "text": "Project handler, done for now I was thinking of adding a translation system for Helyx. I was experimenting with a lot of systems how to do it… well, I might keep this for the end of Helyx so at the end I translate all of the strings. I added the “Add Project” system and some basic detection systems for it such as… Project Name Path Languages (used programming language in project) Used IDE for the project then it will ask you if you really, but REALLY want to add the project and if you proceed it will be added to your Projects menu. After that you can open your Project and see such basic info as… Status Last modified Languages Used IDE Is a GIT Repo I am thinking about adding more, removing some and making it overall more versatile because versatile applications are just the best ones. For now, I created some basic functions for your Projects such as… Open in VS Code Git Status Remove Project (from Helyx) but these are the ones already working, but I am still trying to make them more versatile :p … but there’s more functions that I am currently working on, that I hope won’t be scrapped and I will mention them in next devlog!"}, {"post_id": 9329, "ts": "2026-06-15T17:24:04Z", "hours": 7.76, "text": "Lots of new ideas, lots of scrapped ideas Lately I’ve been working on a way to search for projects automatically but I had to scrap the idea because I didn’t like it at the end… so now I am making it so you can add your own projects and some IDE integrations. I was also trying multiple libraries for TUI interface integration and GUI support with other libraries and input devices. These hours were full of scrapping & making new ideas, but that’s what programming is about!"}, {"post_id": 8639, "ts": "2026-06-14T11:15:51Z", "hours": 1.3039, "text": "The beginning… So I have finally begun to work on this! I was thinking a lot what to create for Stardance and it looks like this might be something I want to create! Originally I wanted to create this in Python but then I really quickly found out that my Python skills wouldn’t be enough to create something like this and I didn’t want this to be a vibe-coding project… SO HERE WE ARE… using C#! So far so good, I guess… Currently I am working on the configuration handler which will have functions for implementing and retrieving info from the configuration file. After that, I am planning to make the interface somewhat versatile, so it is possible to adjust it for yourself or add some new options and such."}]...
|
Title: Helyx by @lix | Stardance
Devlogs:
The beg Title: Helyx by @lix | Stardance
Devlogs:
The beginning… So I have finally begun to work on this! I was thinking a lot what to create for Stardance and it looks like this might be something I want to create! Originally I wanted to create this in Python but then I really quickly found out that my Python skills wouldn’t be enough to create something like this and I didn’t want this to be a vibe-coding project… SO HERE WE ARE… using C#! So far so good, I guess… Currently I am working on the configuration handler which will have functions for implementing and retrieving info from the configuration file. After that, I am planning to make the interface somewhat versatile, so it is possible to adjust it for yourself or add some new options and such.
Lots of new ideas, lots of scrapped ideas Lately I’ve been working on a way to search for projects automatically but I had to scrap the idea because I didn’t like it at the end… so now I am making it so you can add your own projects and some IDE integrations. I was also trying multiple libraries for TUI interface integration and GUI support with other libraries and input devices. These hours were full of scrapping & making new ideas, but that’s what programming is about!
Project handler, done for now I was thinking of adding a translation system for Helyx. I was experimenting with a lot of systems how to do it… well, I might keep this for the end of Helyx so at the end I translate all of the strings. I added the “Add Project” system and some basic detection systems for it such as… Project Name Path Languages (used programming language in project) Used IDE for the project then it will ask you if you really, but REALLY want to add the project and if you proceed it will be added to your Projects menu. After that you can open your Project and see such basic info as… Status Last modified Languages Used IDE Is a GIT Repo I am thinking about adding more, removing some and making it overall more versatile because versatile applications are just the best ones. For now, I created some basic functions for your Projects such as… Open in VS Code Git Status Remove Project (from Helyx) but these are the ones already working, but I am still trying to make them more versatile :p … but there’s more functions that I am currently working on, that I hope won’t be scrapped and I will mention them in next devlog!
Helyx, the IDE detective I’ve been working on the IDE detection system. This took me a long time because I was testing many different ways of how to detect it and then sort them from most probable to least. At the end I have selected the one that uses points based on what the Project includes in its path… so files, extensions and directories. I was experimenting with the Language system that I will make in the future. I just want to be sure what I am doing so later, I won’t be in panic what now and what was my original plan. I have also refactored the code to some point but it is still not great after all of these things I have done above … so still need to do this. I redesigned the menus and made it more universal and made the menu easier to navigate in. I think my progress is going kinda good so far and it looks promising for me. I also added some basic Git function like “git status” but I am about to add more. I’d appreciate if you would write into comments some functions that I should add to Helyx. Not sure if I already mentioned this but I am also planning to add a feature so you can create your own shortcuts for your projects like… some testing shortcut. For instance, you have some project you want to test and you need to build it, then tweak some settings and at the end you actually test. With this, you can do all of this just by one click… Well, that’s at least my imagination and I am not sure if it will get to such point where you can do such tasks but we’ll see Wish me luck!
Huge updates!! Since it is my first time working with Spectre.Console library, I was trying a lot of stuff with it. When I was somewhat happy with what I learned, I cleaned up the code due to the amount of useless lines and duplicated/not used variables . 1, Updated UI/UX I have updated the UI/UX so it looks more modern-ish. This new UI/UX design is for now only on the main pages of Helyx… but I plan to add it to every page very soon! 2, More actions! (even more will be available in the future) I have added more Git Actions that are still in WIP. I also created templates in code of what actions I’d want to add later. I’ll tell you more about them when they will be finished (SOON). 3, More stuff in Settings! I have added more settings into Settings :D Now you can select Default IDE, see if your IDE was found in your system, if not you can manually select the .exe of it. You can also manage the configuration file, well, reset it. 4, Projects sorting Projects are now sorted based on its status. 5, You can manage the projects for Helyx You can now delete the projects and change the status. 6, Future bugs & lots of if statements My code was completely unsafe up to this point, so I had to add many of try/catch and if statements to make it safe. I was experimenting with Spectre.Console, because I have never worked with it. I made some cool stuff that I will add in the future to Helyx! I understand it now better! All of this was quite difficult for me to do, since as I said, on such project where I am using C# with its basic types… I was mostly a Unity C# Developer, where Unity had its own classes and functions and callers that were standard.
Git Actions family is getting bigger! We’ve made a lot of progress! More of the Git Actions are done such as… Status Stage Commit Diff Create Branch Switch Branch Delete Branch Right now I am working on another: Pull Push Sync Stashes I hope they will be done soon! Stay updated!
Git Actions family is getting EVEN bigger! I have finally finished a lot of major stuff and also tried to make some additional things that MAY be added in the future. I finally added Stashes, Pull, Push and Sync to the Git Actions, so now they work! Also, all of Git functions have some automatic repair, so if you do something you shouldn’t, it should be alright… but it is not 100% so don’t try your luck! I still have to finish and a bunch of stuff with it so you can do whatever you want with it without editing the code itself! I was thinking of adding some label for your GitHub repository which you can control via Helyx. Like status… yeah… let’s add a badge that will act as a status info of your project!
Local & Remote Repository status I just finished making the status manager, so now you can change your status locally… but also remotely! Remotely means on GitHub, not like via some controller. Because of this, I created a tab called GitHub Synchronization, where you can enable/disable settings that are linked with GitHub and retrieve/push from/to GitHub. Now, I am planning to work on Backup system and User Scripts.
Cleanup time! I have completely revamped my code… I removed a lot of unused code that was either used for experimenting or was scrapped and I forgot to remove it. Before removing some of the code, I actually tried something with it… but then I realized that they were commented for some reason. I refactored parts of my code to look overall simpler with lambda expressions and LINQ. Not sure if it is more readable now, but it works so it’s fine. If anything, I’ll just add a comment so I know what it does instead of looking at it and brainstorming what it could be. I decided to mainly work on the Backup system because I think that User Scripts will be more complicated to make.
Losing sanity is not fun I honestly think I’ll go insane soon. I have changed the whole system of how Helyx saves Projects to its config file and how every function… EVERY FUNCTION works with it. I just have to say that I’ll try my best to make the code better than the one I am currently editing because 18h spent on redoing the whole codebase (revamping included from devlog before) is 1. crazy and 2. even more crazy. It’s wild how a tiny thing can ruin your whole codebase, I hope I will finish it quickly, because I want to continue working on the Backup system and after that on the User Scripts.
Backup system, done!! I finished the Backup system and also had to fix some major issues I had in helper functions due to the “project looking up system” migration… yeah… awkward name, I know. Now that the Backup system is done, let me continue and begin to work on User Scripts. Just realized that I have to come up with how it will work…
Making User Scripts I am currently working on the User Scripts as I have mentioned in older devlogs. I must say that this is one of my first interactions with interfaces in C# because there was not a huge reason to use it in my code… until now. I must say that User Scripts is the most difficult thing in all Helyx to make because you have to think on everything… how this will work, how shall we display it, how to make it versatile so other actions work with it too, etc… I made the system for adding Blocks (Actions = Blocks) to Scripts and right now I am implementing dialogs to insert properties for each action, such as Duration for Wait Action. These are current actions that are in Helyx (you can suggest new ones in comments) : Wait Wait Until If Loop (should be something like while(), might change the idea of it) End (ends script, so like return/break) Set Variable Get Variable Compare Random Log (logs text) Execute (executes command) Open (opens directory) Create File Create Folder Delete File Delete Folder Right after that I would want to move to make the UI look overall better and function better. Welp, we will see in my next devlog the progress I will make.
Changing my mind over User Scripts So I have finished all of these User Scripts functions and I found out something interesting, that made me remove some of them after I finished them. In the devlog before, I wrote a list of actions that are in Helyx such as… Wait Until, If, Loop, Set/Get Variable, etc… . Well, I found out that making some that I have mentioned would be useless, because I imagined User Scripts mainly as an automatic actions for testing your project, but how could your program get script’s variable from Helyx or set/change it. The same applies for If, If would be also complex to set. With each If Action there would be x^2 (if my calculations are correct) more node pathways and without making some really good UX in TUI environment, it would be difficult to find your way around.
User Scripts done? What next?? As written above, I have finished User Scripts. Yeah, they don’t have that many functions as before, but I am going to add some, that will actually be useful and will stay in Helyx. Right after that I’d want to move to add more things to GitHub Synchronization settings that are per project. This is mainly to make the Helyx project dashboard look better with more interesting info about your current repository. Be aware that you have to be authorized in Helyx via GitHub to access those settings. This may sound funny, but I was thinking about adding Add-on manager to Helyx. No idea how I would make it yet or what packages would even Helyx have, but I hope that after some brainstorming I will have an answer. Before that, I will again think for a while if it is a good idea and if it is even needed. But surely it sounds cool to me, to someone who has never made an add-on manager for his program. At the end I want to transfer my view to hardening the code. Many checkings, many dialog boxes what’s wrong, and such things, so your Helyx window just doesn’t close after you mess up with configuration file or you do something that no one would ever do in his lifetime. ;)
Added new setting, finished overwrite languages and still working on show stats I have finished the overwrite languages function which uses GitHub’s programming languages detection system over Helyx’s one. I added a setting where you can choose your identity (Git -> local, GitHub -> remote). Local is based on Git’s settings and remote one is accessible after authorization with GitHub. I am currently working on retrieving and displaying the GitHub repository statistics. I am using charts to display it nicely and simply. Currently it is showing only Stars, Watchers, Forks and chart of used languages. I also added a few informative labels that tell you that something is actually happening and the program did not freeze. If I didn’t add this you would be looking at an empty black screen. One of the last things I added is active GitHub Authorization Token checker and resolver. Before this if you revoked your OAuth with Helyx on GitHub page, Helyx would think that it is still authorized to your GitHub account, now it checks it and if you revoke it online, Helyx will disable functions that are only accessible when you are authorized via GitHub.
Slowly, but surely We are almost at the end (if no other function to add will come to my mind) and I was messing with access modifiers, accessors, refactoring names of variables, Tasks, voids, properties. I was adding exception handling keywords and many ifs to make sure there will be no bugs and that almost every exception will be caught. I was doing this manually so I might have missed some places where the exception handler is needed but yeah we shall see! I also enabled a search bar, so when you will be looking for your project in Helyx and you have many projects added, you can search for yours! I was also changing styles of my old menus and theirs logic because they weren’t done very well in comparison with style that I am using now… Funny story: while I was messing with the access modifiers and accessors I actually bricked the whole Helyx, because functions that were supposed to resolve configuration file and read/write into it couldn’t. I thought I accidentally removed something important but at the end it was just that, that I was changing the access modifiers and accessors.
Settings and Git pages are receiving more stuff! I added for Settings page: Notes Settings Updates and for Git page: Undo Commit Redo Commit as the name says, Notes Settings are for changing properties of global Notes on every project. There is only one setting that came to my mind and that is encryption. Some of you might paste into it something personal or confidential. Well, this makes sure that these info CANNOT be taken from raw file, but from Helyx directly. (thinking about adding password mechanism lol) Updates, yeah, it looks for updates for Helyx . Undo Commit is a special one, when you commit something and for some reason you want to go back you just undo it. On the other hand, if you somehow accidentaly clicked on Undo Commit or now you want to redo the undo, you can with Redo Commit. My plan now is to add again more functions, such as Custom Badges, option to sync the Custom Badges with your GitHub repo (it will pop up in README.md) and also add Tags sync, so you can edit your repository’s Tags via Helyx. Oh yeah, also going to add custom project status because some people may say that having statuses such as “Active”, “Inactive”, “Paused”, “Archived” is limiting (custom ones will yes, also be synced with GitHub). :) I also mustn’t forget to add the translations for other languages. I am going to do this at the end due to new text appearing every time I add something new.
Adding Custom Statuses, Custom Badges and even more! Here we are again! Today I added: Custom Statuses Custom Badges WIP: Sync badges with GitHub repository Sync topics with GitHub repository My original status system for projects was a hardcoded enum with statuses “Active”, “Inactive”, “Paused” and “Archived”. Then I had a lot of switches which determined color of markup based on which enum it is hah. As you may already know, enums cannot be changed in runtime :) What does that mean? That users cannot add their own statuses in Helyx directly… They would have to hardcode into Helyx their own statuses and that’s just impractical, no? That’s why I spent below mentioned amount of hours redoing so many things to make it actually work and I even learned something from this! That JSON Parsers and Colors are NOT huge friends! (genuinely, I HAD NO IDEA why it wasn’t working until AI told me that JSON parsers cannot translate Color structs). Custom Statuses/Badges currently have Add/Delete functions and right now I am going to add also Edit function, so when you accidentally create a status/badge with wrong color, you don’t have to delete it and create it again :) (just saved 10seconds of your life). I also recategorized my whole codebase with help of Claude Code. I told him to review my whole codebase and suggest what classes, enums, interfaces should be in which files and those files in which folders. It was fun, finally something where I did not have to concentrate much and chill and watch something when doing it. Well, now it is not much fun when functions that I was using are in different files and some classes have different names. But at least my codebase looks more professional! (before this I had like 10 files with a bunch of lines where classes were stacked…) Also, about the WIP stuff above… Sync badges with GitHub repository is going to be something like the Sync status with GitHub repository. It will just pop up in your README.md based on where you put the headers which Helyx will give you for that specific badge. Sync topics on the other hand are classic topics of the repository which you can see in top right corner of your repository page. It will mostly show you which topics are assigned to your repository in Helyx but I’ll make it also so you can assign/unassign topics from your repository. I’m thinking of adding more GitHub Synchronization options, but none are currently coming to my mind. Maybe something with actions, no idea yet, or local AI that will explain to you errors given by Helyx when you will be trying to do something. We will see!
Never expected it to be this hard So the last days I was again changing the structure of my solution and trying to get on with it. It took me a while to create one that Claude agrees with and is good for such open-source projects. Anyways, this was the easy part. In my last devlog I said that I completed Custom Statuses & Custom Badges. Well… I did! But then I found out, that my system was bad… and when I say bad I mean it wasn’t thought out. I found out about all of this when I finished the edit action for both. Originally I used Dictionary<string, TagDefinition>. Key was name of the Status/Badge and TagDefinition was the class of one of them which also has name property. But Helyx was not prepared for this, so for the last days I redid the whole system eight times. Once I used Dictionary, once I used List, then HashSet, then Dictionary, then Dictionary with other types and so on. I just couldn’t settle on the correct type for it. Until now, it took so long even though it is so primitive because it simply didn’t come to my mind and when I was asking Claude for suggestions of how could it be made, it didn’t think of using this type. The final type is simply… Dictionary<Guid, TagDefinition> AND A LOT OF CHANGES. Yeah… don’t worry guys! I am totally devastated by doing this over and over even though it was so simple & primitive to do. Well… maybe not really primitive because the changes were also difficult to do. I mainly didn’t want to use the GUID system because I have Custom Statuses but also Built-in Statuses and I was really worried about Built-in statuses having GUID assigned to them. Those sync options with GitHub are still in work, but I finished the GitHub Repository Stats viewer after a lot of experimenting with layouts and designs/effects/colors. I’m looking forward to the next devlog guys! I hope Helyx will be your good coworker that will actually count for something hah! P.S.: I also made that text of colors is grammatically formatted. At least it should be…
Sync finally done!! It’s 5 AM and I finished “Sync badges with GitHub Repository” and “Sync the status with GitHub repository” (this was already done, but with the enum version of status). I added also a few fail-safes so when you assign some badge or status and then delete it, it will also delete it from GitHub and project. Now it won’t be a ghost that you cannot get rid of haha. This was a little more difficult than I expected to do, the fail-safes because the local changing mechanism and syncing mechanism were written inline in the same function. The only thing that was dividing them was an if statement. It was interesting to make this. To make sure everything will work fine. Even though it didn’t MANY TIMES. Now I will focus on syncing GitHub topics. Wish me luck! P.S.: Forgot to mention, that I have to add this “On Status/Badge Edit, ASAP sync with GitHub” with Edit. I almost forgot lol, just came into my mind. I hope that COPY+PASTE will be enough and I won’t have to create another syncing system specifically for edits…
More bugs are appearing, and being fixed!! So since Helyx is already far and has many advanced functions, it also has some bugs. Today when I was experimenting with assigning a project and syncing it with GitHub, I found out, that if you try to sync the projects in a wrong way… it will not work. For that reason I added more fail-safes to make sure that this will be eliminated. I can’t confirm yet if those fail-safes work, because I am also working on a new Diagnostics action in Git Actions so if something goes wrong, you can fix it by the error Helyx gives you. Right now my testing project is in a state of “Git corrupted” (no idea what I should call it) where rebase was aborted. Because of this, I had to put the “GitHub Sync Topics” synchronization off until later, so I can focus on fixing these major bugs. Also another bug came to my mind that I fixed… Helyx works on a principle of directory paths. Each project is saved in config file under its own unique GUID and its path. The bug is that when you try to rename the directory, the project won’t be found and it will be removed from Helyx. Now, you can either let Helyx find it automatically (sadly can easily fail) or you can select project manually in explorer (recommended!!!).
Doctor Git As you may know, right now I am working on Diagnostics. I am almost done with fully displaying all of the health checks about your Git repository. But I still have to finish all of the fixing actions that it will have. Diagnostics will mainly be for a case where something happens in Helyx and it will need to be fixed. The main idea of it is not aimed at resolving issues with your Git repository outside Helyx. But it may resolve some because you may run into the same issue as you had in Helyx of course. In the last devlog I said that I put GitHub Topics off. Well, that did not happen! I finished displaying GitHub Topics!! I think in some devlogs I said that it was for managing GitHub Topics. Managing meant like adding, removing, editing. Well, that wasn’t actually my main point. I just wanted it to show you your currently assigned topics in GitHub. I also didn’t see a big reason in adding Add, Remove, Edit functions for topics. Topics rarely changed, honestly and the most intuitive way would be doing it via GitHub web interface.
Diagnostics done, other stuff too and some changes! Diagnostics are now fully done! When something messes up, it will give you options to fix it! Some time ago I created GitHub Synchronization settings for managing what to sync with GitHub, so what to retrieve and send with those options: Sync status with GitHub repository Sync badges with GitHub repository Fetch GitHub repository topics Fetch GitHub repository stats Use GitHub’s language detection instead of Helyx’s I created a brand new tab called ‘GitHub Actions’ where this setting is. GitHub Actions is meant to contain all of the actions that are mainly linked with GitHub endpoints. I kept few such as Push, Pull, Sync in Git Actions due to how the layout is already created. Also I added when you are rebasing and it fails, it automatically gives you a prompt to cancel it. So repair it… GitHub Actions will contain a new stuff that will come to Helyx! Managing Issues and Pull Requests!! Maybe also workspaces/actions but I will see how difficult that is and how it is needed/useful in Helyx. Another new function is, that when there’s an update for Helyx and I change the GitHub OAuth scope because of new features… Helyx will warn you and tell you to reauthorize to make sure every function will work correctly. Before this change, Helyx was using its folder name as a name of the project and as a repository name for GitHub. Now, when you add a project to Helyx, Helyx will ask you what’s its name and when you will try to use some GitHub function for the first time on your newly added project on Helyx, it will request a GitHub Repository name from you. ;) There’s still a lot of things to add. Honestly I thought that Helyx was at the very end like 50 hours ago and look! There are many more functions to add haha!
Manage Issues, at your service. After a painful development period I am again here, writing devlog! What changed? Good question! Manage Issues is partly done! I still have to finish making the actual actions but displaying is somewhat finished. When you go to ‘Manage Issues’, you will firstly see a list of issues that are on your GitHub repository. From there you can already see some details about the issues such as: Number State Title Labels Comments (number) Updated (time) Above them are filters, currently those are the available filters: All -> All Commented -> Issues has some comments Assigned -> Issues that have some assignees Labels -> Issues that have some labels But that is not all! There are also their counterparts: No comments Unassigned Unlabeled (there’s no inversion of All because why would you need filter None) Yeah, so you can invert your filters… When you select an issue at the very top you will see its number, then you will have a panel with details about the issue with its title and: State Author Opened (time) Labels Assignees Right under these details are all of the comments in chronological order. When it is done, it will also show the whole timeline of each issue. So when this and this label was added/removed… when was this assignee assigned/unassigned… when was this issue closed/opened…. Of course I am going to add actions so you can add a comment, close issue, open issue, etc… When I’ll finish Manage Issues, I will go to work on Manage Pull Requests. It shouldn’t be that different because Pull Requests are by GitHub a kind of Issue but they are also not the same, so different classes, types, etc… Well, wish me luck people… or should I say… Stardancers?? P.S.: Sorry for the grammar in images in comments. I did it very quick for the preview.
Paging done, functions almost! I finished making the logic for rendering issues. In the last devlog it was just displaying all of the issues at the same time. No paging system so if there was a lot of issues or long issues, they would simply… not appear. It took me a really long time to work this out. I was mainly switching back and forth the rendering logic all the time and it went so far, that I had to use Claude to help me with it. At the end, I ended up with a rendering logic that I am not really keen on, but it is the best one that can be used in Helyx and TUI environment. Main obstacles were the Spectre.Console rendering functions and classes that were under IRenderable interface. And also the limitations of Panels, Grids… Layout had everything I needed . I wanted to cut the part which couldn’t be rendered and it should have looked like, like an unfinished Panel. Well, this was impossible. Without changing the core code of Spectre.Console or creating own system for making Panels it was impossible. Also, I haven’t seen it as something that WOULD NEED an own system that would render comments. So I just made it when a comment cuts, it creates whole Panel with part of the comment that can be rendered and at the bottom is text saying that it continues on the next page… and on the other page at the top there’s text that, hey, it continues here! Let’s finally talk about the Issue functions! I finished some simple one like: Close Reopen and create an issue… But I still have to create a system that can let you: Comment Edit comments Delete comments Lock issue Unlock issue Those are currently in WIP, but in the next devlog they’ll be most probably finished and after everything is done with issues, I will move to Pull Requests!
Manage Issues, completed! PRs, incoming… Manage Issues is now fully completed. I still had a few issues with paging and rendering but now they are fixed. Now you can select a message and delete it & edit it. But also now you can create a comment, lock an issue, unlock an issue and create an issue. I also added a thing that I hope will be appreciated, Helyx renders Markdown from GitHub Issue comment and when you comment via Helyx, Helyx gives you Markdown options such as: Bold Text Italic Text Code Text List Quote Also, when you don’t provide a text to a comment in GitHub, Helyx will say that “No description was provided.” So the same thing as GitHub already does, but in Helyx you must provide text. Why? Because why would you create a comment with no text? So I banned adding a comment with no text. Okay, that would be everything! It was fun to create this because everything was working so well, except the paging system… that was painful to make even with Claude’s help. As I said in past devlogs, after Issues I am going to move to PRs. So yeah, let’s work on PR. I hope it won’t be harder to make, because a PR is a type of Issue in GitHub, so I hope I will use the same function logic and functions and callbacks to make it.
Manage PRs displaying and some logic done After pulling another all-nighter I finished making the Pull Request display functions. List and details about each Pull Request is done and paging also works too (took it from manage issues ;] ). Pull Requests also contain filters such as: Open Drafts Assigned Reviewed and we can’t forget their counterparts either: Closed Ready Unassigned No reviewers Pull Requests now have comment selection and Markdown formatting, but functions to manage Pull Requests are not done yet. The only ones I managed to finish are: Comment Open Browser The biggest problem with PRs is going to be, that their functions and methods for executing those functions are more complex than the ones for Issues. I plan to add these functions for PRs: Delete Comment Merge Review Close PR Reopen PR I am pretty sure that all of this will be done in next devlog, so stay updated! This is going to be very cool, I think. Well, now I am going to sleep so good night everyone!
Manage PRs done! Added few new things… I finally finished making Manage PRs. So now you can: Delete Comment Merge Review Close PR Reopen PR I also had to fix some design flaws and function flaws but now it should be all good. Before doing all of this, there was a bunch of GET requests… now? Now it is also a bunch of PATCH & PUT requests. Also, now when you’ll try to link your GitHub Repository with the local one, you will just select the one that is on your GitHub account. Another thing! When you have conflicts between the local repository and the remote one (GitHub) and you try to sync them, a lot of the time Notepad pops us and tells you to remove the version of the text that you don’t want. Well now Helyx does it too and doesn’t open notepad, but lets you do it directly in TUI interface in my very own notepad. Conflict solver also uses alternate screen for this. (there’s sadly no showoff image for this, because currently I don’t have anything to create a conflict on) I am not sure what to do next in a next devlog, since everything I really wanted to do is already done… well… not everything but everything around the main things is. Maybe I’ll move on another refactoring? Or finishing the language settings? Well, we will see!
Adding new features & fixing bugs I finished making “Analyze Project” which analyzes your whole project and prints stuff such as: Number of files Number of folders Size of the project on disk Number of lines Also you can now see what amount of what programming language makes your project. It also shows you the biggest files in your project directory. And also you can see Git information such as: Branch Number of commits First commit (date) Last commit Working tree .git size So it displays some maybe important and basic information that you may check sometimes or might be interested in. There were like 6 revisions of this because I was testing different styles & designs. I also found a lot of hidden bugs with help of Claude! Before talking about bugs, I will tell you something about new features that I added. Now, when you assign a badge or change a status and you don’t have markers in README.md yet in it, then it will ask you if you want to add them manually or via Helyx. What does that mean? Well, it opens a “text editor” in Helyx which displays README.md and you can insert the badges/statuses where you want instead of opening the file in notepad and inserting the markers manually. Overall it is way quicker to do it now via Helyx. Helyx’s Generic Text Editor is now even better! You can now use all of the arrows, before you could just use Left/Right Arrow to move cursor left or right. Now you can move between lines. Now you can also open your project’s wiki via Helyx. Be aware that it doesn’t check anything, if you have wiki or not. It directly opens the website for the wiki where it should have been for the current linked GitHub Repository. Let’s talk about bugs now! Open an issue called the Markdown handler function and it was accidentally calling GitHub 101 times, when it needed some info. Now it doesn’t. 🆒 Notes have an encryption system, so if you put some sensitive info into it, it couldn’t be directly taken from the file. Only via Helyx. There was a bug, where when you enabled encryption and edit notes of 2 projects, then you turn off encryption globally and open the first project’s notes, it decrypts… but after that you open second project’s notes, it won’t. This was due to having a global bool instead of per project bool when saving if it was encrypted. Fixeddd! Another bug! Sync Status & Sync Badges was deleting staging index. Funny that I was thinking about to restore the staging index whenever using it, but at the end… the logic was wrong 😭 Now it isn’t. Then there was a bug that when you unassigned a badge, it unassigned ALL badges. Fixed! Another bug linked to badges… Unassigning a badge didn’t remove it from GitHub. Yeah… fixed!!
Fixing more bugs I fix bugs mainly with use of Claude Code, because hunting for bugs is not easy and this project is not a small one haha. I had to run MANY code review tools for this, because every time it kept finding new bugs. No idea how but it did. So what we fixed? If a GitHub comment had bold text split across two lines, opening that issue crashed Helyx before it drew anything. A file with a square bracket in its name (e.g. data[1].json) crashed Status, Diff, Commit, Stashes and Log. If anything held config.json open for even a moment, Helyx assumed it was corrupt, reset it, then crashed everywhere that looked for a project. If config.json was missing its Badges section, the startup migration quietly deleted every badge from every project. Committing saved a copy of the project taken before the confirmation prompts, so anything changed in between was silently thrown away. If you linked a GitHub repo during Push, the remote was created with an empty name. Syncing a status that had since been deleted crashed in the middle of a push. A commit message containing a square bracket crashed “View Full Message” (those are just bugs that were missing Markup.Escape() function). Applying a stash said “applied successfully” even when it conflicted. One bad path stored in config.json crashed “Add Project”. This is just a snippet of the amount of fixed bugs. I won’t write all of them here since it would take a lot of text and I am pretty sure that this is enough for you to understand that we fixed a lot of bugs haha. Right now I am going to do the Language System. I am not sure if I mentioned in some devlog, the list of languages that Helyx will support. If not… there it is: English Slovak Spanish French German Russian
Languages almost done, moving onto GitHub & README.md Well guys, Language System is almost done. It is powered by a Resources file that stores all of the translated strings. More bugs were found! But now, all of the bugs should be fixed with also many failsafes! Now, I want to complete the Language System because I am really close to finishing it. I also want to make the README.md for Helyx’s GitHub Repository. Originally I wanted to make it via Obsidian app, but it doesn’t have direct support for Wakatime, so I have to use VS 2026 native Markdown editor with the support of Markdown Editor v2 extension from Mads Kristensen. (not sponsored lol) I also heard that Obsidian app doesn’t use the same Markdown as GitHub does so there would be some things mistyped or not even rendered, but VS 2026 should be fully compatible with GitHub’s Markdown renderer, so we will see!
More bugs fixed, new functions, README & Language System updates! Hello guys, once again at 4 AM! Bugs: As the title says, there are more fixed bugs. Diagnostics crashed Helyx if you ran a rebase in a terminal and hit a conflict. Now it doesn’t! Another fixed bug is that when you opened an issue in Helyx, the footer vanished. At first I was shocked, but it was a simple fix so now your footer doesn’t vanish. Another vanishing bug! The Languages row from the header vanished when you entered a tab where Layout class was being used. Now you will see your sweet programming languages used in your selected project. Guess what! Another vanishing bug! This time the whole header vanished when you exited .Live()! Now it is okay! New behaviour: I unified some color codes with some type of info. E.g. SHA is Dark Orange everywhere, Stash is Yellow, Date is Cadet Blue and Issue Number is Aqua. The README.md editor, when inserting badges/status now has a new keybind: backspace! It is different from DEL! DEL deletes the badges/status but backspace deletes the whole line, including the badge/status that was on that line. README The README is almost done! At least I hope! Claude was a big help here, because I wanted to create an insane README and we really did. Guys, you should be excited about the README file haha! Language System Translations for these languages are already done: English French German Russian Slovak Spanish So basically every language translation is already done. BUT I decided to add even more languages! The new languages that Helyx will support are: Italian Portuguese
New features, new languages, new problems. A new feature that I added is GitHub Actions! It is on the same principle as Manage Issues and Manage PRs, so you have a list of GitHub Actions, you pick one and you can control it, check its log, observe information about it. You can even run an action! I also added a refresh keybind to Manage Issues, Manage PRs and GitHub Actions. Before, you had to go back from the details of an issue/PR/action to the list and then return to the details. Now you don’t have to. You just have to press the keybind displayed in the footer that belongs to refresh. Yes! The Helyx Language System is finally complete! Italian & Portuguese are now available in Helyx! Lately I’ve been working on the README.md file. I was mainly making more GIFs & designing screenshots for it so it will look pretty and futuristic (in my opinion)! As I have mentioned in the title, NEW… PROBLEMS! People… you won’t believe what happened to me today… I use Helyx’s Git & GitHub for testing, so there is no official one yet, and I rarely commit changes or push them. Only when I test something. And it looks like it got back at me. Well… I told Claude Code to remove comments all over my codebase, because they were mainly scrapped code and some temporary information that I had there, that wasn’t used anymore. Okay, so I told it to remove them, and for some reason instead of removing comments, it deleted Helyx’s whole codebase. Thank god README.md was untouched haha. We had to decompile the .dll that was left over from testing Helyx’s latest version, and actually check the diff and rewrite it. We still don’t know if everything was brought back since for some reason Claude Code’s memory got wiped instantly when it realized that it deleted my whole codebase. There were no backups, no restore, no nothing. The only possible thing was to use the forgotten stash that I created and use the .dll as a map to restore Helyx’s outdated codebase and rewrite it again. So that’s what we did. Yeah, so I hope everything was brought back. Claude says it was, but after what it has done I don’t know if I trust it. Just kidding, everything should be back, because it compared the .dll with the rewritten code 1:1 and everything matched.
GitHub done, shipping Helyx today! Today I was messing with the GitHub page for Helyx, fixing the last bugs we found and working on the installer. For the installer I used Inno Setup, because it is the most recognized and the most used one. The point of using an installer is simple: it adds Helyx to PATH. Of course there were other options, but this one seemed like the best fit. We were fighting with the script for a while, because it was doing really weird things, like staying in the background after the installation finished. But those bugs are fixed now! README.md is done, all of those GIFs and screenshots are in it too, and I have to say it looks really good! I was also setting up the GitHub side of things, so the description, the tags, a GitHub Action and so on. With the help of Claude Code, we created the logo and the banner for the installer as well. The installer uses the same logo as Helyx. It’s just a basic H, because nothing else came to mind haha. I also asked Claude Code to review the codebase one last time, and yep, it looks fine! I told it to add the basic documentation comments as well, the <summary> kind. Let’s be real here, nobody does this, and if they do, something else writes it for them, usually an AI, because it understands the function better than the person who wrote it (I know that from my own experience hahaha).
Experimenting with the conflict solver I was thinking about adding a simpler conflict solver, where you wouldn’t have to delete the <<<<<<< , ======= and >>>>>>> markers yourself but would just pick either the first or the second version. But I realized it would be messier than I thought, so in the end I kept it as a basic editor where you remove the version you don’t want by hand.
README.md update I replaced the title in README.md with a banner that contains the text Helyx. I tried a few versions I made and, well, I landed on the one you can see in Helyx’s README.md, or below!
Edited README.md I rewrote the README.md because of the ship review. I also added a couple of recommendations that are worth knowing when you use Helyx. I also removed the <summary> comments that Claude Code wrote for the documentation, I don’t think that anyone would have used them anyway.
Edited README.md, again I was again editing the whole README.md, because reviewers weren’t happy with the current one. Well after spending another hour of editing the whole README.md file, I hope they won’t ask me to rewrite the whole README.md file again, because I don’t even know what else to add/remove/edit.
Added GitHub Issues/PRs events rendering Originally, when you selected Manage GitHub Issues or PRs and opened some issues/PR. You could have only seen messages posted by users, but not when a label was assigned or when the issue/PR was closed. Well… Now you can! Now it displays the exact action that happened and when it happened! Of course, it is also translated to all languages that Helyx supports. Just making sure you didn’t think it wasn’t! I also cleaned up the code a little bit. Removed some useless usings and some files were in the wrong namespace, so that is fixed too.
Replaced hardcoded string colors with Color members for code safety, fixed line breaking while assigning a status/badge Okay so Markup texts (those are the texts with color) were formatted in this format: "[red]Hello World![/]" So it was string-based. And if you accidentally added some character to it for instance: "[redd]Hello World![/]" <- Exception Helyx would crash. I mainly added this, because it is an open-source project. So if someone tried to edit it, they would only have to edit the string and they might have misspelled it. But now, when he goes into the codebase, he will see Color members and he just can’t misspell that, and if he would, compiler would alert him. Basically, now it is like this: $"[{Color.Red}]Hello World![/]" Okay so next I fixed line breaking. What does that mean? Well… In Helyx native README editor, so when you try to assign a status/badge, you’ll get that editor, when you try to add a status/badge to that line, you might have thought that it would be on the same line as the tags above it. But it didn’t… This was happening due to the comment markers for Helyx so Helyx knows where this status/badge is located and which status/badge it is. Now Helyx will put those comment markers in a way that prevents the line from breaking.
Reviewing my codebase and fixing bugs Since all of the features that Helyx was supposed to be finished with are almost all done (maybe even all are done), I will now change my view to another projects for Stardance such as ThetaNexus . But that does not mean that now I will just forget about Helyx. I will be reviewing the codebase sometimes to find some bugs and fix them. You can help me with this, by making an Issue request on Helyx’s GitHub. So what bugs did I fix since the last devlog? I fixed line breaking in badge/status README editor. When you were inserting your badge/status into your README via Helyx’s README editor, it done… messy stuff to the README, not something like really bad what couldn’t be fixed by manually doing it, but it should now insert the badge/status exactly as you see it in the editor. I also introduced a new ‘Found state’ text instead of ‘Found’ text in IDE settings to avoid confusion. To avoid confusion because if an editor was found and you clicked on it… it wrote this: Found Found Found Not Found Found Set by user Now it writes this: Found state Found Found state Not Found Found state Set by user Most of the time, I was reviewing the codebase via Claude Code to actually check everything precisely.
Fixed User Scripts bug So, every path block used Path.GetFullPath(path) instead of Path.GetFullPath(path, script.ProjectPath) . That means it was resolving relative paths against Helyx’s own directory, not your project’s. This is now fixed.
Hackatime integration Hello there! A guy made a feature suggestion on Helyx’s GitHub, that I should add a Hackatime integration into it. So I was thinking… and thinking… and thinking and woah… I ADDED IT! It is not 1:1 like the web interface, that one is better & shows you more things but sadly this was everything that I could request from API (at least I think): Total Seconds Languages Repo URL Total Heartbeats First Heartbeat (DateTime) Last Heartbeat (DateTime) and when combining all of these information, I created a screen where you can see all of this specifically for your project. It works on the principe of authorization. You put in your Hackatime token which authorizes you and then when you go to your project and go on Hackatime Info, it prompts you to select the project from a list of projects that are assigned to your Hackatime account/token.
Ships:
What I made Helyx is a terminal app for Windows that keeps every local Git repository you own in one place and lets you commit, branch, resolve conflicts, repair broken repositories and answer GitHub Issues and Pull Requests without opening anything else. I spent a lot of time thinking about what kind of project I wanted to build. I wanted something that would be genuinely useful to developers in many different ways, and that is how I came up with Helyx, a TUI application that brings many Git and GitHub tasks into one place. What was challenging Learning new libraries, keeping the code organized as it grew, and designing every screen so it looks and feels as polished as I could get it. Deciding what to build next was harder than it sounds, because there was always more that could go in. What I am proud of It has everything I originally planned to include. The diagnostics screen finds what is wrong with a repository and offers the fix instead of just reporting it, the conflict resolver opens the conflicted block in its own editor, and the whole app speaks 8 languages. How to try it Download the latest release from Helyx’s GitHub and run it. It installs into your user folder and adds Helyx to your PATH , so you can start it by typing helyx in any terminal. No administrator rights are needed, and the .NET runtime is bundled inside. Then pick Add project and choose any folder that contains your project. Helyx is open source, so you can also read the code or build it yourself. Just click See source code below....
|
1792810518.606234
|
1792896918.606234
|
|
8100
|
Crawssembly by @The_Craw | Stardance
|
The_Craw
|
3
|
310.71
|
5664
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-08T09:56:51Z", "hours": 137.0, "multiplier": 19.59, "payout": 2622, "blessing": "neutral", "text": "CRAWSSEMBLY - New and Improved! “Programming languages are a lie!” This is Crawssembly, the number 1 project on all of stardance! It’s a project that’s been in production for over a year. It is an educational assembly-like programming language that teaches users how computers actually work. Programming languages like Python, Ruby, and Java pull the wool over your eyes by abstraction and simplification. Crawssembly is the first step to seeing clearly. What is new? INTERNET SOCKETS! CRAWOS COMMAND LINES! DYNAMIC LABEL JUMPING! IMPROVED DEVICES! DEDICATED PACKAGE SHARING WEBSITE! AND MORE! Check it out for yourself! (Shipped early due to Fraud Squad limitations, Crawssembly is too powerful for Hack Club)", "repo": "https://github.com/Jonah-Crawford/Crawssembly", "demo": "https://crawssembly.ultimatecraw.xyz/"}, {"ship_num": 2, "ts": "2026-07-02T17:49:35Z", "hours": 33.0, "multiplier": 19.65, "payout": 633, "blessing": "neutral", "text": "Crawssembly v1.1.0 ready to ship! “Programming languages are a lie!” This is Crawssembly, a project that’s been in production for almost a year. It is an educational assembly-like programming language that teaches users how computers actually work. Programming languages like Python, Ruby, and Java pull the wool over your eyes by abstraction and simplification. Crawssembly is the first step to seeing clearly.", "repo": "https://github.com/Jonah-Crawford/Crawssembly", "demo": "https://crawssembly.ultimatecraw.xyz/"}, {"ship_num": 3, "ts": "2026-06-26T21:15:26Z", "hours": 134.0, "multiplier": 19.78, "payout": 2409, "blessing": "neutral", "text": "Crawssembly: The beginner’s gateway to low-level thinking. \"Programming languages are a lie!\" This is Crawssembly, a project that’s been in production for almost a year. It is an educational assembly-like programming language that teaches users how computers actually work. Programming languages like Python, Ruby, and Java pull the wool over your eyes by abstraction and simplification. Crawssembly is the first step to seeing clearly.", "repo": "https://github.com/Jonah-Crawford/Crawssembly", "demo": "https://crawssembly.ultimatecraw.xyz/"}]...
|
[{"post_id": 79047, "ts": "202 [{"post_id": 79047, "ts": "2026-10-12T14:17:02Z", "hours": 5.8211, "text": "idk where these extra hours are coming from, but as long as I don’t ship them, they won’t count towards stardust so I’ll be fine. In the meantime, enjoy craw slop"}, {"post_id": 73135, "ts": "2026-09-24T13:36:27Z", "hours": 0.8872, "text": "It has come to my attention that not everyone who has followed Crawssembly has starred it on GitHub! Please, if you like my project, star it on GitHub at https://github.com/Jonah-Crawford/Crawssembly Thank you."}, {"post_id": 62476, "ts": "2026-09-05T20:43:32Z", "hours": 1.1861, "text": "I’m back! Fraud Squad unbanned me so WE are all having a party at my house Although I can’t use nano apparently anymore… so Crawssembly will be having it’s final ship very very soon"}, {"post_id": 53379, "ts": "2026-08-23T22:12:14Z", "hours": 4.7478, "text": "I’ve been doing much more testing and implementing the network device. Specifically testing the following commands: io net ip , io net addr , io net connect , io net socket , io net port , io net listen , io net accept , io net send , io net protocol , io net block , and io net recv ."}, {"post_id": 52283, "ts": "2026-08-22T12:07:09Z", "hours": 0.5569, "text": "HTTP requests working 🔥 ts is so peak icl"}, {"post_id": 51913, "ts": "2026-08-21T20:28:29Z", "hours": 4.2456, "text": "I’VE ACTUALLY DONE IT 🔥 Networking is now officially part of Crawssembly. Alpha tests on localhost have all passed"}, {"post_id": 51556, "ts": "2026-08-21T10:23:09Z", "hours": 0.3189, "text": "I’ve brought run back from the dead. You can now use run rXX to run a binary value inside the input register as a Crawssembly instruction"}, {"post_id": 51201, "ts": "2026-08-20T18:32:01Z", "hours": 0.4944, "text": "stardance"}, {"post_id": 50613, "ts": "2026-08-19T20:41:05Z", "hours": 1.6864, "text": "I’m finally getting somewhere with the editor, however I’m now having issues with character deletion, and adding characters inside empty newlines"}, {"post_id": 49579, "ts": "2026-08-18T13:50:02Z", "hours": 4.3281, "text": "Still no clue why characters aren’t being saved to memory in my free heap block Slow day today fr"}, {"post_id": 48745, "ts": "2026-08-17T08:45:08Z", "hours": 2.36, "text": "For some reason, I’ve been banned on slack. I don’t know why, since no one will tell me. This is not good news, but luckily it doesn’t seem to be a stardance-wide ban, so I can still do the hackathon."}, {"post_id": 48355, "ts": "2026-08-16T17:45:02Z", "hours": 8.0639, "text": "Lots of work today, sorry for the . I’ve been struggling with the text editor, heap buffers, cursor allocation, character addresses, etc etc… ad infinitum. However, I’m getting close. Rendering is outputting something, although I don’t know why typing doesn’t seem to add anything…"}, {"post_id": 47504, "ts": "2026-08-15T13:39:53Z", "hours": 4.2456, "text": "I’ve added io keyboard mod to create a bitfield of modification key presses for the keyboard device, so now keys like CTRL and TAB can be handled, which lays the foundation for my next project which is making a basic file editor in casm"}, {"post_id": 46783, "ts": "2026-08-14T09:10:12Z", "hours": 4.3825, "text": "Sorry for the but it’s been a hectic couple of days. I got into University! I’ve also been busy taking a look at a CGOL implementation, truly amazing stuff! Go check it out: https://github.com/srxcode/game-of-life-crawssembly"}, {"post_id": 45634, "ts": "2026-08-12T08:01:02Z", "hours": 1.1425, "text": "I’ve separated the old sleep command into sleepms for millisecond waits and sleepus for microsecond waits. Although, microsecond precision is highly dependent on the OS, so it won’t be as accurate as sleepms for smaller values (Say, n<50)"}, {"post_id": 45230, "ts": "2026-08-11T15:52:21Z", "hours": 1.3411, "text": "I’ve merged the new fgo rules to the project, so now fgo points to labels similar to jmp , but fgo 0 now jumps to the label defined in r01 I was having some issues with using git but I got them sorted"}, {"post_id": 45046, "ts": "2026-08-11T09:08:16Z", "hours": 0.8819, "text": "I’m back from camping! (RIP my 60+ day streak) My plans going forward immediately is improving program counter modifications to allow for higher-level concepts to be bootstrapped onto Crawssembly instruction sets. (Image unrelated)"}, {"post_id": 40794, "ts": "2026-08-04T15:32:01Z", "hours": 1.0728, "text": "I’ve been working with @BetterClient to inprove the program counter and bringing back fgo from casm beta. This is also a reminder that I’ll be OOO until next Monday."}, {"post_id": 40209, "ts": "2026-08-03T16:48:57Z", "hours": 1.4692, "text": "I’ve made publishing packages super easy now, all you need to do is craw init to create the package, and then craw pkg publish . As long as you’re signed into CPM and gh, it’ll just work"}, {"post_id": 40094, "ts": "2026-08-03T14:12:19Z", "hours": 1.1475, "text": "I’ve added Markdown support for CPM packages 🔥"}, {"post_id": 40004, "ts": "2026-08-03T11:00:47Z", "hours": 2.5797, "text": "@imakebloatedcode Thank you for your pr for CPM to include OpenAPI scemata, another great addition from the Craw Systems community Most of my time has been reviewing it and making small edits to include the security auth headers for API keys Official Announcement I’m not going to be online through the 5th August to the 10th August, I’ll be camping for those 5* days in a very low-data spot, and I’m almost certainly not taking my laptop. I might be able to get a tiny amount of code on my phone to keep my streak but certainly not enough to engage in my normal conversation on slack or post devlogs"}, {"post_id": 39500, "ts": "2026-08-02T14:31:42Z", "hours": 1.0703, "text": "Package creation and accounts are now working (theoretically) from the command line 🔥"}, {"post_id": 38989, "ts": "2026-08-01T16:48:04Z", "hours": 2.2369, "text": "The account page is looking better, and it’s survived some user testing 🙏 I need to add some boring stuff though like API key listing and said key management"}, {"post_id": 38863, "ts": "2026-08-01T12:58:59Z", "hours": 3.1425, "text": "I’ve been back working on CPM, focused on user accounts."}, {"post_id": 38130, "ts": "2026-07-31T10:56:08Z", "hours": 1.39, "text": "The Crawssembly community is real 🙏 I’ve been reviewing a PR on the GitHub to improve the multiplication script in the CSL ( std/math/multiply.craw )"}, {"post_id": 37274, "ts": "2026-07-29T21:10:18Z", "hours": 0.7014, "text": "I’ve been messing around with --input tag which seems to mess around a bit in the rust vm, but I think I’m getting closer to the cause"}, {"post_id": 36468, "ts": "2026-07-28T16:32:48Z", "hours": 1.0483, "text": "Hack Club seems to have updated the rules on banner images, claiming it has to be an image of your project working. This is no issue for Crawssembly. The new banner is now the output of one of my programs, creating the banner pixel for pixel. This both compiles with the new rule, as it demonstrates Crawssembly functioning, while maintaining its identity."}, {"post_id": 36310, "ts": "2026-07-28T10:47:11Z", "hours": 2.2539, "text": "I’ve discovered that the input file mechanism is broken, so that’s great. I’ve also been adding more commands to CrawOS"}, {"post_id": 35823, "ts": "2026-07-27T14:42:16Z", "hours": 1.9103, "text": "I’ve been adding some very basic commands, such as exit , help , and clear"}, {"post_id": 34854, "ts": "2026-07-25T21:54:23Z", "hours": 2.7158, "text": "Once you get 1 command working, many more will follow! That’s right, a command line written 100% in Crawssembly code 🔥"}, {"post_id": 34296, "ts": "2026-07-24T21:36:54Z", "hours": 0.505, "text": "icl I’ve not done much today, mostly testing the allocation code and it looks up to spec tbh, not much to say"}, {"post_id": 33496, "ts": "2026-07-23T14:28:32Z", "hours": 1.4308, "text": "Stack allocation and freeing appear to work, but I need to do more testing to prove it"}, {"post_id": 32893, "ts": "2026-07-22T10:59:17Z", "hours": 4.3922, "text": "I’m still working on stack allocation, the complex parts are walking the stack properly to get the headers, along with making sure I don’t corrupt any data. The image attached shows the maximum heap block size in blue, with the data taken up by the header of that block in red (top corner)"}, {"post_id": 32353, "ts": "2026-07-21T13:52:27Z", "hours": 1.4989, "text": "I’m going ahead with this schema for heap blocks, the reserved bits can be used for extra features that I might want to add in later versions"}, {"post_id": 32254, "ts": "2026-07-21T09:37:22Z", "hours": 12.9831, "text": "Staff, please remove the time on this devlog, I accidentally left nano open all night. Sorry!"}, {"post_id": 31982, "ts": "2026-07-20T20:21:19Z", "hours": 1.13, "text": "Reading user input isn’t that easy compared to a language like Python, where you can just do input() . Each character has to be processed as soon as the keyboard records a press, and then saved to memory. I’m currently working on a block method that takes every 16 character you type, and allocates a small block on the heap for each press. This is going to be used for my big project"}, {"post_id": 31817, "ts": "2026-07-20T14:36:29Z", "hours": 1.2011, "text": "I’ve decided to add a heap library to complement the stack library. Doing this should make my next idea easier"}, {"post_id": 31759, "ts": "2026-07-20T12:24:31Z", "hours": 0.7053, "text": "Please also star my actual github page! It’s more important than stardance followers 😤😤 https://github.com/Jonah-Crawford/Crawssembly"}, {"post_id": 31691, "ts": "2026-07-20T09:37:05Z", "hours": 1.4242, "text": "Since IEEE 754 single precision can encode much larger numbers than a standard 32-bit binary number, you can use the library to approximate much larger values for computation"}, {"post_id": 31320, "ts": "2026-07-19T16:50:46Z", "hours": 3.3533, "text": "I’ve been working on a IEEE 754 single precision 32-bit floating point number library for CSL, it turns out it’s more difficult than I expected!"}, {"post_id": 31143, "ts": "2026-07-19T09:51:00Z", "hours": 0.7642, "text": "I realised that my documentation had some issues and unfinished sections, so I touched them up"}, {"post_id": 30931, "ts": "2026-07-18T22:37:22Z", "hours": 0.9317, "text": "Added a simple stack library for function calls and other uses, along with some smaller graphics programs such as screen/rectangle_fill.craw This is also my official announcement that I’ll be doing much less programming, due to summer holiday starting now. This is because I can’t program during family time, camping weeks, and other events. In addition, I have University after summer holidays, so this reduced productivity will continue throughout the rest of Stardance. Thank you all for making Crawssembly the number 1 project on stardance!"}, {"post_id": 29811, "ts": "2026-07-16T23:06:00Z", "hours": 0.5503, "text": "67 followers"}, {"post_id": 29415, "ts": "2026-07-16T11:01:49Z", "hours": 0.8972, "text": "I’m currently focusing on adding new functions to the screen library, such as rectangles, using the line program as a primitive"}, {"post_id": 28832, "ts": "2026-07-15T10:34:49Z", "hours": 2.9103, "text": "The initial line algo only works for the 0-octant, but now my new and improved version works for every line angle!"}, {"post_id": 27711, "ts": "2026-07-13T14:37:24Z", "hours": 1.2111, "text": "We have proper line segments working 🔥"}, {"post_id": 27105, "ts": "2026-07-12T11:30:09Z", "hours": 2.2058, "text": "I’ve been adding line functions at the moment, to be honest it’s harder than the circle! Getting the angles right is the hardest"}, {"post_id": 26637, "ts": "2026-07-11T15:56:48Z", "hours": 1.8617, "text": "Circle made 🔥"}, {"post_id": 26568, "ts": "2026-07-11T14:04:16Z", "hours": 2.7844, "text": "Taking a break from CPM to work on some graphics libraries, drawing lines, circles etc…"}, {"post_id": 25954, "ts": "2026-07-10T14:03:02Z", "hours": 2.3158, "text": "Accounts are going to be tricky, more front-end stuff and some complex security back-end is going to make this tricky"}, {"post_id": 25201, "ts": "2026-07-09T09:27:17Z", "hours": 0.7178, "text": "Thinking about user login for the CPM, might implement this soon"}, {"post_id": 24627, "ts": "2026-07-08T10:43:46Z", "hours": 0.66, "text": "Thanks to @Keyboard1000n17 for making the CPM website!"}, {"post_id": 24593, "ts": "2026-07-08T09:25:31Z", "hours": 0.6333, "text": "I won’t be as active over the next couple of days so don’t expect many updates"}, {"post_id": 24123, "ts": "2026-07-07T14:18:16Z", "hours": 3.4186, "text": "I’m not good at css, but I’m trying to make the CPM website simple and easy to use. It’ll take a while but it’s slowly coming together"}, {"post_id": 23750, "ts": "2026-07-06T21:31:52Z", "hours": 0.2561, "text": "It turns out I was way closer than I thought! Publishing your own Crawssembly projects is now out of alpha, into beta (Because only I have an API key atm!)"}, {"post_id": 23730, "ts": "2026-07-06T20:59:27Z", "hours": 1.5481, "text": "Still not too much progress on CPM, but I’m still confident I can get it working"}, {"post_id": 23656, "ts": "2026-07-06T19:20:07Z", "hours": 4.075, "text": "CPM is being difficult, I’ve gone through multiple iterations now of the craw pkg publish command, but I feel like I’m getting close."}, {"post_id": 23514, "ts": "2026-07-06T15:13:35Z", "hours": 1.2278, "text": "I’ve been fighting with my server for a while now, the connection keeps on interrupting. As votes are currently coming in for Crawssembly v1.1.0, I suspect my score will be lower than expected due to the demo and doc websites coming offline randomly."}, {"post_id": 23449, "ts": "2026-07-06T13:09:35Z", "hours": 2.1969, "text": "My issues at the moment are about getting a command, craw pkg pack to create a CPM ready tarball of your project from the command line. That and my server is having a couple of internet issues at the moment which are hindering my progress. This devlog is also an official announcement that I won’t be as active as normal over the next week. I have family coming around so my time programming will be limited. In addition, when summer holiday starts this will continue, which is why most of my time programming is in the June and early July, the rest of stardance will have fewer updates and less time spent on casm."}, {"post_id": 23401, "ts": "2026-07-06T10:39:43Z", "hours": 2.2703, "text": "CPM officially works! The pipeline of Crawssembly Source -> Tarball -> Github -> CPM -> craw pkg install -> executestd functions!"}, {"post_id": 22937, "ts": "2026-07-05T16:19:57Z", "hours": 0.6922, "text": "I forgot to add on the hackatime projects of my time spent on the CPM and tests, mb"}, {"post_id": 22902, "ts": "2026-07-05T15:21:06Z", "hours": 4.3764, "text": "I’ve registered the Crawssembly Package Manager website, some SQLite problems caused some issues but I’m getting there."}, {"post_id": 22103, "ts": "2026-07-04T11:47:12Z", "hours": 0.8486, "text": "I’ve been having some internet issues with my server recently, so my productivity has slowed. However I’m at the final testing stages of linking github repos to get craw install <package> to work. The test is done on a simple repo but it should be enough to see if it works"}, {"post_id": 22080, "ts": "2026-07-04T10:27:02Z", "hours": 1.33, "text": "Compiling from a local tarball works! I’ll be working on the database soon so users can search and download. My plan is that the program is stored as a github repo, similar to cargo ."}, {"post_id": 21459, "ts": "2026-07-03T12:44:46Z", "hours": 2.6692, "text": "Package manager is coming along… slowly. I’m still working on getting a local package to install into the global executestd file inside the home folder, but it’s taking it’s time!"}, {"post_id": 21375, "ts": "2026-07-03T08:43:14Z", "hours": 2.1081, "text": "v1.2.0 is already underway! I’ve spent some time constructing a cargo crate for Crawssembly to allow other rust programs to use Crawssembly’s logic. So now YOU can add Crawssembly to your programs!"}, {"post_id": 20935, "ts": "2026-07-02T17:47:58Z", "hours": 4.0467, "text": "After helping figure out the Stardance bug with projects, Crawssembly v1.1.0 is ready to ship!"}, {"post_id": 20147, "ts": "2026-07-01T18:08:54Z", "hours": 1.3117, "text": "I’ve added the compare branch, for number checks. == , != , > , >= , < , and <= all included"}, {"post_id": 20079, "ts": "2026-07-01T16:25:10Z", "hours": 1.3397, "text": "I’ve added more CSL files, such as math/power.craw , math/abs.craw , and math/modulo.craw"}, {"post_id": 19299, "ts": "2026-06-30T15:54:10Z", "hours": 1.4808, "text": "Basic multiplication and division are the first to enter the CSL! I focused on making them memory efficient rather than time efficient, because using fewer registers makes it easier for beginners to use them in normal programs. And because Crawssembly is very very quick (Almost C level speeds) a couple extra thousand ticks won’t be missed for these first programs"}, {"post_id": 19219, "ts": "2026-06-30T14:16:39Z", "hours": 1.9419, "text": "File execution is now working! You can insert programs using execute path/to/program.craw , this leads to the Crawssembly Standard Library, a collection of useful programs that can be accessed using executestd program.craw , such as multiply or division code."}, {"post_id": 19106, "ts": "2026-06-30T10:40:13Z", "hours": 1.1736, "text": "I’m going to confess here, I was a bit lazy. I decided that, because I could create the time program, I rewarded myself by adding a native ISO 8601 time output command io text iso rXX . Elegant? Yes. Low-Level? Not as much as I would like. But the choice was either make a single line of code to simplify programs like this massively, or wire in a tediously made, messy 350 line program that doesn’t fully account for the 400 leap year rule or leap seconds. Hmm… TLDR; I caved to simplicity. But CrawFS file listing from boot now display file genesis time!"}, {"post_id": 18658, "ts": "2026-06-29T20:58:53Z", "hours": 1.0361, "text": "The time program finally works! I wrapped it in a loop so it reloads every 200ms to make a real-time clock. Soon I’ll port it to the CrawFS system to read file creation dates"}, {"post_id": 18592, "ts": "2026-06-29T19:40:11Z", "hours": 4.485, "text": "It turns out that time resolution is much harder than I thought! It’s taken me a while but I’ve got the program working for CCYY-MM-DD"}, {"post_id": 18335, "ts": "2026-06-29T13:20:35Z", "hours": 3.6708, "text": "CrawFS reading is almost done, but I need to program a way to take a raw Unix timestamp and convert it into a nice iso 8601 format ( CCYY-MM-DD HH:MM:SS ) for the ‘Time created’ field"}, {"post_id": 17965, "ts": "2026-06-28T22:33:13Z", "hours": 1.9408, "text": "Reading a specific file is clearly much harder than reading the boot sector. It turns out that parsing user input is a devious task itself!"}, {"post_id": 17863, "ts": "2026-06-28T20:03:06Z", "hours": 6.4758, "text": "Did someone say boot sectors? That’s right, Crawssembly can now read CrawFS boot sectors and output the file table data! This took a surprisingly long time, as the binary boot sector is very delicate."}, {"post_id": 17529, "ts": "2026-06-28T10:56:52Z", "hours": 2.0917, "text": "I’ve been working on a basic file system, CrawFS , used as a stepping stone towards real ones like FAT16 , FAT32 , and NTFS ."}, {"post_id": 16918, "ts": "2026-06-27T14:08:58Z", "hours": 1.6475, "text": "No time to waste after v1.0.0 is released! I’ve added raw disk sector editing for Crawssembly; an opt-in way of reading and writing to your real disk, rather than a VM. ! THIS COULD DESTROY YOUR COMPUTER ! So only do it if you know what you’re doing, as a single bit change will probably brick your entire machine if you use the --raw-disk option"}, {"post_id": 16497, "ts": "2026-06-26T20:53:01Z", "hours": 0.2767, "text": "The final updates have been made, the github is ready to ship!"}, {"post_id": 16387, "ts": "2026-06-26T17:43:02Z", "hours": 0.4742, "text": "THIS IS IT! The moment I’ve been waiting for almost a year, the first stable release of Crawssembly v1.0.0 ! And what fortune that I get to share it with you people on Stardance!"}, {"post_id": 16247, "ts": "2026-06-26T11:58:09Z", "hours": 2.7383, "text": "Crawssembly is soon to be shipped on version 1.0.0 ! A massive milestone for a project I started ~11 months ago. The raffle discs have been burned, and final preparations are underway for release."}, {"post_id": 15925, "ts": "2026-06-25T21:28:53Z", "hours": 2.8969, "text": "Basic syntax highlighting for nano ! Simply run craw install-nano to gain access to these beautiful new colours when editing .craw files."}, {"post_id": 15761, "ts": "2026-06-25T17:09:48Z", "hours": 3.3403, "text": "RAFFLE UPDATE! The 3 discs have been completed. Soon, Crawssembly will be shipped on it’s first release! Remember to follow Crawssembly before the 1st July 00:00 UTC for your chance to win one of these beautiful pieces of computing history!"}, {"post_id": 15622, "ts": "2026-06-25T12:32:33Z", "hours": 2.0561, "text": "I’ve been working on fixing up the activities in the README.md, and providing possible solutions for each. The image below is a possible output of the activity “Smiling Screen”"}, {"post_id": 15555, "ts": "2026-06-25T09:06:54Z", "hours": 0.6672, "text": "Adding the last features for pong was quite simple, making the computer lag behind a random amount utilises the current millisecond UNIX timestamp, with the least significant 2 bits being used as the ‘reaction time’, along with a per-frame flag to increase this reaction time to solve for repeating loops. The scoring system at this point is just the number of pixels in the top corner, unlike the real pong which used numbers. Perhaps for a later version?"}, {"post_id": 15542, "ts": "2026-06-25T08:21:44Z", "hours": 6.6775, "text": "PONG is very almost finished, all that needs to be done is to fine-tune the computer movement and finish displaying the score."}, {"post_id": 15086, "ts": "2026-06-24T14:51:07Z", "hours": 1.7008, "text": "I’m now moving onto some game examples. I’m working on a basic version of the popular game PONG, the hardest part is going to be the graphics syncing up with the mathematical logic"}, {"post_id": 14404, "ts": "2026-06-23T14:59:26Z", "hours": 1.9525, "text": "The structure of the compiler is complete, but getting it to work is another beast of debugging. I think this is the first program of its kind; the first program where no one, not even me, can understand it fully. A true milestone for Crawssembly"}, {"post_id": 14331, "ts": "2026-06-23T12:57:06Z", "hours": 3.1389, "text": "Integer parsing requires multiplication by 10, which in Base-10 is easy as you can just add a zero at the end. But in binary you can’t do this, as that would be multiplying by 2. So you need to get a bit more creative when multiplying by a known amount in binary. The code below shows how a number, ‘abc’ can be expressed as 100a + 10b + c. This is real code from my Crawssembly compiler written in Crawssembly."}, {"post_id": 13936, "ts": "2026-06-22T21:21:17Z", "hours": 2.0808, "text": "I’ve done a little experiment with a reduced branch of Crawssembly made for tiny ISA’s, with instructions only a single byte wide! An image of what the CPU’s core might look like is shown below."}, {"post_id": 13603, "ts": "2026-06-22T09:14:02Z", "hours": 5.5197, "text": "The trie is complete! Although I’ve still much to do for the compiler, such as per-character parsing, storage of label elements, calculation of register codes, etc…"}, {"post_id": 12777, "ts": "2026-06-20T21:47:41Z", "hours": 1.7731, "text": "7/24 trie branches have been added to the compiler, totalling just under 1000 lines of Crawssembly code, the longest hand-written .craw program ever made!"}, {"post_id": 12486, "ts": "2026-06-20T12:09:00Z", "hours": 6.3061, "text": "Adding branches still takes a while, but it’s much more efficient than testing every character for every instruction. So far I’ve mapped 17 out of ~64 command strings."}, {"post_id": 12022, "ts": "2026-06-19T16:40:42Z", "hours": 7.6139, "text": "I’ll be taking a break over the weekend, as I’ve just completed my final exams and I’m celebrating. I’ll be back proper on Monday. Today I worked on creating a trie for Crawssembly’s commands, which can be used to increase efficiency in my compiler to parse instructions faster. Rather than checking every char for every instruction like cal add -65 r01 ; if r01 = 65, this will be 0 ifz 10 ; continue if 0 cal add -70 r02 ; if r02 = 65, this will be 0 ifz 20 ; continue if 0 etc... I can split each branch into separate instructions, reducing line count and time-to-compile"}, {"post_id": 11550, "ts": "2026-06-18T20:54:02Z", "hours": 1.8203, "text": "Basic structures are coming together for the compiler"}, {"post_id": 11465, "ts": "2026-06-18T18:55:47Z", "hours": 3.2833, "text": "The C emitter function now works to the same standard as Crawssembly Online! In other news, I’m starting to write a Crawssembly compiler in Crawssembly ! This is a big step and proves that Crawssembly’s language is comprehensive enough to take on this task."}, {"post_id": 11201, "ts": "2026-06-18T10:23:03Z", "hours": 4.2258, "text": "I’m working on a way to convert Crawssembly into native ASM language, by writing to a C file and compiling that output."}, {"post_id": 9958, "ts": "2026-06-16T14:20:14Z", "hours": 0.7653, "text": "ATTENTION! The moment has arrived; The CRAWSSEMBLY Raffle! Get the chance to win a LIMITED-EDITION installer and collectable Crawssembly Disc! The disc contains the official compiler, virtual machine, and documentation. Also included are un-released legacy files from development. Simply follow Crawssembly on Stardance to enter your name! Shipping may vary depending on the UK Postal service. There are 3 physical First Edition discs available worldwide. If you’re outside the UK, I may ask you to contribute towards postage if shipping costs are high. The 3 winners will be announced on the 1st of July! So get your entry in before 23:59 UTC 30th June! Don’t miss this opportunity! Follow Crawssembly today and support open-source learning!"}, {"post_id": 9903, "ts": "2026-06-16T12:33:41Z", "hours": 0.4594, "text": "I want to thank the Stardance devs for my Super Star tag! Peak staff fr"}, {"post_id": 9210, "ts": "2026-06-15T13:50:37Z", "hours": 1.9831, "text": "Random number generator has been added to the example group, I used XOR and bit shifts with the new command io time milli , which extracts the current UNIX timestamp in milliseconds, as the seed. Basic, but quite random from a human perspective."}, {"post_id": 9153, "ts": "2026-06-15T10:18:06Z", "hours": 5.0008, "text": "I’ve been working on some examples, the biggest one being a simple calculator."}, {"post_id": 8769, "ts": "2026-06-14T16:05:49Z", "hours": 2.1869, "text": "Graphics bug fixed! Crawssembly for macOS is officially working!"}, {"post_id": 8694, "ts": "2026-06-14T13:21:09Z", "hours": 0.2944, "text": "File input now works for macOS Crawssembly! Run craw myprogram.craw --file myinputs.file to run! (The image is from Linux, not from my Mac because it’s too old for me to log in to stardance and post a ss from it, but I can assure you it works!)"}, {"post_id": 8685, "ts": "2026-06-14T13:00:13Z", "hours": 1.8931, "text": "macOS can now do everything windows can except use the speakers, scan-line free graphics, and access files. These will be the largest source of my time."}, {"post_id": 8634, "ts": "2026-06-14T11:02:36Z", "hours": 1.2475, "text": "I’m currently working on getting macOS support running. At the moment, macOS is only confirmed to work to the same level as Crawssembly Online. Hopefully I can get it to the same standard as Linux and Dos systems!"}, {"post_id": 8214, "ts": "2026-06-13T17:40:18Z", "hours": 1.2083, "text": "My respect to real CPU designers, this is tricky work! The most difficult thing is working with the 256 different registers, that’s lots of wiring to get done."}, {"post_id": 8022, "ts": "2026-06-13T11:56:22Z", "hours": 0.4569, "text": "Dedicated documentation website created, and the new demo is live at https://crawssembly.ultimatecraw.xyz/"}, {"post_id": 8011, "ts": "2026-06-13T11:23:53Z", "hours": 0.9736, "text": "Demo and README in working order, for real this time! The final things to do before shipping: Full macOS functionality: Maybe Add documentation to demo: Yes Add syntax highlighting to demo: Maybe Final Cleanup: Yes"}, {"post_id": 7748, "ts": "2026-06-12T22:53:22Z", "hours": 0.7378, "text": "I don’t usually work with frontend, so the demo won’t look anywhere near as nice as some of the other projects on Stardance, but as long as it’s usable then I’m happy."}, {"post_id": 7722, "ts": "2026-06-12T21:43:33Z", "hours": 0.8628, "text": "Crawssembly demo now working! Luckily it wasn’t as hard as I expected. I’ve tied it to an old URL for now, and it’s basic, but it works. https://demo.ultimatecraw.xyz/"}, {"post_id": 7681, "ts": "2026-06-12T20:38:11Z", "hours": 4.555, "text": "README.md Complete! The final steps is creating the demo! (And maybe getting MacOS working)"}, {"post_id": 7517, "ts": "2026-06-12T15:35:42Z", "hours": 2.0622, "text": "Many thanks to Koy Camerini-Yachdav , who tested Crawssembly on Mac OS! Their efforts go towards helping more people understand how computers actually work. ❤️ In other news, Crawssembly is soon ready for the first official release. I estimate <2 weeks before a ship fully working on both Linux and Windows systems will be made!"}, {"post_id": 7381, "ts": "2026-06-12T09:39:51Z", "hours": 0.5978, "text": "File inputs are finally ready, I think craw now has all it needs for the first release. Exciting times!"}, {"post_id": 7124, "ts": "2026-06-11T22:07:29Z", "hours": 2.2083, "text": "README.md now has documentation about all commands that will be in the first release. I’m yet to make the live demo and the documentation about machine codes though!"}, {"post_id": 7034, "ts": "2026-06-11T19:54:59Z", "hours": 3.0742, "text": "Crawssembly Programs can now be force-quit by pressing CRTL+C. I should have added this long ago, but I added it in the end."}, {"post_id": 6771, "ts": "2026-06-11T10:45:07Z", "hours": 5.2019, "text": "I’ve been doing some user testing, and have made changes to the documentation and program, such as adding craw myfile.craw --dump-decoded and craw myfile.craw --tui commands easy to use and run."}, {"post_id": 6180, "ts": "2026-06-10T11:48:41Z", "hours": 21.6656, "text": "Dynamic graphic size achieved! You can now set the screen size of the Crawssembly program by running craw myfile.craw --screen WIDTHxHEIGHT using the –screen argument."}, {"post_id": 5582, "ts": "2026-06-09T13:09:25Z", "hours": 4.1789, "text": "README.md now contains enough information about Crawssembly to make it Turing Complete. The rest involves storage, input devices, and output service commands."}, {"post_id": 5471, "ts": "2026-06-09T08:19:39Z", "hours": 0.3619, "text": "Crawssembly is officially clear for Windows & Linux OS releases! Mac OS support will hopefully come soon. There may be some linux distros that are special and cause some weird and wonderful problems, but for the generic versions (Think Ubuntu) I’m confident that Crawssembly is compatible."}, {"post_id": 5456, "ts": "2026-06-09T07:45:58Z", "hours": 4.5339, "text": "Never understood what binary actually is? Why is it important, and why are binary skills becoming less important? All this, and more, is revealed in the Crawssembly Project; the ultimate guide to learning the fundamentals of real computer design, and assembly-like languages."}, {"post_id": 4930, "ts": "2026-06-08T15:11:03Z", "hours": 3.2828, "text": "More work done on the docs today. I’m assuming near-zero knowledge about computing to allow all to access the Crawssembly Project"}, {"post_id": 4319, "ts": "2026-06-07T16:05:58Z", "hours": 3.4303, "text": "Most of my efforts today are going to the README.md file, helping beginners get their heads around Assembly-like languages"}, {"post_id": 3567, "ts": "2026-06-06T15:47:13Z", "hours": 1.5453, "text": "Currently working on adding logical branching (‘if’ statements) to CRISP, my high-level language to compile into Crawssembly"}, {"post_id": 2869, "ts": "2026-06-05T18:56:50Z", "hours": 0.5139, "text": "Crawssembly - Initial Post"}]...
|
Title: Crawssembly by @The_Craw | Stardance
Devlo Title: Crawssembly by @The_Craw | Stardance
Devlogs:
Crawssembly - Initial Post
Currently working on adding logical branching (‘if’ statements) to CRISP, my high-level language to compile into Crawssembly
Most of my efforts today are going to the README.md file, helping beginners get their heads around Assembly-like languages
More work done on the docs today. I’m assuming near-zero knowledge about computing to allow all to access the Crawssembly Project
Never understood what binary actually is? Why is it important, and why are binary skills becoming less important? All this, and more, is revealed in the Crawssembly Project; the ultimate guide to learning the fundamentals of real computer design, and assembly-like languages.
Crawssembly is officially clear for Windows & Linux OS releases! Mac OS support will hopefully come soon. There may be some linux distros that are special and cause some weird and wonderful problems, but for the generic versions (Think Ubuntu) I’m confident that Crawssembly is compatible.
README.md now contains enough information about Crawssembly to make it Turing Complete. The rest involves storage, input devices, and output service commands.
Dynamic graphic size achieved! You can now set the screen size of the Crawssembly program by running craw myfile.craw --screen WIDTHxHEIGHT using the –screen argument.
I’ve been doing some user testing, and have made changes to the documentation and program, such as adding craw myfile.craw --dump-decoded and craw myfile.craw --tui commands easy to use and run.
Crawssembly Programs can now be force-quit by pressing CRTL+C. I should have added this long ago, but I added it in the end.
README.md now has documentation about all commands that will be in the first release. I’m yet to make the live demo and the documentation about machine codes though!
File inputs are finally ready, I think craw now has all it needs for the first release. Exciting times!
Many thanks to Koy Camerini-Yachdav , who tested Crawssembly on Mac OS! Their efforts go towards helping more people understand how computers actually work. ❤️ In other news, Crawssembly is soon ready for the first official release. I estimate <2 weeks before a ship fully working on both Linux and Windows systems will be made!
README.md Complete! The final steps is creating the demo! (And maybe getting MacOS working)
Crawssembly demo now working! Luckily it wasn’t as hard as I expected. I’ve tied it to an old URL for now, and it’s basic, but it works. https://demo.ultimatecraw.xyz/
I don’t usually work with frontend, so the demo won’t look anywhere near as nice as some of the other projects on Stardance, but as long as it’s usable then I’m happy.
Demo and README in working order, for real this time! The final things to do before shipping: Full macOS functionality: Maybe Add documentation to demo: Yes Add syntax highlighting to demo: Maybe Final Cleanup: Yes
Dedicated documentation website created, and the new demo is live at https://crawssembly.ultimatecraw.xyz/
My respect to real CPU designers, this is tricky work! The most difficult thing is working with the 256 different registers, that’s lots of wiring to get done.
I’m currently working on getting macOS support running. At the moment, macOS is only confirmed to work to the same level as Crawssembly Online. Hopefully I can get it to the same standard as Linux and Dos systems!
macOS can now do everything windows can except use the speakers, scan-line free graphics, and access files. These will be the largest source of my time.
File input now works for macOS Crawssembly! Run craw myprogram.craw --file myinputs.file to run! (The image is from Linux, not from my Mac because it’s too old for me to log in to stardance and post a ss from it, but I can assure you it works!)
Graphics bug fixed! Crawssembly for macOS is officially working!
I’ve been working on some examples, the biggest one being a simple calculator.
Random number generator has been added to the example group, I used XOR and bit shifts with the new command io time milli , which extracts the current UNIX timestamp in milliseconds, as the seed. Basic, but quite random from a human perspective.
I want to thank the Stardance devs for my Super Star tag! Peak staff fr
ATTENTION! The moment has arrived; The CRAWSSEMBLY Raffle! Get the chance to win a LIMITED-EDITION installer and collectable Crawssembly Disc! The disc contains the official compiler, virtual machine, and documentation. Also included are un-released legacy files from development. Simply follow Crawssembly on Stardance to enter your name! Shipping may vary depending on the UK Postal service. There are 3 physical First Edition discs available worldwide. If you’re outside the UK, I may ask you to contribute towards postage if shipping costs are high. The 3 winners will be announced on the 1st of July! So get your entry in before 23:59 UTC 30th June! Don’t miss this opportunity! Follow Crawssembly today and support open-source learning!
I’m working on a way to convert Crawssembly into native ASM language, by writing to a C file and compiling that output.
The C emitter function now works to the same standard as Crawssembly Online! In other news, I’m starting to write a Crawssembly compiler in Crawssembly ! This is a big step and proves that Crawssembly’s language is comprehensive enough to take on this task.
Basic structures are coming together for the compiler
I’ll be taking a break over the weekend, as I’ve just completed my final exams and I’m celebrating. I’ll be back proper on Monday. Today I worked on creating a trie for Crawssembly’s commands, which can be used to increase efficiency in my compiler to parse instructions faster. Rather than checking every char for every instruction like cal add -65 r01 ; if r01 = 65, this will be 0 ifz 10 ; continue if 0 cal add -70 r02 ; if r02 = 65, this will be 0 ifz 20 ; continue if 0 etc... I can split each branch into separate instructions, reducing line count and time-to-compile
Adding branches still takes a while, but it’s much more efficient than testing every character for every instruction. So far I’ve mapped 17 out of ~64 command strings.
7/24 trie branches have been added to the compiler, totalling just under 1000 lines of Crawssembly code, the longest hand-written .craw program ever made!
The trie is complete! Although I’ve still much to do for the compiler, such as per-character parsing, storage of label elements, calculation of register codes, etc…
I’ve done a little experiment with a reduced branch of Crawssembly made for tiny ISA’s, with instructions only a single byte wide! An image of what the CPU’s core might look like is shown below.
Integer parsing requires multiplication by 10, which in Base-10 is easy as you can just add a zero at the end. But in binary you can’t do this, as that would be multiplying by 2. So you need to get a bit more creative when multiplying by a known amount in binary. The code below shows how a number, ‘abc’ can be expressed as 100a + 10b + c. This is real code from my Crawssembly compiler written in Crawssembly.
The structure of the compiler is complete, but getting it to work is another beast of debugging. I think this is the first program of its kind; the first program where no one, not even me, can understand it fully. A true milestone for Crawssembly
I’m now moving onto some game examples. I’m working on a basic version of the popular game PONG, the hardest part is going to be the graphics syncing up with the mathematical logic
PONG is very almost finished, all that needs to be done is to fine-tune the computer movement and finish displaying the score.
Adding the last features for pong was quite simple, making the computer lag behind a random amount utilises the current millisecond UNIX timestamp, with the least significant 2 bits being used as the ‘reaction time’, along with a per-frame flag to increase this reaction time to solve for repeating loops. The scoring system at this point is just the number of pixels in the top corner, unlike the real pong which used numbers. Perhaps for a later version?
I’ve been working on fixing up the activities in the README.md, and providing possible solutions for each. The image below is a possible output of the activity “Smiling Screen”
RAFFLE UPDATE! The 3 discs have been completed. Soon, Crawssembly will be shipped on it’s first release! Remember to follow Crawssembly before the 1st July 00:00 UTC for your chance to win one of these beautiful pieces of computing history!
Basic syntax highlighting for nano ! Simply run craw install-nano to gain access to these beautiful new colours when editing .craw files.
Crawssembly is soon to be shipped on version 1.0.0 ! A massive milestone for a project I started ~11 months ago. The raffle discs have been burned, and final preparations are underway for release.
THIS IS IT! The moment I’ve been waiting for almost a year, the first stable release of Crawssembly v1.0.0 ! And what fortune that I get to share it with you people on Stardance!
The final updates have been made, the github is ready to ship!
No time to waste after v1.0.0 is released! I’ve added raw disk sector editing for Crawssembly; an opt-in way of reading and writing to your real disk, rather than a VM. ! THIS COULD DESTROY YOUR COMPUTER ! So only do it if you know what you’re doing, as a single bit change will probably brick your entire machine if you use the --raw-disk option
I’ve been working on a basic file system, CrawFS , used as a stepping stone towards real ones like FAT16 , FAT32 , and NTFS .
Did someone say boot sectors? That’s right, Crawssembly can now read CrawFS boot sectors and output the file table data! This took a surprisingly long time, as the binary boot sector is very delicate.
Reading a specific file is clearly much harder than reading the boot sector. It turns out that parsing user input is a devious task itself!
CrawFS reading is almost done, but I need to program a way to take a raw Unix timestamp and convert it into a nice iso 8601 format ( CCYY-MM-DD HH:MM:SS ) for the ‘Time created’ field
It turns out that time resolution is much harder than I thought! It’s taken me a while but I’ve got the program working for CCYY-MM-DD
The time program finally works! I wrapped it in a loop so it reloads every 200ms to make a real-time clock. Soon I’ll port it to the CrawFS system to read file creation dates
I’m going to confess here, I was a bit lazy. I decided that, because I could create the time program, I rewarded myself by adding a native ISO 8601 time output command io text iso rXX . Elegant? Yes. Low-Level? Not as much as I would like. But the choice was either make a single line of code to simplify programs like this massively, or wire in a tediously made, messy 350 line program that doesn’t fully account for the 400 leap year rule or leap seconds. Hmm… TLDR; I caved to simplicity. But CrawFS file listing from boot now display file genesis time!
File execution is now working! You can insert programs using execute path/to/program.craw , this leads to the Crawssembly Standard Library, a collection of useful programs that can be accessed using executestd program.craw , such as multiply or division code.
Basic multiplication and division are the first to enter the CSL! I focused on making them memory efficient rather than time efficient, because using fewer registers makes it easier for beginners to use them in normal programs. And because Crawssembly is very very quick (Almost C level speeds) a couple extra thousand ticks won’t be missed for these first programs
I’ve added more CSL files, such as math/power.craw , math/abs.craw , and math/modulo.craw
I’ve added the compare branch, for number checks. == , != , > , >= , < , and <= all included
After helping figure out the Stardance bug with projects, Crawssembly v1.1.0 is ready to ship!
v1.2.0 is already underway! I’ve spent some time constructing a cargo crate for Crawssembly to allow other rust programs to use Crawssembly’s logic. So now YOU can add Crawssembly to your programs!
Package manager is coming along… slowly. I’m still working on getting a local package to install into the global executestd file inside the home folder, but it’s taking it’s time!
Compiling from a local tarball works! I’ll be working on the database soon so users can search and download. My plan is that the program is stored as a github repo, similar to cargo .
I’ve been having some internet issues with my server recently, so my productivity has slowed. However I’m at the final testing stages of linking github repos to get craw install <package> to work. The test is done on a simple repo but it should be enough to see if it works
I’ve registered the Crawssembly Package Manager website, some SQLite problems caused some issues but I’m getting there.
I forgot to add on the hackatime projects of my time spent on the CPM and tests, mb
CPM officially works! The pipeline of Crawssembly Source -> Tarball -> Github -> CPM -> craw pkg install -> executestd functions!
My issues at the moment are about getting a command, craw pkg pack to create a CPM ready tarball of your project from the command line. That and my server is having a couple of internet issues at the moment which are hindering my progress. This devlog is also an official announcement that I won’t be as active as normal over the next week. I have family coming around so my time programming will be limited. In addition, when summer holiday starts this will continue, which is why most of my time programming is in the June and early July, the rest of stardance will have fewer updates and less time spent on casm.
I’ve been fighting with my server for a while now, the connection keeps on interrupting. As votes are currently coming in for Crawssembly v1.1.0, I suspect my score will be lower than expected due to the demo and doc websites coming offline randomly.
CPM is being difficult, I’ve gone through multiple iterations now of the craw pkg publish command, but I feel like I’m getting close.
Still not too much progress on CPM, but I’m still confident I can get it working
It turns out I was way closer than I thought! Publishing your own Crawssembly projects is now out of alpha, into beta (Because only I have an API key atm!)
I’m not good at css, but I’m trying to make the CPM website simple and easy to use. It’ll take a while but it’s slowly coming together
I won’t be as active over the next couple of days so don’t expect many updates
Thanks to @Keyboard1000n17 for making the CPM website!
Thinking about user login for the CPM, might implement this soon
Accounts are going to be tricky, more front-end stuff and some complex security back-end is going to make this tricky
Taking a break from CPM to work on some graphics libraries, drawing lines, circles etc…
Circle made 🔥
I’ve been adding line functions at the moment, to be honest it’s harder than the circle! Getting the angles right is the hardest
We have proper line segments working 🔥
The initial line algo only works for the 0-octant, but now my new and improved version works for every line angle!
I’m currently focusing on adding new functions to the screen library, such as rectangles, using the line program as a primitive
67 followers
Added a simple stack library for function calls and other uses, along with some smaller graphics programs such as screen/rectangle_fill.craw This is also my official announcement that I’ll be doing much less programming, due to summer holiday starting now. This is because I can’t program during family time, camping weeks, and other events. In addition, I have University after summer holidays, so this reduced productivity will continue throughout the rest of Stardance. Thank you all for making Crawssembly the number 1 project on stardance!
I realised that my documentation had some issues and unfinished sections, so I touched them up
I’ve been working on a IEEE 754 single precision 32-bit floating point number library for CSL, it turns out it’s more difficult than I expected!
Since IEEE 754 single precision can encode much larger numbers than a standard 32-bit binary number, you can use the library to approximate much larger values for computation
Please also star my actual github page! It’s more important than stardance followers 😤😤 https://github.com/Jonah-Crawford/Crawssembly
I’ve decided to add a heap library to complement the stack library. Doing this should make my next idea easier
Reading user input isn’t that easy compared to a language like Python, where you can just do input() . Each character has to be processed as soon as the keyboard records a press, and then saved to memory. I’m currently working on a block method that takes every 16 character you type, and allocates a small block on the heap for each press. This is going to be used for my big project
Staff, please remove the time on this devlog, I accidentally left nano open all night. Sorry!
I’m going ahead with this schema for heap blocks, the reserved bits can be used for extra features that I might want to add in later versions
I’m still working on stack allocation, the complex parts are walking the stack properly to get the headers, along with making sure I don’t corrupt any data. The image attached shows the maximum heap block size in blue, with the data taken up by the header of that block in red (top corner)
Stack allocation and freeing appear to work, but I need to do more testing to prove it
icl I’ve not done much today, mostly testing the allocation code and it looks up to spec tbh, not much to say
Once you get 1 command working, many more will follow! That’s right, a command line written 100% in Crawssembly code 🔥
I’ve been adding some very basic commands, such as exit , help , and clear
I’ve discovered that the input file mechanism is broken, so that’s great. I’ve also been adding more commands to CrawOS
Hack Club seems to have updated the rules on banner images, claiming it has to be an image of your project working. This is no issue for Crawssembly. The new banner is now the output of one of my programs, creating the banner pixel for pixel. This both compiles with the new rule, as it demonstrates Crawssembly functioning, while maintaining its identity.
I’ve been messing around with --input tag which seems to mess around a bit in the rust vm, but I think I’m getting closer to the cause
The Crawssembly community is real 🙏 I’ve been reviewing a PR on the GitHub to improve the multiplication script in the CSL ( std/math/multiply.craw )
I’ve been back working on CPM, focused on user accounts.
The account page is looking better, and it’s survived some user testing 🙏 I need to add some boring stuff though like API key listing and said key management
Package creation and accounts are now working (theoretically) from the command line 🔥
@imakebloatedcode Thank you for your pr for CPM to include OpenAPI scemata, another great addition from the Craw Systems community Most of my time has been reviewing it and making small edits to include the security auth headers for API keys Official Announcement I’m not going to be online through the 5th August to the 10th August, I’ll be camping for those 5* days in a very low-data spot, and I’m almost certainly not taking my laptop. I might be able to get a tiny amount of code on my phone to keep my streak but certainly not enough to engage in my normal conversation on slack or post devlogs
I’ve added Markdown support for CPM packages 🔥
I’ve made publishing packages super easy now, all you need to do is craw init to create the package, and then craw pkg publish . As long as you’re signed into CPM and gh, it’ll just work
I’ve been working with @BetterClient to inprove the program counter and bringing back fgo from casm beta. This is also a reminder that I’ll be OOO until next Monday.
I’m back from camping! (RIP my 60+ day streak) My plans going forward immediately is improving program counter modifications to allow for higher-level concepts to be bootstrapped onto Crawssembly instruction sets. (Image unrelated)
I’ve merged the new fgo rules to the project, so now fgo points to labels similar to jmp , but fgo 0 now jumps to the label defined in r01 I was having some issues with using git but I got them sorted
I’ve separated the old sleep command into sleepms for millisecond waits and sleepus for microsecond waits. Although, microsecond precision is highly dependent on the OS, so it won’t be as accurate as sleepms for smaller values (Say, n<50)
Sorry for the but it’s been a hectic couple of days. I got into University! I’ve also been busy taking a look at a CGOL implementation, truly amazing stuff! Go check it out: https://github.com/srxcode/game-of-life-crawssembly
I’ve added io keyboard mod to create a bitfield of modification key presses for the keyboard device, so now keys like CTRL and TAB can be handled, which lays the foundation for my next project which is making a basic file editor in casm
Lots of work today, sorry for the . I’ve been struggling with the text editor, heap buffers, cursor allocation, character addresses, etc etc… ad infinitum. However, I’m getting close. Rendering is outputting something, although I don’t know why typing doesn’t seem to add anything…
For some reason, I’ve been banned on slack. I don’t know why, since no one will tell me. This is not good news, but luckily it doesn’t seem to be a stardance-wide ban, so I can still do the hackathon.
Still no clue why characters aren’t being saved to memory in my free heap block Slow day today fr
I’m finally getting somewhere with the editor, however I’m now having issues with character deletion, and adding characters inside empty newlines
stardance
I’ve brought run back from the dead. You can now use run rXX to run a binary value inside the input register as a Crawssembly instruction
I’VE ACTUALLY DONE IT 🔥 Networking is now officially part of Crawssembly. Alpha tests on localhost have all passed
HTTP requests working 🔥 ts is so peak icl
I’ve been doing much more testing and implementing the network device. Specifically testing the following commands: io net ip , io net addr , io net connect , io net socket , io net port , io net listen , io net accept , io net send , io net protocol , io net block , and io net recv .
I’m back! Fraud Squad unbanned me so WE are all having a party at my house Although I can’t use nano apparently anymore… so Crawssembly will be having it’s final ship very very soon
It has come to my attention that not everyone who has followed Crawssembly has starred it on GitHub! Please, if you like my project, star it on GitHub at https://github.com/Jonah-Crawford/Crawssembly Thank you.
idk where these extra hours are coming from, but as long as I don’t ship them, they won’t count towards stardust so I’ll be fine. In the meantime, enjoy craw slop
Ships:
Crawssembly: The beginner’s gateway to low-level thinking. "Programming languages are a lie!" This is Crawssembly, a project that’s been in production for almost a year. It is an educational assembly-like programming language that teaches users how computers actually work. Programming languages like Python, Ruby, and Java pull the wool over your eyes by abstraction and simplification. Crawssembly is the first step to seeing clearly.
Crawssembly v1.1.0 ready to ship! “Programming languages are a lie!” This is Crawssembly, a project that’s been in production for almost a year. It is an educational assembly-like programming language that teaches users how computers actually work. Programming languages like Python, Ruby, and Java pull the wool over your eyes by abstraction and simplification. Crawssembly is the first step to seeing clearly.
CRAWSSEMBLY - New and Improved! “Programming languages are a lie!” This is Crawssembly, the number 1 project on all of stardance! It’s a project that’s been in production for over a year. It is an educational assembly-like programming language that teaches users how computers actually work. Programming languages like Python, Ruby, and Java pull the wool over your eyes by abstraction and simplification. Crawssembly is the first step to seeing clearly. What is new? INTERNET SOCKETS! CRAWOS COMMAND LINES! DYNAMIC LABEL JUMPING! IMPROVED DEVICES! DEDICATED PACKAGE SHARING WEBSITE! AND MORE! Check it out for yourself! (Shipped early due to Fraud Squad limitations, Crawssembly is too powerful for Hack Club)...
|
1792839280.3425412
|
1792925680.3425412
|
|
1983
|
rasterminal by @PavolUlicny | Stardance
|
PavolUlicny
|
1
|
470.39
|
8580
|
[{"ship_num": 1, "ts": "2026-0 [{"ship_num": 1, "ts": "2026-09-08T16:24:17Z", "hours": 449.0, "multiplier": 19.99, "payout": 8580, "blessing": "neutral", "text": "rasterminal rasterminal is a 3D model viewer in the terminal Why i decided to build it The original idea didn’t really have any big inspiration, I’ve just always been fascinated by the inner workings of 3D and how that all works. I’ve been wanting to build a project involving 3D for a while and I didn’t want to make just another program that uses libraries and GPU drivers to do all the work. So I came up with the idea: a software rasterizer that renders in the terminal! There are lots of TUIs and lots of boring old software rasterizer projects, so I just combined the two into something unique. And over time, I realized I could make it an actually useful tool, with no real competition: a 3D model viewer in the terminal. Sure, there are some similar projects on GitHub (like taigrr’s trophy), but none are actually usable with heavier models or support pixel graphics. What I learned I learned a lot. I really mean a lot. Anything from math and rendering to how terminals work and how to control them using escape sequences. I don’t want to sit here and name everything I learned over the period of the last 5 months, but I can confidently say that this project really taught me how much work goes into everyday software and how to actually develop and maintain a project professionally. The future of rasterminal The whole project is very far from done. You can see that from the latest release version: v0.1.0-alpha.2. I’ve got a lot of work to do and I’ve roughly got the major landmarks mapped out. Main things I definitely want to change/add at some point before v1 are: Add animation support (currently can only render still meshes) Complete the renderer (complete support for basically every feature of every format that makes sense to support) Add optional GPU acceleration (after I’m satisfied with everything else) Hardware / OS support Supports every major OS (Windows, Linux, MacOS, and any other POSIX-based OS, so practically everything), and every CPU that I could think of (any architecture, 32 or 64bit). You would have to actually try a to find a platform that it doesn’t support (most of the unsupported hardware are big-endian systems, which are basically phased out completely). This is one of the main goals of the project, so (almost) any modern machine with a terminal can run it. Special thanks Special thanks to anyone who followed, liked, helped, or otherwise supported the project in any way. I wouldn’t have had the motivation to push it this far if it wasn’t for you guys.", "repo": "https://github.com/PavolUlicny/rasterminal", "demo": "https://github.com/PavolUlicny/rasterminal/releases/tag/v0.1.0-alpha.2"}]...
|
[{"post_id": 70278, "ts": "202 [{"post_id": 70278, "ts": "2026-09-18T21:10:51Z", "hours": 6.11, "text": "Code quality and CI improvements Finally did the long overdue main loop refactor. The main loop is now way shorter, more readable and more testable. I just split off some of the main loop’s work into it’s own modules, which made them way better looking and also, since they are now standalone modules, actually testable. A big win for repo structure. In the process, I also replaced the input handling’s long if chain that made each character do it’s job with a switch statement. It’s more readable and theoretically faster, although since I compile it with -O3, it probably made no difference or an unnoticeable one at best. I also finally fixed the super long CI times. Until now, CI used to take ~50 minutes (depending on how fast the GitHub runner was) because of cppcheck. Everything else finished in under 10 minutes, but cppcheck stalled it for an hour. It was stalling in mesh_assimp.cpp (the assimp wrapper) for most of it’s runtime. I always thought it was because assimp is a very large library. So I experimented with it a little. I included everything I include in the wrapper into a test file with a little code and ran cppcheck on that. It finished in less than 10 seconds. Eventually, I found out it was somehow taking that long because the main loader function was too long and handled too much by itself. So i just refactored it into 3 separate functions, without changing the behavior at all. Somehow, I still don’t get why, it reduced the whole cppcheck run to 9 minutes. a more than 5x improvement, just because I split a function into more functions. I’m not complaining, but it’s definitely weird. CI is now way faster and adding new things is gonna be way smoother now."}, {"post_id": 68728, "ts": "2026-09-15T17:06:41Z", "hours": 6.6975, "text": "Miscellaneous fixes and improvements Fixed two races in platform code (one MacOS, one Windows) Removed build flags that disabled some compiler security hardening at the cost of a little performance Fixed the test framework to not freak out on NaN in near assertions Improved thread launching and handling in loaders and renderer So overall just boring fixes and improvements, nothing special."}, {"post_id": 66825, "ts": "2026-09-12T18:42:57Z", "hours": 8.5847, "text": "Refactored the platform layer The whole platform layer was just one file until now. Since I did a lot of work on it recently, it grew to over 2400 lines of code. It was super confusing and disorienting. So I decided to refactor it (split it) into 8 files, based on what they handle: console.h - saving/restoring terminal state control.h - termination signal handling file.h - file operations (64bit) input_reader.h - handling input (not parsing, that is it’s own file) shared_memory.h - shared memory handling for the kitty protocol terminal_io.h - writes output to the terminal terminal_query.h - querying the terminal for things like graphics capability, etc. timing.h - frame timing and sleeps"}, {"post_id": 64252, "ts": "2026-09-08T14:55:07Z", "hours": 2.3467, "text": "Last pre-release checks and cleanup I’m finally ready to release v0.1.0-alpha.2. Only notable thing I changed here is that I changed the default thread count: It now defaults to hardware concurrency everywhere. Other than that, I of course did final documentation checks and fixes and now I’m just waiting for CI to pass so I can tag it and let the release workflow do the last step. So this is hopefully the last devlog before my ship!"}, {"post_id": 63837, "ts": "2026-09-07T20:19:19Z", "hours": 10.4164, "text": "Did some polish and cleanup of the platform layer Did final polish and cleanup of the platform layer since I want to actually finally cut a release relatively soon and I just did a lot of work there. Fixed things like useless tests, outdated or wrong comments and some platform specific quirks. Probably actually gonna cut a release soon (this time for real). Also added early rejections for BVH and CSM files, since they contain no model geometry (they can’t currently be displayed at all) and documented the change. The code is basically done (hopefully, I really don’t want to find another big gap that’s gonna take a week to close), I just want to correct anything wrong in the README, changelog, manpage or help menu and maybe make them look a little better before cutting a release and shipping."}, {"post_id": 62122, "ts": "2026-09-05T11:43:50Z", "hours": 9.5678, "text": "Working on SIGSTOP and SIGCONT handling SIGSTOP and SIGCONT are POSIX signals for stopping and resuming a running process. I’m working on adding handling for these, so you can safely pause and unpause rasterminal at any time. This is a lot of work, since until now, we just set up the terminal on program start and cleaned up when the program exited. There’s a lot of quirks and weird scenarios that I have to handle, for example if another signal gets sent while cleaning up the terminal for SIGSTOP. I’m trying to catch as many edge cases by just doing random things while using the program and also with the help of AI to come up with potentially uncaught scenarios."}, {"post_id": 59763, "ts": "2026-09-01T18:10:34Z", "hours": 4.3639, "text": "Added handling for SIGINT, SIGTERM, SIGQUIT and SIGHUP I don’t really have much to say here, I just added the full per-spec handling for all these. Only remaining POSIX-only gap is now SIGSTOP/SIGCONT (stop/resume process). I’m also starting school now, so I’ll be working on this less."}, {"post_id": 58964, "ts": "2026-08-31T15:12:04Z", "hours": 3.8394, "text": "Fully fixed and merged the first POSIX cleanup item Well, would you look at that! That took significantly less time than the Windows fix. It is partly because it was a smaller fix and only part whole POSIX fix, while the Windows one was the whole thing and also the foundation had already been laid out from the Windows work and I just integrated the POSIX path into that, but it is also very much because Microsoft is a horrible, terrible company that can’t make good software. I mean, look at GitHub, they have been going downhill ever since they got acquired by Microsoft. Now that I got that out of my system, here’s what was fixed: If the program cannot enable raw mode at startup, it safely fails instead of continuing and corrupting the terminal state If the cleanup gets interrupted, it retries cleanup so it doesn’t leave the terminal state corrupted after one failed attempt Onto the next POSIX fix: handling SIGQUIT and SIGHUP."}, {"post_id": 58269, "ts": "2026-08-30T17:14:59Z", "hours": 8.6936, "text": "Merged the full Windows console restoration branch My nightmare is over. I hopefully won’t have to deal with Windows for a while now. Summary of what is now fixed/handled on Windows: Ctrl+C, Ctrl+Break and Q exits fully recover the terminal’s state Ctrl+C and Ctrl+Break don’t leak mouse escape sequences into the next prompt if you terminate while actively dragging a model A bunch of other minor Windows or cmd.exe specific quirks Only thing that isn’t handled (didn’t find a good way to handle it) is task manager “end process”. It kills the program without cleaning up and sometimes freezes the shell."}, {"post_id": 56881, "ts": "2026-08-28T21:26:16Z", "hours": 9.6883, "text": "I HATE WINDOWS Windows just doesn’t work. It doesn’t work. Nothing works on Windows. Everything breaks. I don’t get it. THE UNIT TESTS PASS ON WINDOWS CI BUT WHEN I ACTUALLY RUN THE TESTS ON WINDOWS IT FAILS????? HOW IS THAT EVEN POSSIBLE. The release is now definitely getting delayed by at least a week because I keep running into more and more and more and more and more and more and more and more and more issues. I hate Windows. Microslop is the only company that could mess up a basic terminal emulator. And I also have to reboot my PC every time I fix something and push it and then reboot to get back to linux. this is torture. At one point I tried to do it on a Windows VM on linux but that was too slow so I just gave up."}, {"post_id": 55585, "ts": "2026-08-27T15:06:53Z", "hours": 8.8714, "text": "Found a bunch of terminal cleanup gaps Most of them are Windows or cmd.exe specific (nothing ever works on Windows), but some are present on POSIX too. The Windows specific ones are: cmd.exe for some unknown reason doesn’t turn off the raw input sequences, so arrow keys don’t work like they should, even though I explicitly turn it off (????????) (I hate Windows, they always have to do something unexplainable for no reason just so your code doesn’t work as it should) when you terminate the program with ctrl+c or ctrl+break while actively dragging the model around, it sometimes leaks mouse escape sequences into the next prompt bunch of other weird small stuff that nobody cares about And the few on POSIX are mostly ctrl+z suspend/resume behaviour not recovering the terminal and the same thing with ctrl+\\ (SIGQUIT). I’m still working on fixing these. Most of the windows ones are already fixed, but I haven’t even started with the linux/POSIX ones. I have postponed the planned release to when I fix these + any other issues I find."}, {"post_id": 54695, "ts": "2026-08-25T19:14:01Z", "hours": 10.7308, "text": "Cutting a release The repo is in a pretty complete and polished state, so I’ll cut a release here. This will also probably be the last release before I ship, so I’m making sure that nothing is broken and everything works on every platform. I’ve still got a lot of work to do though, even after the end of stardance, like animations, glTF PBR, format completeness for every format, GPU acceleration, etc."}, {"post_id": 53861, "ts": "2026-08-24T15:48:08Z", "hours": 10.9639, "text": "Merged the full assimp integration into main I really don’t have much to say here, I’ve already put all the info about the branch into the past devlogs. All the formats work and the wrapper is very sturdy. I’ve found more bugs in assimp itself than my code (devlog on that soon). So, rasterminal can now load basically any 3D model you throw at it. Some of the formats assimp supports are so niche, I’ve never even heard of them."}, {"post_id": 53278, "ts": "2026-08-23T18:46:58Z", "hours": 13.1411, "text": "Fuzzing my assimp wrapper I’m trying a bunch of hand-crafted models from all the formats that I can load and trying to find things that dont load or render properly. Also had AI write me a simple fuzzer in python and I’m just letting it run for a few hours. Also auditing the assimp loader paths against my wrapper to find any format specific behaviour that should be handled. I’ve already found a bunch of things and I’m still finding more. Assimp has a lot of weird quirks and issues that I keep running into. Honestly kinda regretting the decision to integrate it, but since I’m already so deep in, I’ll just keep going."}, {"post_id": 52574, "ts": "2026-08-22T19:13:37Z", "hours": 11.0969, "text": "Still working on the assimp intgration Currently trying various models from all the different model formats that assimp loads. So far found a segfault, some weird behavior and integration mistakes that I made. Also found a small bug in assimp itself, for which I’ve submitted the PR with the fix to their GitHub repo. For anyone interested, here’s the PR: https://github.com/assimp/assimp/pull/6799"}, {"post_id": 51884, "ts": "2026-08-21T19:41:32Z", "hours": 6.9825, "text": "Working on assimp integration Yop, I’m adding the Open Asset Import Library as a fallback for any model formats that aren’t natively supported with their own dedicated loader (only ones with dedicated loaders are glTF2, PLY, STL and OBJ). I’m still keeping the dedicated loaders, because they are more feature-complete, to-spec and wayyy faster (especially the glTF one). I added it because I feel like for a 3D model viewer, support for many formats, even niche and obscure ones, is pretty important, even though nobody might use them. This roughly doubled compile time and almost quadrupled binary size, which also made CI take way longer (of course). It somehow made the MacOS runners take 50 minutes to compile (from the previous 3 minutes), but I fixed that by bounding the number of processes CMake can spawn to the number of threads on the runner (previously was using -j which spawns as many as it wants and it was spawning about 230 of them). I’m still testing how it handles various model formats and trying to find any reachable segfaults."}, {"post_id": 51275, "ts": "2026-08-20T20:14:42Z", "hours": 6.7119, "text": "Cleanup and restructuring changes After I just merged three big feature branches (kitty and sixel graphics protocols and the high-res performance branch), I needed to do some overdue cleanup and refactoring. And so I did: Collapsed the super long changelog entries into way more readable and legible points Restructured the src directory into multiple subdirectories because it had like 50 files already Sadly completely removed the Make build system, so now you can only build with CMake (CMake is very much evil and even more evil but it’s the only one of the two that supports windows and I was tired of managing two build systems) Removed the –graphics-scale flag, so now everything renders at native resolution And some small docs and comment cleanup"}, {"post_id": 50683, "ts": "2026-08-20T00:07:13Z", "hours": 12.3297, "text": "Finally merging the performance branch It’s finally time to merge the performance branch. I basically redesigned the whole renderer and rasterizer around high resolution workloads, where it would still choose the old high-poly paths where they were faster. Even snuck in some SSE2 SIMD code (picture), although I will probably be switching to a dispatch SIMD library like Google’s Highway. Not entirely sure it will be Highway or even if I will do that yet, that depends on the code complexity and before/after benchmarks."}, {"post_id": 49184, "ts": "2026-08-17T20:28:00Z", "hours": 14.5689, "text": "Still optimizing… Spent the first ~7 hours trying to find microoptimizations and each one was either a wash or worse somehow. The compiler works in mysterious ways. At some point, I just gave up and let Claude have a go at the optimizing. Surprisingly it actually came up with a lot of interesting optimization techniques and solutions that I definitely couldn’t have come up with on my own. But it found so much, that the whole diff adds 5k lines of code. So now I’ll be cleaning up, testing, and maybe further optimizing that diff…"}, {"post_id": 48227, "ts": "2026-08-16T15:09:59Z", "hours": 3.5944, "text": "My reported bug in libtermkey has been fixed in the newest version Just got an email from one of the maintainers that the crash bug i reported a month ago was fixed in the new release. libtermkey is a terminal input parsing library that I considered using and found a crash bug in. The bug was already fixed in neovim’s fork of the library, so i just pointed the maintainers at that fix. For anybody interested, here’s the issue link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1142891"}, {"post_id": 48078, "ts": "2026-08-16T11:20:07Z", "hours": 11.47, "text": "Working on improving performance With the addition of the high-res protocols, the target resolutions quickly went from hundreds or thousands of pixels to millions. So I now desperately need to improve performance. So far it’s looking promising: A whole model covering the camera 6 moving at 4k went from about 8 fps to 20-30 fps. Not ideal yet, but I think we’re on the right track. Super dense meshes (more than 2 million polygons) improved 2-3x Meshes with transparent parts improved about 2x While these wins may seem really big (they kinda are), the jump in resolutions still means they are barely usable interactively. I do want to add gpu acceleration later (with the cpu path as a fallback), but until then I want to make it as fast as I possibly can."}, {"post_id": 47112, "ts": "2026-08-14T19:18:15Z", "hours": 9.0333, "text": "Fully merged sixel Fully merged the sixel protocol implementation. Works on all platforms everywhere that supports it. So now both high-res terminal protocols done. Moving onto other minor things and especially performance."}, {"post_id": 46486, "ts": "2026-08-13T18:38:49Z", "hours": 10.6753, "text": "Working on adding full Sixel support Working on adding support for the other mainstream terminal pixel protocol of the main two - Sixel. Already did fully implemented the kitty protocol last time, so once I’m done with this one, I’ll be done with terminal protocols (at least for the near future, hopefully). There are some other ones like the iterm2 protocol, but that one’s pretty rare and I won’t add it unless I really don’t have anything better to do. It’s basically done, just need to polish it and test it on a bunch of terminals and operating systems to make sure everything works before merging."}, {"post_id": 44676, "ts": "2026-08-10T16:23:20Z", "hours": 4.0767, "text": "Fully merged and done with Kitty Finally completed the kitty protocol implementation. It is kinda slow, since the resolution is so much bigger, so I will try to optimize the high-res performance even more. So now the next two big milestones are: Add Sixel on top of kitty, that’ll be a lot of work Optimize the rasterizer even more I was thinking of maybe adding gpu rendering as an option for super large meshes or high-res scenarios, but idk. I’ll definetly keep the pure cpu renderer for computers without gpus, but I’m not sure about a gpu implementation. It would be hard to do, less portable and it might not even work that well."}, {"post_id": 44513, "ts": "2026-08-10T09:59:08Z", "hours": 6.8483, "text": "Found a bug in Ghostty’s kitty protocol handling Ghostty is a modern and fast terminal emulator that i personally use. While testing the kitty protocol feature in rasterminal, I found a Ghostty bug that lagged my whole computer after a few minutes. I tested it in Kitty (terminal emulator) and there it worked fine. I looked at Ghostty’s code vs Kitty’s, found the bug and reported it to the Ghostty maintainers. Mitchell himself (the creator) fixed it in like 2 hours. Honestly I’m kinda sad I didn’t get to become a contributor and fix the bug, but since it was a small fix and I already described it in the issue, I get why Mitchell just fixed it in main. Here’s the full issue: https://github.com/ghostty-org/ghostty/discussions/13719"}, {"post_id": 43513, "ts": "2026-08-08T20:35:37Z", "hours": 7.6361, "text": "Working on adding support for the Kitty protocol Some modern terminals like Kitty and Ghostty have support for the Kitty protocol. It’s a feature that allows you to display high resolution content like images and videos in the terminal without it looking super pixelated. There’s also the Sixel protocol, which is basically the same thing but a little worse and more widely supported (even Windows terminal has it). I’ll add Sixel after i merge Kitty to main. It is very clearly a worthwhile feature and I have been planning to add it from the start of the project. Today I finally decided that it’s time. Most of the work is already done on the branch and i’m just polishing out the bugs and issues before I merge. In the photos, you can see the comparison between using just the block characters and using Kitty. It is a night and day difference. Although the performance isn’t great at that high of a resolution, but I’m still working on optimizing that."}, {"post_id": 42752, "ts": "2026-08-07T17:00:51Z", "hours": 3.5125, "text": "Minor comment cleanup Just did some comment cleanup: Deleted redundant comments and why comments Removed separator comments Compressed or rewrote some really long comments (without removing the info they give)"}, {"post_id": 42161, "ts": "2026-08-06T19:24:06Z", "hours": 8.2153, "text": "Added issue templates + contributing documentation Added templates and a config for submitting GitHub issues, for both bug reports and feature requests. Also added a CONTRIBUTING.md for clear instructions on how to make, structure and audit code contributions. (tests, linters, formatting, etc.) I tried to make some optimizations to the renderer by auditing the compiler generated assembly and looking for inefficiencies, but everything i tried turned out to actually hurt performance. And GitHub actions decided to have a major outage right when i pushed the commits, so that’s awesome"}, {"post_id": 39599, "ts": "2026-08-02T18:05:04Z", "hours": 7.4436, "text": "Completely redesigned and rewrote the HUD The HUD used to be just a single line at the bottom of the screen aligned to the left. It looked pretty bad, but it did tell the user everything they needed to know. [picture 1] First, I added model name sanitization, so models with control bytes like newline ( \\n ), line feed or other symbols like emojis can’t break the whole program when trying to display them in the HUD. Then, I completely redesigned the whole HUD to look better and be more robust, while still telling the user everything they need to know. I went with this design [picture 2]: On the left, you only have the model name. In the middle, first you have the current shading mode (highlighted in cyan), then the lighting mode in plain white and then the background color in gray. All three middle indicators are separated with a dot and are different colors, so nobody can confuse them. On the right, there’s 3 boolean indicators: spin (if the model spin is on), backface cull (if it’s currently culling backfaces) and texture (if it’s showing the texture, isn’t there at all on models without a texture). They are gray if inactive and cyan if active. The last thing on the right is just the fps number. There can also be optional indicators: Wireframe color (in the middle, after the shading mode) which only shows up in wireframe mode. [picture 3] First person speed multiplier (on the right, between the bools and the fps number) which shows up only in first person mode. [picture 4] I also made each “island” cleanly disappear when the terminal’s width is too low instead of just slowly getting cut off letter by letter. I think this design looks better, less cluttered and is pretty easy to understand at a glance. I would very much appreciate a star on GitHub!"}, {"post_id": 38478, "ts": "2026-07-31T21:36:35Z", "hours": 7.7572, "text": "Did a smaller fix and added a pretty big feature First, let’s talk about the small fix: I Fixed a super long model name showing up in the HUD in it’s full length, often blocking out other HUD elements. Previously, the HUD would display a model name of any length. Now there’s a hard cap of 24 chars, with any name longer than that truncated (middle style truncation) to fit into that limit. And now the big feature: Added a first person noclip-style camera mode. It’s accessed with the –first-person flag and let’s you explore the model as a floating camera (not bound like the default orbit camera). It was honestly easier to implement than I thought it would be. With it, I added two new keybinds special to the first person mode - E and V for going up and down. They don’t do nothing in orbit mode. Also added a second –first-person-speed flag for controlling the initial movement speed. It is also controllable during runtime with scrolling or +/- (I didn’t know what to bind these to in this mode since you can’t zoom like in orbit mode and this was the only place where they fit). In the photos, you can see some angles taken in the first person mode that weren’t possible in the default orbit mode."}, {"post_id": 37806, "ts": "2026-07-30T19:08:29Z", "hours": 2.7436, "text": "Finally committed and pushed the input rework Tested it on both linux and windows and everything seems to work. No inputs interpreted as other inputs, all edge cases handled, just works. Finally can move onto other things."}, {"post_id": 37656, "ts": "2026-07-30T15:25:21Z", "hours": 9.285, "text": "Still working on the input parsing system It is very hard and I keep finding bugs and reasons to redesign it. I’m in pain. I do think I’m getting closer to the final robust design."}, {"post_id": 36697, "ts": "2026-07-28T22:28:53Z", "hours": 9.9361, "text": "Working on completely rewriting the current input parsing handling The current input handling is subpar at best; it interprets a lot of random keys as escape, which currently quits the program (This will also be changed to Q and Ctrl+C only. Kind of a no-brainer since this is the more standard choice for TUIs - for example btop - and it also means I don’t have to deal with the headache of distinguishing function keys and others from escape) and has a lot of other quirky behavior that needs fixing. I’ll also try to improve robustness against malformed input like a leaky SSH session. There are a lot of various edge cases and situations where you have no way to distinguish real input from malformed input. This is all a very major pain in the ass. And I thought figuring out the raw mode output would be the hard part. And after all this, I’ll end up with way less attention than strictly slower, less robust competitors, just because they already have an audience from other projects. I bet nobody will even read this. I’m basically talking to myself right now. Or maybe, just to spite me, the algorithm will push this more than my other devlogs."}, {"post_id": 35924, "ts": "2026-07-27T17:55:43Z", "hours": 8.7953, "text": "So, i found two memory bugs in a widely used terminal input library I was researching terminal input libraries to use for this project because my current approach was so buggy that it wasn’t worth fixing. Both of them are memory bugs in the libtermkey library. There are forks of the lib with this fixed, but since many projects still rely on this lib, i submitted them anyways. I’ve also confirmed that the bug is present on my machine on Ubuntu 24.04 LTS on Neovim, because it links the vulnerable shared library. I didn’t mark them as CVEs (hopefully that isn’t a problem). If anyone want’s to look at the bug reports, they are at https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1142891 and https://bugs.launchpad.net/ubuntu/+source/libtermkey/+bug/2161916"}, {"post_id": 33607, "ts": "2026-07-23T17:38:48Z", "hours": 4.5575, "text": "Added more CLI flags for startup customizability Added flags to set the camera pitch, yaw and zoom on startup. Now every runtime-settable variable can be set during startup through the CLI. The R button now resets the state to the CLI set state, not to factory defaults."}, {"post_id": 32607, "ts": "2026-07-21T21:48:11Z", "hours": 4.4442, "text": "Added –spin-speed and –spin-direction flags Added CLI flags for the spin speed and direction. The speed is in deg/s and the directions is simply left or right. Here’s what 1000 deg/s looks like spinning to the right:"}, {"post_id": 30923, "ts": "2026-07-18T22:17:24Z", "hours": 8.6892, "text": "Did a bunch of small code quality and usability improvements Fixed a Windows bug that crashed the program on model sizes bigger than 2GB, improved the orbit usability (fixed mouse drag behavior when models are turned upside down), and did a few cleanups and fixes in the CLI parsing. I’m planning on adding a few CLI flags that I think can be very useful for some people, specifically better spin settings, starting camera angle/zoom control and a few more."}, {"post_id": 29772, "ts": "2026-07-16T21:27:23Z", "hours": 0.7175, "text": "Finally merged color-fallback, I can move onto other things The branch is finally merged. I’ve accumulated a bunch of usability and code quirks and issues that i can finally get to now that the branch is merged. So now I’ll be reworking all the CLI flags, camera and other components. And we also passed the 700 commit mark with this merge!"}, {"post_id": 29484, "ts": "2026-07-16T13:40:29Z", "hours": 4.9444, "text": "Changed the 24bit to 256 color palette conversion logic Until now, the conversion picked the closest color possible mathematically. But from testing on a bunch of different models, I’ve realized that it doesn’t actually look very close to the human eye. So I swapped it out for a different method, called CIELAB distance. Now it still doesn’t look perfect, but as a fallback for older terminals it’s close enough."}, {"post_id": 28408, "ts": "2026-07-14T17:26:16Z", "hours": 9.2258, "text": "Working on a –color compatibility flag The color terminal compatibility thing I was working on has landed in the branch, now I’m adding a –color flag to override the automatic capability detection for situations like ssh, where we almost always degrade to the 256 color pallete for maximum compatibility. So now you’re gonna be able to use the right color mode even if the automatic detection is wrong for your situation."}, {"post_id": 27302, "ts": "2026-07-12T19:23:17Z", "hours": 10.3522, "text": "Working on terminal color capability detection I am adding automatic terminal capability detection, meaning that rasterminal will get the terminal type and either refuse to render on super old or “dumb” terminals, degrade on some terminals and render normally on modern ones."}, {"post_id": 24314, "ts": "2026-07-07T20:18:01Z", "hours": 5.1908, "text": "Working on adding 256 color support Some older terminals can’t display full 24bit RGB colors and use a 256 color palette instead. I’m adding a fallback so the older terminals can still use rasterminal. It still calculates the full old RGB colors, but then just maps them to the nearest 256 color with LUTs. On a side note, I switched my terminal emulator from Kitty to Ghostty."}, {"post_id": 23070, "ts": "2026-07-05T20:10:12Z", "hours": 10.4403, "text": "Working on portability Did a bunch of small fixes and improvements in the last ~week. Right now I’m on vacation for the next couple of days, so I won’t be active. I am currently working on broader terminal and platform support, so older systems and terminals will be able to run cleanly with some fallbacks or will fail loud with a clear message about what isn’t supported."}, {"post_id": 19371, "ts": "2026-06-30T17:34:50Z", "hours": 5.1925, "text": "Completely removed the shadow map Before, rasterminal built a shadow map on model load and displayed it during runtime. I now completely removed it, because it was slower during load, slower during runtime, sometimes looked broken on curved surfaces and added essentially no value. Here, the first picture is with the shadow map and the second is without."}, {"post_id": 18685, "ts": "2026-06-29T21:27:29Z", "hours": 13.4722, "text": "Wasted 7 hours of my life Did a bunch of smaller cleanups and fixes, and then I tried to template the unlit and lit paths in the rasterize_flat function, which turned out to be a performance regression. Awesome."}, {"post_id": 17021, "ts": "2026-06-27T17:00:39Z", "hours": 5.7733, "text": "Added a release workflow, manpage and changelog I added a github release workflow that works alongside the changelog and released the first pre-release version: v0.1.0-alpha.1 Also added a manpage and an install target to make and cmake that installs the binary, docs and manpage into the path."}, {"post_id": 16313, "ts": "2026-06-26T15:28:43Z", "hours": 5.1883, "text": "Pararelized the wireframe shading mode I did a bunch of small things alongside it, but the main feature for this devlog is the pararelization of the wireframe shading mode. It was previously fully single threaded, but it wasn’t that hard to pararelize, i just had to make the function it used to write into the framebuffer (draw_line) CAS atomic, to avoid race conditions. Now wireframe is the fastest shading mode in basically all scenarios. Below, you can see a performance benchmark (built into rasterminal using a flag) with wireframe mode on a super dense mesh and how the wireframe mode looks like (you can also cycle the colors)."}, {"post_id": 15932, "ts": "2026-06-25T21:35:36Z", "hours": 1.9053, "text": "Split the tests into sub-directories The test suite is now very long (20k LOC across 47 files), so i decided to split it into sub-directories instead of just having 47 files in one flat dir. It’s cleaner, more maintainable and looks better."}, {"post_id": 15741, "ts": "2026-06-25T16:48:43Z", "hours": 4.9903, "text": "Completely removed gouraud shading mode Gouraud was previously the main shading mode, but now I’ve just completely removed it. It was by far the slowest, while not adding any actual value to the project. Blinn-phong lighting is faster AND it supports more features (normal maps, etc.), so there was just no point in keeping gouraud. Now that I’ve removed it, the project has less code to maintain and a faster default shading mode with more features."}, {"post_id": 15551, "ts": "2026-06-25T08:50:38Z", "hours": 3.7597, "text": "Added proper OBJ bump map support OBJ bump maps are textures for simulating bumps and wrinkles on models. Blender used to author bump maps as normal maps for some reason, so I made it automatically detect if it’s a normal map disguised as a bump map and handle it well, since there are a lot of old Blender OBJ models in the wild. But it also handles bump maps as bump maps normally, so it’s basically the best of both worlds."}, {"post_id": 15117, "ts": "2026-06-24T15:43:58Z", "hours": 6.87, "text": "Added texture transform into the TEXCOORD branch and merged it into main Not that hard, just read it, pass it to the rasterizer and then display it. I did have a very sneaky bug in the loader that made the whole feature render wrong, where I just had to negate one value to fully fix it, but now everything fully works. Below you can see the Khronos test asset for texture transforms. (tick means fully working, clearcoat is not yet implemented so it doesn’t show as working)"}, {"post_id": 13839, "ts": "2026-06-22T17:59:12Z", "hours": 5.2097, "text": "Added TEXCOORD_1 support glTF sometimes authors a second TEXCOORD set (first one is TEXCOORD_0, 0 indexed numbering). The official spec only requires support for the first two TEXCOORD sets, even though there can theoretically be any number of them in a model. That said, major model exporters don’t author any more than the two sets, so to avoid extra work, I only added support for 0 and 1. (not merged into main yet, I want to polish it a little and maybe add KHR_texture_transform support on top of it first)"}, {"post_id": 12798, "ts": "2026-06-20T22:37:18Z", "hours": 7.6314, "text": "Optimized the transparent cleanup path in the renderer After rendering the model in the transparent path, we have to resolve the transparent pixels, which basically just pastes in the pixels behind it and sometimes tints it based on how dark and what color the transparent material is (tinted glass will make the things behind it darker, normal glass will be mostly completely untinted). Before, the resolve function looped over every single pixel in the frame, even non-transparent and background ones. This is obviously wasteful. So I made it find the smallest box, in which all the transparent pixels of the whole frame fit and just looped over that. It recovered the overhead of the transparent resolve on models with smaller transparent parts, but it also made fully transparent or mostly transparent models slightly slower (it still basically loops over almost the whole screen on these types of models, so keeping track of the smallest bounding box while also still doing the same work as before made it a little slower). But the performance benefits for the average model outweighed the losses on rare fully transparent models. In the image, you can see the benchmark results versus the baseline."}, {"post_id": 12171, "ts": "2026-06-19T21:42:34Z", "hours": 6.6653, "text": "Made the shading mode branches compile time instead of runtime in the renderer with templates Did the same template if constexpr (compile time if branches) thing that we already do for opaque/transparent models with the shading mode (was a runtime per triangle if branch before), which improved performance. It basically just makes a new copy of the function for each shading mode x each transparency mode, so 4x2 which is 8 slightly different functions and uses the correct one on each call. That increases binary size and icache pressure, but drops per triangle or per pixel if branches that hurt performance, so it’s an overall performance win. Benchmarked across a ton of different resolutions, models, shading modes, etc. (the benchmark by itself took like 2 hours to run)"}, {"post_id": 10115, "ts": "2026-06-16T18:24:38Z", "hours": 4.0297, "text": "Added support for wrap modes for textures Only in glTF and OBJ models (the only ones that support it) and verified with the Khronos group sample assets model. Also added PLY texture support."}, {"post_id": 9453, "ts": "2026-06-15T20:20:25Z", "hours": 4.6839, "text": "Working on adding supersampling anti-aliasing Still a work in progress and I might not merge it into main, because it’s a lot of work for not that much benefit. I have to catch a lot of bad_allocs and things like that for super large SSAA sizes, which is really annoying and can affect performance. SSAA works by rendering at a higher resolution and then downscaling for better edges (makes edges smooth and fade-in instead of jagged) Picture with 2x SSAA and without SSAA:"}, {"post_id": 8652, "ts": "2026-06-14T11:36:32Z", "hours": 5.2058, "text": "Adapted the arg parsing and CLI behaviour to the GNU standard Now, rasterminal’s CLI behaves under the GNU CLI standards, so on par with most linux tools."}, {"post_id": 8162, "ts": "2026-06-13T16:37:29Z", "hours": 2.8394, "text": "Added deduplicating vertices to the stl loader. After two unsuccessful and unmerged branches, I finally did something useful on main. I used to deduplicate the vertices in stl_reader and then reduplicate them in the loader. But now, we just dedup in stl_reader and use those. That also allowed me to enable ambient occlusion, which was disabled for stl before. And now crease smoothing fully works too. And it’s faster (runtime wise, load time is slower because of ambient occlusion and crease smoothing that weren’t there before). So an all-round very positive change, and also an end to my non-merging dry spell."}, {"post_id": 7990, "ts": "2026-06-13T10:20:35Z", "hours": 2.4908, "text": "Replaced tinyobjloader with rapidobj for way faster obj parsing But after actually replacing it and integrating it into the source code, i realized it’s not worth it, because rapidobj just has too many downsides and isn’t very actively supported anymore. For example, it doesn’t support multiple mtl files, which is against the spec. So if i want to keep it spec compliant, I need to find a workaround for it, which just isn’t worth the speed increase of rapidobj, even if it’s like 4x faster (from my testing on a large obj) The graph is from this article: https://aras-p.info/blog/2022/05/14/comparing-obj-parse-libraries/"}, {"post_id": 7643, "ts": "2026-06-12T19:26:54Z", "hours": 8.7975, "text": "I tried to rewrite the STL loader from scratch for more performance But it’s taking super long and I’m way too bored with it, so I think I’ll just abandon the branch and work on something else."}, {"post_id": 6791, "ts": "2026-06-11T11:35:25Z", "hours": 3.6575, "text": "Added full native 32 bit support for all platforms Didn’t have to redesign any of the source code (thankfully), just some warning suppressing and fixing some static casts. Also added a CI job that’ll flag future 32 bit compatibility regressions."}, {"post_id": 5755, "ts": "2026-06-09T17:34:17Z", "hours": 4.1133, "text": "Transparency is fully done and merged. Did some polish, cleanup and optimization on the transparency branch and successfully merged into main."}, {"post_id": 4897, "ts": "2026-06-08T13:53:56Z", "hours": 3.2906, "text": "Transparency is basically done, with caveats. Transparency works correctly, but transmission , which is completely different, is simplified to transparency. So for spec-complete gltf, I would need to implement the whole transmission pipeline, which I’m way too lazy to do right now. So for now, we just simplify it to transparency and call it a day."}, {"post_id": 4320, "ts": "2026-06-07T16:09:10Z", "hours": 6.2586, "text": "Working on adding transparency support. For that, I have to completely rework the rendering loop and the rasterizers, so basically the whole core of the project. It’s going very badly. And since performance is a big factor here, I’m going for a template approach so the transparency overhead doesn’t affect non-transparent meshes."}, {"post_id": 3846, "ts": "2026-06-06T22:11:48Z", "hours": 3.5269, "text": "I did a hot-loop performance cleanup run, because the hot loops were getting slower with new features, and I found a big optimization opportunity in clip-near call sites: clip_near slices off the part of a triangle that pokes behind the camera’s near plane, but almost every triangle is fully in front of it with nothing to clip. The pipeline still called it for all of them, and in the compiled binary that common case just copied all three vertices to memory and back, millions of times a frame. The fix was to check inline whether the triangle is fully in front and skip the call entirely if so. Result on a 2.77M-triangle model: median frame time dropped from 21.1 ms to 19.2 ms, about 8.7% faster."}, {"post_id": 3572, "ts": "2026-06-06T15:51:49Z", "hours": 2.4386, "text": "Because of all the libraries I added, the binary size increased significantly. I don’t use most of the vendored code, so I added build flags to ignore unused code in the final binary. Other than that, I added some other performance flags and also a CMakePresets.txt. It took longer than it should’ve, because I tested and benchmarked a bunch of other configs and flags. I put off PGO for now."}, {"post_id": 2939, "ts": "2026-06-05T20:55:20Z", "hours": 3.9267, "text": "I wired in Webp image format support by vendoring in google’s libwebp decoding library. It wasn’t that hard to wire into the source code, the hard part was the vendoring, dealing with licenses and professional vendoring practices. Only thing that remains to add for full gltf extension support is avif image support, but I’ll do that later."}, {"post_id": 2739, "ts": "2026-06-05T14:38:57Z", "hours": 1.3417, "text": "I just added unlit material support, which means materials that are supposed to stay intentionally unaffected by lighting render correctly. Pretty straightforward change, just read it at load time and then check if that material is unlit during the lighting pass and skip it."}, {"post_id": 2631, "ts": "2026-06-05T08:21:00Z", "hours": 3.3225, "text": "Reworked the whole readme with better instructions, screenshots and a gif. The gif was super annoying to polish, because i used asciinema which records all the setup escape sequences so there were gaps at the start and end that i had to manually read and remove. And I also had to perfectly close it exactly when it did one full rotation and that took like an hour to perfect. At least now I don’t have to touch the readme for a while."}, {"post_id": 2311, "ts": "2026-06-04T18:46:14Z", "hours": 3.1892, "text": "Well, I tried to refactor the main rendering loop for like the third time, because it’s horrifyingly indented, but it has defeated me once again. At this point, I’m confident that it’s impossible to do without a noticeable drop in performance, or g++ is just ragebaiting me. I installed a rainbow indentation neovim plugin just to show the absurdity of this."}, {"post_id": 386, "ts": "2026-06-01T18:58:14Z", "hours": 0.6783, "text": "I just implemented KTX2 and Basis texture support, which are special compressed texture formats. So now any models with these textures are viewable in rasterminal."}, {"post_id": 359, "ts": "2026-06-01T17:59:06Z", "hours": 4.5428, "text": "Hey everyone, I want to introduce my project! rasterminal is a full software 3D rasterizer and model viewer that runs entirely in your terminal. The whole rendering pipeline is implemented from scratch. I only rely on third-party libraries for load-time things like 3D model parsing, image parsing, and decompression. It doesn’t touch the GPU at all, running purely on the CPU. That makes it completely safe for SSH usage, though it does come with a performance cost. I use multithreading to recover some of what’s lost, and the result is still significantly faster than any other terminal 3D viewer I’ve come across. Right now I’m focused on broader 3D format feature support and transparent material rendering. If you want to try it out, I’d love to hear what you think, feedback and issues are very welcome over on GitHub. https://github.com/PavolUlicny/rasterminal Thanks for any support! 🙏"}]...
|
Title: rasterminal by @PavolUlicny | Stardance
De Title: rasterminal by @PavolUlicny | Stardance
Devlogs:
Hey everyone, I want to introduce my project! rasterminal is a full software 3D rasterizer and model viewer that runs entirely in your terminal. The whole rendering pipeline is implemented from scratch. I only rely on third-party libraries for load-time things like 3D model parsing, image parsing, and decompression. It doesn’t touch the GPU at all, running purely on the CPU. That makes it completely safe for SSH usage, though it does come with a performance cost. I use multithreading to recover some of what’s lost, and the result is still significantly faster than any other terminal 3D viewer I’ve come across. Right now I’m focused on broader 3D format feature support and transparent material rendering. If you want to try it out, I’d love to hear what you think, feedback and issues are very welcome over on GitHub. https://github.com/PavolUlicny/rasterminal Thanks for any support! 🙏
I just implemented KTX2 and Basis texture support, which are special compressed texture formats. So now any models with these textures are viewable in rasterminal.
Well, I tried to refactor the main rendering loop for like the third time, because it’s horrifyingly indented, but it has defeated me once again. At this point, I’m confident that it’s impossible to do without a noticeable drop in performance, or g++ is just ragebaiting me. I installed a rainbow indentation neovim plugin just to show the absurdity of this.
Reworked the whole readme with better instructions, screenshots and a gif. The gif was super annoying to polish, because i used asciinema which records all the setup escape sequences so there were gaps at the start and end that i had to manually read and remove. And I also had to perfectly close it exactly when it did one full rotation and that took like an hour to perfect. At least now I don’t have to touch the readme for a while.
I just added unlit material support, which means materials that are supposed to stay intentionally unaffected by lighting render correctly. Pretty straightforward change, just read it at load time and then check if that material is unlit during the lighting pass and skip it.
I wired in Webp image format support by vendoring in google’s libwebp decoding library. It wasn’t that hard to wire into the source code, the hard part was the vendoring, dealing with licenses and professional vendoring practices. Only thing that remains to add for full gltf extension support is avif image support, but I’ll do that later.
Because of all the libraries I added, the binary size increased significantly. I don’t use most of the vendored code, so I added build flags to ignore unused code in the final binary. Other than that, I added some other performance flags and also a CMakePresets.txt. It took longer than it should’ve, because I tested and benchmarked a bunch of other configs and flags. I put off PGO for now.
I did a hot-loop performance cleanup run, because the hot loops were getting slower with new features, and I found a big optimization opportunity in clip-near call sites: clip_near slices off the part of a triangle that pokes behind the camera’s near plane, but almost every triangle is fully in front of it with nothing to clip. The pipeline still called it for all of them, and in the compiled binary that common case just copied all three vertices to memory and back, millions of times a frame. The fix was to check inline whether the triangle is fully in front and skip the call entirely if so. Result on a 2.77M-triangle model: median frame time dropped from 21.1 ms to 19.2 ms, about 8.7% faster.
Working on adding transparency support. For that, I have to completely rework the rendering loop and the rasterizers, so basically the whole core of the project. It’s going very badly. And since performance is a big factor here, I’m going for a template approach so the transparency overhead doesn’t affect non-transparent meshes.
Transparency is basically done, with caveats. Transparency works correctly, but transmission , which is completely different, is simplified to transparency. So for spec-complete gltf, I would need to implement the whole transmission pipeline, which I’m way too lazy to do right now. So for now, we just simplify it to transparency and call it a day.
Transparency is fully done and merged. Did some polish, cleanup and optimization on the transparency branch and successfully merged into main.
Added full native 32 bit support for all platforms Didn’t have to redesign any of the source code (thankfully), just some warning suppressing and fixing some static casts. Also added a CI job that’ll flag future 32 bit compatibility regressions.
I tried to rewrite the STL loader from scratch for more performance But it’s taking super long and I’m way too bored with it, so I think I’ll just abandon the branch and work on something else.
Replaced tinyobjloader with rapidobj for way faster obj parsing But after actually replacing it and integrating it into the source code, i realized it’s not worth it, because rapidobj just has too many downsides and isn’t very actively supported anymore. For example, it doesn’t support multiple mtl files, which is against the spec. So if i want to keep it spec compliant, I need to find a workaround for it, which just isn’t worth the speed increase of rapidobj, even if it’s like 4x faster (from my testing on a large obj) The graph is from this article: https://aras-p.info/blog/2022/05/14/comparing-obj-parse-libraries/
Added deduplicating vertices to the stl loader. After two unsuccessful and unmerged branches, I finally did something useful on main. I used to deduplicate the vertices in stl_reader and then reduplicate them in the loader. But now, we just dedup in stl_reader and use those. That also allowed me to enable ambient occlusion, which was disabled for stl before. And now crease smoothing fully works too. And it’s faster (runtime wise, load time is slower because of ambient occlusion and crease smoothing that weren’t there before). So an all-round very positive change, and also an end to my non-merging dry spell.
Adapted the arg parsing and CLI behaviour to the GNU standard Now, rasterminal’s CLI behaves under the GNU CLI standards, so on par with most linux tools.
Working on adding supersampling anti-aliasing Still a work in progress and I might not merge it into main, because it’s a lot of work for not that much benefit. I have to catch a lot of bad_allocs and things like that for super large SSAA sizes, which is really annoying and can affect performance. SSAA works by rendering at a higher resolution and then downscaling for better edges (makes edges smooth and fade-in instead of jagged) Picture with 2x SSAA and without SSAA:
Added support for wrap modes for textures Only in glTF and OBJ models (the only ones that support it) and verified with the Khronos group sample assets model. Also added PLY texture support.
Made the shading mode branches compile time instead of runtime in the renderer with templates Did the same template if constexpr (compile time if branches) thing that we already do for opaque/transparent models with the shading mode (was a runtime per triangle if branch before), which improved performance. It basically just makes a new copy of the function for each shading mode x each transparency mode, so 4x2 which is 8 slightly different functions and uses the correct one on each call. That increases binary size and icache pressure, but drops per triangle or per pixel if branches that hurt performance, so it’s an overall performance win. Benchmarked across a ton of different resolutions, models, shading modes, etc. (the benchmark by itself took like 2 hours to run)
Optimized the transparent cleanup path in the renderer After rendering the model in the transparent path, we have to resolve the transparent pixels, which basically just pastes in the pixels behind it and sometimes tints it based on how dark and what color the transparent material is (tinted glass will make the things behind it darker, normal glass will be mostly completely untinted). Before, the resolve function looped over every single pixel in the frame, even non-transparent and background ones. This is obviously wasteful. So I made it find the smallest box, in which all the transparent pixels of the whole frame fit and just looped over that. It recovered the overhead of the transparent resolve on models with smaller transparent parts, but it also made fully transparent or mostly transparent models slightly slower (it still basically loops over almost the whole screen on these types of models, so keeping track of the smallest bounding box while also still doing the same work as before made it a little slower). But the performance benefits for the average model outweighed the losses on rare fully transparent models. In the image, you can see the benchmark results versus the baseline.
Added TEXCOORD_1 support glTF sometimes authors a second TEXCOORD set (first one is TEXCOORD_0, 0 indexed numbering). The official spec only requires support for the first two TEXCOORD sets, even though there can theoretically be any number of them in a model. That said, major model exporters don’t author any more than the two sets, so to avoid extra work, I only added support for 0 and 1. (not merged into main yet, I want to polish it a little and maybe add KHR_texture_transform support on top of it first)
Added texture transform into the TEXCOORD branch and merged it into main Not that hard, just read it, pass it to the rasterizer and then display it. I did have a very sneaky bug in the loader that made the whole feature render wrong, where I just had to negate one value to fully fix it, but now everything fully works. Below you can see the Khronos test asset for texture transforms. (tick means fully working, clearcoat is not yet implemented so it doesn’t show as working)
Added proper OBJ bump map support OBJ bump maps are textures for simulating bumps and wrinkles on models. Blender used to author bump maps as normal maps for some reason, so I made it automatically detect if it’s a normal map disguised as a bump map and handle it well, since there are a lot of old Blender OBJ models in the wild. But it also handles bump maps as bump maps normally, so it’s basically the best of both worlds.
Completely removed gouraud shading mode Gouraud was previously the main shading mode, but now I’ve just completely removed it. It was by far the slowest, while not adding any actual value to the project. Blinn-phong lighting is faster AND it supports more features (normal maps, etc.), so there was just no point in keeping gouraud. Now that I’ve removed it, the project has less code to maintain and a faster default shading mode with more features.
Split the tests into sub-directories The test suite is now very long (20k LOC across 47 files), so i decided to split it into sub-directories instead of just having 47 files in one flat dir. It’s cleaner, more maintainable and looks better.
Pararelized the wireframe shading mode I did a bunch of small things alongside it, but the main feature for this devlog is the pararelization of the wireframe shading mode. It was previously fully single threaded, but it wasn’t that hard to pararelize, i just had to make the function it used to write into the framebuffer (draw_line) CAS atomic, to avoid race conditions. Now wireframe is the fastest shading mode in basically all scenarios. Below, you can see a performance benchmark (built into rasterminal using a flag) with wireframe mode on a super dense mesh and how the wireframe mode looks like (you can also cycle the colors).
Added a release workflow, manpage and changelog I added a github release workflow that works alongside the changelog and released the first pre-release version: v0.1.0-alpha.1 Also added a manpage and an install target to make and cmake that installs the binary, docs and manpage into the path.
Wasted 7 hours of my life Did a bunch of smaller cleanups and fixes, and then I tried to template the unlit and lit paths in the rasterize_flat function, which turned out to be a performance regression. Awesome.
Completely removed the shadow map Before, rasterminal built a shadow map on model load and displayed it during runtime. I now completely removed it, because it was slower during load, slower during runtime, sometimes looked broken on curved surfaces and added essentially no value. Here, the first picture is with the shadow map and the second is without.
Working on portability Did a bunch of small fixes and improvements in the last ~week. Right now I’m on vacation for the next couple of days, so I won’t be active. I am currently working on broader terminal and platform support, so older systems and terminals will be able to run cleanly with some fallbacks or will fail loud with a clear message about what isn’t supported.
Working on adding 256 color support Some older terminals can’t display full 24bit RGB colors and use a 256 color palette instead. I’m adding a fallback so the older terminals can still use rasterminal. It still calculates the full old RGB colors, but then just maps them to the nearest 256 color with LUTs. On a side note, I switched my terminal emulator from Kitty to Ghostty.
Working on terminal color capability detection I am adding automatic terminal capability detection, meaning that rasterminal will get the terminal type and either refuse to render on super old or “dumb” terminals, degrade on some terminals and render normally on modern ones.
Working on a –color compatibility flag The color terminal compatibility thing I was working on has landed in the branch, now I’m adding a –color flag to override the automatic capability detection for situations like ssh, where we almost always degrade to the 256 color pallete for maximum compatibility. So now you’re gonna be able to use the right color mode even if the automatic detection is wrong for your situation.
Changed the 24bit to 256 color palette conversion logic Until now, the conversion picked the closest color possible mathematically. But from testing on a bunch of different models, I’ve realized that it doesn’t actually look very close to the human eye. So I swapped it out for a different method, called CIELAB distance. Now it still doesn’t look perfect, but as a fallback for older terminals it’s close enough.
Finally merged color-fallback, I can move onto other things The branch is finally merged. I’ve accumulated a bunch of usability and code quirks and issues that i can finally get to now that the branch is merged. So now I’ll be reworking all the CLI flags, camera and other components. And we also passed the 700 commit mark with this merge!
Did a bunch of small code quality and usability improvements Fixed a Windows bug that crashed the program on model sizes bigger than 2GB, improved the orbit usability (fixed mouse drag behavior when models are turned upside down), and did a few cleanups and fixes in the CLI parsing. I’m planning on adding a few CLI flags that I think can be very useful for some people, specifically better spin settings, starting camera angle/zoom control and a few more.
Added –spin-speed and –spin-direction flags Added CLI flags for the spin speed and direction. The speed is in deg/s and the directions is simply left or right. Here’s what 1000 deg/s looks like spinning to the right:
Added more CLI flags for startup customizability Added flags to set the camera pitch, yaw and zoom on startup. Now every runtime-settable variable can be set during startup through the CLI. The R button now resets the state to the CLI set state, not to factory defaults.
So, i found two memory bugs in a widely used terminal input library I was researching terminal input libraries to use for this project because my current approach was so buggy that it wasn’t worth fixing. Both of them are memory bugs in the libtermkey library. There are forks of the lib with this fixed, but since many projects still rely on this lib, i submitted them anyways. I’ve also confirmed that the bug is present on my machine on Ubuntu 24.04 LTS on Neovim, because it links the vulnerable shared library. I didn’t mark them as CVEs (hopefully that isn’t a problem). If anyone want’s to look at the bug reports, they are at https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1142891 and https://bugs.launchpad.net/ubuntu/+source/libtermkey/+bug/2161916
Working on completely rewriting the current input parsing handling The current input handling is subpar at best; it interprets a lot of random keys as escape, which currently quits the program (This will also be changed to Q and Ctrl+C only. Kind of a no-brainer since this is the more standard choice for TUIs - for example btop - and it also means I don’t have to deal with the headache of distinguishing function keys and others from escape) and has a lot of other quirky behavior that needs fixing. I’ll also try to improve robustness against malformed input like a leaky SSH session. There are a lot of various edge cases and situations where you have no way to distinguish real input from malformed input. This is all a very major pain in the ass. And I thought figuring out the raw mode output would be the hard part. And after all this, I’ll end up with way less attention than strictly slower, less robust competitors, just because they already have an audience from other projects. I bet nobody will even read this. I’m basically talking to myself right now. Or maybe, just to spite me, the algorithm will push this more than my other devlogs.
Still working on the input parsing system It is very hard and I keep finding bugs and reasons to redesign it. I’m in pain. I do think I’m getting closer to the final robust design.
Finally committed and pushed the input rework Tested it on both linux and windows and everything seems to work. No inputs interpreted as other inputs, all edge cases handled, just works. Finally can move onto other things.
Did a smaller fix and added a pretty big feature First, let’s talk about the small fix: I Fixed a super long model name showing up in the HUD in it’s full length, often blocking out other HUD elements. Previously, the HUD would display a model name of any length. Now there’s a hard cap of 24 chars, with any name longer than that truncated (middle style truncation) to fit into that limit. And now the big feature: Added a first person noclip-style camera mode. It’s accessed with the –first-person flag and let’s you explore the model as a floating camera (not bound like the default orbit camera). It was honestly easier to implement than I thought it would be. With it, I added two new keybinds special to the first person mode - E and V for going up and down. They don’t do nothing in orbit mode. Also added a second –first-person-speed flag for controlling the initial movement speed. It is also controllable during runtime with scrolling or +/- (I didn’t know what to bind these to in this mode since you can’t zoom like in orbit mode and this was the only place where they fit). In the photos, you can see some angles taken in the first person mode that weren’t possible in the default orbit mode.
Completely redesigned and rewrote the HUD The HUD used to be just a single line at the bottom of the screen aligned to the left. It looked pretty bad, but it did tell the user everything they needed to know. [picture 1] First, I added model name sanitization, so models with control bytes like newline ( \n ), line feed or other symbols like emojis can’t break the whole program when trying to display them in the HUD. Then, I completely redesigned the whole HUD to look better and be more robust, while still telling the user everything they need to know. I went with this design [picture 2]: On the left, you only have the model name. In the middle, first you have the current shading mode (highlighted in cyan), then the lighting mode in plain white and then the background color in gray. All three middle indicators are separated with a dot and are different colors, so nobody can confuse them. On the right, there’s 3 boolean indicators: spin (if the model spin is on), backface cull (if it’s currently culling backfaces) and texture (if it’s showing the texture, isn’t there at all on models without a texture). They are gray if inactive and cyan if active. The last thing on the right is just the fps number. There can also be optional indicators: Wireframe color (in the middle, after the shading mode) which only shows up in wireframe mode. [picture 3] First person speed multiplier (on the right, between the bools and the fps number) which shows up only in first person mode. [picture 4] I also made each “island” cleanly disappear when the terminal’s width is too low instead of just slowly getting cut off letter by letter. I think this design looks better, less cluttered and is pretty easy to understand at a glance. I would very much appreciate a star on GitHub!
Added issue templates + contributing documentation Added templates and a config for submitting GitHub issues, for both bug reports and feature requests. Also added a CONTRIBUTING.md for clear instructions on how to make, structure and audit code contributions. (tests, linters, formatting, etc.) I tried to make some optimizations to the renderer by auditing the compiler generated assembly and looking for inefficiencies, but everything i tried turned out to actually hurt performance. And GitHub actions decided to have a major outage right when i pushed the commits, so that’s awesome
Minor comment cleanup Just did some comment cleanup: Deleted redundant comments and why comments Removed separator comments Compressed or rewrote some really long comments (without removing the info they give)
Working on adding support for the Kitty protocol Some modern terminals like Kitty and Ghostty have support for the Kitty protocol. It’s a feature that allows you to display high resolution content like images and videos in the terminal without it looking super pixelated. There’s also the Sixel protocol, which is basically the same thing but a little worse and more widely supported (even Windows terminal has it). I’ll add Sixel after i merge Kitty to main. It is very clearly a worthwhile feature and I have been planning to add it from the start of the project. Today I finally decided that it’s time. Most of the work is already done on the branch and i’m just polishing out the bugs and issues before I merge. In the photos, you can see the comparison between using just the block characters and using Kitty. It is a night and day difference. Although the performance isn’t great at that high of a resolution, but I’m still working on optimizing that.
Found a bug in Ghostty’s kitty protocol handling Ghostty is a modern and fast terminal emulator that i personally use. While testing the kitty protocol feature in rasterminal, I found a Ghostty bug that lagged my whole computer after a few minutes. I tested it in Kitty (terminal emulator) and there it worked fine. I looked at Ghostty’s code vs Kitty’s, found the bug and reported it to the Ghostty maintainers. Mitchell himself (the creator) fixed it in like 2 hours. Honestly I’m kinda sad I didn’t get to become a contributor and fix the bug, but since it was a small fix and I already described it in the issue, I get why Mitchell just fixed it in main. Here’s the full issue: https://github.com/ghostty-org/ghostty/discussions/13719
Fully merged and done with Kitty Finally completed the kitty protocol implementation. It is kinda slow, since the resolution is so much bigger, so I will try to optimize the high-res performance even more. So now the next two big milestones are: Add Sixel on top of kitty, that’ll be a lot of work Optimize the rasterizer even more I was thinking of maybe adding gpu rendering as an option for super large meshes or high-res scenarios, but idk. I’ll definetly keep the pure cpu renderer for computers without gpus, but I’m not sure about a gpu implementation. It would be hard to do, less portable and it might not even work that well.
Working on adding full Sixel support Working on adding support for the other mainstream terminal pixel protocol of the main two - Sixel. Already did fully implemented the kitty protocol last time, so once I’m done with this one, I’ll be done with terminal protocols (at least for the near future, hopefully). There are some other ones like the iterm2 protocol, but that one’s pretty rare and I won’t add it unless I really don’t have anything better to do. It’s basically done, just need to polish it and test it on a bunch of terminals and operating systems to make sure everything works before merging.
Fully merged sixel Fully merged the sixel protocol implementation. Works on all platforms everywhere that supports it. So now both high-res terminal protocols done. Moving onto other minor things and especially performance.
Working on improving performance With the addition of the high-res protocols, the target resolutions quickly went from hundreds or thousands of pixels to millions. So I now desperately need to improve performance. So far it’s looking promising: A whole model covering the camera 6 moving at 4k went from about 8 fps to 20-30 fps. Not ideal yet, but I think we’re on the right track. Super dense meshes (more than 2 million polygons) improved 2-3x Meshes with transparent parts improved about 2x While these wins may seem really big (they kinda are), the jump in resolutions still means they are barely usable interactively. I do want to add gpu acceleration later (with the cpu path as a fallback), but until then I want to make it as fast as I possibly can.
My reported bug in libtermkey has been fixed in the newest version Just got an email from one of the maintainers that the crash bug i reported a month ago was fixed in the new release. libtermkey is a terminal input parsing library that I considered using and found a crash bug in. The bug was already fixed in neovim’s fork of the library, so i just pointed the maintainers at that fix. For anybody interested, here’s the issue link: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1142891
Still optimizing… Spent the first ~7 hours trying to find microoptimizations and each one was either a wash or worse somehow. The compiler works in mysterious ways. At some point, I just gave up and let Claude have a go at the optimizing. Surprisingly it actually came up with a lot of interesting optimization techniques and solutions that I definitely couldn’t have come up with on my own. But it found so much, that the whole diff adds 5k lines of code. So now I’ll be cleaning up, testing, and maybe further optimizing that diff…
Finally merging the performance branch It’s finally time to merge the performance branch. I basically redesigned the whole renderer and rasterizer around high resolution workloads, where it would still choose the old high-poly paths where they were faster. Even snuck in some SSE2 SIMD code (picture), although I will probably be switching to a dispatch SIMD library like Google’s Highway. Not entirely sure it will be Highway or even if I will do that yet, that depends on the code complexity and before/after benchmarks.
Cleanup and restructuring changes After I just merged three big feature branches (kitty and sixel graphics protocols and the high-res performance branch), I needed to do some overdue cleanup and refactoring. And so I did: Collapsed the super long changelog entries into way more readable and legible points Restructured the src directory into multiple subdirectories because it had like 50 files already Sadly completely removed the Make build system, so now you can only build with CMake (CMake is very much evil and even more evil but it’s the only one of the two that supports windows and I was tired of managing two build systems) Removed the –graphics-scale flag, so now everything renders at native resolution And some small docs and comment cleanup
Working on assimp integration Yop, I’m adding the Open Asset Import Library as a fallback for any model formats that aren’t natively supported with their own dedicated loader (only ones with dedicated loaders are glTF2, PLY, STL and OBJ). I’m still keeping the dedicated loaders, because they are more feature-complete, to-spec and wayyy faster (especially the glTF one). I added it because I feel like for a 3D model viewer, support for many formats, even niche and obscure ones, is pretty important, even though nobody might use them. This roughly doubled compile time and almost quadrupled binary size, which also made CI take way longer (of course). It somehow made the MacOS runners take 50 minutes to compile (from the previous 3 minutes), but I fixed that by bounding the number of processes CMake can spawn to the number of threads on the runner (previously was using -j which spawns as many as it wants and it was spawning about 230 of them). I’m still testing how it handles various model formats and trying to find any reachable segfaults.
Still working on the assimp intgration Currently trying various models from all the different model formats that assimp loads. So far found a segfault, some weird behavior and integration mistakes that I made. Also found a small bug in assimp itself, for which I’ve submitted the PR with the fix to their GitHub repo. For anyone interested, here’s the PR: https://github.com/assimp/assimp/pull/6799
Fuzzing my assimp wrapper I’m trying a bunch of hand-crafted models from all the formats that I can load and trying to find things that dont load or render properly. Also had AI write me a simple fuzzer in python and I’m just letting it run for a few hours. Also auditing the assimp loader paths against my wrapper to find any format specific behaviour that should be handled. I’ve already found a bunch of things and I’m still finding more. Assimp has a lot of weird quirks and issues that I keep running into. Honestly kinda regretting the decision to integrate it, but since I’m already so deep in, I’ll just keep going.
Merged the full assimp integration into main I really don’t have much to say here, I’ve already put all the info about the branch into the past devlogs. All the formats work and the wrapper is very sturdy. I’ve found more bugs in assimp itself than my code (devlog on that soon). So, rasterminal can now load basically any 3D model you throw at it. Some of the formats assimp supports are so niche, I’ve never even heard of them.
Cutting a release The repo is in a pretty complete and polished state, so I’ll cut a release here. This will also probably be the last release before I ship, so I’m making sure that nothing is broken and everything works on every platform. I’ve still got a lot of work to do though, even after the end of stardance, like animations, glTF PBR, format completeness for every format, GPU acceleration, etc.
Found a bunch of terminal cleanup gaps Most of them are Windows or cmd.exe specific (nothing ever works on Windows), but some are present on POSIX too. The Windows specific ones are: cmd.exe for some unknown reason doesn’t turn off the raw input sequences, so arrow keys don’t work like they should, even though I explicitly turn it off (????????) (I hate Windows, they always have to do something unexplainable for no reason just so your code doesn’t work as it should) when you terminate the program with ctrl+c or ctrl+break while actively dragging the model around, it sometimes leaks mouse escape sequences into the next prompt bunch of other weird small stuff that nobody cares about And the few on POSIX are mostly ctrl+z suspend/resume behaviour not recovering the terminal and the same thing with ctrl+\ (SIGQUIT). I’m still working on fixing these. Most of the windows ones are already fixed, but I haven’t even started with the linux/POSIX ones. I have postponed the planned release to when I fix these + any other issues I find.
I HATE WINDOWS Windows just doesn’t work. It doesn’t work. Nothing works on Windows. Everything breaks. I don’t get it. THE UNIT TESTS PASS ON WINDOWS CI BUT WHEN I ACTUALLY RUN THE TESTS ON WINDOWS IT FAILS????? HOW IS THAT EVEN POSSIBLE. The release is now definitely getting delayed by at least a week because I keep running into more and more and more and more and more and more and more and more and more issues. I hate Windows. Microslop is the only company that could mess up a basic terminal emulator. And I also have to reboot my PC every time I fix something and push it and then reboot to get back to linux. this is torture. At one point I tried to do it on a Windows VM on linux but that was too slow so I just gave up.
Merged the full Windows console restoration branch My nightmare is over. I hopefully won’t have to deal with Windows for a while now. Summary of what is now fixed/handled on Windows: Ctrl+C, Ctrl+Break and Q exits fully recover the terminal’s state Ctrl+C and Ctrl+Break don’t leak mouse escape sequences into the next prompt if you terminate while actively dragging a model A bunch of other minor Windows or cmd.exe specific quirks Only thing that isn’t handled (didn’t find a good way to handle it) is task manager “end process”. It kills the program without cleaning up and sometimes freezes the shell.
Fully fixed and merged the first POSIX cleanup item Well, would you look at that! That took significantly less time than the Windows fix. It is partly because it was a smaller fix and only part whole POSIX fix, while the Windows one was the whole thing and also the foundation had already been laid out from the Windows work and I just integrated the POSIX path into that, but it is also very much because Microsoft is a horrible, terrible company that can’t make good software. I mean, look at GitHub, they have been going downhill ever since they got acquired by Microsoft. Now that I got that out of my system, here’s what was fixed: If the program cannot enable raw mode at startup, it safely fails instead of continuing and corrupting the terminal state If the cleanup gets interrupted, it retries cleanup so it doesn’t leave the terminal state corrupted after one failed attempt Onto the next POSIX fix: handling SIGQUIT and SIGHUP.
Added handling for SIGINT, SIGTERM, SIGQUIT and SIGHUP I don’t really have much to say here, I just added the full per-spec handling for all these. Only remaining POSIX-only gap is now SIGSTOP/SIGCONT (stop/resume process). I’m also starting school now, so I’ll be working on this less.
Working on SIGSTOP and SIGCONT handling SIGSTOP and SIGCONT are POSIX signals for stopping and resuming a running process. I’m working on adding handling for these, so you can safely pause and unpause rasterminal at any time. This is a lot of work, since until now, we just set up the terminal on program start and cleaned up when the program exited. There’s a lot of quirks and weird scenarios that I have to handle, for example if another signal gets sent while cleaning up the terminal for SIGSTOP. I’m trying to catch as many edge cases by just doing random things while using the program and also with the help of AI to come up with potentially uncaught scenarios.
Did some polish and cleanup of the platform layer Did final polish and cleanup of the platform layer since I want to actually finally cut a release relatively soon and I just did a lot of work there. Fixed things like useless tests, outdated or wrong comments and some platform specific quirks. Probably actually gonna cut a release soon (this time for real). Also added early rejections for BVH and CSM files, since they contain no model geometry (they can’t currently be displayed at all) and documented the change. The code is basically done (hopefully, I really don’t want to find another big gap that’s gonna take a week to close), I just want to correct anything wrong in the README, changelog, manpage or help menu and maybe make them look a little better before cutting a release and shipping.
Last pre-release checks and cleanup I’m finally ready to release v0.1.0-alpha.2. Only notable thing I changed here is that I changed the default thread count: It now defaults to hardware concurrency everywhere. Other than that, I of course did final documentation checks and fixes and now I’m just waiting for CI to pass so I can tag it and let the release workflow do the last step. So this is hopefully the last devlog before my ship!
Refactored the platform layer The whole platform layer was just one file until now. Since I did a lot of work on it recently, it grew to over 2400 lines of code. It was super confusing and disorienting. So I decided to refactor it (split it) into 8 files, based on what they handle: console.h - saving/restoring terminal state control.h - termination signal handling file.h - file operations (64bit) input_reader.h - handling input (not parsing, that is it’s own file) shared_memory.h - shared memory handling for the kitty protocol terminal_io.h - writes output to the terminal terminal_query.h - querying the terminal for things like graphics capability, etc. timing.h - frame timing and sleeps
Miscellaneous fixes and improvements Fixed two races in platform code (one MacOS, one Windows) Removed build flags that disabled some compiler security hardening at the cost of a little performance Fixed the test framework to not freak out on NaN in near assertions Improved thread launching and handling in loaders and renderer So overall just boring fixes and improvements, nothing special.
Code quality and CI improvements Finally did the long overdue main loop refactor. The main loop is now way shorter, more readable and more testable. I just split off some of the main loop’s work into it’s own modules, which made them way better looking and also, since they are now standalone modules, actually testable. A big win for repo structure. In the process, I also replaced the input handling’s long if chain that made each character do it’s job with a switch statement. It’s more readable and theoretically faster, although since I compile it with -O3, it probably made no difference or an unnoticeable one at best. I also finally fixed the super long CI times. Until now, CI used to take ~50 minutes (depending on how fast the GitHub runner was) because of cppcheck. Everything else finished in under 10 minutes, but cppcheck stalled it for an hour. It was stalling in mesh_assimp.cpp (the assimp wrapper) for most of it’s runtime. I always thought it was because assimp is a very large library. So I experimented with it a little. I included everything I include in the wrapper into a test file with a little code and ran cppcheck on that. It finished in less than 10 seconds. Eventually, I found out it was somehow taking that long because the main loader function was too long and handled too much by itself. So i just refactored it into 3 separate functions, without changing the behavior at all. Somehow, I still don’t get why, it reduced the whole cppcheck run to 9 minutes. a more than 5x improvement, just because I split a function into more functions. I’m not complaining, but it’s definitely weird. CI is now way faster and adding new things is gonna be way smoother now.
Ships:
rasterminal rasterminal is a 3D model viewer in the terminal Why i decided to build it The original idea didn’t really have any big inspiration, I’ve just always been fascinated by the inner workings of 3D and how that all works. I’ve been wanting to build a project involving 3D for a while and I didn’t want to make just another program that uses libraries and GPU drivers to do all the work. So I came up with the idea: a software rasterizer that renders in the terminal! There are lots of TUIs and lots of boring old software rasterizer projects, so I just combined the two into something unique. And over time, I realized I could make it an actually useful tool, with no real competition: a 3D model viewer in the terminal. Sure, there are some similar projects on GitHub (like taigrr’s trophy), but none are actually usable with heavier models or support pixel graphics. What I learned I learned a lot. I really mean a lot. Anything from math and rendering to how terminals work and how to control them using escape sequences. I don’t want to sit here and name everything I learned over the period of the last 5 months, but I can confidently say that this project really taught me how much work goes into everyday software and how to actually develop and maintain a project professionally. The future of rasterminal The whole project is very far from done. You can see that from the latest release version: v0.1.0-alpha.2. I’ve got a lot of work to do and I’ve roughly got the major landmarks mapped out. Main things I definitely want to change/add at some point before v1 are: Add animation support (currently can only render still meshes) Complete the renderer (complete support for basically every feature of every format that makes sense to support) Add optional GPU acceleration (after I’m satisfied with everything else) Hardware / OS support Supports every major OS (Windows, Linux, MacOS, and any other POSIX-based OS, so practically everything), and every CPU that I could think of (any architecture, 32 or 64bit). You would have to actually try a to find a platform that it doesn’t support (most of the unsupported hardware are big-endian systems, which are basically phased out completely). This is one of the main goals of the project, so (almost) any modern machine with a terminal can run it. Special thanks Special thanks to anyone who followed, liked, helped, or otherwise supported the project in any way. I wouldn’t have had the motivation to push it this far if it wasn’t for you guys....
|
1792831867.873963
|
1792918267.873963
|