{"id":19416243,"url":"https://github.com/geokureli/newgrounds","last_synced_at":"2026-02-07T21:31:31.552Z","repository":{"id":28773233,"uuid":"119288702","full_name":"Geokureli/Newgrounds","owner":"Geokureli","description":"Newgrounds API for haxe","archived":false,"fork":false,"pushed_at":"2024-05-03T20:53:15.000Z","size":10502,"stargazers_count":52,"open_issues_count":3,"forks_count":17,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-08-09T14:40:48.772Z","etag":null,"topics":["game-dev","game-development","haxe","newgrounds","newgrounds-medals","newgrounds-scoreboards","newgroundsio","strawberryclock"],"latest_commit_sha":null,"homepage":"http://newgrounds.io","language":"Haxe","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Geokureli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-01-28T19:05:58.000Z","updated_at":"2025-06-25T14:31:35.000Z","dependencies_parsed_at":"2023-12-01T22:23:18.849Z","dependency_job_id":"5fa5154d-2166-4a54-bbf5-33bf960ef265","html_url":"https://github.com/Geokureli/Newgrounds","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/Geokureli/Newgrounds","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Geokureli%2FNewgrounds","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Geokureli%2FNewgrounds/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Geokureli%2FNewgrounds/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Geokureli%2FNewgrounds/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Geokureli","download_url":"https://codeload.github.com/Geokureli/Newgrounds/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Geokureli%2FNewgrounds/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29208705,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-07T20:33:12.493Z","status":"ssl_error","status_checked_at":"2026-02-07T20:30:47.381Z","response_time":63,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["game-dev","game-development","haxe","newgrounds","newgrounds-medals","newgrounds-scoreboards","newgroundsio","strawberryclock"],"created_at":"2024-11-10T12:46:58.094Z","updated_at":"2026-02-07T21:31:31.536Z","avatar_url":"https://github.com/Geokureli.png","language":"Haxe","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![MIT License](https://img.shields.io/github/license/geokureli/newgrounds.svg?style=flat)](LICENSE.md)\n[![Haxelib Version](https://img.shields.io/github/tag/geokureli/newgrounds.svg?style=flat\u0026label=haxelib)](https://lib.haxe.org/p/newgrounds/)\n\n# Newgrounds\n\nBefore using this library make sure you have read the \n\u003ca href=\"http://www.newgrounds.io/\"\u003eIntroduction to Newgrounds.io\u003c/a\u003e!\n\nIf you're confused by anything be sure to \n\u003ca href=\"https://www.newgrounds.com/projects/games/1181322/preview/\"\u003etry out the test project\u003c/a\u003e.\n\n## Installing the library\n\n**using haxelib:**\n`haxelib install newgrounds`\n\n## Implement an instance of io.newgrounds.core into your game:\n\nAdd `\u003chaxelib name=\"newgrounds\" /\u003e` to your project.xml.\nYou can also just include the local library in your xml\nvia `\u003cclasspath path=\"../[libr path]/lib/src\" /\u003e`\n\nIf you hate my shitty core helpers, you can enable\nthe compiler flag `ng_lite` to limit NG.core's\nfunctionality to basic component calls and responses.\n\n### Creating the core\n\n```haxe\nNG.create(\"app id here\", \"session id, here, if you know it\");\n```\n\nOnce the core is created you can access it via NG.core but \nthis is not possible if the core was instantiated directly.\n\nWhen your game is being played on Newgrounds.com you can\nfind the sessionId in the loaderVars, or you can have the\nAPI find it automatically with\n\n```haxe\nNG.createAndCheckSession(\"app id here\", \"backup session id, if none is found\");\n```\n\n\nThis will also determine the host that will be used when\nlogging events (except when ng_lite is active). You can\nalso set or change the host using `NG.core.host`. The\nhost is used to track views and various other events logged\nto NG.io.\n\n### Manual Login\n\nIf no session ID was found, you will need to start one.\n\n```haxe\nif (NG.core.loggedIn == false) {\n    NG.core.requestLogin(\n        function(outcome:LoginOutcome):Void {\n            if (outcome.match(SUCCESS))\n                trace(\"logged on\");\n        }\n    );\n}\n```\n\n### Encryption\n\nSetting the encryption method is easy, just call:\n\n```haxe\nNG.core.setupEncryption(\"encryption key\", AES_128, BASE_64);\n```\n\nEncryption Ciphers:\n- **io.newgrounds.crypto.Cipher.NONE**\n- **io.newgrounds.crypto.Cipher.AES-128**(default)\n- **io.newgrounds.crypto.Cipher.RC4**\n\nEncryption Ciphers:\n- **io.newgrounds.crypto.EncryptionFormat.BASE_64** (default)\n- **io.newgrounds.crypto.EncryptionFormat.HEX**\n\nYou can also use your own encryption method - if you're some kind of crypto-god from The Matrix -\nby directly setting NG.core.encryptionHandler\n\n#### Example\n```haxe\nNG.core.encryptionHandler = myEncryptionHandler;\n\nfunction myEncryptionHandler(data:String):String {\n    \n    var encrytedData:String;\n    // stuff\n    return encrytedData;\n}\n```\n\n## Using fla assets\nIf your project already uses a .swf you can add them to your .fla \nand they will automatically listen to your core for events. \nYou can also instantiate them in code. These assets work with ng_lite enabled (with caveats)\n\n**MedalPopup:** Just add it where you want it to show and it will \nautoplay when you call medal.unlock(), and the server response with a success event. \nIf multiple achievements are unlocked at the same time they will play one after another\n\n_**Note:** If the ng_lite compiler flag is true this will not automatically appear,\nyou must call playAnim(iconDisplayObj, medalName, medalPoints).\nIf ng_lite is false MedalPopup will request medals as soon as you start a NG.io session_\n\n**ScoreBrowser:** Once it's added to the stage and a NG.io has started it loads board data, \nit has the following public properties\n - **boardId:** The numeric ID of the scoreboard to display. Defaults to the first ID sent back from the server.\n - **period:** The time-frame to pull scores from (see notes for acceptable values). Defaults to all-time\n - **title:** The title of the scoreBrowser, defaults to whatever the swf already has.\n - **tag:** A tag to filter results by\n - **social:** Whether to only list scores by the user and their friends, defaults to false\n\n## Using Core Objects\nUsing core methods will cause the core to automatically keep track of server data in the underlying calls. \nmuch like how `NG.core.requestLogin()` stores the resulting sessionId for future calls, Medal and Scoreboard \ndata is maintained from NG.core methods, but not direct `NG.core.calls` \n\n### Medals \nUse `NG.core.medals.loadList()` to populate `NG.core.medals`, once Medal objects are created \nyou can interface with them directly. For instance: \n```haxe\nvar medal =  NG.core.medals.get(id);\ntrace('${medal.name} is worth ${medal.value}');\n\nif (!medal.unlocked) {\n    \n    medal.onUnlock.add(function ():Void { trace('${medal.name} unlocked:${medal.unlocked}'); });\n    medal.unlock();\n}\n```\n\n### ScoreBoards\nJust like Medals `NG.core.scoreBoards` is populated from `NG.core.scoreBoards.loadList()` \nwhich allows you make postScore and getScores calls directly on the board.\n\n**Note:** ScoreBoard instances persist across multiple scoreBoards.loadList calls, but a ScoreBoard's score instances do not\n\n### CloudSaves\nSimilarly to medals and scoreboards CloudSaves have `NG.core.saveSlots` which is populated by `NG.core.saveSlots.loadList`.\nOn top of the normal [SaveSlot properties](http://www.newgrounds.io/help/objects/#SaveSlot), each saveSlot will have a\nreadonly `contents` field that is null until you call `load` on that SaveSlot instance (`load()` will throw an error\nif there is no save in that slot, check this using `isEmpty()`). You can also call `save(mySaveContents)` or `clear()` on\nSaveSlots.\n\n## Calling Components and Handling Outcomes\nYou can talk to the NG.io server directly, but NG.core won't automatically handle \nthe response for you (unlike NG.core.requestMedals()). All of the component calls are \nin `NG.core.call.[componentName].[callName](\"call args\")`\n\n#### Example:\n```haxe\nvar call = NG.core.calls.medal.unlock(medalId);\ncall.send();\n```\n\n### Handling responses\nYou can add various listeners to a call to track successful or unsuccessful responses from the NG server.\n\n```haxe\nvar call = NG.core.calls.medal.unlock(medalId);\ncall.addOutcomeHandler(onMedalUnlockDataReceived);\ncall.send();\n```\n\nThe various calls types result in different response data structures. For instance medal.unlock \nresponds with a `CallOutcome\u003cio.newgrounds.objects.events.Data\u003e` object. The outcome type determines the data \ncontained in the `SUCCESS(data)`. \n\n#### Example Usage:\n\n```haxe\nvar call = NG.core.calls.medal.unlock(medalId);\ncall.addOutcomeHandler(\n    function(outcome:CallOutcome\u003cMedalUnlockData\u003e):Void {\n        \n        switch(outcome) {\n            \n            case SUCCESS(data): trace('Medal unlocked, [name=${data.medal.name}]');\n            case FAIL(error): trace('Error unlocking medal: ' + error.toString());\n        }\n    }\n);\ncall.send();\n```\n\nYou can use `myCall.addSuccessHandler(function():Void { trace(\"success\"); });` \nto only listen for successful responses from the server\n\nYou can also use myCall.addErrorHandler to listen for errors thrown by NG server, or errors\nresulting from general Http remoting\n\n```haxe\nmyCall.addErrorHandler(\n    function(e:io.newgrounds.objects.Error):Void {\n        \n        trace('Error: $e');\n    }\n);\n```\n\n### Chaining call methods\nAll Call methods support chaining, meaning you can setup your calls without using local vars.\n```haxe\nNG.core.call.medalUnlock(id)\n    .setProperty(\"debug\", true)\n    .addSuccessHandler(onSuccess)\n    .addErrorHandler(onFail)\n    .addStatusHandler(onStatusChange)\n    .send();\n```\n\n### Queueing calls\nAll calls can be queued so that they are sent sequentially rather than sending them all at once.\n\n```haxe\nNG.core.session = \"session id here\";\nNG.core.calls.app.checkSession().queue();\nNG.core.calls.medal.unlock(id).queue();\n```\n\n## TODO\n - ~~AES-128 encryption~~\n - ~~Hex encoding~~\n - ~~Enable AES-128 and Hex in the GUI test project~~\n - ~~Pretty up the GUI test project in general~~\n - ~~Replace successCallbacks and failCallbacks with outcomeCallbacks (2.0.0)~~\n - Explain OutcomeTools in readme\n - kill all humans\n - flash API assets\n     - ad viewer - not supported in ng.io v3\n     - auto connector - requires ads?\n - continuous integrations\n - local storage\n    - save unsent medal unlocks and scoreboard posts\n    - save previous session rather than creating a new one\n - allow synchronous http requests\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeokureli%2Fnewgrounds","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgeokureli%2Fnewgrounds","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgeokureli%2Fnewgrounds/lists"}