wibi's blog

  • user warning: Table './glorioustrainwrecks/sessions' is marked as crashed and should be repaired query: SELECT COUNT(sid) AS count FROM sessions WHERE timestamp >= 1710628072 AND uid = 0 in /var/www/glorioustrainwrecks/includes/database.mysql.inc on line 175.
  • user warning: Table './glorioustrainwrecks/sessions' is marked as crashed and should be repaired query: SELECT DISTINCT u.uid, u.name, s.timestamp FROM users u INNER JOIN sessions s ON u.uid = s.uid WHERE s.timestamp >= 1710628072 AND s.uid > 0 ORDER BY s.timestamp DESC in /var/www/glorioustrainwrecks/includes/database.mysql.inc on line 175.
wibi's picture

gems


every day imgur is not dead is another little miracle.

so those in that game would be gems. but what's up with that?

firstly this is all about an upcoming (not anymore, it has already released) version of jumper 4 real.
secondly i should talk about how saves work.

for the most part everything about a save slot is stored in a file named slotN.txt where N is the slot number. it is a pretty human-readable format. here's an example:
https://pastebin.com/raw/HWbdkX6f

gems, however, are stored in a different file, slotN.j4g, in a condensed format. (j4g is a format i came up with short for "jumper 4 gems".) this is partly so collecting a bunch of gems doesn't take up a bunch of disk space, and partly so that it's much quicker for the menu to just read off how many gems each slot has. in future i may put other info the menu wants to read quickly here as well, like how many different rooms the user has triggered the "you win" screen from.
here's the j4g specifications. you'll note there's no header.

big-endian

2 BYTES UINT16 {BLUE GEM COUNT}
2 BYTES UINT16 {RED GEM COUNT}
12 BYTES {RESERVED}
2 BYTES INT16 [THE X POSITION OF THE 1ST BLUE GEM; SIGNED]
2 BYTES INT16 [THE Y POSITION OF THE 1ST BLUE GEM; SIGNED]
2 BYTES INT16 [THE X POSITION OF THE 2ND BLUE GEM; SIGNED]
2 BYTES INT16 [THE Y POSITION OF THE 2ND BLUE GEM; SIGNED]
... {AMOUNT OF BYTES TO READ IS DETERMINED BY BLUE GEM COUNT}
2 BYTES INT16 [THE X POSITION OF THE 1ST RED GEM; SIGNED]
2 BYTES INT16 [THE Y POSITION OF THE 1ST RED GEM; SIGNED]
2 BYTES INT16 [THE X POSITION OF THE 2ND RED GEM; SIGNED]
2 BYTES INT16 [THE Y POSITION OF THE 2ND RED GEM; SIGNED]
... {AMOUNT OF BYTES TO READ IS DETERMINED BY RED GEM COUNT}

up to four versions of this file exist per levelset: slot 1, slot 2, slot 3, and combined (union)

"the x position" and "the y position" refer to the x and y position of the room the gem is in.
(what you would call "levels", jumper 4 real would call "rooms", and every room is somewhere on a grid spanning from -32768 to 32767.)
(if there's multiple gems of the same type in the same room, there is a mechanic where all of them turn out to be holograms except the last one you try to collect.)

"combined (union)" is this:

named "union" because it is the "union" of all gems you have across all savefiles (as well as deleted savefiles). it's like a permanent progress indicator.
whenever you collect some new gems and go back to the menu, when the game writes what new gems you've collected in save slot N, it also tries to update the "union" file. it cross references with all the gems you have in slot N and ticks off whatever gems are already present in the union file, and the remainder gets appended.
well not actually "appended" since the structure of j4g files means new blue gems have to be inserted into the middle of the file, and also i implemented it really weirdly such that the "union" table of gems effectively gets replaced with the "slot N" table of gems and then has the gems that aren't in slot N appended to it, but that part doesn't really matter since lua's pairs function has no defined order and that's how i iterate through all the gem tables anyway (the key is a room position and the value is true).

but now you may be wondering about that number to the right of the /. you may be wondering how the menu knows what the total amount of each type of gem is, without manually scanning every single level for gems.

the answer is... it doesn't! it just checks two variables you set from the editor. (if either of them are 0 or left empty, then it doesn't show the gem total at all. also, there is nothing stopping you from lying about the total amount of gems your levelset contains.)

however, the editor does have a "recount gems" button that automatically totals up the amount of gems every room has.
how are rooms stored? well hey i have another freaking pastebin link woah.
https://pastebin.com/raw/625G65ES

OK THIS PART OF THE POST IS ABOUT HOW ROOMS WORK.

map data itself is two bytes per tile - the first byte being a "bank" (though this, like many other decisions, is entirely arbitrary and not really enforced) - with the additional restraint (for the time being) that every byte has to be printable ASCII. also there's some hacky compression for rows that are all the same tile or adjacent rows that are identical.
you'll notice there's no separator between each tile. this might lead you to believe "oh, ok, so you used some string buffer thing, and you check an initial byte to see if it's | and if so you know it's map data, and from there on you consume 2 bytes at a time" but no!!! i wrote a stupid custom string split function that specifically only splits across multiples of n (2 in this case). that was back when i didn't even know string buffers existed. where were we? oh, right.
so right away there's a problem: we can't just use string.find for the 2 bytes that comprise a blue or red gem, because what if i got really pressed for space for some reason (95 tlies/objects per bank isn't infinite!!) and started using using { or | as a bank? then if it were right next to a tile that ended in O, it falsely finds O{ or O| and thinks it's got a gem. but it don't! and it's not possible to tell what parity a tile is on except relative to the last newline (not to the start of file).
so i COULD just write another hacky mess that's like string.find but only for specific parities and also considers the last line break to be parity 0. but i had a better idea that was way faster.
up to this point i had three agreed-upon "starting characters" for this pseudo-format i saved as .txt:

  1. ===. indicates a header, kinda like puzzlescript. and yes it has to be exactly three =s because uhh it looks nice. also there has to be a === at the end too. the main bulk of the header is expected to be ONLY UPPERCASE LETTERS, but it can have a : to denote a "phase", which can be UPPERCASE LETTERS INCLUDING NUMB3RS.
  2. |. indicates data of any sort. can rarely have lowercase letters before it, usually to indicate what type the following data is (number, string, bool).
  3. >. indicates a "command", like duplicating rows of map data, or switching how data is interpreted (like a sub-header). i think a long time ago i had an internal rule that commands should all be 3 letters long but that doesn't matter anymore, and anything that can follow a | can follow a >.

is there some central parser that knows what to do with all these characters? no! no there isn't. in fact, i've probably written roughly the same parsing code about 4-5 times, with the difference mainly being where data goes and what commands do.
so to store what gems are in a level at the very start of the file more easily, i introduced a fourth character:
  1. !. indicates arbitrary-ish bytes follow. all bytes must have the top bit set so none of them will be ascii, and the byte sequence is terminated with a zero-byte. (and then a line break.)

so now every room has a header starting with !, 0x80 (np++ assigns this to €), and a zero-byte..
whenever a room is saved, the process that jots down each tile also checks if that tile corresponds to a blue gem or a red gem. if it's a blue gem, it flips the last of the 2nd byte of the header. if it's a red gem, it flips the penultimate bit of the 2nd byte of the header. i.e. blue gem only is 1, red gem only is 2, blue gem and red gem is 3.
and the "recount gems" button just nips the first 2 bytes of every room in the levelset.
it checks the first byte. if the first byte isn't !, then it notes that the room is using an old version of the level format with no header, and it will print how many such rooms it encountered once it's done counting.
then it checks the second byte. if the last bit is set, it knows the room contains a blue gem. if the penultimate bit is set, it knows the room contains a red gem. so it just sums all that up and then fills the textboxes above it with the results it got.

in retrospect, having introduced a header into my level format, i probably should have had the first byte (well, last 7 bits of the first byte) be a version number instead of gem information, so if i make any more silly changes then i can know definitively what version of the room "format" each room was saved with.
indeed i should. but so far, i haven't.
yay!

wibi's picture

Knytt Scraps/WIPs

Collection of ideas for scrapped KS levels, or those I don't know if I'll ever finish.

Knytter: Exploration level with the red/blue switch mechanics of REDDER. Never made a single room for it.

Hourglass Shape: Level where all of the rooms were arranged in the shape of an hourglass. Would feature a part near the end with seemingly unscalable overhangs that would grant you an easter egg if climbed. One of the few rooms I made for it would later be used as the starting room for garden.

Columbo: Juni wakes up, goes to her workplace to set a disguised explosive under the desk in her cubicle, works her shift, then goes back home before the bomb eventually explodes. You'd be traversing with no run powerup through a boring flat landscape both to get to work and on the way back. Entirely meant to riff on one particular Columbo episode with virtually the same plot where it took from the beginning of the show to the first or second ad break for this to actually happen.

crate pushing level: Shift-based level that would have played like a side-view sokoban with gravity. Juni would walk into the side of a crate to "push" it. Abandoned by the second screen.

flambe level: Another shift-based thing. The foreground and background are both transparent, only the foreground is solid. Shifting would cause the foreground and background to switch places. Combined with KS+'s Overlay=True feature, this would make it look like the shift is actually sending you between the layers.

minimalistic closer: Prototype of Get focus. I had almost the whole map layed out, but never got around to A) finishing the final area or B) actually adding the "closing behind you" effect.

Space is Cliche: Dr. Cliche's lab in space. The whole gimmick was that you'd occasionally exit the safety of his various rooms and tubes, and a timed shift (plus a custom object that resembled a timer) would kill you if you were outside for too long.

Good Day For Poker: Would start out as a pastiche of Healy's style, with the plot being that your neighbor just invited you to come over for a game of poker, but her house is too high up to get there without both jump upgrades. Eventually you'd stumble into some virtual reality room (like the one in Dark Sea) and go through all sorts weird settings like the space station from VVVVVV.

Quick KS Editor Demonstration: Self-explanatory. I tried to make the kind of guide that could have gotten me into level-making a long time ago.

careful!: The first draft for this was a level where you could "die" from trivial things, like falling on the lawn and "choking on a blade of grass" thus giving you tons of different endings to achieve. Then I abandoned that for some reason, and tried making a level where you had to infiltrate Dr. Cliche's lab from behind most of his structures.

You Have to Put the Juni in the Juni: KS+ level, map is enabled, map resembles Juni's sprite. No idea where to go with it.

wibi's picture

Kneat Swapzeese

Complications have arose! For me. It'll take me a while to finish my half of the swapsy (or it'll just be shorter than normal) because I've barely had any time or focus to put into it. Sorry yo

wibi's picture

Proof that EVERY VIDEO GAME takes place in a coma.

Because anything can happen in a coma, it's all up to your imagination, and your imagination can simulate anything it pleases.

Knytt Stories: Coma.
Grand Theft Auto series: Chief of police's coma.
Drawn to Life: Self-explanatory. The part where he wakes up from the coma is also part of a coma.
Super Mario Bros.: Coma.
Super Mario Bros. 2: Coma. Everyone just pretends it was a dream.
Super Mario Bros. 3: This was a coma that Mario had while he was watching live theater.
Super Mario Bros. 4: Coma.
Scribblenauts: Coma in English class.
Super Scribblenauts: Another coma in English class.
Knytt: Coma.
Knytt Underground: Coma.
Knytt Nano: Coma.
OFF: Coma.
Scribblenauts Remix: Coma ported to mobile devices.
Pacman Without A Cause: Really short coma.
Pick Up the Phone Booth and Die: Coma.
Cool Spot: Coma in a future where adverts are inserted into peoples' dreams.
Action 52: 52 comas in a row suffered by a complete imbecile.
Doki Doki Literature Club: Coma.
Hello Neighbor: Coma.
Super Mario World: Coma.
Super Mario World 2: Yoshi's Island: Coma.
Pick Up the Phone Booth and Aisle: Coma.
Sokoban: Coma had by a warehouse keeper who dropped a crate on their head.
Chip's Challenge: Coma.
Chip's Challenge 2: Coma. Apparently having too many nosebleeds can really do something to you.
Chuck's Challenge: Definitely a coma.
Ace Attorney series: Coma.
Chuck's Challenge 3D: Coma.
Ben 10 5D Game Generator: Coma.
Aisle: Coma.
You Have to Put the Ball in the Cup: Coma.
You Have to Put the Ball in the Cup Physical Version: A non-fictional coma.
You Have to Put the Ball in the Cup *DELUXE EDITION*: Deluxe coma.
Cactus Block: Coma.
Cactus Block 2013: See, the Cactus Block coma lasted a long time.
Yellow Jogger Laser Platform Madness: Coma.
Yellow Jogger Laser Platform Madness 2017: The Yellow Jogger is never going to wake up from his coma.
Powerhouse: Coma within a coma.
Every .io game: Coma.
Freedom Planet: Coma.
Mario Bros.: Coma.
Sonic and the Yellow Jogger: Coma.
Metal Gear Solid series: Coma.
Pokemon Blue: Blue coma.
Pokemon Red: Red coma.
Sonic and the Green Jogger: Green coma.
Portal: Coma.
Half-Life: Coma.
Half-Life 3: Coma.
VG2: Coma.
Frank Sinatra in "River, Stay Away From My Door": Coma. Not Frank Sinatra's coma, though.
Tile Studio: Coma.
Tile World: Coma.
Tile Factory: Completely unrelated coma.
Family Feud: Coma.
bbycast: Coma.
Keylugger: Coma.
!!!!!! - The Game That Appears First In Alphabetical Listings: Coma had by a man who was strapped upside-down to a ceiling.
VVVVVV: Coma had by another man who was also strapped upside-down to a ceiling.
Within a Deep Forest: Coma.
ModArchive Story: Coma in .mod format, somehow.
MAS2: Operator Status: Coma.
100 Nano Dragon: Coma.
Tetris: Coma.
Sudoku: Coma.
Pong: Coma, in which the ball is the patient and the paddles are abusive doctors.
Breakout: Coma, where someone's trying to wake the patient by slamming them against a wall.
Snake: Coma.
Super Kaizo World: Coma.
Enough Plumbers: Many comas.
Enough Plumbers 2: Many more comas.
Portal 2: Coma.
Snakes on a Cartesian Plane: Coma.
Undertale: Coma.
NetHack: Coma.
ADOM: Coma.
Mystery Dungeon series: Previous coma, but in Japan.
Pokemon Mystery Dungeon series: Previous coma, but milked for all its worth.
Chocobo's Dungeon series: Previous coma, but... wait, what?
Etrian Mystery Dungeon: What the hell?
Rogue: Coma.
Final Fantasy series: All comas.
Super Smash Bros. series: Basically like, twelve hospitals full of patients who are all simultaneously in comas.
Minecraft: Coma.
Metroid: Coma in space.
Candy Crush Saga: Coma. The person having the coma is being robbed blind.
Super Metroid: Coma in space, and this time you can walljump.
I Wanna Be The Guy: The Movie: The Game: Coma.
Zork: Coma.
Getting Over It: Coma.
Sexy Hiking: Sexier coma.

wibi's picture

ncrecc Plot Inventory

I'm told this is what cool people do. Domination fantasies in red, fantasies of being dominated(???) in blue. Will be updated as I make more games.

Lesson in Trickery: Kidnap blue people with sticky nets.
Sokoban Jr.: Understand the basics of the game.
Trail: Go home.
Jumper Two TutorialKindaThing: Read text blocks.
Xtreme Gardening: Stop on yellow dots while simultaneously gardening at 50mph.
You Have to Put the Machine in the Juni: Be a morally ambiguous surgeon.
Super Kaizo Pling: Get the ball in the X.
NOTPRISON: Get shot.
super security protocol: Turn off devices and kick ass.
Press A to Slow Down Zone: Transition between screens.
Get focus: Destroy a cave and everyone in it by doing absolutely nothing.
YELLOW JOGGE: Get your shoes back.
Kaizo Pling 2: Kaizo Pling: Get the ball in the X, again.
Super Associative Block Pushing to elevator muzak: Have your call transferred.
cat game: Open and close a door.
Jump the City: Get arrested.
Super Kaizo Pling 2: Kaizo Pling 3: Get the ball in the X... at night.
9 Boring Levels: Leave your opinion.
PSYCHO PLING IV: THE CALLING OF THE INSANITY: Get the ball in the X, except this time you're the violent ghost of a murderer.
garden: Explode.
What is google adwords and which is top ppc agencies?: Correctly identify things.
In The Case Of Shifting Tipping Is Imperative Or Not When Hire Packers And Movers Bangalore: Get from one side of a building to another.
000000bestknyttauthor - bestknyttgame: Get TO Doctro Clictchies Lab Or Else The Bomjb Will Go Offwards
PICK UP THE PHONE BOOTH AND AISLE RIPOFF: Do anything imaginable within the constraints of anything I've bothered to imagine.
Wait: Examine signs.
0 Kaizo Pling: The Prelude: Get the ball in the X, except this time it's more all-around embarrassing.
Simple Block Observing Game: Observe blocks.
CHIP OF THE MONTH: CHIP OF THE MONTH
Nectar: Destroy the world and everyone in it by doing absolutely something or other.

Syndicate content
pensive-mosquitoes