Skip to content

GameJolt Integration (co-authored by GamerPablito) - #1058

Open
SplatterDash wants to merge 3 commits into
CodenameCrew:mainfrom
SplatterDash:gamejolt
Open

GameJolt Integration (co-authored by GamerPablito)#1058
SplatterDash wants to merge 3 commits into
CodenameCrew:mainfrom
SplatterDash:gamejolt

Conversation

@SplatterDash

Copy link
Copy Markdown

With thanks to both GamerPablito and LJ

This PR adds optional integrations with GameJolt for achievements, leaderboards and data storage in softcoded mods. The PR includes:

  • Flags to be set in .ini: MOD_GAMEJOLT_GAME_ID and MOD_GAMEJOLT_TOKEN, as well as a Project.xml define to toggle GameJolt API on/off.
  • Utility GJUtil.hx, to handle front-facing calls to GameJolt including logging in/out and pinging the session.
  • Backend utility GameJoltSecurity.hx, to handle sending/receiving calls and token decryption. This is intentionally blocked from access in HScript and hardcode, with GameJoltSecurityPublic.hx providing a forward-facing version of the script for hardcoders.
  • Implementation of HaxeFoundation's Crypto library, for encryption methods (regarding the game token). It's not a cryptocurrency module.
  • Automatic handling of GameJolt sessions when switching mods and closing the program.

PR is self-marked as WIP because ideally I'd want to have full "cheese control" and be able to prevent players from injecting calls to cheese leaderboards or achievements. Down for feedback/ideas with that.

IF PR IS APPROVED: I am happy to privately send the version of GameJoltSecurity.hx that has been privated by .gitignore. Including it on this PR, or in the open-source code, is a major security risk as it reveals the encryption methods used in my testing and can allow anyone to decrypt and reveal the game key (which is bad).

prevents leaks!
saves login information to save file (with options) when successfully logged in
@r6915ee

r6915ee commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

I'm very skeptical of this PR. There is already a class in flixel-addons called flixel.addons.api.FlxGameJolt that already serves this purpose, at least from my understanding of what this PR adds. I also think this is something that needs to be handled solely by the mod developer, not built into the engine, considering having access to the private key allows access to destructive changes with the GameJolt API.

@ItsLJcool

Copy link
Copy Markdown
Contributor

I'm very skeptical of this PR. There is already a class in flixel-addons called flixel.addons.api.FlxGameJolt that already serves this purpose, at least from my understanding of what this PR adds. I also think this is something that needs to be handled solely by the mod developer, not built into the engine, considering having access to the private key allows access to destructive changes with the GameJolt API.

The issue isn't "it already exists" the issue is it's not secure and this is a solution attempt.

I haven't read the pr yet but we chatted in DM's, the point of making GameJolt support directly for CNE is so that you can't just hijack the data stream or make your own fake requests to a GameJolt server. You can easily do that if you softcode the support and it's been a pain in the ass for me to do so.

@Raltyro

Raltyro commented Aug 10, 2026

Copy link
Copy Markdown
Member

This is sick good

@MRK2009

MRK2009 commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Noice
That would be good for Indie Cross, etc.

@r6915ee

r6915ee commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

I'm very skeptical of this PR. There is already a class in flixel-addons called flixel.addons.api.FlxGameJolt that already serves this purpose, at least from my understanding of what this PR adds. I also think this is something that needs to be handled solely by the mod developer, not built into the engine, considering having access to the private key allows access to destructive changes with the GameJolt API.

Okay, I don't like this response of mine, it's far too vague (and in some cases far too different from what I think now) and I've been thinking about this pull request and the response from LJ. I do think GameJolt integration is a good idea, especially for things like keeping save data in GameJolt's data store (which in my opinion would be a huge benefit) and achievements, but I do think that this pull request could have some additional security.

I believe that there should still be some restriction on what softcoded mods can do, and from my understanding of the new classes this pull request includes, that doesn't seem to happen. I think that in this case, "set" operations of any kind (such as trophy addition, data store removal, etc.) should be exclusively done by compiled code, not HScript.

A "set" operation with the way this is implemented will usually bypass the private key in its entirety. It's very easy to edit scripts to add "malevolent" sets in this case, so this can have a variety of its own complications; one thing that immediately comes to mind are the endpoints for setting items in the data store, as the GameJolt API explicitly distinguishes between the global data store and the user data store. This can also be as simple as adding achievements the player hasn't actually collected. If sets are allowed in HScript code, then that bypasses the point of the private key and allows people to cheat the API.

@SplatterDash

Copy link
Copy Markdown
Author

Okay, I don't like this response of mine, it's far too vague (and in some cases far too different from what I think now) and I've been thinking about this pull request and the response from LJ. I do think GameJolt integration is a good idea, especially for things like keeping save data in GameJolt's data store (which in my opinion would be a huge benefit) and achievements, but I do think that this pull request could have some additional security.

I believe that there should still be some restriction on what softcoded mods can do, and from my understanding of the new classes this pull request includes, that doesn't seem to happen. I think that in this case, "set" operations of any kind (such as trophy addition, data store removal, etc.) should be exclusively done by compiled code, not HScript.

A "set" operation with the way this is implemented will usually bypass the private key in its entirety. It's very easy to edit scripts to add "malevolent" sets in this case, so this can have a variety of its own complications; one thing that immediately comes to mind are the endpoints for setting items in the data store, as the GameJolt API explicitly distinguishes between the global data store and the user data store. This can also be as simple as adding achievements the player hasn't actually collected. If sets are allowed in HScript code, then that bypasses the point of the private key and allows people to cheat the API.

In all honesty I've been worried about the lack of restrictions too, especially with softcoded mods utilizing the GJ system. That's what I'm thinking of when it comes to "cheese control" - preventing people from modifying the softcode to basically cheese achievements, leaderboards and the like. I've had a few ideas to address it, but because every one of those ideas led to me realizing "modifying this element or that code gets around it", I'm still trying to brainstorm how to tackle the issue.
Game key encryption for this PR is being finalized really soon (hopefully tonight), so once that happens I wanna focus on the restriction issue before finishing my work on this.

- tested/modified settings to ensure both GameJoltSecurity and NEW GameJoltData are inaccessible via Hscript
- NEW SecretMacro - reads .env file if provided, and generates new one if missing (alongside new randomly-generated AES key if missing)
- new method of initializing GameJolt for mods!
 > place Game ID in modpack.ini for GAMEJOLT_GAME_ID
 > place owner username/user token, raw game token (if you're worried keep reading), trophies, leaderboards, and data items in gamejolt.xml in data/config folder
 > load mod in-game - owner/game token info will be wiped from xml, game gives xml key, and game sets everything in xml (except game token and user token) in global data store for game
 > running a mod with gamejolt relies on global data store items for trophies, leaderboards, etc - only page owner can update this global key
 > for those worried about keys - each key can hold 16 MB, and in testing a global key with 6 trophies, a leaderboard, one custom data setting, and owner items takes up around 0.7 KB
- some starts on GameJolt menus - WIP at time of commit

encrypting/protecting game security keys is complete! part two now is limiting the attack surface for API calls - most of the calls that can be made now for softcoding are fetch calls and a planned GJUtil function for custom trophies (there are some that can be inputted for "defined" events - loading the mod for the first time, getting a first FC, completing all songs, completing a week - but these are inaccessible from softcode).
still a bunch planned, especially with menus - but it's a fun little commit hehe
@SplatterDash

Copy link
Copy Markdown
Author

A little checkpoint commit was pushed just now for the work I've done so far, here's a little more on the commit beyond just notes:

  • Phase One of the commit (securing game keys) is complete. While GameJoltSecurity.hx is no longer on .gitignore, the actual encryption key (the most important part) is hidden on a .env file and that's kept on .gitignore instead. GameJoltSecurity.hx is tested inaccessible through Hscript.
  • SecretMacro.hx is a macro that has a similar purpose to Funkin's EnvironmentMacro, but in addition to reading environment variables it also generates a .env file if missing AND will randomly generate an encryption key for AES encryption if the variable is missing. This macro can of course be expanded on if needed for future projects.
  • There's a new process for registering a mod to work with GameJolt integrations:
  1. Add your game's ID (NOT security key) in modpack.ini in the Common section for flag GAMEJOLT_GAME_ID.
  2. Create gamejolt.xml in data/config. Add the username and user token of the owner, raw game security key (it's not staying in that file - keep reading), trophy data, leaderboard data, and additional data items to save when a user saves to your game's data store.
    a. Trophy data comes in two types - defined and custom. defined mainly addresses common trophies you might find in a mod - opening it up for the first time, getting a first FC, completing a week, completing all songs, FCing all songs, etc. The list of defined types is available in GameJoltData.hx. custom addresses any other types not covered by defined. Softcoders can only send calls to unlock custom trophies, not defined. All trophy nodes also have additional options - name of the week to unlock (for week complete trophies), exceptions (for FC all or complete all trophies), required trophies to unlock before unlocking the current trophy (for any trophy).
    b. Leaderboard data mainly works for songs. They are separated by variation, but you can either set leaderboards per difficulty or have one for all difficulties.
    c. Additional data is for when users save their own data on your game's data stores. By default, I plan to have CNE base controls, CNE base options, and highscores for the mod saved on individual users' tokens in said mod's data store; however, if other mods need more info stored, they can set this and indicate where the data is (default FlxG save, but it could be anywhere).
  3. Load the mod in Codename. Once you do, (provided your owner username/token and game security key are correct) it'll upload the data in the XML to your game's data store under a global key, automatically remove the owner credentials and game security key from the XML, encrypt your game security key using the AES key, and give you a screen that allows you to copy the exact flag you need to paste in your mod's modpack.ini file. After that, you can also discard the gamejolt.xml file unless you (as in, the owner) wants to change the global data later on.
image

Why do that method? To mainly limit the attack surface for players and modders. Leaving all of that data in softcode makes it easy to manipulate; we have the GameJolt data store, it's much more secure, and each key can hold 16 megabytes (to give you an idea - 6 trophies, a leaderboard, one data indicator, an owner username, and the ID of the owner's account all amounts to 0.7 kilobytes, meaning we got plenty of room to work with), so it's a good way to keep things secure.

  • The calls made with the GameJolt API for softmodders is now limited to mainly fetch calls (except data, no softcoders can access data calls), and TROPHY_REMOVE (although might remove it now that I think about it? don't wanna give XP farmers any ideas). All of those other calls are handled via hardcoding. That means posting to leaderboards, unlocking defined trophies (custom trophies are called via softcode), handling data... all of that's planned to be handled by hardcode. Which means I have to make some menus! (some WIP ones are in this commit).

I'm absolutely down for feedback - the specific defined calls for reference as well (as in "the calls that softmodders can't call") are open-first (first time opening the mod), friday-night (play on a friday night), week (complete a week), complete-all (complete all songs in a mod), fc-first (FC a song for the first time), and fc-all (FC all songs in a mod). I'm also planning on adding death-first (first time dying) to that list. So, any requests or feedback on that, or anything else, is welcome!

Comment on lines +80 to +90
var menuItem:FlxSprite = new FlxSprite(FlxG.width - 138, FlxG.height - 138).loadGraphic(Paths.image('menus/gamejolt-icon'));
menuItem.setGraphicSize(128);
menuItem.updateHitbox();
menuItem.animation.add('idle', [0], 1, false);
menuItem.animation.add('selected', [0], 1, false);
menuItem.animation.play('idle');
menuItem.ID = menuItems.length;
menuItems.add(menuItem);
menuItem.scrollFactor.set();
menuItem.antialiasing = true;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps accessing the GameJolt menu the way it's done across this file could be done in an example addon or repository instead? I think this may cause some complications with mods that only extend the main menu if it's part of the main source code, especially with the menuItems.txt file.

Comment thread project.xml
Comment on lines +69 to +71
<!-- Comment this out to disable GameJolt API integration !-->
<define name="GAMEJOLT_API" if="GITHUB_API"/>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it may also be a good idea to additionally constrain GAMEJOLT_API against STRIPPED_COMPILE so that it gets disabled, as not everyone may want to immediately compile support for the Game API in, such as when working on a pull request.

<define name="GAMEJOLT_API" if="GITHUB_API" unless="STRIPPED_COMPILE"/>

Comment on lines +40 to +47
add(loginButton = new UIButton(windowSpr.x + windowSpr.bWidth - 20 - 125, windowSpr.y + windowSpr.bHeight - 16 - 32, "Login", function() {
if (GJUtil.attemptLogin(usernameBox.label.text, userTokenBox.label.text, true)) {
FlxG.state.openSubState(new GameJoltLoginSuccess());
close();
} else {

}
}, 125));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it may be a good idea to constrain this against GAMEJOLT_API being active, as GJUtil.attemptLogin will not be compiled if GAMEJOLT_API is inactive.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants