diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 000000000..43ebb20c9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,17 @@ +root = true + +[*] +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +indent_style = space +indent_size = 4 + +charset = utf-8 + +[*.yaml] +indent_size = 2 + +[*.yml] +indent_size = 2 diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 000000000..2c13e0d0b --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @nekitdev @Wyliemaster @SMJSGaming diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 02fb2d2d6..48280c500 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,3 +1 @@ -# Why the hell not? - -github: Homurasama, SMJSgaming, NeKitDS, Altenhh, GDColon, 13laze \ No newline at end of file +github: Wyliemaster, nekitdev, SMJSGaming, naoei diff --git a/.github/dependebot.yml b/.github/dependebot.yml new file mode 100644 index 000000000..4c42f9d06 --- /dev/null +++ b/.github/dependebot.yml @@ -0,0 +1,28 @@ +version: 2 + +updates: + - package-ecosystem: github-actions + directory: "/" + + labels: + - A-dependencies + - P-normal + - S-triage + + schedule: + interval: daily + + open-pull-requests-limit: 10 + + - package-ecosystem: pip + directory: "/" + + labels: + - A-dependencies + - P-normal + - S-triage + + schedule: + interval: daily + + open-pull-requests-limit: 10 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 000000000..542fb9479 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,41 @@ +name: docs + +on: + push: + branches: + - main + - docs + +jobs: + docs: + name: Docs + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Setup Python 3.10 + uses: actions/setup-python@v4 + with: + python-version: "3.10" + + - name: Update PATH + run: echo "$HOME/.local/bin" >> $GITHUB_PATH + + - name: Install Poetry + run: curl -sSL https://install.python-poetry.org/ | python - + + - name: Update Poetry + run: poetry self update --preview + + - name: Configure Poetry + run: poetry config virtualenvs.in-project true + + - name: Install dependencies + run: poetry install --with docs + + - name: Pull + run: git pull + + - name: Deploy the documentation + run: poetry run mkdocs gh-deploy diff --git a/.gitignore b/.gitignore index cae7906eb..3063c7ea5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,22 @@ -node_modules +# editors + .idea/ .vs/ -package-lock.json \ No newline at end of file +# virtual environments + +.env +env/ +env.bak/ + +.venv +venv/ +venv.bak/ + +# documentation + +site/ + +# remove if lock file should be included + +poetry.lock diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..2707a97cf --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,137 @@ +# Code of Conduct + +## Our Pledge + +We as members, contributors, and leaders pledge to make participation in our +community a harassment-free experience for everyone, regardless of age, body +size, visible or invisible disability, ethnicity, sex characteristics, gender +identity and expression, level of experience, education, socio-economic status, +nationality, personal appearance, race, caste, color, religion, or sexual +identity and orientation. + +We pledge to act and interact in ways that contribute to an open, welcoming, +diverse, inclusive, and healthy community. + +## Our Standards + +Examples of behavior that contributes to a positive environment for our +community include: + +* Demonstrating empathy and kindness toward other people +* Being respectful of differing opinions, viewpoints, and experiences +* Giving and gracefully accepting constructive feedback +* Accepting responsibility and apologizing to those affected by our mistakes, + and learning from the experience +* Focusing on what is best not just for us as individuals, but for the overall + community + +Examples of unacceptable behavior include: + +* The use of sexualized language or imagery, and sexual attention or advances of + any kind +* Trolling, insulting or derogatory comments, and personal or political attacks +* Public or private harassment +* Publishing others' private information, such as a physical or email address, + without their explicit permission +* Other conduct which could reasonably be considered inappropriate in a + professional setting + +## Enforcement Responsibilities + +Community leaders are responsible for clarifying and enforcing our standards of +acceptable behavior and will take appropriate and fair corrective action in +response to any behavior that they deem inappropriate, threatening, offensive, +or harmful. + +Community leaders have the right and responsibility to remove, edit, or reject +comments, commits, code, wiki edits, issues, and other contributions that are +not aligned to this Code of Conduct, and will communicate reasons for moderation +decisions when appropriate. + +## Scope + +This Code of Conduct applies within all community spaces, and also applies when +an individual is officially representing the community in public spaces. +Examples of representing our community include using an official email address, +posting via an official social media account, or acting as an appointed +representative at an online or offline event. + +## Enforcement + +Instances of abusive, harassing, or otherwise unacceptable behavior may be +reported to the community leaders responsible for enforcement to +[conduct@gd-programming.org][Email]. + +All complaints will be reviewed and investigated promptly and fairly. + +All community leaders are obligated to respect the privacy and security of the +reporter of any incident. + +## Enforcement Guidelines + +Community leaders will follow these Community Impact Guidelines in determining +the consequences for any action they deem in violation of this Code of Conduct: + +### 1. Correction + +**Community Impact**: Use of inappropriate language or other behavior deemed +unprofessional or unwelcome in the community. + +**Consequence**: A private, written warning from community leaders, providing +clarity around the nature of the violation and an explanation of why the +behavior was inappropriate. A public apology may be requested. + +### 2. Warning + +**Community Impact**: A violation through a single incident or series of +actions. + +**Consequence**: A warning with consequences for continued behavior. No +interaction with the people involved, including unsolicited interaction with +those enforcing the Code of Conduct, for a specified period of time. This +includes avoiding interactions in community spaces as well as external channels +like social media. Violating these terms may lead to a temporary or permanent +ban. + +### 3. Temporary Ban + +**Community Impact**: A serious violation of community standards, including +sustained inappropriate behavior. + +**Consequence**: A temporary ban from any sort of interaction or public +communication with the community for a specified period of time. No public or +private interaction with the people involved, including unsolicited interaction +with those enforcing the Code of Conduct, is allowed during this period. +Violating these terms may lead to a permanent ban. + +### 4. Permanent Ban + +**Community Impact**: Demonstrating a pattern of violation of community +standards, including sustained inappropriate behavior, harassment of an +individual, or aggression toward or disparagement of classes of individuals. + +**Consequence**: A permanent ban from any sort of public interaction within the +community. + +## Attribution + +This Code of Conduct is adapted from the [Contributor Covenant][Home], +version 2.1, available at +[https://contributor-covenant.org/version/2/1/code_of_conduct][v2.1]. + +Community Impact Guidelines were inspired by +[Mozilla's Code of Conduct enforcement ladder][Mozilla Code of Conduct]. + +For answers to common questions about this code of conduct, see the FAQ at +[https://contributor-covenant.org/faq][FAQ]. Translations are available at +[https://contributor-covenant.org/translations][Translations]. + +[Email]: mailto:conduct@gd-programming.org + +[Home]: https://contributor-covenant.org/ +[v2.1]: https://contributor-covenant.org/version/2/1/code_of_conduct + +[Mozilla Code of Conduct]: https://github.com/mozilla/diversity + +[FAQ]: https://contributor-covenant.org/faq +[Translations]: https://contributor-covenant.org/translations diff --git a/LICENSE b/LICENSE index 5c3cd9117..4961e0493 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2020 GD Programming +Copyright (c) 2020-present, GD Programming Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 6084a6230..84305109a 100644 --- a/README.md +++ b/README.md @@ -1,31 +1,64 @@ -
- book -
+# `gd.docs` -# GDDocs +[![gd.docs][Badge]][gd.docs] -**Some documentation for Geometry Dash's servers, and the game itself.** +**Documentation for Geometry Dash.** ----- +`gd.docs` is a project built to openly give advanced information for aspiring developers looking to interface +with *Geometry Dash*. We primarily aim to create this as a website for people to learn more about the inner +workings of *Geometry Dash* along with its data. -**GDDocs** is a project built to openly give advanced information and readable information for aspiring developers looking to interface with Geometry Dash. Primarily, we aim to create this as a website for people to learn more about the inner workings of geometry dash, along with it's data. +You can find the website over [here][gd.docs]. -The GDDocs website can be found [here](https://docs.gdprogra.me/#/) +## Installing -## Running/Building -**You will require Node.js `>=12` to debug and run this project.** +**Python 3.7 is required to build the documentation.** -GDDocs is built off of the `docsify` engine, outputted to a generator file to be able to work well on server environments, rather than GitHub pages. This is primarily to allow for easy domain usage and development in a place where it can always update, and be hosted upon locally rather than over GitHub's servers. +Firstly, you need to clone the `gd.docs` repository: -As such, rather than having to install using the package.json; (which we would recommended doing anyways using `npm install`,) the installation and such has been included in `generator.js`. +```console +$ git clone https://github.com/gd-programming/gd.docs +$ cd gd.docs +``` + +Then you can install the dependencies via: + +```console +$ python -m pip install . +``` -```plain -node generator.js +Alternatively, if you are using poetry: + +```console +$ poetry install ``` -To debug it, you will need to properly clone or pull this repository. +## Building + +`gd.docs` is built using `mkdocs` library. Building the documentation is as simple as: + +```console +$ mkdocs build +``` + +The result will be placed in the `site` directory. + +## Serving + +In order to make the documentation easier to work on, one can use the following command: + +```console +$ mkdocs serve +``` + +It will run a local server, updating all changes to documentation on-the-fly. ## Contributing -Contributions are preferably made to the documentation, rather than the simple `generator.js` file; unless need be. Contributions to all aspects of this project are preferred to be made over pull requests and issues. Ideas on what to contribute or read over can be read in the [issues](https://github.com/gd-programming/gddocs/issues) section of this repository. +Contributions to all aspects of this project are preferred to be made over pull requests and issues. +Ideas on what to add or improve can be found in the [issues][Issues] section of this repository. + +[gd.docs]: https://docs.gd-programming.org/ +[Issues]: https://github.com/gd-programming/gd.docs/issues +[Badge]: https://github.com/gd-programming/gd.docs/workflows/docs/badge.svg diff --git a/assets/gddocs-icon.png b/assets/gddocs-icon.png deleted file mode 100644 index 0c3e1efb2..000000000 Binary files a/assets/gddocs-icon.png and /dev/null differ diff --git a/assets/icons/gd.docs.png b/assets/icons/gd.docs.png new file mode 100644 index 000000000..e257b1533 Binary files /dev/null and b/assets/icons/gd.docs.png differ diff --git a/docs/.nojekyll b/docs/.nojekyll deleted file mode 100644 index e69de29bb..000000000 diff --git a/docs/CNAME b/docs/CNAME new file mode 100644 index 000000000..9cb50b9df --- /dev/null +++ b/docs/CNAME @@ -0,0 +1 @@ +docs.gd-programming.org diff --git a/docs/CREDITS.md b/docs/CREDITS.md deleted file mode 100644 index 59c0b2d31..000000000 --- a/docs/CREDITS.md +++ /dev/null @@ -1,12 +0,0 @@ -# Credits - -Thanks to the **Geometry Dash Programming** experts, and the **GDDocs** contributors for making this project a reality. Without you guys, this project wouldn't have even been possible. - -*-- Team professionally led by [SMJS](https://github.com/SMJSGaming)* -- [nekit](https://github.com/nekitdev) -- [Wylie](https://github.com/Wyliemaster) -- [Andre](https://github.com/AndreNIH) -- [Cvolton](https://github.com/Cvolton) -- [Colon](https://github.com/GDColon) -- [AlFas](https://github.com/AlFasGD) -- [zmx](https://github.com/kyurime) diff --git a/docs/ProjectCard.css b/docs/ProjectCard.css deleted file mode 100644 index 7d71eb6c1..000000000 --- a/docs/ProjectCard.css +++ /dev/null @@ -1,189 +0,0 @@ -/*html, body { - font-family: Torus, "Helvetica Neue",Tahoma,Arial,"Hiragino Kaku Gothic ProN",Meiryo,"Microsoft YaHei","Apple SD Gothic Neo",sans-serif !important; - font-weight: 300; -}*/ - -*, :before, :after { - position: relative; - box-sizing: border-box; -} - -.project_cards { - display: grid; - grid-gap: 10px; - grid-template-columns: repeat(auto-fill, minmax(200px, 290px)); - justify-content: center; -} - -.projects_card { - display: inline-block; - width: 100%; - height: 120px; - background-color: hsl(160, 20%, 20%); - border-radius: 10px; - overflow: hidden; - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.25); - transition: all .22s ease-in-out; -} - -.project_card_background-container { - position: absolute; - top: 0; - left: 0; - height: 100%; - width: 100%; -} - -.project_card-background { - border-radius: 10px; - position: absolute; - left: 0; - top: 0; - height: 100%; - width: 100%; - object-fit: cover; - transition: opacity .22s ease-in-out; -} - -.project_card-background-overlay { - background: hsla(160, 20%, 15%, .7); - position: absolute; - top: 0; - left: 0; - height: 100%; - width: 100%; - border-radius: 10px; -} - -.projects_card-card { - color: white; - text-decoration: none; - display: flex; - flex-direction: column; - justify-content: space-between; - pointer-events: none; - height: 100%; -} - -.projects_card_content { - padding: 10px; -} - -.projects_card_content-details { - display: grid; - grid-template-columns: minmax(min-content, auto) 1fr; -} - -.projects_card_logo { - display: flex; - align-items: center; - width: 60px; - height: 60px; - flex: none; -} - -.projects_card_logo-image { - position: absolute; - left: 0; - top: 0; - height: 100%; - width: 100%; - border-radius: 6px; - -o-object-fit: contain; - object-fit: contain; - background-color: hsl(160,20%,20%); - transition: opacity .22s ease-in-out; -} - -.projects_card_details { - display: grid; - grid-template-rows: 26px 1fr; - margin-left: 10px; -} - -.projects_card_title { - display: flex; - align-items: center; - min-width: 0; - font-size: 15px; -} - -.projects_card_authors { - display: flex; - min-width: 0; - font-size: 12px; - top: 0; - left: 0; -} - -.projects_card_content-stats { - display: flex; - flex-direction: row; - align-items: center; - padding-top: 0; -} - -.projects_card_stats { - display: flex; - align-items: center; - min-width: 0; - margin-right: 15px; -} - -.projects_card_language-icon-container { - display: inline-flex; - justify-content: center; - align-items: center; - flex: none; - width: 10px; -} - -.projects_card_language-icon { - border-radius: 50%; - width: 10px; - height: 10px; -} - -.projects_card_language-icon--cs { - background: #BDFF00; -} - -.projects_card_language-icon--js { - background: #FFC700; -} - -.projects_card_language-icon--html { - background: #FF7F66; -} - -.projects_card_language-icon--py { - background: #66B6FF; -} - -.projects_card_language-message { - display: flex; - flex-direction: column; - margin-left: 5px; - font-size: 12px; - min-width: 0; -} - -.projects_card:hover:after { - position: absolute; - left: 0; - top: 0; - height: 100%; - width: 100%; - content: ""; - border: 2px solid hsl(160,40%,80%); - border-radius: 10px; - pointer-events: none; -} - -.projects_card:hover { - box-shadow: 0 3px 6px rgba(0, 0, 0, 0.25); -} - -.project_cards-compact { - display: block; -} \ No newline at end of file diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index e2658c90e..000000000 --- a/docs/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# Introduction - -Welcome to the Geometry Dash Programming **[Discord](https://discord.gg/jEwtDBK)** server's online iteration of documentation for Geometry Dash. Here, you'll find all sorts of information, documents, and resources for interacting with **[Geometry Dash](http://robtopgames.com)**. We aim to make **[GDDocs](https://github.com/gd-programming/gddocs)** the most comprehensive and open source of information for the game, created by many people who have interacted with the game and wish to share such with others. - -The provided documentation is available on it's repository, over [here](https://github.com/gd-programming/gddocs). For all issues regarding information found here, please consult us by creating an issue. - -## Projects - -### Geometry Dash Wrappers - -A few people, or teams have gone out of their way to create proper wrappers and API's around the **Geometry Dash** servers and it's client. All of the known and endorsed projects will find their way here, as a listing of resources people can use for their own projects. - -#### Python - -* [gd.py](https://github.com/NeKitDS/gd.py) by [NeKitDS](https://github.com/NeKitDS) - -#### C# - -* [GDAPI](https://github.com/gd-edit/GDAPI) by the [GDEdit Team](https://github.com/gd-edit) -* [GDNET](https://github.com/GDdotNET/GDNET) by the [GD.NET Team](https://github.com/GDdotNET) - -### Geometry Dash Projects - -These are generally projects that generally interface over the Geometry Dash servers, and overall have built up their own recognition and traction along the community, and developers alike. - -#### Node.js - -* [GDBrowser](https://github.com/GDColon/GDBrowser) by [GDColon](https://github.com/GDColon) -* [GD-NodeJS-API](https://github.com/SMJSGaming/GD-NodeJS-API) by [SMJS](https://github.com/SMJSGaming) - -#### C# - -* [GDEdit](https://github.com/gd-edit/GDE) by the [GDEdit Team](https://github.com/gd-edit) - -#### C++ - -* [GDAddon](https://github.com/Keenlos/GDAddonSDK) by the [Keenlos Team](https://github.com/Keenlos/Keenlos/blob/master/ABOUT.md) -* [GDCrypto](https://github.com/Cos8o/GDCrypto) by [Cos8o](https://github.com/Cos8o) - -## Outside Remarks - -With this documentation, the Geometry Dash Programming staff team would love to see your interesting ideas with this project, and the kinds of things you create with the information provided. Make sure to hit us up on our discord, and show us of such! diff --git a/docs/_404.md b/docs/_404.md deleted file mode 100644 index cbafc5a4c..000000000 --- a/docs/_404.md +++ /dev/null @@ -1,5 +0,0 @@ -# Uh oh, you did a fucky wucky - -Wonder how you got here. Maybe an invalid link? - -I'd suggest reporting about it to [the team](https://github.com/gd-programming/gddocs/issues) as best as you can. diff --git a/docs/_sidebar.md b/docs/_sidebar.md deleted file mode 100644 index 327414df7..000000000 --- a/docs/_sidebar.md +++ /dev/null @@ -1,120 +0,0 @@ - - -- [Intro](/) -- [Reference](/reference.md) -- [Credits](/CREDITS.md) - -## **Resources** - -- **Server** - - [Comment](/resources/server/comment.md) - - [Friend Request](/resources/server/friendrequest.md) - - [Gauntlet](/resources/server/gauntlet.md) - - [Leaderboard Score](/resources/server/leaderboardscore.md) - - [Level](/resources/server/level.md) - - [Map Pack](/resources/server/mappack.md) - - [Message](/resources/server/message.md) - - [Song](/resources/server/song.md) - - [User](/resources/server/user.md) - - [Restore](/resources/server/restore.md) -- **Client** - - [Gamesave](/resources/client/gamesave.md) - - [Encoder Keys](resources/client/gamesave/kCEK.md) - - [GS Values](/resources/client/gamesave/GS_Value.md) - - [GLM](/resources/client/gamesave/GLM.md) - - [Value Keeper](/resources/client/gamesave/valueKeeper.md) - - [Game Variables](/resources/client/gamesave/gv.md) - - [Achievements](/resources/client/gamesave/achievement.md) - - [Quests](/resources/client/gamesave/quests.md) - - - [Level](/resources/client/level.md) - - [Capacity String](/resources/client/level-components/capacity-string.md) - - [Level Colors](/resources/client/level-components/level-colors.md) - - [Inner Level String](/resources/client/level-components/inner-level-string.md) - - [Level Object](/resources/client/level-components/level-object.md) - - [Color String](/resources/client/level-components/color-string.md) - - [Guideline String](/resources/client/level-components/guideline-string.md) -**Endpoints** - -- Comments - - [deleteGJAccComment20](/endpoints/deleteGJAccComment20.md) - - [deleteGJComment20](/endpoints/deleteGJComment20.md) - - [getGJAccountComments20](/endpoints/getGJAccountComments20.md) - - [getGJCommentHistory](/endpoints/getGJCommentHistory.md) - - [getGJComments21](/endpoints/getGJComments21.md) - - [uploadGJAccComment20](/endpoints/uploadGJAccComment20.md) - - [uploadGJComment21](/endpoints/uploadGJComment21.md) -- Level Packs - - [getGJGauntlets21](/endpoints/getGJGauntlets21.md) - - [getGJMapPacks21](/endpoints/getGJMapPacks21.md) -- Levels - - [deleteGJLevelUser20](/endpoints/deleteGJLevelUser20.md) - - [downloadGJLevel22](/endpoints/downloadGJLevel22.md) - - [getGJDailyLevel](/endpoints/getGJDailyLevel.md) - - [getGJLevels21](/endpoints/getGJLevels21.md) - - [rateGJDemon21](/endpoints/rateGJDemon21.md) - - [rateGJStars211](/endpoints/rateGJStars211.md) - - [reportGJLevel](/endpoints/reportGJLevel.md) - - [suggestGJStars](/endpoints/suggestGJStars.md) - - [updateGJDesc20](/endpoints/updateGJDesc20.md) - - [uploadGJLevel21](/endpoints/uploadGJLevel21.md) -- Messages - - [deleteGJMessages20](/endpoints/deleteGJMessages20.md) - - [downloadGJMessage20](/endpoints/downloadGJMessage20.md) - - [getGJMessages20](/endpoints/getGJMessages20.md) - - [uploadGJMessage20](/endpoints/uploadGJMessage20.md) -- Miscellaneous - - [getAccountURL](/endpoints/getAccountURL.md) - - [getTop1000](/endpoints/getTop1000.md) - - [getGJSongInfo](/endpoints/getGJSongInfo.md) - - [getGJTopArtists](/endpoints/getGJTopArtists.md) - - [getSaveData](/endpoints/getSaveData.md) - - [testSong](/endpoints/testSong.md) - - [likeGJItem211](/endpoints/likeGJItem211.md) - - [requestUserAccess](/endpoints/requestUserAccess.md) - - [restoreGJItems](/endpoints/restoreGJItems.md) -- Relationships - - [acceptGJFriendRequest20](/endpoints/acceptGJFriendRequest20.md) - - [blockGJUser20](/endpoints/blockGJUser20.md) - - [deleteGJFriendRequests20](/endpoints/deleteGJFriendRequests20.md) - - [getGJFriendRequests20](/endpoints/getGJFriendRequests20.md) - - [getGJUserList20](/endpoints/getGJUserList20.md) - - [readGJFriendRequest20](/endpoints/readGJFriendRequest20.md) - - [removeGJFriend20](/endpoints/removeGJFriend20.md) - - [unblockGJUser20](/endpoints/unblockGJUser20.md) - - [uploadFriendRequest20](/endpoints/uploadFriendRequest20.md) -- Rewards - - [getGJChallenges](/endpoints/getGJChallenges.md) - - [getGJRewards](/endpoints/getGJRewards.md) -- Scores - - [getGJLevelScores211](/endpoints/getGJLevelScores211.md) - - [getGJScores20](/endpoints/getGJScores20.md) -- Users - - - [getGJUserInfo20](/endpoints/getGJUserInfo20.md) - - [getGJUsers20](/endpoints/getGJUsers20.md) - - [updateGJAccSettings20](/endpoints/updateGJAccSettings20.md) - - [updateGJUserScore22](/endpoints/updateGJUserScore22.md) - -- **Accounts** - - - [Login](/endpoints/accounts/loginGJAccount.md) - - [Registration](/endpoints/accounts/registerGJAccount.md) - -- [Request](/endpoints/request.md) - -**Topics** - -- [Level Passwords](/topics/level_passwords.md) -- [Level Encoding/Decoding](/topics/levelstring_encoding_decoding.md) -- [Game Save Files Encryption/Decryption](/topics/localfiles_encrypt_decrypt.md) -- [Status Codes](/topics/status_codes.md) -- [Vault Codes](/topics/vault_codes.md) -- [Shop](/topics/shop) -- [Tags](/topics/tags) -- **Encryption** - - [Base64 Encoding](topics/encryption/base64.md) - - [CHK Generation](topics/encryption/chk.md) - - [RS, UDID and UUID](topics/encryption/id.md) - - [XOR Cipher](topics/encryption/xor.md) - - [Data Zipping](topics/encryption/zip.md) diff --git a/docs/client/gamesave.md b/docs/client/gamesave.md new file mode 100644 index 000000000..32366307d --- /dev/null +++ b/docs/client/gamesave.md @@ -0,0 +1,133 @@ +# Client Gamesave Resource + +## CCGameManager.dat + +Your CCGameManager.dat File contains a lot of information regarding your account. it is encrypted using [Xor](/topics/encryption/xor.md) with a key of 11 / 0xB, [url-Safe Base64](/topics/encryption/base64.md) and [Gzip](/topics/encryption/zip.md) and is in the [XML](https://en.wikipedia.org/wiki/XML) format + +## Gamesave Key structure + +| Key | Type | description | +| :-------| :--- | :-----------| +| bgVolume| Float| any value between 0 - 1 | +| sfxVolume| Float| any value between 0 - 1 | +| playerUDID| [UDID](/topics/encryption/id?id=udid)| The UDID of the user | +| playerName| String| The In-game Name of the player| +| playerUserID| Integer| The userID of the player| +| playerFrame| [Icon](enumerations.md)| The ID of the player Cube | +| playerShip| [Icon](enumerations.md)| The ID of the player Ship | +| playerBall| [Icon](enumerations.md)| The ID of the player Ball | +| playerBird| [Icon](enumerations.md)| The ID of the player UFO | +| playerDart| [Icon](enumerations.md)| The ID of the player Wave | +| playerRobot| [Icon](enumerations.md)| The ID of the player Robot | +| playerSpider| [Icon](enumerations.md)| The ID of the player Spider | +| playerColor| [Icon](enumerations.md)| The ID of the player Color | +| playerColor2| [Icon](enumerations.md)| The ID of the player Color2 | +| playerStreak| [Icon](enumerations.md)| The ID of the player Trail | +| playerDeathEffect| [Icon](enumerations.md)| The ID of the player Death Effect | +| playerIconType| [Icon](enumerations.md)| The Index of the player's IconType | +| playerGlow| Bool| if Glow is enabled or not | +| secretNumber| Integer| the answer to `cod3breaker` in the vault of secrets | +| hasRP | Bool | If the player is a moderator | +| [valueKeeper](/resources/client/gamesave/valueKeeper.md)| Dictionary | Dictionary filled with GV values you have enabled | +| unlockValueKeeper | Dictionary | Dictionary of Unlockable GV values| +| customObjectDict| Dictionary | Dictionary of object data of custom objects saved| +| reportedAchievements| Dictionary | contains a dictonary of all reported achievements on your account| +| showSongMarkers| Bool | if showSongMarkers is enabled | +| showProgressBar| Bool | if showProgressBar is enabled | +| clickedGarage| Bool | if Garage has been clicked | +| clickedEditor| Bool | if Editor has been clicked | +| clickedPractice| Bool | if Practice mode button has been clicked | +| showedEditorGuide| Bool | if EditorGuide has been clicked | +| showedLowDetailDialog| Bool | if low detail mode has been has been clicked | +| bootups| integer | The ammount of times you have opened Geometry Dash | +| hasRatedGame| Bool | if you have rated the game | +| binaryVersion| integer | The Games Binary Version | +| resolution| integer | The games resolution? | +| texQuality| integer | how high the text quality is | +| timeOffset| integer | music offset in milliseconds | + +### GLM + +| Key | Type | description | +| :-------| :--- | :-----------| +| [GLM_01](/resources/client/gamesave/GLM.md#GLM_01) | [Level](/resources/server/level.md)| All Official Levels you have progress on are stored here | +| [GLM_02](/resources/client/gamesave/GLM.md#GLM_02) | [level](/resources/server/level.md) | Uploaded levels - before the account System | +| [GLM_03](/resources/client/gamesave/GLM.md#GLM_03) | [Level](/resources/server/level.md)| online levels played| +| [GLM_04](/resources/client/gamesave/GLM.md#GLM_04) | rating| Shows what levels you have rated. was removed after 1.9 | +| [GLM_06](/resources/client/gamesave/GLM.md#GLM_06) | AccountIDs| The AccountIDs of all creators you follow | +| [GLM_07](/resources/client/gamesave/GLM.md#GLM_07) | levelID| Levels played in last session | +| [GLM_08](/resources/client/gamesave/GLM.md#GLM_08) | filters | Search Filters States | +| [GLM_09](/resources/client/gamesave/GLM.md#GLM_09) | filters | Search Filters for Online Levels | +| [GLM_10](/resources/client/gamesave/GLM.md#GLM_10) | [Level](/resources/server/level.md)| Completed dailies | +| [GLM_11](/resources/client/gamesave/GLM.md#GLM_11) | Integer| Current Daily ID | +| [GLM_12](/resources/client/gamesave/GLM.md#GLM_12) | likes | Something Related to likes | +| [GLM_13](/resources/client/gamesave/GLM.md#GLM_13) | levelID | All levels you submitted a rating on | +| [GLM_14](/resources/client/gamesave/GLM.md#GLM_14) | reportedLevels| A dictionary of all levels you have reported| +| [GLM_15](/resources/client/gamesave/GLM.md#GLM_15) | levelID | all Demon levels you have submitted a rating for | +| [GLM_16](/resources/client/gamesave/GLM.md#GLM_16) | [Level](/resources/server/level.md)| All the levels found in the Gauntlets that you have progress on are stored in here | +| [GLM_17](/resources/client/gamesave/GLM.md#GLM_17) | integer| Current Weekly ID | +| [GLM_18](/resources/client/gamesave/GLM.md#GLM_18) | Folder | The Folder Names for saved levels | +| [GLM_19](/resources/client/gamesave/GLM.md#GLM_19) | Folder | The Folder names for Local Levels | + +### GS + +| Key | Type | +| :-------| :--- | +| [GS_value](/resources/client/gamesave/GS_Value?id=gs-value-structure)| Player Stats | +| [GS_completed](/resources/client/gamesave/GS_Value?id=gs_completed)| Completed Levels | +| [GS_3](/resources/client/gamesave/GS_Value?id=gs_3)| Completed levels with coins `{levelID}_{number of coins aquired from level}` | +| [GS_4](/resources/client/gamesave/GS_Value?id=gs_4)| Completed levels with coins `{levelID}_{number of coins aquired from level}` | +| [GS_5](/resources/client/gamesave/GS_Value?id=gs_5)| Completed Mappacks + rewarded stars `pack_{MappackID}{Stars rewarded}` | +| [GS_6](/resources/client/gamesave/GS_Value?id=gs_6)| all Purchased Icons/Colours in the shops `{ListingID}{Price}` | +| [GS_7](/resources/client/gamesave/GS_Value?id=gs_7)| level progress `{levelID}{percentage}` | +| [GS_8](/resources/client/gamesave/GS_Value?id=gs_8)| Unused | +| [GS_9](/resources/client/gamesave/GS_Value?id=gs_9)| How many stars downloaded levels give `{levelID}{rewardedStars}` | +| [GS_10](/resources/client/gamesave/GS_Value?id=gs_10)| Offical level progress `{ID}{percentage}` | +| [GS_11](/resources/client/gamesave/GS_Value?id=gs_11)| All rewards gained from Daily Chests | +| [GS_12](/resources/client/gamesave/GS_Value?id=gs_12)| Contains [Quests](resources/client/gamesave/quests.md)| +| [GS_14](/resources/client/gamesave/GS_Value#GS_14)| Daily/Challenges rewards | +| [GS_15](/resources/client/gamesave/GS_Value?id=gs_15)| Contains Upcoming [Quests](resources/client/gamesave/quests.md)| +| [GS_16](/resources/client/gamesave/GS_Value?id=gs_16)| Daily/Weekly level progress `{Daily/WeeklyID}{percentage}` | +| [GS_17](/resources/client/gamesave/GS_Value?id=gs_17)| Daily/Weekly Stars `{Daily/WeeklyID}{Stars}` | +| [GS_18](/resources/client/gamesave/GS_Value?id=gs_18)| Gauntlet Level Progress `{levelID}{percentage}` | +| [GS_19](/resources/client/gamesave/GS_Value#GS_19)| All the Rewards from unlocked chests in the treasure room | +| [GS_20](/resources/client/gamesave/GS_Value?id=gs_20)| Demon Keys | +| [GS_21](/resources/client/gamesave/GS_Value#GS_21)| All rewards for Completed Gauntlets + rewards for Demon quest/social medias | +| [GS_22](/resources/client/gamesave/GS_Value?id=gs_22)| Rewards from Geometry Dash world | +| [GS_23](/resources/client/gamesave/GS_Value?id=gs_23)| Gauntlet Level Progress `{levelID}{percentage}` | +| [GS_24](/resources/client/gamesave/GS_Value?id=gs_24)| Daily/Weekly Percentage | +| [GS_25](/resources/client/gamesave/GS_Value#GS_25)| All the rewards from completed weekly Demons | + +### GJA + +| Key | Value| +| :-- |:-----------| +| GJA_001 | Username| +| GJA_002 | Password (in plaintext)| +| GJA_003 | AccountID | + +#### GDL22 GJA +| Key | Value| +| :-- |:-----------| +| GJA_004 | SessionID | + +### LLM + +| Key | Value| +| :-- |:-----------| +| LLM_01 | Local Levels | +| LLM_02 | Hardcoded to `binaryVersion`| + +### MDLM + +| Key | Value | +|:----|:------| +| MDLM_001 | Dictionary of SongInfoObject | +| MDLM_002 | Song Priority of a song | + +### KBM + +| Key | Value | +|:----|:------| +| KBM_001 | Keybindings | +| KBM_002 | Keybindings | diff --git a/docs/client/gamesave/GLM.md b/docs/client/gamesave/GLM.md new file mode 100644 index 000000000..7dbaee00f --- /dev/null +++ b/docs/client/gamesave/GLM.md @@ -0,0 +1,185 @@ +# GLM + +GLM (Global Levels Manager) are various Dictionaries that contain every bit of information you need to know about online levels + +## GLM_01 + +GLM_01 is used to store all progress the player has made on official levels + +| Key | description | +|:----|:------------| +| kCEK 4 | [level data](resources/client/level.md) | + +## GLM_02 + +GLM_02 was used before the account system to keep track of who owned Specific levels, currently unused + +| Key | description | +|:----|:------------| +| k_{Num} | what place the level is placed in your level list | +| kCEK 4 | [level data](resources/client/level.md) | + +## GLM_03 + +GLM_03 is used to store progress the player has done on all online levels + +| Key | description | +|:----|:------------| +| kCEK 4 | [level data](resources/client/level.md) | + +## GLM_04 + +GLM_04 contains all the difficulty ratings you have given levels, currently unused + +| key | value | +|:----|:------------| +| `{levelID}`| `{diffID}` | + + +## GLM_06 + +GLM_06 contains all of the creators you follow in game + +| key | value | description | +|:----|:------|:------------| +| AccountID | 1 | Doing this would place the creators levels in the followed tab | + +## GLM_07 + +GLM_07 contains the levels you played in the last session + +| Key | description | +|:----|:------------| +| levelID | accompanied with a 1 | + +## GLM_08 + +GLM_08 are the states of search filters + +| Key | Value | +|:----|:------| +| Diff0 | NA | +| Diff1 | Auto | +| Diff2 | Easy | +| Diff3 | Normal | +| Diff4 | Hard | +| Diff5 | Harder | +| Diff6 | Insane | +| Diff7 | Demon | +| Len0 | Tiny | +| Len1 | Short | +| Len2 | Medium | +| Len3 | Long | +| Len4 | XL | +| demon_filter | [Demon ID](/resources/server/level?id=level-structure) | +| uncompleted_filter | bool | +| completed_filter | bool | +| featured_filter | bool | +| song_filter | official SongID | +| original_filter | bool | +| twoP_filter | bool | +| enable_songFilter | bool | +| customsong_filter | songID | +| nostar_filter | bool | +| coin_filter | bool | +| follow_filter | bool | +| friend_filter | bool | +| epic_filter | bool | +| star_filter | bool | + +## GLM_09 + +GLM_09 shows all search filters available + +| Key | Value | +|:----|:------| +| Diff0 | NA | +| Diff1 | Auto | +| Diff2 | Easy | +| Diff3 | Normal | +| Diff4 | Hard | +| Diff5 | Harder | +| Diff6 | Insane | +| Diff7 | Demon | +| Len0 | Tiny | +| Len1 | Short | +| Len2 | Medium | +| Len3 | Long | +| Len4 | XL | +| demon_filter | [Demon ID](/resources/server/level?id=level-structure) | +| uncompleted_filter | bool | +| completed_filter | bool | +| featured_filter | bool | +| song_filter | official SongID | +| original_filter | bool | +| twoP_filter | bool | +| enable_songFilter | bool | +| customsong_filter | songID | +| nostar_filter | bool | +| coin_filter | bool | +| follow_filter | bool | +| friend_filter | bool | +| epic_filter | bool | +| star_filter | bool | + +## GLM_10 + +GLM_10 contains every daily level you have ever had progress on + +| Key | Description | +|:----|:------------| +| {timelyID} | A dictionary which contains the Encoder key for levels | +| kCEK 4 | The Encoder key which contains [level data](resources/client/level.md) + +## GLM_11 + +GLM_11 is the current Daily ID + +## GLM_12 + +GLM_12 contains likes given to a level + +| key | Description | +|:----|:------------| +| `like_{LikeType}_{LevelID}_{like/dislike}_{ID}` | needs investigating more | + +## GLM_13 + +GLM_13 Contains all the levelIDs for levels you have submitted a rating for + +## GLM_14 + +GLM_14 Contains all the levelIDs of levels you have reported + +## GLM_15 + +GLM_15 Contains all the levelIDs of Demons you have rated + +## GLM_16 + +GLM_16 contains every Gauntlet level you have ever had progress on + +| Key | Description | +|:----|:------------| +| {timelyID} | A dictionary which contains the Encoder key for levels | +| kCEK 4 | The Encoder key which contains [level data](resources/client/level.md) + +## GLM_17 + +GLM_17 is the current WeeklyID + +## GLM_18 + +GLM_18 is a dictionary of the Saved Levels folder for online levels + +| Key | Value | +|:----|:------| +| `{folder ID}` | `{Folder Name}` | + +## GLM_19 + +GLM_19 is a dictionary of the folders for local levels + +| Key | Value | +|:----|:------| +| `{folder ID}` | `{Folder Name}` | diff --git a/docs/client/gamesave/GS_Value.md b/docs/client/gamesave/GS_Value.md new file mode 100644 index 000000000..a255d2ec0 --- /dev/null +++ b/docs/client/gamesave/GS_Value.md @@ -0,0 +1,246 @@ +# GS Value + +GS values contain Information regarding certain aspects of the game + +## GS Value structure + +| key | value | +|:----|:------| +| 1 | Jumps | +| 2 | Attempts | +| 3 | Total Completed Official Levels | +| 4 | Total Completed Online Levels | +| 5 | Completed Demons | +| 6 | Total Stars | +| 7 | Total Completed MapPacks | +| 8 | Secret Coins Collected | +| 9 | Destroyed Players on the menu | +| 10 | Total Liked/Disliked levels | +| 11 | Total Rated Levels | +| 12 | User coins collected | +| 13 | Total Diamonds | +| 14 | current orbs | +| 15 | Completed Daily Levels | +| 16 | Fire Shards | +| 17 | Ice Shards | +| 18 | Poison Shards | +| 19 | Shadow Shards | +| 20 | Lava Shards | +| 21 | Bonus Shards | +| 22 | Total Orbs Collected | +| unique_{LevelID}_{Coins Collected} | The Coins Collected on the Official Levels + +## GS_completed + +all completed levels + +| Key | Value | +|:----|:------| +| `n_{levelID}`| beaten in normal Mode | +| `c_{levelID}` | Completed level| +| `d_{levelID}` | completed daily +| `g_{levelID}` | completed gauntlet +| `star_{levelID}` | Collected Stars| +| `dstar_{levelID}` | Collected Stars for daily| +| `gstar_{levelID}` | Collected Stars for gauntlet | +| `demon_{levelID}` | Collected Demon | +| `ddemon_{levelID}` | Collected Demon for weekly| +| `gdemon_{levelID}` | Collected Demon for gauntlet| + +## GS_3 + +GS_3 contains info about all levels you have collected unverified coins for + +| Structure | +|:----------| +|`{levelID}_{coins collected}`| + +## GS_4 + +GS_4 contains info about all levels you have collected verified coins for + +| Structure | +|:----------| +|`{levelID}_{coins collected}`| + +## GS_5 + +GS_5 contains info about all the MapPacks you have beaten + +| Structure | +|:----------| +|`pack_{packID}{stars Rewarded}`| + +## GS_6 + +GS_6 contains all the Purchased Icons on your account + +| Structure | +|:----------| +|`{ListingID}{Price}`| + +## GS_7 + +GS_7 is the Highscore attempt of levels + +| Structure | +|:----------| +|`{levelID}{percentage}`| + +## GS_8 + +Unused + +## GS_9 + +GS_9 provides info about how many stars downloaded levels give to you + +| Structure | +|:----------| +|`{levelID}{rewardedStars}`| + +## GS_10 + +GS_10 Contains the high score of All Official Levels you have played + +| Structure | +|:----------| +|`{ID}{percentage}`| + +## GS_11 + +GS_11 Contains the reward data for the Timely Chests you have opened + +| key | Description | +|:----|:------| +| `{ChestType}_{ChestID}` | reward Object | +| `k_{number}` | RewardItems -> the number corresponds to how many RewardItems the player will recieve | +| `kCEK` | The [encoder keys](/resources/client/gamesave/kCEK?id=kcek-8-and-9-structure) | + +### Chest Types + +| ID | type | +|:---|:-----| +| 1 | 4 hour chest | +| 2 | 24 hour chest | + +## GS_12 + +GS_12 Contains the currently active [Quests](/resources/client/gamesave/quests) + +## GS_14 + +The Diamond Rewards Collected from Challenges and Daily levels + +| structure | type |Description | +|:----------|:------|:-----------| +|`{TypeID}{challenge/dailyID}` | int | The Number of Diamonds Earned | + +### TypeID's + +| Types | Description | +|:------|:------------| +| c | Challenges/quests | +| d | daily levels | + +## GS_15 + +GS_15 Contains the upcoming [Quests](/resources/client/gamesave/quests) + +## GS_16 + +GS_16 contains the High Scores for daily and weekly demons + +| Structure | +|:----------| +|`{TimelyID}{percentage}`| + +## GS_17 + +GS_17 contains the Stars rewarded for daily and weekly demons + +| Structure | +|:----------| +|`{TimelyID}{Stars}`| + +## GS_18 + +GS_18 contains the High Scores for Gauntlet Levels + +| Structure | +|:----------| +|`{levelID}{percentage}`| + +## GS_19 + +GS_19 Contains the reward data for the Treasure room chests you have opened + +| key | Description | +|:----|:------| +| `{ChestID}` | reward Object | +| `k_{number}` | RewardItems -> the number corresponds to how many RewardItems the player will recieve | +| `kCEK` | The [encoder keys](/resources/client/gamesave/kCEK?id=kcek-8-and-9-structure) | + +## GS_20 + +GS_20 seems to be the total amount of Demon Keys you have had over your accounts lifespan + +## GS_21 + +GS_21 Contains the reward data for the gauntlets you have completed + +| key | Description | +|:----|:------| +| `g_{GauntletID}` | the gauntlet number | +| `000{ChestID}` | ChestIDs for Reward Chests | +| `k_{number}` | RewardItems -> the number corresponds to how many RewardItems the player will recieve | +| `kCEK` | The [encoder keys](/resources/client/gamesave/kCEK?id=kcek-8-and-9-structure) | + +### Chest IDs + +| ID | how to get | +|:----|:------| +| 0001 | Beat the Challenge | +| 0002 | Release the Demon Guardian | +| 0003 | Chamber of Time Chest| +| 0004 | Treasure Room 50 key Chest| +| 0005 | Treasure Room 100 Key Chest| +| 0006 | Treasure Room 200 Key Chest| +| 0007 | YouTube Chest | +| 0008 | Twitter Chest | +| 0009 | Facebook Chest | + + +## GS_22 + +GS_22 Contains reward data for all of the ad chests from Geometry Dash world + +| Key | Value | +|:----|:------| +| `{unix Timestamp}` | orbs | + +## GS_23 + +GS_23 contains the High Scores for daily and weekly demons + +| Structure | +|:----------| +|`{TimelyID}{percentage}`| + +## GS_24 + +GS_24 contains the High Scores for Gauntlet Levels + +| Structure | +|:----------| +|`{levelID}{percentage}`| + +## GS_25 + +GS_25 Contains the reward data for every weekly demon you have completed + +| key | Description | +|:----|:------| +| `d100{number}` | The Timely ID of the weekly Demon you have beaten | +| `k_{number}` | RewardItems -> the number corresponds to how many RewardItems the player will recieve | +| `kCEK` | The [encoder keys](/resources/client/gamesave/kCEK?id=kcek-8-and-9-structure) | diff --git a/docs/client/gamesave/achievement.md b/docs/client/gamesave/achievement.md new file mode 100644 index 000000000..2b7e8bc16 --- /dev/null +++ b/docs/client/gamesave/achievement.md @@ -0,0 +1,318 @@ +# Achievements + +Geometry Dash has 266 achievements that you can aquire, 2 of them are exclusive to the Steam version of the game. You can find out how to get all the achievements [here](https://geometry-dash.fandom.com/wiki/Achievements). + +keep in mind that adding the achievements into your save data manually will only show them as completed in game but won't give you the reward for the completion + +## Achievement key structure + +Inside CCGameManager.dat, every achievement you have progress on can be found in the `reportedAchievements` Dictionary. they are all organised like this + ```xml + geometry.ach.[internal achievement name][percentage complete]geometry.ach.[internal achievement name][percentage complete] + ``` + +## Internal Names + +| Internal name | How it's acquired | +| :-------------| :-------------- | +| geometry.ach.level01b | Beat Stereo Madness in normal Mode | +| geometry.ach.level01a | Beat Stereo Madness in practice Mode | +| geometry.ach.level02b | Beat Back On Track in normal Mode | +| geometry.ach.level02a | Beat Back On Track in practice Mode | +| geometry.ach.level03b | Beat Polargeist in normal Mode | +| geometry.ach.level03a | Beat Polargeist in practice Mode | +| geometry.ach.level04b | Beat Dry Out in normal Mode | +| geometry.ach.level04a | Beat Dry Out in practice Mode | +| geometry.ach.level05b | Beat Base after Base in normal Mode | +| geometry.ach.level05a | Beat Base After Base in practice Mode | +| geometry.ach.level06b | Beat Cant Let Go in normal Mode | +| geometry.ach.level06a | Beat Cant Let Go in practice Mode | +| geometry.ach.level07b | Beat Jumper in normal Mode | +| geometry.ach.level07a | Beat Jumper in practice Mode | +| geometry.ach.level08b | Beat Time Machine in normal Mode | +| geometry.ach.level08a | Beat Time Machine in practice Mode | +| geometry.ach.level09b | Beat Cycles in normal Mode | +| geometry.ach.level09a | Beat Cycles in practice Mode | +| geometry.ach.level10b | Beat Xstep in normal Mode | +| geometry.ach.level10a | Beat Xstep in practice Mode | +| geometry.ach.level11b | Beat Clutterfunk in normal Mode | +| geometry.ach.level11a | Beat Clutterfunk in practice Mode | +| geometry.ach.level12b | Beat Theory Of Everything in normal Mode | +| geometry.ach.level12a | Beat Theory Of Everything in practice Mode | +| geometry.ach.level13b | Beat Electroman Adventures in normal Mode | +| geometry.ach.level13a | Beat Electroman Adventures in practice Mode | +| geometry.ach.level14b | Beat Clubstep in normal Mode | +| geometry.ach.level14a | Beat Clubstep in practice Mode | +| geometry.ach.level15b | Beat Electrodynamix in normal Mode | +| geometry.ach.level15a | Beat Electrodynamix in practice Mode | +| geometry.ach.level16b | Beat Hexagon Force in normal Mode | +| geometry.ach.level16a | Beat Hexagon Forece in practice Mode | +| geometry.ach.level17b | Beat Blast Processing in normal Mode | +| geometry.ach.level17a | Beat Blast Processing in practice Mode | +| geometry.ach.level18b | Beat Theory Of Everything 2 in normal Mode | +| geometry.ach.level18a | Beat Theory Of Everything 2 in practice Mode | +| geometry.ach.level19b | Beat Geometrical Dominator in normal Mode | +| geometry.ach.level19a | Beat Geometrical Dominator in practice Mode | +| geometry.ach.level20b | Beat Deadlocked in normal Mode | +| geometry.ach.level20a | Beat Deadlocked in practice Mode | +| geometry.ach.level21b | Beat Fingerdash in normal Mode | +| geometry.ach.level21a | Beat Fingerdash in practice Mode | +| geometry.ach.steam01 | Beat Stereo Madness, Back On Track and Polargeist in normal mode (steam exlusive) | +| geometry.ach.steam02 | Beat Clubstep in normal mode (steam exlusive) | +| geometry.ach.demoncoin01 | Beat Clubstep in with all coins| +| geometry.ach.demoncoin02 | Beat Theory Of Everything 2 in with all coins| +| geometry.ach.demoncoin03 | Beat Deadlocked in with all coins| +| geometry.ach.mappacks01 | Complete 1 Map Pack | +| geometry.ach.mappacks02 | Complete 5 Map Packs | +| geometry.ach.mappacks03 | Complete 10 Map Packs | +| geometry.ach.mappacks04 | Complete 15 Map Packs | +| geometry.ach.mappacks05 | Complete 20 Map Packs | +| geometry.ach.mappacks06 | Complete 25 Map Packs | +| geometry.ach.mappacks07 | Complete 30 Map Packs | +| geometry.ach.mappacks08 | Complete 35 Map Packs | +| geometry.ach.mappacks09 | Complete 40 Map Packs | +| geometry.ach.mappacks10 | Complete 45 Map Packs | +| geometry.ach.custom01 | Complete 1 User Created Level in Normal Mode| +| geometry.ach.custom02 | Complete 10 User Created Level in Normal Mode| +| geometry.ach.custom03 | Complete 50 User Created Level in Normal Mode| +| geometry.ach.custom04 | Complete 100 User Created Level in Normal Mode| +| geometry.ach.custom05 | Complete 200 User Created Level in Normal Mode| +| geometry.ach.custom06 | Complete 300 User Created Level in Normal Mode| +| geometry.ach.custom07 | Complete 500 User Created Level in Normal Mode| +| geometry.ach.custom08 | Complete 1,000 User Created Level in Normal Mode| +| geometry.ach.stars01 | Collect 100 stars| +| geometry.ach.stars02 | Collect 200 stars| +| geometry.ach.stars03 | Collect 300 stars| +| geometry.ach.stars04 | Collect 400 stars| +| geometry.ach.stars05 | Collect 500 stars| +| geometry.ach.stars06 | Collect 600 stars| +| geometry.ach.stars07 | Collect 700 stars| +| geometry.ach.stars08 | Collect 800 stars| +| geometry.ach.stars09 | Collect 900 stars| +| geometry.ach.stars10 | Collect 1,000 stars| +| geometry.ach.stars11 | Collect 1,500 stars| +| geometry.ach.stars12 | Collect 2,000 stars| +| geometry.ach.stars13 | Collect 2,500 stars| +| geometry.ach.stars14 | Collect 3,000 stars| +| geometry.ach.stars15 | Collect 3,500 stars| +| geometry.ach.stars16 | Collect 4,000 stars| +| geometry.ach.stars17 | Collect 4,500 stars| +| geometry.ach.stars18 | Collect 5,000 stars| +| geometry.ach.stars19 | Collect 5,500 stars| +| geometry.ach.stars20 | Collect 6,000 stars| +| geometry.ach.stars21 | Collect 6,500 stars| +| geometry.ach.stars22 | Collect 7,000 stars| +| geometry.ach.stars23 | Collect 7,500 stars| +| geometry.ach.stars24 | Collect 8,000 stars| +| geometry.ach.stars25 | Collect 9,000 stars| +| geometry.ach.stars26 | Collect 10,000 stars| +| geometry.ach.demon01 | Beat 1 Demon| +| geometry.ach.demon02 | Beat 2 Demons| +| geometry.ach.demon03 | Beat 3 Demons| +| geometry.ach.demon04 | Beat 4 Demons| +| geometry.ach.demon05 | Beat 5 Demons| +| geometry.ach.demon06 | Beat 10 Demons| +| geometry.ach.demon07 | Beat 15 Demons| +| geometry.ach.demon08 | Beat 20 Demons| +| geometry.ach.demon09 | Beat 30 Demons| +| geometry.ach.demon10 | Beat 40 Demons| +| geometry.ach.demon11 | Beat 50 Demons| +| geometry.ach.demon12 | Beat 60 Demons| +| geometry.ach.coins01 | Collect 5 Secret Coins| +| geometry.ach.coins02 | Collect 10 Secret Coins| +| geometry.ach.coins03 | Collect 15 Secret Coins| +| geometry.ach.coins04 | Collect 20 Secret Coins| +| geometry.ach.coins05 | Collect 25 Secret Coins| +| geometry.ach.coins06 | Collect 30 Secret Coins| +| geometry.ach.coins07 | Collect 35 Secret Coins| +| geometry.ach.coins08 | Collect 40 Secret Coins| +| geometry.ach.coins09 | Collect 45 Secret Coins| +| geometry.ach.coins10 | Collect 50 Secret Coins| +| geometry.ach.coins11 | Collect 55 Secret Coins| +| geometry.ach.coins12 | Collect 60 Secret Coins| +| geometry.ach.coins13 | Collect 65 Secret Coins| +| geometry.ach.coins14 | Collect 70 Secret Coins| +| geometry.ach.coins15 | Collect 75 Secret Coins| +| geometry.ach.coins16 | Collect 80 Secret Coins| +| geometry.ach.coins17 | Collect 85 Secret Coins| +| geometry.ach.coins18 | Collect 90 Secret Coins| +| geometry.ach.coins19 | Collect 95 Secret Coins| +| geometry.ach.coins20 | Collect 100 Secret Coins| +| geometry.ach.coins21 | Collect 105 Secret Coins| +| geometry.ach.coins22 | Collect 110 Secret Coins| +| geometry.ach.coins23 | Collect 115 Secret Coins| +| geometry.ach.coins24 | Collect 120 Secret Coins| +| geometry.ach.coins25 | Collect 130 Secret Coins| +| geometry.ach.usercoins01 | Collect 1 user Coin| +| geometry.ach.usercoins02 | Collect 10 user Coins| +| geometry.ach.usercoins03 | Collect 20 user Coins| +| geometry.ach.usercoins04 | Collect 30 user Coins| +| geometry.ach.usercoins05 | Collect 40 user Coins| +| geometry.ach.usercoins06 | Collect 50 user Coins| +| geometry.ach.usercoins07 | Collect 60 user Coins| +| geometry.ach.usercoins08 | Collect 70 user Coins| +| geometry.ach.usercoins09 | Collect 80 user Coins| +| geometry.ach.usercoins10 | Collect 90 user Coins| +| geometry.ach.usercoins11 | Collect 100 user Coins| +| geometry.ach.usercoins12 | Collect 110 user Coins| +| geometry.ach.usercoins13 | Collect 120 user Coins| +| geometry.ach.usercoins14 | Collect 130 user Coins| +| geometry.ach.usercoins15 | Collect 140 user Coins| +| geometry.ach.usercoins16 | Collect 150 user Coins| +| geometry.ach.usercoins17 | Collect 160 user Coins| +| geometry.ach.usercoins18 | Collect 170 user Coins| +| geometry.ach.usercoins19 | Collect 180 user Coins| +| geometry.ach.usercoins20 | Collect 190 user Coins| +| geometry.ach.usercoins21 | Collect 200 user Coins| +| geometry.ach.usercoins22 | Collect 225 user Coins| +| geometry.ach.usercoins23 | Collect 250 user Coins| +| geometry.ach.usercoins24 | Collect 300 user Coins| +| geometry.ach.usercoins25 | Collect 350 user Coins| +| geometry.ach.usercoins26 | Collect 425 user Coins| +| geometry.ach.usercoins27 | Collect 500 user Coins| +| geometry.ach.usercoins28 | Collect 600 user Coins| +| geometry.ach.usercoins29 | Collect 700 user Coins| +| geometry.ach.usercoins30 | Collect 800 user Coins| +| geometry.ach.usercoins31 | Collect 900 user Coins| +| geometry.ach.usercoins32 | Collect 1,000 user Coins| +| geometry.ach.diamonds01 | Collect 100 Diamonds| +| geometry.ach.diamonds02 | Collect 250 Diamonds| +| geometry.ach.diamonds03 | Collect 500 Diamonds| +| geometry.ach.diamonds04 | Collect 1,000 Diamonds| +| geometry.ach.diamonds05 | Collect 1,500 Diamonds| +| geometry.ach.diamonds06 | Collect 2,000 Diamonds| +| geometry.ach.diamonds07 | Collect 2,500 Diamonds| +| geometry.ach.diamonds08 | Collect 3,000 Diamonds| +| geometry.ach.diamonds09 | Collect 4,000 Diamonds| +| geometry.ach.diamonds10 | Collect 5,000 Diamonds| +| geometry.ach.shardFire01 | Collect 5 Fire Shards| +| geometry.ach.shardFire02 | Collect 15 Fire Shards| +| geometry.ach.shardFire03 | Collect 35 Fire Shards| +| geometry.ach.shardFire04 | Collect 65 Fire Shards| +| geometry.ach.shardFire05 | Collect 100 Fire Shards| +| geometry.ach.shardIce01 | Collect 5 Ice Shards| +| geometry.ach.shardIce02 | Collect 15 Ice Shards| +| geometry.ach.shardIce03 | Collect 35 Ice Shards| +| geometry.ach.shardIce04 | Collect 65 Ice Shards| +| geometry.ach.shardIce05 | Collect 100 Ice Shards| +| geometry.ach.shardPoison01 | Collect 5 Poison Shards| +| geometry.ach.shardPoison02 | Collect 15 Poison Shards| +| geometry.ach.shardPoison03 | Collect 35 Poison Shards| +| geometry.ach.shardPoison04 | Collect 65 Poison Shards| +| geometry.ach.shardPoison05 | Collect 100 Poison Shards| +| geometry.ach.shardShadow01 | Collect 5 Shadow Shards| +| geometry.ach.shardShadow02 | Collect 15 Shadow Shards| +| geometry.ach.shardShadow03 | Collect 35 Shadow Shards| +| geometry.ach.shardShadow04 | Collect 65 Shadow Shards| +| geometry.ach.shardShadow05 | Collect 100 Shadow Shards| +| geometry.ach.shardLava01 | Collect 5 Lava Shards| +| geometry.ach.shardLava02 | Collect 15 Lava Shards| +| geometry.ach.shardLava03 | Collect 35 Lava Shards| +| geometry.ach.shardLava04 | Collect 65 Lava Shards| +| geometry.ach.shardLava05 | Collect 100 Lava Shards| +| geometry.ach.shardBonus01 | Collect 5 of each Shard| +| geometry.ach.shardBonus02 | Collect 15 of each Shard| +| geometry.ach.shardBonusa03 | Collect 35 of each Shard| +| geometry.ach.shardBonus04 | Collect 65 of each Shard| +| geometry.ach.shardBonus05 | Collect 100 of each Shard| +| geometry.ach.followCreator | follow 1 Creator| +| geometry.ach.followCreator2 | follow 10 Creators| +| geometry.ach.friends01 | Befriend 1 user| +| geometry.ach.friends02 | Befriend 10 users| +| geometry.ach.youtube | subscribe to [RobTop](https://www.youtube.com/user/RobTopGames) on YouTube| +| geometry.ach.youtube | Follow [RobTop](https://twitter.com/robtopgames) on Twitter| +| geometry.ach.youtube | Like [RobTop](https://www.facebook.com/geometrydash) on Facebook| +| geometry.ach.attempt01 | Do 100 Attempts | +| geometry.ach.attempt02 | Do 500 Attempts | +| geometry.ach.attempt03 | Do 2,000 Attempts | +| geometry.ach.attempt04 | Do 10,000 Attempts | +| geometry.ach.attempt05 | Do 20,000 Attempts | +| geometry.ach.jump01 | Jump 1,000 Times | +| geometry.ach.jump02 | Jump 10,000 Times | +| geometry.ach.jump03 | Jump 20,000 Times | +| geometry.ach.jump04 | Jump 50,000 Times | +| geometry.ach.jump05 | Jump 100,000 Times | +| geometry.ach.submit | Submit an online level | +| geometry.ach.rate | Click the supporter icon when it's locked | +| geometry.ach.rateDiff | Rate the stars of an online level | +| geometry.ach.rateDiff02 | Rate the stars of 100 online levels | +| geometry.ach.rateDiff02b | Rate the stars of 500 online levels | +| geometry.ach.rateDiff03 | Rate the stars of 1,000 online levels | +| geometry.ach.rateDiff04 | Rate the stars of 2,000 online levels | +| geometry.ach.like | Like or dislike an online level | +| geometry.ach.like02 | Like or dislike 100 online levels | +| geometry.ach.like02b | Like or dislike 500 online levels | +| geometry.ach.like03 | Like or dislike 1,000 online levels | +| geometry.ach.like04 | Like or dislike 2,000 online levels | +| geometry.ach.moreGames | Click the "More Games" button | +| geometry.ach.special01 | Die at over 95% on a main level | +| geometry.ach.creator01 | Get 100 likes on your level | +| geometry.ach.creator02 | Get a star rate on your level | +| geometry.ach.creator03 | Get 50 likes on your level | +| geometry.ach.secret01 | Destroy an icon on the main menu | +| geometry.ach.secret02 | Destroy 50 icons on the main menu | +| geometry.ach.secret02b | Destroy 100 icons on the main menu | +| geometry.ach.secret03 | Destroy 200 icons on the main menu | +| geometry.ach.secret03b | Destroy 500 icons on the main menu | +| geometry.ach.secret04 | Found the hidden gold coin by scrolling through the level page 3 times | +| geometry.ach.secret05 | Type 'lenny' into the 2.0 Vault | +| geometry.ach.secret06 | Type 'sparky' into the 2.0 Vault | +| geometry.ach.secret07 | Type 'spooky' into the 2.0 Vault | +| geometry.ach.secret08 | Type 'blockbite' into the 2.0 Vault | +| geometry.ach.secret09 | Type 'robotop' into the 2.0 Vault | +| geometry.ach.secret10 | Type 'ahead' into the 2.0 Vault | +| geometry.ach.secret11 | Destroy the 55th cube on the main menu | +| geometry.ach.secret12 | Destroy the 50th cube on the main menu | +| geometry.ach.secret13 | Type 'mule' into the 2.0 Vault | +| geometry.ach.secret14 | Type 'neverending' into the 2.0 Vault | +| geometry.ach.secret15 | Type 'gandalfpotter' into the 2.0 Vault | +| geometry.ach.secret16 | Consecutively type '8', '16', '30', '32', '46' and '84' into the 2.0 Vault | +| geometry.ach.secret17 | Type your username into the 2.0 Vault | +| geometry.ach.v2.secret01 | Type 'brainpower' into the Vault of Secrets | +| geometry.ach.v2.secret02 | Type 'cod3breaker' and the solution to the puzzle into the Vault of Secrets | +| geometry.ach.v2.secret03 | Solve the 'glubfub' puzzle | +| geometry.ach.v2.secret04 | Type 'octocube' into the Vault of Secrets | +| geometry.ach.v2.secret05 | Type your star count into the Vault of Secrets | +| geometry.ach.v2.secret06 | Type 'seven' into the Vault of Secrets | +| geometry.ach.v2.secret07 | Type 'gimmiethecolor' into the Vault of Secrets | +| geometry.ach.v2.secret08 | Type 'thechickenisonfire' into the Vault of Secrets | +| geometry.ach.v3.secret01 | Type 'darkness' into the Chamber of Time | +| geometry.ach.v3.secret02 | Type 'silence' into the Chamber of Time | +| geometry.ach.v3.secret03 | Type 'river' into the Chamber of Time | +| geometry.ach.v3.secret04 | Type 'hunger' into the Chamber of Time | +| geometry.ach.v3.secret05 | Type 'volcano' into the Chamber of Time | + +## GD Meltdown Achievements +| Internal name | How it's acquired | +| :-------------| :-------------- | +| geometry.ach.mdlevel01b | Beat The Seven Seas in normal mode | +| geometry.ach.mdlevel02b | Beat Viking Arena in normal mode | +| geometry.ach.mdlevel03b | Beat Airborne Robots in normal mode | +| geometry.ach.mdcoin01 | Collect all 3 coins on The Seven Seas | +| geometry.ach.mdcoin02 | Collect all 3 coins on Viking Arena | +| geometry.ach.mdcoin03 | Collect all 3 coins on Airborne Robots | +| geometry.ach.mdrate | Click the icon with ID 71 when it's locked (positioned as 11th) | + +## GD World Achievements +| Internal name | How it's acquired | +| :-------------| :-------------- | +| geometry.ach.world.level001b | Beat Payload in normal mode | +| geometry.ach.world.level002b | Beat Beast Mode in normal mode | +| geometry.ach.world.level003b | Beat Machina in normal mode | +| geometry.ach.world.level004b | Beat Years in normal mode | +| geometry.ach.world.level005b | Beat Frontlines in normal mode | +| geometry.ach.world.level006b | Beat Space Pirates in normal mode | +| geometry.ach.world.level007b | Beat Striker in normal mode | +| geometry.ach.world.level008b | Beat Embers in normal mode | +| geometry.ach.world.level009b | Beat Round 1 in normal mode | +| geometry.ach.world.level010b | Beat Monster Dance Off in normal mode | + +## GD Subzero Achievements +| Internal name | How it's acquired | +| :-------------| :-------------- | +| geometry.ach.subzero.level001 | Beat Press Start in normal mode | +| geometry.ach.subzero.level002 | Beat Nock Em in normal mode | +| geometry.ach.subzero.level003 | Beat Power Trip in normal mode | +| geometry.ach.subzero.coins001 | Collect all 3 coins on Press Start| +| geometry.ach.subzero.coins002 | Collect all 3 coins on Nock Em | +| geometry.ach.subzero.coins003 | Collect all 3 coins on Power Trip | diff --git a/docs/client/gamesave/gv.md b/docs/client/gamesave/gv.md new file mode 100644 index 000000000..ef0834697 --- /dev/null +++ b/docs/client/gamesave/gv.md @@ -0,0 +1,179 @@ +# Game Variables + +Game Variables (gvs) are found inside of the [ValueKeeper](/resources/client/gamesave/valueKeeper.md) Dictionary and each gv value corresponds with a specific ingame setting + +## GV Structure + +| Key | Value| +| :-- |:-----------| +| gv_0001 | Follow PLayer (editor) | +| gv_0002 | play Music (editor) | +| gv_0003 | Swipe (editor) | +| gv_0004 | Free Move (editor) | +| gv_0005 | Delete filter (editor) | +| gv_0006 | Delete custom objectID (editor) | +| gv_0007 | Toggle rotate (editor) | +| gv_0008 | Toggle snap (editor) | +| gv_0009 | Ignore Damage (editor) | +| gv_0010 | flip2PlayerControls | +| gv_0011 | alwaysLimitControls | +| gv_0012 | showedCommentingRules | +| gv_0013 | increaseMaxUndoRedo | +| gv_0014 | disableExplosionShake | +| gv_0015 | flipPauseButton | +| gv_0016 | showedSongTOS | +| gv_0018 | noSongLimit | +| gv_0019 | songsInMemory | +| gv_0022 | higherAudioQuality | +| gv_0023 | smoothFix | +| gv_0024 | showCursor In-Game | +| gv_0025 | Windowed Mode | +| gv_0026 | autoRetry | +| gv_0027 | autoCheckpoints | +| gv_0028 | disableThumbstick | +| gv_0029 | showedOptionsText | +| gv_0030 | vsyncEnabled | +| gv_0031 | callGLFinish -> seems to be unused | +| gv_0032 | forceTimerEnabled -> seems to be unused | +| gv_0033 | ChangeSongPath | +| gv_0034 | GameCenterEnabled | +| gv_0036 | PreviewMode (editor) | +| gv_0037| showGround (editor) | +| gv_0038 | showGrid (editor) | +| gv_0039 | gridOnTop (editor) | +| gv_0040 | showPercentage | +| gv_0041 | showObjectInfo (editor) | +| gv_0042 | increaseMaxLevels | +| gv_0043 | effectLinesEnabled (editor) | +| gv_0044 | drawTriggerBoxes (editor) | +| gv_0045 | debugDraw (editor) | +| gv_0046 | hideUIOnTest (editor) | +| gv_0047 | showedProfileText | +| gv_0048 | viewedOwnProfile | +| gv_0049 | buttonsPerRow (editor) | +| gv_0050 | buttonRows (editor) | +| gv_0051 | showedNGMessage (editor) | +| gv_0052 | fastPracticeReset| +| gv_0053 | Free Games Popup | +| gv_0055 | checkIfServerOnline.php | +| gv_0056 | disableObjectAlert | +| gv_0057 | editorHoldToSwipe| +| gv_0058 | durationLines (editor) | +| gv_0059 | swipeCycleMode | +| gv_0060 | defaultMiniIcon| +| gv_0061 | switchSpiderTeleportColor | +| gv_0062 | switchDashFireColor | +| gv_0063 | showedUnverifiedCoinsMessage | +| gv_0064 | selectFilter (editor) | +| gv_0065 | enableMoveOptimization | +| gv_0066 | highCapacityMode | +| gv_0067 | highStartPosAccuracy | +| gv_0068 | quickCheckpointMode | +| gv_0069 | commentMode | +| gv_0070 | showedUnlistedLevelMessage | +| gv_0072 | disableGravityEffect | +| gv_0073| newCompletedFilter| +| gv_0074| showRestartButton| +| gv_0075| disableComments| +| gv_0076| disableAccountComments| +| gv_0077| featuredLevelsOnly | +| gv_0078| hideBackground (editor) | +| gv_0079| hideGridOnPlay (editor) | +| gv_0081| disableShakeEffects | +| gv_0082| disableHighObjectAlert| +| gv_0083 | disableSongAlert| +| gv_0084| manualOrder| +| gv_0088| smallCommentsMode| +| gv_0089| extendedInfoMode | +| gv_0090| autoloadComments | +| gv_0091| myLevels folder number | +| gv_0092| onlineLevels folder number | +| gv_0093| increaseLocalLevelsPerPage | +| gv_0094| moreCommentsMode | +| gv_0095| flippyUselessMode (Just Dont)| +| gv_0096| switchWaveTrailColor| +| gv_0097| enableLinkControls (editor) | +| gv_0098| levelLeaderboardType | +| gv_0099| showLeaderboardPercent | +| gv_0100| practiceDeathEffect| +| gv_0101| forceSmoothFix | +| gv_0102 | smoothFixInEditor | + + +### 2019 Leak GV's + +| Key | Value| +| :-- |:-----------| +| gv_0103 | Layer Locking | +| gv_0104 | Record Order | +| gv_0105 | StartPos Playback | +| gv_0106 | Show Meltdown Promo | +| gv_0108 | Auto Low Detail | +| gv_0109 | Level Info Label | +| gv_0110 | Fast Editor Preview | +| gv_0113 | Flip Platformer Controls | +| gv_0115 | Show FPS | +| gv_0116 | Use Custom FPS | +| gv_0117 | Preview Particle | +| gv_0118 | Preview Animation | +| gv_0119 | Dont Save Level Data | + + +# Unlocked Game Variables + +Unlocked Game Variables (ugv) are used to check if ingame events have been completed + +## UGV Structure + +| Key | Value| +| :-- |:-----------| +| ugv_1 | Unlocked the challenge | +| ugv_2 | Gubflub hint | +| ugv_3 | Gubflub hint 2 | +| ugv_4 | The Challenge completed | +| ugv_5 | Treasure Room unlocked | +| ugv_6 | Chamber of Time unlocked | +| ugv_7 | Chamber of Time Discovered | +| ugv_8 | shown Master Emblem | +| ugv_9 | GateKeeper Dialog | +| ugv_10 | Scratch Dialog | +| ugv_11 | Secret Shop unlocked | +| ugv_12 | Spoken to Demon Guardian | +| ugv_13 | Demon Freed | +| ugv_14 | Has Demon Key 1 | +| ugv_15 | Has Demon Key 2 | +| ugv_16 | Has Demon Key 3 | +| ugv_17 | Shop Keeper first dialog (500 orbs) | +| ugv_18 | online levels unlocked in GDW | +| ugv_19 | Demon Discovered in Demon Room | +| ugv_20 | Community shop unlocked | +| ugv_21 | PotBor dialog | +| ugv_22 | YouTube Chest unlocked | +| ugv_23 | FaceBook Chest unlocked | +| ugv_24 | Twitter Chest unlocked | + +### 2019 Leak UGV's + +| Key | Value| +| :-- |:-----------| +| ugv_25 | FireBird GateKeeper | +| ugv_26 | Twitch Chest Unlocked | +| ugv_27 | Discord Chest Unlocked | + +### Undiscovered/unknown GV's + +| GV_ID | Existance Proven | notes | +|:------|:-------|:------| +| 0017 | **False** | | +| 0020 | **False** | | +| 0021 | **False** | | +| 0035 | **False** | | +| 0054 | **False** || +| 0071 | **False** || +| 0080 | **False** || +| 0085 | **False** || +| 0086 | **False** || +| 0087 | **False** || +| 0112 | **True** | Used in `EditorUI` (**2019 Leak**) | +| 0114 | **True** | Used in `PlayerObject` (**2019 Leak**) | +| 0120 | **True** | Shown in RobTop's 2020 Twitch Streams | diff --git a/docs/client/gamesave/kCEK.md b/docs/client/gamesave/kCEK.md new file mode 100644 index 000000000..3e28efe51 --- /dev/null +++ b/docs/client/gamesave/kCEK.md @@ -0,0 +1,53 @@ +# kCEK Encoder Keys + +| Key | Name/Value | description | +| :-- | :----------------------------- | :-----------| +| 4 | [GJGameLevel](resources/client/level.md) | Contains Keys for levels you played in the past | +| 6 | [SongInfoObject](resources/server/song?id=song-structure) | Contains Keys for songs downloaded | +| 7 | [GJChallengeItem](resources/client/gamesave/quests.md) | Contains Keys that the game uses to show quests when offline | +| 8 | [GJRewardItem](resources/client/gamesave/kCEK.md) | object that holds `GJRewardObject` | +| 9 | [GJRewardObject](resources/client/gamesave/kCEK.md) | contains data for Rewards | + +## kCEK 8 and 9 Structure + +`GJRewardItem` is a dictionary which contains `GJRewardObject` + +| key | encoder Key | use/description | +|:----|:------------|:------------| +| 1 | 8 | Depends on the [GS_Value](/resources/client/gamesave/GS_Value) it is inside of | +| 2 | 8 | Depends on the [GS_Value](/resources/client/gamesave/GS_Value) it is inside of | +| 3 | 8 | GJRewardObject | +| 1 | 9 | item type | +| 2 | 9 | customItemID | +| 3 | 9 | reward amount | +| 4 | 9 | itemUnlockValue -> [presumedly contains data that unlocks an item in the garage?](https://media.discordapp.net/attachments/801840133355470888/806137688905875496/unknown.png) | + +### ItemIDs + +| key | value | +|:----|:------| +| 1 | Fire Shard | +| 2 | Ice Shard | +| 3 | Poison Shard | +| 4 | Shadow Shard | +| 5 | Lava Shard | +| 6 | Demon Key | +| 7 | Orbs | +| 8 | Diamonds | +| 9 | Custom Object (shares the same ID for Demon guardian key, icons and colours) | + +### GJRewardItem GS Keys + +#### GS_11 + +| key | value | +|:----|:------------| +| 1 | ChestID | +| 2 | ChestType | + +##### Chest Types + +| ID | type | +|:---|:-----| +| 1 | 4 hour chest | +| 2 | 24 hour chest | \ No newline at end of file diff --git a/docs/client/gamesave/quests.md b/docs/client/gamesave/quests.md new file mode 100644 index 000000000..44d6b1bd3 --- /dev/null +++ b/docs/client/gamesave/quests.md @@ -0,0 +1,18 @@ +# Client Quest Resources + +## Quests + +After you click on the quest button when playing Geometry Dash, information about the quest is saved into your CCGameManager files so you can complete the quests offline. + +## Quest Key structure + +| Key | Name/Value | type |Description | +| :-- | :----------------------------- |:-----|:--------------------------------------------------------------- | +| 1 | Quest Type | [quest](enumerations.md) |This is used to diffrenciate the type of quest needs to be completed: 1 = Orbs, 2 = Coins, 3 = Stars | +| 2 | Progress | integer | How many of the required stats have been gained since you started the quest| +| 3 | Goal | integer | How many of the required stats you need to gain to complete the quest| +| 4 | Reward | integer | How many diamonds earned upon completion of the quest| +| 5 | time left | integer | How much time is left until new quests appear | +| 6 | isActive | Bool | Set to True if the challenge is active | +| 7 | Quest Name | String | The quest name | +| 8 | Position | [Quest Position](enumerations.md) | where abouts on screen the quest should be: 1 = top, 2 = middle, 3 = bottom| \ No newline at end of file diff --git a/docs/client/gamesave/valueKeeper.md b/docs/client/gamesave/valueKeeper.md new file mode 100644 index 000000000..8ca8d8b2f --- /dev/null +++ b/docs/client/gamesave/valueKeeper.md @@ -0,0 +1,19 @@ +# ValueKeeper + +Value Keeper is a giant Dictionary found in CCGameManager.dat that contains the states of unlockables and game values + +## ValueKeeper Stucture + +| prefix | Description | +|:-------|:------------| +| [gv_{ID}](/resources/client/gamesave/gv.md) | enabled Game Variables | +| i_{ID} | The playerCubes you have unlocked | +| ship_{ID} | The PlayerShips you have unlocked | +| ball_{ID} | The PlayerBalls you have unlocked | +| bird_{ID} | The PlayerBirdss you have unlocked | +| dart_{ID} | The PlayerDarts you have unlocked | +| robot_{ID} | The PlayerRobots you have unlocked | +| special_{ID} | The PlayerStreaks you have unlocked| +| c0_{ID} | The Colour1's you have unlocked | +| c1_{ID} | The Colour2's you have unlocked | +| death_{ID} | Unlocked Death Effects | diff --git a/docs/client/level-components/capacity-string.md b/docs/client/level-components/capacity-string.md new file mode 100644 index 000000000..aa20caf5a --- /dev/null +++ b/docs/client/level-components/capacity-string.md @@ -0,0 +1,144 @@ +# Capacity String + +> The Capacity String (commonly known as the `extra string`) is a long string split up into 54 components each having an Integer assigned to them. The role of the Capacity String is to save the cost of memory re-allocation when rendering levels + +## Example + +Below is the Capacity String for the level `Bloodlust` by Knobbelboy + + 0_2044_1248_57_0_70_1988_963_0_0_4526_6982_465_0_623_995_0_0_0_0_0_0_53_0_0_0_0_0_0_0_0_0_35_105_38_0_0_0_0_0_0_0_0_0_294_1173_38_0_0_0_0_0_0_0_0 + +## Structure + +Each component of the Capacity String are tied to their own `CCSpriteBatchNode` field based on the properties of certain objects. + +There are `5` different types of batchNodes. `4` of which the Capacity string uses + +**Note: BatchID 4 isn't used in the Capacity String** + +| BatchID | Type | Description | +|:--------|:-----|:------------| +| 1 | BatchNodePlayer | | +| 2 | BatchNodeText | All text GameObjects | +| 3 | EffectBatchNode | All animated GameObjects | +| 4 | DefaultBatchNode | All GameObjects that don't fit into other BatchNodes, usually objects that only render in the editor exclusively | +| 5 | BatchNode | Most GameObjects | + +Each of these BatchNodeTypes are then divided into sub-categories based on certain properties the object has + +**Note: Index refers to order that the BatchNode can be found on the capacity string** +The names for each BatchNode were provided by [RobTop himself](https://twitter.com/RobTopGames/status/1415783982621413376?s=20) + +| Index | BatchNode | Properties | zOrder | +|:------|:----------|:-----------|:-------| +| 0 | BatchNodeAddTop2 | Blending, zLayer T2 | 16 | +| 1 | BatchNode | zLayer T1 | 10 | +| 2 | BatchNodeAdd | Blending, zLayer T1 | 9 | +| 3 | BatchNodePlayer | unknown -> something about the player | 3 | +| 4 | BatchNodeAddPlayer | unknown -> something about the player | 2 | +| 5 | BatchNodeAddMid | Blending, zLayer B1 (zLayer = 4)| 1 | +| 6 | BatchNodeBottom | zLayer B1 | -1 | +| 7 | BatchNodeAddBottom | Blending, zLayer B1 | -2 | +| 8 | EffectBatchNode | Animated, zLayer B1 | -6 | +| 9 | EffectBatchNodeAdd | Blending, Animated, zLayer B1 | -7 | +| 10 | BatchNodeBottom2 | zLayer B2 | -8 | +| 11 | BatchNodeAddBottom2 | Blending, zLayer B2 | -9 | +| 12 | BatchNodeAddGlow | Blending, Glow, zLayer T1 | 9 | +| 13 | BatchNodeAddBottomGlow | Blending, Glow, zLayer B1 | -2 | +| 14 | BatchNodeAddBottom2Glow | Blending, Glow, zLayer B2 | -9 | +| 15 | BatchNodeBottomGlow2 | Glow, zLayer B1 | -22 | +| 16 | BatchNodeAddBottom4 | Blending, zLayer B4 | -23 | +| 17 | BatchNodeAddBottom4Glow | Blending, Glow, zLayer B4 | -23 | +| 18 | BatchNodeBottom3 | zLayer B3 | -15 | +| 19 | BatchNodeAddBottom3 | Blending, zLayer B3 | -16 | +| 20 | BatchNodeAddBottom3Glow | Blending, Glow, zLayer B3 | -16 | +| 21 | BatchNodeTop2 | zLayer T2 | 17 | +| 22 | BatchNodeAddGlowTop2 | Blending, Glow, zLayer T2 | 16 | +| 23 | BatchNodeTop3 | zLayer T3 | 25 | +| 24 | BatchNodeAddTop3 | Blending, zLayer T3 | 24 | +| 25 | BatchNodeAddGlowTop3 | Blending, Glow zLayer T3 | 24 | +| 26 | BatchNodeAddTop4 | Blending, zLayer T4 | 26 | +| 27 | EffectBatchNodeTop3 | Animated, zLayer T3 | 19 | +| 28 | EffectBatchNodeAddTop3 | Animated, Blending, zLayer T3 | 18 | +| 29 | EffectBatchNodeTop2 | Animated, zLayer T2 | 12 | +| 30 | EffectBatchNodeAddTop2 | Animated, Blending, zLayer T2 | 11| +| 31 | EffectBatchNodeTop1 | Animated, zLayer T1 | 5 | +| 32 | EffectBatchNodeAddTop1 | Animated, Blending, zLayer T1 | 4 | +| 33 | EffectBatchNodeBot2 | Animated, zLayer B2 | -13 | +| 34 | EffectBatchNodeAddBot2 | Animated, Blending, zLayer B2 | -14 | +| 35 | EffectBatchNodeBot3 | Animated, zLayer B3 | -20 | +| 36 | EffectBatchNodeAddBot3 | Animated, Blending, zLayer B3 | -21 | +| 37 | EffectBatchNodeBot4 | Animated, zLayer B4 | -27 | +| 38 | EffectBatchNodeAddBot4 | Animated, Blending, zLayer B4 | -28 | +| 39 | BatchNodeTextTop3 | Text, zLayer T3 | 21 | +| 40 | BatchNodeTextAddTop3 | Text, Blending, zLayer T3 | 22 | +| 41 | BatchNodeTextTop2 | Text, zLayer T2 | 13 | +| 42 | BatchNodeTextAddTop2 | Text, Blending, zLayer T2 | 14 | +| 43 | BatchNodeTextTop1 | Text, zLayer T1 | 6 | +| 44 | BatchNodeTextAddTop1 | Text, Blending, zLayer T1 | 7 | +| 45 | BatchNodeText | Text, zLayer B1 | -5 | +| 46 | BatchNodeAddText | Text, Blending, zLayer B1 | -4 | +| 47 | BatchNodeTextBot2 | Text, zLayer B2 | -12 | +| 48 | BatchNodeAddTextBot2 | Text, Blending, zLayer B2 | -11 | +| 49 | BatchNodeTextBot3 | Text, zLayer B3 | -19 | +| 50 | BatchNodeAddTextBot3 | Text, Blending, zLayer B3 | -18 | +| 51 | BatchNodeTextBot4 | Text, zLayer B4 | -26 | +| 52 | BatchNodeAddTextBot5 | Text, Blending, zLayer B4 | -25 | +| 53 | EffectBatchNodeAddTop4 | Animated, Blending, zLayer T4 | 20 | + +## Legacy String + +There are other types of Capacity Strings from older versions of the game. The total number of Nodes is used to identify them + +| Update | Node count | +|:-------|:-----------| +| 1.9 | 4 | +| 2.0 | 16 | + +The capacity string in 2.0 is quite easy to understand as it only contains the first 16 batch nodes in 2.1's capacity string. 1.9 is quite different with certain indexes containing multiple batch nodes. + +> **Below is a table for 1.9's Capacity String.** +> Refer to the [Structure](/resources/client/level-components/Capacity-string?id=structure) section for the properties of the batchNodes + +| Index | BatchNode(s) | +|:------|:-------------| +| 0 | BatchNode | +| 1 | BatchNodeAdd
BatchNodeAddGlow | +| 2 | BatchNodeBottom
BatchNodeBottom2 | +| 3 | BatchNodeAddBottom
BatchNodeAddBottom2
BatchNodeAddBottomGlow
BatchNodeAddBottom2Glow | + +## High Capacity Mode + +In the game options, there is a option the player can toggle called `High Capacity Mode`. when enabled, the Capacity for each BatchNode is set to a hardcoded value. There are 3 capacity sizes + +| size | Batch Type | +|:-----|:-----------| +| 999 | BatchNode | +| 200 | EffectBatchNode | +| 100 | BatchNodeText | + +If enabled, the Capacity string is disregarded and these values are used instead. + + + +## Capacity String Generation + +The Capacity String is only generated during verification of the level. When playing the level, the game stores the the highest number of GameObjects that the Batch is responsible for inside its textureAtlas as the capacity. After the level is verified, the following function is called + +```cpp +// This is only a re-creation of the function used and is not an accurate decompilation +// we have refactored the code to make it easier to understand + +int capacity = BatchNode->getAtlasCapacity(); + +if(capacity <= 29) + return 0; + +// Increasing the capacity by a small amount to ensure there is enough memory +int newCapacity = capacity * 1.1f; + +// returning the new capacity with a limit of 9999 +return std::min(newCapacty, 9999); + ``` + +After the capacity is calculated, it adds the value to the capacity string. Once the entire string is finished, it is then stored in `GJGameLevel->CapacityString_` where it will then be sent to the servers during the upload diff --git a/docs/client/level-components/color-string.md b/docs/client/level-components/color-string.md new file mode 100644 index 000000000..cd9d6ca64 --- /dev/null +++ b/docs/client/level-components/color-string.md @@ -0,0 +1,37 @@ +# Client Color String Resource + +## Color String +The color string contains the information for the initial state of the colors being used in the level. Its raw representation is formatted as follows: + +`{color}|{color}|...`, where `color` is formatted as: + +`{property_key}_{property_value}_{property_key}_{property_value}_...`. + +## Color Properties +The color entries have the following properties: + +| Key | Name | Type | Description | +|:----|:--------------------|:------------------------------------|:-------------------------------------------| +| 1 | FromColourRed | **Integer** | the Red component of the color | +| 2 | FromColourGreen | **Integer** | the Green component of the color | +| 3 | FromColourBlue | **Integer** | the Blue component of the color | +| 4 | PlayerColor | **[Player Color](enumerations.md)** | the Player Color that the color is copying | +| 5 | Blending | **Bool** | the Blending property of the color | +| 6 | ColourChannelIndex | **Integer** | the Color Channel ID of the color | +| 7 | FromOpacity | **Float** | the Opacity property of the color | +| 8 | ToggleOpacity | **Bool** | toggled if opacity and be changed | +| 9 | InheritedColourChannelIndex | **Integer** | the Color Channel ID of the copied color | +| 10 | HSV | **[HSV]()** | the HSV of the copied color | +| 11 | ToColourRed | **Integer** | the Red component that the colour changes to| +| 12 | ToColourGreen | **Integer** | the Green component that the colour changes to| +| 13 | ToColourBlue | **Integer** | the blue component that the colour changes to| +| 14 | DeltaTime | **Float** | delta used in colour change | +| 15 | ToOpacity | **Float** | opacity that fromOpacity should change too | +| 16 | Duration | **Float** | duration for From->To | +| 17 | CopyOpacity | **Bool** | the Copy Opacity property of the color | + +***Undiscovered properties*** + +| Key | Type | Proven Existence | Common Value | +|:----|:------------|:-----------------|:-------------| +| 18 | **bool**(?) | yes | 0 | diff --git a/docs/client/level-components/guideline-string.md b/docs/client/level-components/guideline-string.md new file mode 100644 index 000000000..99821541c --- /dev/null +++ b/docs/client/level-components/guideline-string.md @@ -0,0 +1,40 @@ +# Client Guideline String Resource + +## Guideline String +The guideline string is the linearized string format of the guidelines of a level. It is contained within the [inner level string](inner-level-string.md). It is formatted as follows: + +`{guideline}~{guideline}~{guideline}~...`, where `guideline` is formatted as: + +`{timestamp}~{color_value}`, with `timestamp` being in seconds and both values being floats. + +E.g.: + +`0.5~0.8~0.7~0.9~1~1` represents the following guidelines: + +- Guideline (`0.5~0.8`) + - Timestamp: 0.5 + - Color value: 0.8 (orange) +- Guideline (`0.7~0.9`) + - Timestamp: 0.7 + - Color value: 0.9 (yellow) +- Guideline (`1~1`) + - Timestamp: 1 + - Color value: 1 (green) + +## Color Values +The valid supported color values are the following: + +| Value | Color | +|:------|:-------| +| 0.8 | orange | +| 0.9 | yellow | +| 1.0 | green | + +***Unexpected Behavior Information*** + +- A color value of 0 will result in an orange guideline. +- Color values less than 0.8 will result in a transparent guideline. +- Color values above 0.8 that do not match the yellow or the green guideline color values will result in an orange guideline. + +### Trivia +- A number of guidelines with color value 0.7 were found in Blast Processing, which are all transparent. diff --git a/docs/client/level-components/inner-level-string.md b/docs/client/level-components/inner-level-string.md new file mode 100644 index 000000000..800dad35d --- /dev/null +++ b/docs/client/level-components/inner-level-string.md @@ -0,0 +1,96 @@ +# Client Inner Level String Resource + +## Inner Level String +The inner level string consists of information about the starting state of the level and the objects it contains. It is encoded in [base64](). Its raw representation is formatted as follows: + +`{level_start};{object_string}`, where + +- `level_start` is the level start object, +- `object_string` is the [object string](). + +Theoretically, the inner level string in its entirety is the object string, however the level start object is treated specially, unlike every other object, and doesn't even have an ID. + +## Level Start Object +The level start object is still an object and formated exactly like a normal [level object](level-object.md), but has the following properties instead: + +| Key | Name | Type | Description | +|:-----|:-----------------------|:--------------------------------------------|:---------------------------------------------------------------------------------------------------------------| +| kA1 | AudioTrack | **Integer** | The audio track which the level uses | +| kA2 | Gamemode | **[Gamemode](enumerations.md)** | the gamemode the player starts with | +| kA3 | Mini Mode | **bool** | determines whether the player starts off as mini Mode | +| kA4 | Speed | **[Speed](enumerations.md)** | the speed of the level at the starts | +| kA6 | Background Texture ID | **integer** | the ID of the background texture that is being used in the level
(enumerated in the same order as appears) | +| kA7 | Ground Texture ID | **integer** | the ID of the ground texture that is being used in the level
(enumerated in the same order as appears) | +| kA8 | Dual Mode | **bool** | determines whether the player starts off in dual Mode | +| kA9 | Level/Start Pos Object | **bool** | determines whether this object represents a Level Start or a Start Pos object (true for the latter) | +| kA10 | 2-Player Mode | **bool** | determines whether 2-Player Mode is toggled on for this level | +| kA11 | Flip Gravity | **bool** | determines whether the player starts off in flipped Gravity | +| kA13 | Song Offset | **float** | the song offset in seconds from which the level begins | +| kA14 | Guidelines | **[Guideline String](guideline-string.md)** | the editor song guidelines of the level | +| kA15 | Fade In | **bool** | determines whether the song will fade in as soon as the level starts | +| kA16 | Fade Out | **bool** | determines whether the song will fade in as soon as the level ends | +| kA17 | Ground Line | **integer** | the ID of the ground line that is being used in the level | +| kA18 | Font | **integer** | the ID of the font that is being used in the level | +| kA22 | Platformer Mode | **Bool** | If platformer Mode is toggled on or off (currently only available in the December 2019 2.2 leaks) | +| kS38 | Colors | **[Color String](color-string.md)** | the color channels that are being used in this level | +| kS39 | Color Page | **integer** | the color page which was last displayed in the color channel display window | + +***Pre-2.0 Keys*** + +The following keys were valid prior to 2.0 and are deprecated, since they are included in the new `kS38` key. They all represented a color channel that is now indexed through the respective color channel ID. + +| Key | Name | Color Channel ID | +|:-----|:-------------|:-----------------| +| kS29 | BG Color | 1000 | +| kS30 | Ground Color | 1001 | +| kS31 | Line Color | 1002 | +| kS32 | Object Color | 1004 | +| kS33 | Color 1 | 1 | +| kS34 | Color 2 | 2 | +| kS35 | Color 3 | 3 | +| kS36 | Color 4 | 4 | +| kS37 | 3DL Color | 1003 | + +***Pre-1.9 Keys*** + +The following keys were valid prior to 1.9 and were deprecated as of 1.9, since they were included in the keys `kS29`-`kS33`. Each color, instead of using one key, used 3 keys to represent Red, Green, and Blue values, respectively. In 1.7 and 1.8, the game used a fourth key to determine if a color channel used a player color, and which player color it would use. + +| Key(s) | Name | Key in 1.9 | +|:----------|:--------------------|:-----------| +| kS1-kS3 | BG Color | kS29 | +| kS4-kS6 | Ground Color | kS30 | +| kS7-kS9 | Line Color | kS31 | +| kS10-kS12 | Object Color | kS32 | +| kS13-kS15 | Obj-2 Color | kS33 | +| kS16 | BG Player Color | kS29 | +| kS17 | Ground Player Color | kS30 | +| kS18 | Line Player Color | kS31 | +| kS19 | Object Player Color | kS32 | +| kS20 | Obj-2 Player Color | kS33 | + +Keys `kS16`-`kS20` used to determine the player color that was being used and their values were interpreted according to the following table: + +| Value | Color | +|:------|:---------------| +| 0 | Neither | +| 1 | Player Color 1 | +| 2 | Player Color 2 | + +### Start Pos Object +The Start Pos object has the same special properties the level start object has, with a few not working. `kA9` must be set to `1` in the case that the object is indeed a Start Pos. + +Specifically, the only functional properties in a Start Pos object are the ones involving gameplay state, thus excluding visual-related ones (BG/ground textures, font, colors, etc.) + +Confirmed properties that do not work in the Start Pos: + +| Key | +|:-----| +| kA6 | +| kA7 | +| kA10 | +| kA13 | +| kA14 | +| kA15 | +| kA16 | +| kA18 | +| kS* | diff --git a/docs/client/level-components/level-colors.md b/docs/client/level-components/level-colors.md new file mode 100644 index 000000000..019e0e7d2 --- /dev/null +++ b/docs/client/level-components/level-colors.md @@ -0,0 +1,104 @@ +# Level Colors +This document goes in depth on how colors, copy colors and player color work as base colors or in color/pulse triggers. + +## Color classes +There are 3 color classes (not to be confused with the GD's classes). Every aspect in GD levels that use colors only take one of the classes. All of the properties that do not belong to the color class being used is ignored. + +### BaseColor +This class contains a static color along with opacity and blending. + +These are the properties that are important for a BaseColor: + +| Name | Type | Description | +|:---------|:------------|:----------------------| +| Red | **integer** | The red component of the BaseColor. Goes from `0` to `255` | +| Green | **integer** | The green component of the BaseColor. Goes from `0` to `255` | +| Blue | **integer** | The blue component of the BaseColor. Goes from `0` to `255` | +| Opacity | **float** | The alpha component of the BaseColor. Goes from `0` to `1` | +| Blending | **bool** | The blending property of the BaseColor | + +**Note**: Blending causes the color to add its color properties by basically using the OpenGL blend mode `glBlendFunc(GL_SRC_ALPHA, GL_ONE)` + +### PlayerColor +This class contains a static color refering to one of the player's icon color along with opacity and blending. + +These are the properties that are important for a PlayerColor: + +| Name | Type | Description | +|:-------------|:------------|:----------------------| +| Player Color | **integer** | This determines which of the player's color is getting used. The actual values are not documented here yet. | +| Opacity | **float** | The alpha component of the PlayerColor. Goes from `0` to `1` | +| Blending | **bool** | The blending property of the PlayerColor | + +### CopyColor +This class contains a dynamic color copied from another color channel. This color changes according to the current color of the channel that is being copied. + +| Name | Type | Description | +|:----------------|:------------|:----------------------| +| Copy Channel ID | **integer** | The color channel ID that the CopyColor is copying the color from | +| Copy Opacity | **bool** | This determines whenever CopyColor should also copy the opacity belonging to the color channel in `Copy Color ID` | +| Opacity | **float** | The alpha component of the Copy Color. If `Copy Opacity` is true. This property is ignored. | +| Blending | **bool** | The blending property of the CopyColor since it cannot be copied | +| Copy HSV | **[HSV](resources/client/level-components/level-object.md?id=object-string)** | The HSV property that changes the color's tint depending on the value | + +### Determining which class is used +Here is a simple JavaScript function that determines what color class the color object has: + +```javascript +function getColorClass(color) { + if (color.copy_channel_id != 0) + return COPY_COLOR; + + if (color.player_color != PLAYER_COLOR_NONE) + return PLAYER_COLOR; + + return BASE_COLOR; +} +``` + +## Color Channel ID's +Here are all of the different color id's: + +| Interval | Name | Description | +|:----------|:------------------|:----------------------| +| `1 - 999` | **Custom colors** | These are the colors that are avalible for the creator to use | +| `1000` | **BG** | This is the color of the background | +| `1001` | **G1** | This is the primary color of the ground | +| `1002` | **LINE** | This is the color of the ground line | +| `1003` | **3DL** | This is the color of the 3D line objects | +| `1004` | **OBJ** | This is the OBJ color | +| `1005` | **P1** | This is the static color channel refering to the primary color of the player's icon | +| `1006` | **P2** | This is the static color channel refering to the secondary color of the player's icon | +| `1007` | **LBG** | This is the static color channel that is a lighter version of `BG` | +| `1009` | **G2** | This is the secondary color of the ground | +| `1010` | **BLACK** | This is the static color channel which is always `r: 0, g: 0, b: 0`. Used in saws that are black by default | + +### Undiscovered color channel IDs +`WHITE`: Static color that is always `r: 255, g: 255, b: 255` +`LIGHTER`: A lighter version of the primary color in objects. Used in the white small blocks found in `build tab 2 on page 6`. + +### 1.9 color channel ID's +GD's 1.9 version used a different ID scheme to identify color channels. In 2.0+, these IDs are still present, but only used in the legacy `1.9 Color Channel ID` property of 1.9 objects. They are as follows: +| 1.9 Channel ID | Name | Corresponding 2.0+ ID | +|:----|:---------|:-----------------------------| +| `1` | **P1** | `1005` +| `2` | **P2** | `1006` +| `3` | **COL 1** | `1` +| `4` | **COL 2** | `2` +| `5` | **LBG** | `1007` +| `6` | **COL 3** | `3` +| `7` | **COL 4** | `4` +| `8` | **3DL** | `1003` + +### Light Background (LBG) calculation +The LBG takes the HSV of background. Subtracts `20` from its saturation, then interpolates from `P1` to the last HSV by a factor of the last HSV's value devided by `100`. + +Here is a JavaScript example: +```javascript +function lightBG(bg, p1) { + let hsv = RGBtoHSV(bg); + hsv.s -= 20; + + return blendColor( p1, HSVtoRGB(hsv), hsv.v / 100 ); +} +``` diff --git a/docs/client/level-components/level-object.md b/docs/client/level-components/level-object.md new file mode 100644 index 000000000..e68ca8687 --- /dev/null +++ b/docs/client/level-components/level-object.md @@ -0,0 +1,181 @@ +# Client Level Object Resource + +## Level Object +A level object is an object within a Geometry Dash level, containing data about its behavior. + +### Object String +The object string is contained within the [inner level string](). It is formatted as follows: + +`{object};{object};{object};...`, where `object` is formatted as: + +`{propertyKey},{propertyValue},{propertyKey},{propertyValue},...`. + +E.g.: + +`1,1,2,15,3,15,21,3,24,7;1,1,2,15,3,15,20,5,25,-1;` represents the following objects: + +- Standard Block + - ID: 1 (`1,1`) + - X: 15 (`2,15`) + - Y: 15 (`3,15`) + - Main Color ID: 3 (`21,3`) + - Z Layer: 7 (`24,7`) +- Standard Block + - ID: 1 (`1,1`) + - X: 15 (`2,15`) + - Y: 15 (`3,15`) + - Editor Layer 1: 5 (`20,5`) + - Z Order: -1 (B3) (`25,-1`) + +Notice that every single objects contains at least 3 properties, `1`, `2`, `3`, which represent the object ID, X position and Y position respectively. Even in the case that the objects' X and Y positions are 0, the keys are not omitted. + +Property keys reflect the keys found in the following table, whereas property values are formatted as follows + +| Type | Formatting | +|:--------------------|:--------------------------------------------------------------------------------------------| +| **integer** | decimal numerical value string (e.g. `421`) | +| **bool** | `1` if true, `0` if false | +| **float** | decimal numerical value string, using `.` as the decimal point separator (e.g. `12.41`) | +| **any enumeration** | same as **integer** | +| **integer array** | all values are separated by `.` (e.g. `1.42.51.23` for `{ 1, 42, 51, 23 }`) | +| **[HSV]()** | `{h}a{s}a{v}a{s_checked}a{v_checked}`, where each name reflects the respective HSV property | +| **string** | raw string without quotation marks (e.g. `ExampleString`) | + +### Level Object Data +**Level Object Structure** + +| Key | Name/Value | Type | Description | +|:----|:-------------------------------------|:------------------------------------------------|:-----------------------------------------------------------------------------------| +| 1 | Object ID | **integer** | the ID of the object | +| 2 | X Position | **float** | the X position of the object | +| 3 | Y Position | **float** | the Y position of the object | +| 4 | Flipped Horizontally | **bool** | whether the object is horizontally flipped | +| 5 | Flipped Vertically | **bool** | whether the object is vertically flipped | +| 6 | Rotation | **float** | the rotation of the objects in degrees, CW is positive, top is 0 | +| 7 | Red | **integer** | the Red component of the color in a trigger | +| 8 | Green | **integer** | the Green component of the color in a trigger | +| 9 | Blue | **integer** | the Blue component of the color in a trigger | +| 10 | Duration | **float** | the duration of an effect in a trigger | +| 11 | Touch Triggered | **bool** | the Touch Triggered property of a trigger | +| 12 | Secret Coin ID | **integer** | the ID of a Secret Coin | +| 13 | Special Object Checked | **bool** | the checked property of some special objects (gamemode, speed, dual portals, etc.) | +| 14 | Tint Ground | **bool** | the Tint Ground property of the BG Color trigger | +| 15 | Player Color 1 | **bool** | the Player Color 1 property of any Color trigger | +| 16 | Player Color 2 | **bool** | the Player Color 2 property of any Color trigger | +| 17 | Blending | **bool** | the Blending property of any Color trigger | +| 19 | 1.9 Color Channel ID | **integer** | the legacy Color Channel ID property used in 1.9 levels. If set to a valid value, both the Main and Secondary Color Channel ID properties will be ignored. | +| 20 | Editor Layer 1 | **integer** | the Editor Layer 1 property of the object | +| 21 | Main Color Channel ID | **integer** | the Main Color Channel ID property of the object | +| 22 | Secondary Color Channel ID | **integer** | the Secondary Color Channel ID property of the object | +| 23 | Target Color ID | **integer** | the Target Color ID property in an interactive object | +| 24 | Z Layer | **integer** | the Z Layer of the object | +| 25 | Z Order | **integer** | the Z Order of the object | +| 28 | Offset X | **integer** | the Offset X property of the Move trigger | +| 29 | Offset Y | **integer** | the Offset Y property of the Move trigger | +| 30 | Easing | **[Easing](enumerations.md)** | the Easing type of the effect of a trigger | +| 31 | Text | **string** | the text of the text object in [base64]() | +| 32 | Scaling | **float** | the scaling of the object | +| 33 | Single Group ID | **integer** | a group ID given to the object | +| 34 | Group Parent | **bool** | the Group Parent property of the object | +| 35 | Opacity | **float** | the opacity value of a trigger | +| 41 | Main Color HSV Enabled | **bool** | whether the HSV mode is enabled for the Main Color of the object | +| 42 | Secondary Color HSV Enabled | **bool** | whether the HSV mode is enabled for the Secondary Color of the object | +| 43 | Main Color HSV | **[HSV]()** | the HSV adjustment values of the Main Color of the object | +| 44 | Secondary Color HSV | **[HSV]()** | the HSV adjustment values of the Secondary Color of the object | +| 45 | Fade In | **float** | the Fade In property of the Pulse trigger | +| 46 | Hold | **float** | the Hold property of the Pulse trigger | +| 47 | Fade Out | **float** | the Fade Out property of the Pulse trigger | +| 48 | Pulse Mode | **[Pulse Mode](enumerations.md)** | the Pulse Mode property of the Pulse trigger | +| 49 | Copied Color HSV | **[HSV]()** | the HSV adjustment values of the Copied Color property of a trigger | +| 50 | Copied Color ID | **integer** | the Copied Color Channel ID in a trigger | +| 51 | Target Group ID | **integer** | the Target Group ID in a trigger | +| 52 | Pulse Target Type | **[Pulse Target Type](enumerations.md)** | the Target Type property of the Pulse trigger | +| 54 | Yellow Teleportation Portal Y Offset | **float** | the Y offset of the yellow from the blue teleportation portal | +| 55 | Teleport Portal Ease | **bool** | The Smooth Ease property within Teleport Portals | +| 56 | Activate Group | **bool** | the Activate Group property of the trigger | +| 57 | Group IDs | **integer array** | the group IDs of the object | +| 58 | Lock To Player X | **bool** | the Lock To Player X property of the Move trigger | +| 59 | Lock To Player Y | **bool** | the Lock To Player Y property of the Move trigger | +| 60 | Copy Opacity | **bool** | the Copy Opacity property of a trigger | +| 61 | Editor Layer 2 | **integer** | the Editor Layer 2 of an object | +| 62 | Spawn Triggered | **bool** | the Spawn Triggered property of a trigger | +| 63 | Spawn Delay | **float** | the Spawn Delay property of the Spawn trigger | +| 64 | Don't Fade | **bool** | the Don't Fade property of the object | +| 65 | Main Only | **bool** | the Main Only property of the Pulse trigger | +| 66 | Detail Only | **bool** | the Detail Only property of the Pulse trigger | +| 67 | Don't Enter | **bool** | the Don't Enter property of the object | +| 68 | Degrees | **integer** | the Degrees property of the Rotate trigger | +| 69 | Times 360 | **integer** | the Times 360 property of the Rotate trigger | +| 70 | Lock Object Rotation | **bool** | the Lock Object Rotation property of the Rotate trigger | +| 71 | Secondary Group ID | **integer** | the Secondary (Follow, Target Pos, Center) Group ID property of some triggers | +| 72 | X Mod | **float** | the X Mod property of the Follow trigger | +| 73 | Y Mod | **float** | the Y Mod property of the Follow trigger | +| 75 | Strength | **float** | the Strength property of the Shake trigger | +| 76 | Animation ID | **integer** | the Animation ID property of the Animate trigger | +| 77 | Count | **integer** | the Count property of the Pickup trigger or the Pickup Item | +| 78 | Subtract Count | **bool** | the Subtract Count property of the Pickup trigger or the Pickup Item | +| 79 | Pickup Mode | **[Pickup Item Mode](enumerations.md)** | the Pickup Mode property of the Pickup Item | +| 80 | Item/Block ID | **integer** | the Item/Block ID property of an object | +| 81 | Hold Mode | **bool** | the Hold Mode property of the Touch trigger | +| 82 | Toggle Mode | **[Touch Toggle Mode](enumerations.md)** | the Toggle Mode property of the Touch trigger | +| 84 | Interval | **float** | the Interval property of the Shake trigger | +| 85 | Easing Rate | **float** | the Easing Rate property of a trigger | +| 86 | Exclusive | **bool** | the Exclusive property of a Pulse trigger | +| 87 | Multi-Trigger | **bool** | the Multi-Trigger property of a trigger | +| 88 | Comparison | **[Instant Count Comparison](enumerations.md)** | the Comparison property of the Instant Count trigger | +| 89 | Dual Mode | **bool** | the Dual Mode property of the Touch trigger | +| 90 | Speed | **float** | the Speed property of the Follow Player Y trigger | +| 91 | Follow Delay | **float** | the Follow Delay property of the Follow Player Y trigger | +| 92 | Y Offset | **float** | the Y Offset property of the Follow Player Y trigger | +| 93 | Trigger On Exit | **bool** | the Trigger On Exit property of the Collision trigger | +| 94 | Dynamic Block | **bool** | the Dynamic Block property of the Collision block | +| 95 | Block B ID | **integer** | the Block B ID property of the Collision trigger | +| 96 | Disable Glow | **bool** | the Disable Glow property of the object | +| 97 | Custom Rotation Speed | **float** | the Custom Rotation Speed property of the rotating object in degrees per second | +| 98 | Disable Rotation | **bool** | the Disable Rotation property of the rotating object | +| 99 | Multi Activate (Orbs) | **bool** | the Multi Activate property of Orbs | +| 100 | Enable Use Target | **bool** | the Enable Use Target property of the Move trigger | +| 101 | Target Pos Coordinates | **[Target Pos Coordinates](enumerations.md)** | the Target Pos Coordinates property of the Move trigger | +| 102 | Editor Disable | **bool** | the Editor Disable property of the Spawn trigger | +| 103 | High Detail | **bool** | the High Detail property of the object | +| 104 | Multi Activate (Triggers) | **bool** | The Multi Activate Property of Triggers | +| 105 | Max Speed | **float** | the Max Speed property of the Follow Player Y trigger | +| 106 | Randomize Start | **bool** | the Randomize Start property of the animated object | +| 107 | Animation Speed | **float** | the Animation Speed property of the animated object | +| 108 | Linked Group ID | **integer** | the Linked Group ID property of the object | + +***Undiscovered Existing Features*** + +The following features are discovered in current local save files, however their purpose is undisclosed. + +| Key | Type | Info | +|:----|:------------|:---------------------------------------------------------------------------------------------------| +| 36 | **bool** | suspected to be handling whether an object's X position is locked and unaffected by a Move trigger | +| 74 | **bool**(?) | only found in the Follow Player Y trigger | + +***Potentially Discarded Features*** + +The following key ranges are potentially discarded features, whose appearance in earlier versions of the game is unknown and untested. + + + + + + + + + + + + + + + + + + + + + + +
Key StartKey End
18
2627
3740
53
83
diff --git a/docs/client/level.md b/docs/client/level.md new file mode 100644 index 000000000..0ffb5c189 --- /dev/null +++ b/docs/client/level.md @@ -0,0 +1,120 @@ +# Client Level Resource + +## Level + +A level is a playable object in Geometry Dash, namely coming with data that explains on what it is, and the string that the client interprets, known as a level string. It is stored in [XML](https://en.wikipedia.org/wiki/XML) format, and each level entry is a dictionary, containing key/value pairs denoting the level's properties. + +### Level Data + +**Level Structure** + +| Key | Name/Value | Type | Description | +| :-- | :----------------------------- | :--------------------------------------------------------------- | :------------------------------------------------------------------------------- | +| k1 | Level ID | **integer** | the id of the level | +| k2 | Level Name | **string** | the name of the level | +| k3 | Description | **string** | the level description, encoded in [base64](https://en.wikipedia.org/wiki/Base64) | +| k4 | Inner Level String | **[inner level string](/resources/client/level-components/inner-level-string.md)** | the inner level string, or the playable level | +| k5 | Creator | **[user](./user.md)Name** | the name of the level creator | +| k6 | UserID | **integer** | The UserID of the level Creator | +| k7 | level difficulty | **integer** | the difficulty the level has | +| k8 | Official Song ID | **[Audio Track](/reference?id=audio-track)** | the official Song ID (if used) | +| k9 | Rating | **integer** | The rating a level has | +| k10 | RatingSum | **integer** | the sum of all the ratings a level has | +| k11 | Downloads | **integer** | the amount of times the level's been downloaded | +| k12 | setCompletes | **integer** | level completions for that particular level | +| k13 | isEditable | **Bool** | used to stop people editing online and Official levels | +| k14 | Verified | **bool** | whether the level is verified or not | +| k15 | Uploaded | **bool** | whether the level is uploaded to the server or not | +| k16 | Level Version | **integer** | the version of the level | +| k17 | Game Version | **integer** | The Games Version | +| k18 | Attempts | **integer** | the number of attempts that are made to this level | +| k19 | Normal Mode Percentage | **integer** | the max percentage that has been achieved in normal mode in this level | +| k20 | Practice Mode Percentage | **integer** | the max percentage that has been achieved in practice mode in this level | +| k21 | levelType | **Integer** | The Level Type (1 = Official, 2 = Local, 3 = Saved, 4 = Online) | +| k22 | Like Rating | **integer** | the level's like rating (`likes - dislikes`) | +| k23 | Length | **[Length](enumerations.md)** | the level's length | +| k24 | Dislikes | **integer** | how many dislikes a level has (unused) | +| k25 | isDemon | **Bool** | if the level is demon or not | +| k26 | Stars | **integer** | the stars the level is worth | +| k27 | FeatureScore | **integer** | A featured levels Feature Score | +| k33 | Auto | **Bool** | If the level is auto | +| k34 | Replay Data | **[Gziped String](/topics/encryption/zip.md)** | Contains a Gzipped String which contains replay data for levels | +| k35 | isPlayable? | **Bool** | if the level is downloaded (honestly not much is known about this) | +| k36 | Jumps | **integer** | total Jumps on a level | +| k37 | required coins | **Integer** | coins required to unlock an official level | +| k38 | isUnlocked | **Bool** | is Official level Unlocked | +| k39 | level Size | **integer** | `this->levelSize = std::floor(this->levelString.length() * 0.152);` | +| k40 | Build Version | **integer** | the games build version | +| k41 | Password | **integer** | the [password]() set for the level | +| k42 | Original | **integer** | The ID the of the original level (if the level was copied) | +| k43 | Two-Player Mode | **Bool** | If the level is 2 player mode | +| k45 | Custom Song ID | **integer** | the custom Song ID (if used) | +| k46 | Level Revision | **integer** | the revision of the level | +| k47 | hasBeenModified | **Bool** | if the level has been modified from outside the GD editor | +| k48 | Object Count | **integer** | the object count of the level | +| k50 | Binary Version | **integer** | hardcoded to binary Version | +| k51 | capacity001 | **integer** | BatchNodes | +| k52 | capacity002 | **integer** | BatchNodes | +| k53 | capacity003 | **integer** | BatchNodes | +| k54 | capacity004 | **integer** | BatchNodes | +| k60 | AccountID | **integer** | the Creators AccountID | +| k61 | First Coin Acquired | **bool** | whether the first coin is acquired during verification | +| k62 | Second Coin Acquired | **bool** | whether the second coin is acquired during verification | +| k63 | Third Coin Acquired | **bool** | whether the third coin is acquired during verification | +| k64 | Total Coins | **Integer** | How many Coins the level has | +| k65 | areCoinsVerified | **Bool** | denotes if the coins are verified or not | +| k66 | Requested Stars | **integer** | the requested stars during publication of the level | +| k67 | [Capacity String](/resources/client/level-components/capacity-string.md) | **String** | Contains batch information about levels | +| k68 | triggeredAntiCheat | **Bool** | if you trigger the anticheat when beating demons | +| k69 | High Object Count | **Bool** | If a level has a high object count | +| k71 | Mana Orb Percentage | **integer** | the percentage up until the orb reward has been granted | +| k72 | hasLowDetailMode | **Bool** | If a level has LDM | +| k73 | toggleLDM | **Bool** | If a LDM is Enabled | +| k74 | timelyID | **integer** | the timelyID for a level | +| k75 | isEpic | **Bool** | if a level has been awarded an epic rating | +| k76 | demon type | **integer** | Demon Type Enum | +| k77 | isGauntlet | **Bool** | is the level in a gauntlet | +| k78 | isAltGame | **Bool** | Levels that were completed on the free games | +| k79 | Unlisted | **bool** | whether the level is to be marked as unlisted or not during publication | +| k80 | Seconds Spent Editing | **integer** | the number of seconds spent editing the level | +| k81 | Seconds spent Editing (copies) | **integer** | the number of seconds spent editing the level (Previous copies) | +| k82 | isLevelFavourited | **Bool** | if you put the level in your favourites | +| k83 | levelOrder | **integer** | ordering for levels | +| k84 | Level Folder | **integer** | the folder in which the level belongs (0 represents no folder) | +| k85 | Clicks | **integer** | Clicks done on the best attempt | +| k86 | Player Time | **integer** | the amount of time on a players best attempt | +| k87 | level Seed | **[LevelScoreSeed](/topics/encryption/chk?id=level-leaderboard)**| Contains info to verify the integrity of levelScores | +| k88 | Level Progress | **String** | Contains a list of high score differences seperated by a `,` | +| k89 | vfDChk | **Bool** | used to check for level completion | +| k90 | Leaderboard percentage | **integer** | Contains the percentage for level Leaderboards | + + +**Last Editor State Key/Value Pairs** +The last editor state key/value pairs contain a few values that indicate the last state of the editor before exiting the editor on that level. + +| Key | Name/Value | Type | Description | +| :-- | :----------------------- | :------------- | :--------------------------------------- | +| kI1 | Editor Camera X Position | **float** | the X position of the editor camera | +| kI2 | Editor Camera Y Position | **float** | the Y position of the editor camera | +| kI3 | Editor Camera Zoom | **float** | the zoom level of the editor camera | +| kI4 | Build Tab Page | **integer** | the displayed page within the build tab | +| kI5 | Build Tab | **integer** | the selected build tab | +| kI6 | Build Tab Pages | **dictionary** | the last browsed pages of each build tab | +| kI7 | Editor Layer | **float** | the last selected index of a layer | + +Note that the build tab pages do not depend on the user's button row/column settings. That means, if the settings are changed, the build tab pages will not reflect the correct changes. For example: + +The build tab page is 5, and the button settings are 6x2 (default), meaning the currently shown elements range from `5 * 6 * 2` = 60 to `6 * 6 * 2 - 1` = 71 (zero-indexed). If the user changes the button settings to 12x3, the tab page will remain as 5, showing elements ranging from `5 * 12 * 3` = 180 to `6 * 12 * 3 - 1` = 215 (zero-indexed). + +### GDL22 + + + +**Current Unknown Values** + +| Key | Type | Info | +| :-- | :---------- | :------------------------------------------------------- | +| k91 | **string** | | +| k92 | **integer** | | +| k93 | **Bool** | unlimited Objects? | +| k94 | **Bool** | Platformer? | diff --git a/docs/client/topics/vault_codes.md b/docs/client/topics/vault_codes.md new file mode 100644 index 000000000..0ed034a54 --- /dev/null +++ b/docs/client/topics/vault_codes.md @@ -0,0 +1,65 @@ +# Vault Codes + +In *Geometry Dash* there are three different vaults you can access: [The Vault](#the-vault), +[Vault of Secrets](#vault-of-secrets) and [Chamber of Time](#chamber-of-time). + +Each vault has a number of codes that you can enter to unlock icons and colors. + +## Encoding + +[The Vault](#the-vault): Codes are in plain text (not encoded). + +[Vault of Secrets](#vault-of-secrets) and [Chamber of Time](#chamber-of-time): `ask2fpcaqCQ2` +is added to the code, then [robtop encoding][robtop_encoding] is applied. + +## The Vault + +| code | reward | +|---------------------------------------|--------| +| `spooky` | cube | +| `lenny` | cube | +| `{name}`\* | cube | +| `mule` | ship | +| `blockbite` | UFO | +| `neverending` | UFO | +| `ahead` | wave | +| `8`, `16`, `30`, `32`, `46`, `84`\*\* | wave | +| `robotop` | robot | +| `gandalfpotter` | trail | +| `sparky` | coin | + +\* `name` is the in-game name of the player. + +\*\* Consecutively enter one code at a time. + +## Vault of Secrets + +| code | reward | +|----------------------|-----------------| +| `{stars}`\* | cube | +| `cod3breaker`\*\* | cube | +| `brainpower` | cube | +| `octocube` | cube | +| `seven` | cube | +| `thechickenisonfire` | secondary color | +| `gimmethecolor` | primary color | +| `glubflub` | coin | + +\* `stars` is the in-game count of stars the player has. + +\*\* You will be given a sequence of numbers. You need to find difference between each +overlapping pair of numbers, combining the results into the final code. +For example, for sequence `1, 2, 4, 8, 16, 32` the differences are `1, 2, 4, 8, 16`, +therefore the final code is `124816`. + +## Chamber of Time + +| code | reward | +|------------|-----------------| +| `silence` | cube | +| `hunger` | cube | +| `darkness` | cube | +| `volcano` | wave | +| `river` | secondary color | + +[robtop_encoding]: /topics/encoding/robtop diff --git a/docs/code_of_conduct.md b/docs/code_of_conduct.md new file mode 100644 index 000000000..01f2ea20d --- /dev/null +++ b/docs/code_of_conduct.md @@ -0,0 +1 @@ +--8<-- "CODE_OF_CONDUCT.md" diff --git a/docs/encoding/aes.md b/docs/encoding/aes.md new file mode 100644 index 000000000..de3bad2fc --- /dev/null +++ b/docs/encoding/aes.md @@ -0,0 +1 @@ +# AES diff --git a/docs/encoding/base64.md b/docs/encoding/base64.md new file mode 100644 index 000000000..f26dba0b5 --- /dev/null +++ b/docs/encoding/base64.md @@ -0,0 +1,89 @@ +# Base64 + +[Base64][base64] encoding is widely used amongst different endpoints in Geometry Dash. + +It is used to encode fields like level data, level descriptions, comments, etc. + +GD uses *URL-safe* Base64 encoding, which uses `[A-Z]` and `[a-z]` letters +along with `_` and `-` as special characters. + +## Code + +```python +# taken from gd.py + +from base64 import b64decode as standard_decode_base64 +from base64 import b64encode as standard_encode_base64 +from base64 import urlsafe_b64decode as standard_decode_base64_url_safe +from base64 import urlsafe_b64encode as standard_encode_base64_url_safe + +# encoding + +DEFAULT_ENCODING = "utf-8" +DEFAULT_ERRORS = "strict" + +# padding + +BASE64_PAD = 4 +BASE64_INVALID_TO_PAD = 1 +BASE64_PADDING = b"=" + +# last + +LAST = ~0 + + +def enforce_valid_base64(data: bytes) -> bytes: + required = len(data) % BASE64_PAD + + if required: + if required == BASE64_INVALID_TO_PAD: + data = data[:LAST] + + else: + data += BASE64_PADDING * (BASE64_PAD - required) + + return data + + +def decode_base64(data: bytes) -> bytes: + return standard_decode_base64(enforce_valid_base64(data)) + + +def encode_base64(data: bytes) -> bytes: + return standard_encode_base64(data) + + +def decode_base64_url_safe(data: bytes) -> bytes: + return standard_decode_base64_url_safe(enforce_valid_base64(data)) + + +def encode_base64_url_safe(data: bytes) -> bytes: + return standard_encode_base64_url_safe(data) + + +def decode_base64_string( + string: str, encoding: str = DEFAULT_ENCODING, errors: str = DEFAULT_ERRORS +) -> str: + return decode_base64(string.encode(encoding, errors)).decode(encoding, errors) + + +def encode_base64_string( + string: str, encoding: str = DEFAULT_ENCODING, errors: str = DEFAULT_ERRORS +) -> str: + return encode_base64(string.encode(encoding, errors)).decode(encoding, errors) + + +def decode_base64_string_url_safe( + string: str, encoding: str = DEFAULT_ENCODING, errors: str = DEFAULT_ERRORS +) -> str: + return decode_base64_url_safe(string.encode(encoding, errors)).decode(encoding, errors) + + +def encode_base64_string_url_safe( + string: str, encoding: str = DEFAULT_ENCODING, errors: str = DEFAULT_ERRORS +) -> str: + return encode_base64_url_safe(string.encode(encoding, errors)).decode(encoding, errors) +``` + +[base64]: https://en.wikipedia.org/wiki/Base64 diff --git a/docs/encoding/checks.md b/docs/encoding/checks.md new file mode 100644 index 000000000..9eee28023 --- /dev/null +++ b/docs/encoding/checks.md @@ -0,0 +1,176 @@ +# Checks + +Check is a common parameter in requests, which is intended to "improve security". +It is often sent in request as `chk`. + +Check is generated like so: + +1. Take an arbitrary amount of values. +2. Combine them and add *salt* if there is one. +3. Apply [SHA-1][sha1] hashing to combined values and get its hexadecimal digest. +4. Apply [XOR Cipher][xor_cipher] to the digest with the desired key. +5. [Base64][base64] encode the result. + +## Code + +The generator can be implemented like this: + +```python +from hashlib import sha1 as standard_sha1 +from typing import Iterable + +EMPTY = str() + +concat = EMPTY.join + +DEFAULT_ENCODING = "utf-8" +DEFAULT_ERRORS = "strict" + + +def sha1_string( + string: str, salt: str = EMPTY, encoding: str = DEFAULT_ENCODING, errors: str = DEFAULT_ERRORS +) -> str: + return standard_sha1((data + salt).encode(encoding, errors)).hexdigest() + + +def generate_check( + values: Iterable[str], + key: str, + salt: str = EMPTY, + encoding: str = DEFAULT_ENCODING, + errors: str = DEFAULT_ERRORS, +) -> str: + string = concat(values) + + hashed = sha1_string(string, encoding, errors) + + xored = cyclic_xor_string(hashed, key, encoding, errors) + + encoded = encode_base64_string_url_safe(xored, encoding, errors) + + return encoded +``` + +[XOR][xor] keys can be found [here][xor_keys]. + +Here is a summary of *Check* values and explanations on their generation: + +## [Get Level][get_level] + +| name | description +|-------------|-----------------------------------------------| +| `levelID` | ID of the level to download. | +| `inc` | Unknown functionality. Set to `1`. | +| `rs` | [Random String][random_string]. | +| `accountID` | Account ID of the user downloading the level. | +| `udid` | [UDID][udid] of the user. | +| `uuid` | [UUID][uuid] of the user. | + +## [Upload Level][upload_level] + +| name | description | +|---------|-----------------------------------------------------------------| +| `seed2` | See [generating upload seed][upload_seed] for more information. | + +## [Post Comment][post_comment] + +| name | description | +|------------|---------------------------------------------------------------------| +| `userName` | Name of the user commenting. | +| `comment` | The content of the comment. | +| `levelID` | The ID of the level containing the comment (`0` for user comments). | +| `percent` | The percentage on the level (`0` for user comments). | +| `cType` | The comment type (`0` for level comments, `1` for user comments). | + +## [Get Quests][get_quests] + +| name | description | +|-------|-----------------------------------------------------------------------------------------------| +| `chk` | To generate: [random string][random_string] of length `5` + [encoded random integer][robtop]. | + +## [Get Chests][get_chests] + +| name | description | +|-------|-----------------------------------------------------------------------------------------------| +| `chk` | To generate: [random string][random_string] of length `5` + [encoded random integer][robtop]. | + +## [Like Item][like_item] + +| name | description | +|-------------|---------------------------------------------------------------------------------------------| +| `special` | Special value. `0` for levels, `levelID` for level comments, `commentID` for user comments. | +| `itemID` | ID of the level comment, level or user comment. | +| `like` | Whether to like the item. | +| `rs` | [Random String][random_string]. | +| `accountID` | Account ID of the user (dis)liking an item. | +| `udid` | [UDID][udid] of the user. | +| `uuid` | [UUID][uuid] of the user. | + +## [Update Profile][update_profile] + +| name | description | +|----------------|--------------------------------------| +| `accountID` | The account ID of the user updating. | +| `userCoins` | The user coins count. | +| `demons` | The demons beaten count. | +| `stars` | The stars count. | +| `coins` | The secret coins count. | +| `iconType` | The icon type. | +| `icon` | ID of the icon. | +| `diamonds` | The diamonds count. | +| `accIcon` | ID of the cube selected. | +| `accShip` | ID of the ship selected. | +| `accBall` | ID of the ball selected. | +| `accBird` | ID of the UFO selected. | +| `accDart` | ID of the wave selected. | +| `accRobot` | ID of the robot selected. | +| `glow` | Whether to enable glow. | +| `accSpider` | ID of the spider selected. | +| `accExplosion` | ID of the explosion selected. | + +## [Level Leaderboard][get_level_leaderboard] + +| name | description | +|---------------|---------------------------------------------------------------------------| +| `accountID` | The account ID of the user requesting. | +| `levelID` | ID of the level to find leaderboard for. | +| `percent` | The record percentage on the level. | +| `jumps` | The total count of jumps on the level. | +| `attempts` | The total count of attempts spent. | +| `seed` | See [generating leaderboard seed][leaderboard_seed] for more information. | +| `differences` | Personal best differences, e.g `0 -> 13 -> 100 => 13,87`. | +| `unknown` | Unknown functionality. Set to `1`. | +| `coins` | The coins count on the level. | +| `timelyID` | The timely ID of the level (`0` if not timely). | +| `seed` | [Random String][random_string]. | + +## Salts + +| salt | usage | +|----------------|-------------------| +| `xI25fpAapCQg` | Level | +| `xPT6iUrtws0J` | Comment | +| `ysg6pUrtjn0J` | Like or Rate | +| `xI35fsAapCRg` | User | +| `yPg6pUrtWn0J` | Level Leaderboard | + +[sha1]: https://en.wikipedia.org/wiki/SHA-1 + +[base64]: /encoding/base64 +[xor_cipher]: /encoding/xor#xor-cipher +[xor]: /encoding/xor +[xor_keys]: /encoding/xor#xor-keys +[random_string]: /encoding/ids.md#random-string +[udid]: /encoding/ids#udid +[uuid]: /encoding/ids#uuid +[upload_seed]: /encoding/seeds#upload-seed +[leaderboard_seed]: /encoding/seeds#leaderboard-seed + +[upload_level]: /server/endpoints/levels/upload_level +[get_level]: /server/endpoints/levels/get_level +[post_comment]: /server/endpoints/comments/post_comment +[get_quests]: /server/endpoints/quests/get_quests +[get_chests]: /server/endpoints/chests/get_chests +[like_item]: /server/endpoints/likes/like_item +[update_profile]: /server/endpoints/users/update_profile +[get_level_leaderboard]: /server/endpoints/levels/get_level_leaderboard diff --git a/docs/encoding/ids.md b/docs/encoding/ids.md new file mode 100644 index 000000000..366f4ce71 --- /dev/null +++ b/docs/encoding/ids.md @@ -0,0 +1,64 @@ +# Random String, UUID and UDID + +These are the parameters that can be frequently noticed when sending a request. + +## Random String + +Random Seed, or Random String, is essentially just a string containing *n* (often *10*) +random alphanumeric characters. It is mainly sent as `rs` in requests. + +Generating it is quite simple: + +```python +from random import choices +from string import ascii_letters, digits + +CHARSET = ascii_letters + digits + +EMPTY = str() +LENGTH = 10 + +concat = EMPTY.join + + +def generate_random_string(length: int = LENGTH, charset: str = CHARSET) -> str: + return concat(choices(charset, k=length)) +``` + +## UUID + +[UUID][UUID] stands for Universally Unique Identifier. It is sent as `uuid` in requests. + +It can be randomly generated using `uuid` module: + +```py +from uuid import uuid4 + +def generate_uuid() -> str: + return str(uuid4()) +``` + +## UDID + +[UDID][UDID] is an abbreviation for Unique Device Identifier that is sent as `udid` in requests. +It does not really have a defined format, but frequently has structure like `S` followed by digits, +or it can be the same as user ID. + +Generating UDID means merely generating a random integer: + +```python +from random import randrange as random_range + +PREFIX = "S" +DEFAULT_START = 100_000 +DEFAULT_STOP = 100_000_000 + + +def generate_udid( + prefix: str = PREFIX, start: int = DEFAULT_START, stop: int = DEFAULT_STOP +) -> str: + return prefix + str(random_range(start, stop)) +``` + +[UUID]: https://en.wikipedia.org/wiki/Universally_unique_identifier +[UDID]: https://en.wikipedia.org/wiki/UDID diff --git a/docs/encoding/robtop.md b/docs/encoding/robtop.md new file mode 100644 index 000000000..06eaa8a9a --- /dev/null +++ b/docs/encoding/robtop.md @@ -0,0 +1 @@ +# RobTop Encoding diff --git a/docs/encoding/seeds.md b/docs/encoding/seeds.md new file mode 100644 index 000000000..9fd8bf213 --- /dev/null +++ b/docs/encoding/seeds.md @@ -0,0 +1,41 @@ +# Seeds + +## Upload Seed + +```python +from typing import AnyStr as AnyString + +COUNT = 50 + + +def generate_upload_seed(data: AnyString, count: int = COUNT) -> AnyString: + length = len(data) + + if length < count: + return data # not enough data + + step = length // count + + return data[::step][:count] +``` + +## Leaderboard Seed + +```python +HAS_PLAYED_MULTIPLY = 1482 +JUMPS_ADD = 3991 +PERCENTAGE_ADD = 8354 +SECONDS_ADD = 4085 + +SUBTRACT = JUMPS_ADD * PERCENTAGE_ADD + SECONDS_ADD * SECONDS_ADD + + +def generate_leaderboard_seed( + jumps: int, percentage: int, seconds: int, has_played: bool = True +) -> int: + return ( + HAS_PLAYED_MULTIPLY * (has_played + 1) + + (jumps + JUMPS_ADD) * (percentage + PERCENTAGE_ADD) + + pow((seconds + SECONDS_ADD), 2) - SUBTRACT + ) +``` diff --git a/docs/encoding/xor.md b/docs/encoding/xor.md new file mode 100644 index 000000000..1ac6136f3 --- /dev/null +++ b/docs/encoding/xor.md @@ -0,0 +1,81 @@ +# XOR + +[XOR][XOR] is a *bit-wise* binary operation that is commonly written as `^` in programming languages. + +Each character in a string is essentially represented as bytes, to which *XOR* is applied. + +## XOR Cipher + +*XOR Cipher* elaborates on the idea of applying *XOR* to each to byte, +one in the data and one in the key. + +Here are our *XOR Cipher* empty functions: + +```python +def cyclic_xor(data: bytes, key: bytes) -> bytes: + ... + + +def cyclic_xor_string(string: str, key: str, encoding: str = ..., errors: str = ...) -> str: + ... +``` + +*XOR Cipher* pairs each byte in the string with a byte in the key (which is cycled), +then applies *XOR* operation for each pair. + +Returning back to our functions: + +```python +from itertools import cycle + +DEFAULT_ENCODING = "utf-8" +DEFAULT_ERRORS = "strict" + + +def cyclic_xor(data: bytes, key: bytes) -> bytes: + return bytes(byte ^ key_byte for byte, key_byte in zip(data, cycle(key))) + + +def cyclic_xor_string( + string: str, key: str, encoding: str = DEFAULT_ENCODING, errors: str = DEFAULT_ERRORS +) -> str: + result = cyclic_xor(string.encode(encoding, errors), key.encode(encoding, errors)) + + return result.decode(encoding, errors) +``` + +XOR Cipher can also use one byte as the key: + +```python +def xor(data: bytes, key: int) -> bytes: + return bytes(byte ^ key for byte in data) + + +def xor_string( + string: str, key: str, encoding: str = DEFAULT_ENCODING, errors: str = DEFAULT_ERRORS +) -> str: + result = xor(string.encode(encoding, errors), key.encode(encoding, errors)) + + return result.decode(encoding, errors) +``` + +## XOR Keys + +Here is a list of XOR keys currently used in GD: + +| Key | Usage | +|---------|-------------------| +| `14251` | Messages | +| `26364` | Level Password | +| `37526` | User Password | +| `39673` | Level Leaderboard | +| `41274` | Level Seed | +| `29481` | Comment Check | +| `19847` | Challenges | +| `59182` | Rewards | +| `58281` | Like and Rate | +| `85271` | User Profile | +| `19283` | Vault Codes | +| `48291` | Load Data | + +[XOR]: https://en.wikipedia.org/wiki/Bitwise_operation#XOR diff --git a/docs/encoding/zip.md b/docs/encoding/zip.md new file mode 100644 index 000000000..6491272bd --- /dev/null +++ b/docs/encoding/zip.md @@ -0,0 +1 @@ +# ZIP diff --git a/docs/endpoints/accounts/register.md b/docs/endpoints/accounts/register.md deleted file mode 100644 index c44f8c084..000000000 --- a/docs/endpoints/accounts/register.md +++ /dev/null @@ -1,3 +0,0 @@ -# accounts/register.php - -Account registration via a webpage diff --git a/docs/endpoints/testSong.md b/docs/endpoints/testSong.md deleted file mode 100644 index 48d6acf37..000000000 --- a/docs/endpoints/testSong.md +++ /dev/null @@ -1,45 +0,0 @@ -# testSong.php - -Gets whitelist/artist info about a song. **THIS IS A GET REQUEST.** - -## Parameters - -### Required Parameters - -**songID** - The ID of the song on newgrounds - -## Response - -A human-readable response stating who the artist is, whether they're whitelisted and scouted, the song name, and whether they allow external API use - -## Example - - - -### **Python** - -```py -import requests - -songID = 787311 - -req = requests.post(f'http://boomlings.com/database/testSong.php?songID={songID}') -print(req.text) -``` - -**Response** -```html -Artist: DePianoman
Artist is NOT Whitelisted.
Artist is Scouted.

Song: Newbie - Space
External API allowed. -``` - -**Human-Readable Response** -``` -Artist: DePianoman -Artist is NOT Whitelisted. -Artist is Scouted. - -Song: Newbie - Space -External API allowed. -``` - - \ No newline at end of file diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index 6df068a0c..000000000 --- a/docs/index.html +++ /dev/null @@ -1,84 +0,0 @@ - - - - - - Geometry Dash Documentation - - - - - - - - - - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 000000000..e5cc8ca77 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,68 @@ +# Introduction + +Welcome to the Geometry Dash Programming [Discord][Discord] server's online iteration +of documentation for *Geometry Dash*. Here you can find all sorts of information, +documents, and resources for interacting with the game and its servers. We aim to make +[`gd.docs`][gd.docs] the most comprehensive open source of information for the game, +created by many people who have interacted with the game and wish to share knowledge with others. + +The provided documentation is available in the [repository][GitHub]. +For all issues regarding information found here, please consult us by creating an issue. + +## Projects + +### Geometry Dash Wrappers + +A few people and teams have gone out of their way to create proper wrappers and APIs around +the *Geometry Dash* servers and its client. All of the known and endorsed projects will find +their way here, as a listing of resources people can use for their own projects. + +#### Python + +- [gd.py][gd.py] by [nekit][nekit] + +#### JS + +- [gd.js][gd.js] by [101arrowz][101arrowz] + +#### Java + +- [jdash][jdash] by [Alex1304][Alex1304] + +### Geometry Dash Projects + +These are projects that generally interface over the *Geometry Dash* servers and client, +and overall have built up their own recognition and traction along the community and developers alike. + +#### Node + +- [GDBrowser][GDBrowser] by [Colon][Colon] + +#### C++ + +- [GDCrypto][GDCrypto] by [cos8o][cos8o] + +## Outside Remarks + +With this documentation, the Geometry Dash Programming staff team would love to see your +interesting ideas with this project, and kinds of things you create with the information provided. +Make sure to hit us up on our discord, and show us of such! + +[gd.docs]: https://docs.gd-programming.org/ + +[Discord]: https://gd-programming.org/discord +[GitHub]: https://github.com/gd-programming/gd.docs + +[gd.py]: https://github.com/nekitdev/gd.py +[gd.js]: https://github.com/101arrowz/gd.js +[jdash]: https://github.com/Alex1304/jdash + +[GDBrowser]: https://github.com/GDColon/GDBrowser +[GDCrypto]: https://github.com/cos8oih/GDCrypto + +[nekit]: https://github.com/nekitdev +[101arrowz]: https://github.com/101arrowz +[Alex1304]: https://github.com/Alex1304 + +[Colon]: https://github.com/GDColon +[cos8o]: https://github.com/cos8oih diff --git a/docs/playground.md b/docs/playground.md deleted file mode 100644 index d0ca052d4..000000000 --- a/docs/playground.md +++ /dev/null @@ -1,63 +0,0 @@ -# Miko's Playground - -You're able to use this publicly, just like a sandbox. Please make sure ***not*** to commit this ***EVER***. - - - -### **python** - -import this - -```py -import base64 - -def decode_level_password(password: str) -> str: - # decode the password from base64 - decoded_base64 = base64.b64decode(password.encode()).decode() - # put it through the xor cipher with the key "26364") - decoded = xor_cipher(decoded_base64, "26364") - - return decoded -``` - -### **java** - -fuck it - - - -\* = do you like disclaimers, i don't - -
- - background -
-
-
-
- -
-
-
- GDDocs -
-
-
-
- Team GDProgramming -
-
-
-
-
-
-
-
-
-
HTML
-
-
-
-
\ No newline at end of file diff --git a/docs/reference.md b/docs/reference.md deleted file mode 100644 index fb26ff068..000000000 --- a/docs/reference.md +++ /dev/null @@ -1,58 +0,0 @@ -# Geometry Dash References - -### Audio Track - -Part of levels and requests for them is a term known as `audio track`, or the id of the track of a song in the game. - -| ID | Server ID | Track Name | Track Author | -|------|-----------|--------------------------|--------------| -| - | -1 | Practice: Stay Inside Me | OcularNebula | -| 1 | 0 | Stereo Madness | Foreverbound | -| 2 | 1 | Back on Track | DJVI | -| 3 | 2 | Polargeist | Step | -| 4 | 3 | Dry Out | DJVI | -| 5 | 4 | Base after Base | DJVI | -| 6 | 5 | Cant Let Go | DJVI | -| 7 | 6 | Jumper | Waterflame | -| 8 | 7 | Time Machine | Waterflame | -| 9 | 8 | Cycles | DJVI | -| 10 | 9 | xStep | DJVI | -| 11 | 10 | Clutterfunk | Waterflame | -| 12 | 11 | Theory of Everything | DJ-Nate | -| 13 | 12 | Electroman Adventures | Waterflame | -| 14 | 13 | Clubstep | DJ-Nate | -| 15 | 14 | Electrodynamix | DJ-Nate | -| 16 | 15 | Hexagon Force | Waterflame | -| 17 | 16 | Blast Processing | Waterflame | -| 18 | 17 | Theory of Everything 2 | DJ-Nate | -| 19 | 18 | Geometrical Dominator | Waterflame | -| 20 | 19 | Deadlocked | F-777 | -| 21 | 20 | Fingerdash | MDK | -| 1001 | 21 | The Seven Seas | F-777 | -| 1002 | 22 | Viking Arena | F-777 | -| 1003 | 23 | Airborne Robots | F-777 | -| 3001 | 24 | The Challenge | RobTop | -| 2001 | 25 | Payload | Dex Arson | -| 2002 | 26 | Beast Mode | Dex Arson | -| 2003 | 27 | Machina | Dex Arson | -| 2004 | 28 | Years | Dex Arson | -| 2005 | 29 | Frontlines | Dex Arson | -| 2006 | 30 | Space Pirates | Waterflame | -| 2007 | 31 | Striker | Waterflame | -| 2008 | 32 | Embers | Dex Arson | -| 2009 | 33 | Round 1 | Dex Arson | -| 2010 | 34 | Monster Dance Off | F-777 | -| 4001 | 35 | Press Start | MDK | -| 4002 | 36 | Nock Em | Bossfight | -| 4003 | 37 | Power Trip | Boom Kitty | - -### Secrets - -To interact with the Geometry Dash API you need a 11 character long string called `secret`. As of 2.1 there are `4` secrets that are currently known of. - -| Secret | type | Usage | -|:-------|:-----|:------| -| `Wmfd2893gb7` | **Common Secret** | Used in the majority of requests | -| `Wmfv3899gc9` | **Account Secret** | Used for all account related requests | -| `Wmfv2898gc9` | **Level Secret** | Used in level deletion | -| `Wmfp3879gc3` | **Mod Secret** | Used in moderator only requests | diff --git a/docs/endpoints/acceptGJFriendRequest20.md b/docs/server/endpoints/accept_friend_request.md similarity index 100% rename from docs/endpoints/acceptGJFriendRequest20.md rename to docs/server/endpoints/accept_friend_request.md diff --git a/docs/endpoints/accounts/loginGJAccount.md b/docs/server/endpoints/accounts/login.md similarity index 100% rename from docs/endpoints/accounts/loginGJAccount.md rename to docs/server/endpoints/accounts/login.md diff --git a/docs/endpoints/accounts/registerGJAccount.md b/docs/server/endpoints/accounts/register.md similarity index 98% rename from docs/endpoints/accounts/registerGJAccount.md rename to docs/server/endpoints/accounts/register.md index 0d46d5510..f0feb846d 100644 --- a/docs/endpoints/accounts/registerGJAccount.md +++ b/docs/server/endpoints/accounts/register.md @@ -22,7 +22,7 @@ Registers an account -### **Python** +### Python ```py import requests diff --git a/docs/server/endpoints/accounts/register_web.md b/docs/server/endpoints/accounts/register_web.md new file mode 100644 index 000000000..cee3c1c05 --- /dev/null +++ b/docs/server/endpoints/accounts/register_web.md @@ -0,0 +1,9 @@ +# Register (Web) + +*Account registration online (on the website).* + +## Endpoint + +| method | endpoint | +|--------|----------------| +| `GET` | `register.php` | diff --git a/docs/endpoints/blockGJUser20.md b/docs/server/endpoints/block_user.md similarity index 100% rename from docs/endpoints/blockGJUser20.md rename to docs/server/endpoints/block_user.md diff --git a/docs/server/endpoints/comments/delete_level_comment.md b/docs/server/endpoints/comments/delete_level_comment.md new file mode 100644 index 000000000..a2a9b9814 --- /dev/null +++ b/docs/server/endpoints/comments/delete_level_comment.md @@ -0,0 +1,58 @@ +# Delete Level Comment + +*Deletes a level comment.* + +## Endpoint + +| method | endpoint | +|--------|-------------------------| +| `POST` | `deleteGJComment20.php` | + +## Parameters + +| name | description | +|------------------|----------------------------------------------------------------------------| +| `accountID` | The account ID of the user who is deleting the comment. | +| `gjp` | The [encoded password][passwords] of the user who is deleting the comment. | +| `commentID` | ID of the comment. | +| `levelID` | ID of the level the comment is on. | +| `secret` | The [common secret][secrets]. | +| `gameVersion`? | The current [game version][versions]. | +| `binaryVersion`? | The current [binary version][versions]. | +| `gdw`? | Whether the level comment is in *Geometry Dash World*. | + +## Response + +Returns `1` if deleted, `-1` if failed. + +## Example + +### Code + +```python +import requests + +# with this code, DevExit is deleting the comment on a level + +data = { + "accountID": 173831, # DevExit's account ID + "gjp": "********", # this would be DevExit's encoded password + "commentID": 31415926, # comment ID + "levelID": 54953085, # ID of the level the comment is on + "secret": "Wmfd2893gb7", # common secret +} + +response = requests.post("http://boomlings.com/database/deleteGJComment20.php", data=data) + +print(response.text) +``` + +### Output + +```console +1 +``` + +[passwords]: /server/topics/passwords +[secrets]: /server/topics/secrets +[versions]: /server/topics/versions diff --git a/docs/server/endpoints/comments/delete_user_comment.md b/docs/server/endpoints/comments/delete_user_comment.md new file mode 100644 index 000000000..7792c099c --- /dev/null +++ b/docs/server/endpoints/comments/delete_user_comment.md @@ -0,0 +1,56 @@ +# Delete User Comment + +*Deletes a user comment.* + +## Endpoint + +| method | endpoint | +|--------|----------------------------| +| `POST` | `deleteGJAccComment20.php` | + +## Parameters + +| name | description | +|------------------|---------------------------------------------------------------------| +| `accountID` | The account ID of the user deleting the comment. | +| `gjp` | The [encoded password][passwords] of the user deleting the comment. | +| `commentID` | The ID of the comment being deleted. | +| `secret` | The [common secret][secrets]. | +| `gameVersion`? | The current [game version][versions]. | +| `binaryVersion`? | The current [binary version][versions]. | +| `gdw`? | Whether the comment is in *Geometry Dash World*. | + +## Response + +`1` if the comment was deleted, `-1` if there was an error. + +## Example + +### Code + +```py +import requests + +# with this code, DevExit is deleting one of her comments + +data = { + "accountID": 173831, # DevExit's account ID + "gjp": "********", # this would be DevExit's encoded password + "commentID": 1772717, # comment ID + "secret": "Wmfd2893gb7", # common secret +} + +response = requests.post('http://boomlings.com/database/deleteGJAccComment20.php', data=data) + +print(response.text) +``` + +### Output + +```console +1 +``` + +[passwords]: /server/topics/passwords +[secrets]: /server/topics/secrets +[versions]: /server/topics/versions diff --git a/docs/endpoints/deleteGJAccComment20.md b/docs/server/endpoints/delete_account_comment.md similarity index 100% rename from docs/endpoints/deleteGJAccComment20.md rename to docs/server/endpoints/delete_account_comment.md diff --git a/docs/endpoints/deleteGJFriendRequests20.md b/docs/server/endpoints/delete_friend_request.md similarity index 100% rename from docs/endpoints/deleteGJFriendRequests20.md rename to docs/server/endpoints/delete_friend_request.md diff --git a/docs/endpoints/deleteGJLevelUser20.md b/docs/server/endpoints/delete_level.md similarity index 100% rename from docs/endpoints/deleteGJLevelUser20.md rename to docs/server/endpoints/delete_level.md diff --git a/docs/endpoints/deleteGJComment20.md b/docs/server/endpoints/delete_level_comment.md similarity index 100% rename from docs/endpoints/deleteGJComment20.md rename to docs/server/endpoints/delete_level_comment.md diff --git a/docs/endpoints/deleteGJMessages20.md b/docs/server/endpoints/delete_message.md similarity index 100% rename from docs/endpoints/deleteGJMessages20.md rename to docs/server/endpoints/delete_message.md diff --git a/docs/endpoints/downloadGJLevel22.md b/docs/server/endpoints/download_level.md similarity index 100% rename from docs/endpoints/downloadGJLevel22.md rename to docs/server/endpoints/download_level.md diff --git a/docs/endpoints/downloadGJMessage20.md b/docs/server/endpoints/download_message.md similarity index 100% rename from docs/endpoints/downloadGJMessage20.md rename to docs/server/endpoints/download_message.md diff --git a/docs/server/endpoints/friend_requests/accept_friend_request.md b/docs/server/endpoints/friend_requests/accept_friend_request.md new file mode 100644 index 000000000..ebe413465 --- /dev/null +++ b/docs/server/endpoints/friend_requests/accept_friend_request.md @@ -0,0 +1,58 @@ +# Accept Friend Request + +*Accepts an incoming friend request.* + +## Endpoint + +| method | endpoint | +|--------|-------------------------------| +| `POST` | `acceptGJFriendRequest20.php` | + +## Parameters + +| name | description | +|-------------------|----------------------------------------------------------------------| +| `accountID` | Account ID of the user to accept the friend request from. | +| `gjp` | The [encoded password][passwords] of the user accepting the request. | +| `targetAccountID` | Account ID of the user who sent the friend request. | +| `requestID` | ID of the friend request to accept. | +| `secret` | The [common secret][secrets]. | +| `gameVersion`? | The current [game version][versions]. | +| `binaryVersion`? | The current [binary version][versions]. | +| `gdw`? | Whether the level is in *Geometry Dash World*. | + +## Response + +Always returns `1`, regardless of whether the friend request exists or not. + +## Example + +### Code + +```python +import requests + +# with this code, DevExit is accepting a friend request from PasswordFinders + +data = { + "accountID": 173831, # DevExit's account ID + "gjp": "********", # This would be DevExit's encoded password + "targetAccountID": 5317656, # PasswordFinders' account ID + "requestID": 43248797, # request ID + "secret": "Wmfd2893gb7", # common secret +} + +response = requests.post("http://boomlings.com/database/acceptGJFriendRequest20.php", data=data) + +print(response.text) +``` + +### Output + +```console +1 +``` + +[passwords]: /server/topics/passwords +[secrets]: /server/topics/secrets +[versions]: /server/topics/versions diff --git a/docs/server/endpoints/friend_requests/delete_friend_request.md b/docs/server/endpoints/friend_requests/delete_friend_request.md new file mode 100644 index 000000000..f16857ff1 --- /dev/null +++ b/docs/server/endpoints/friend_requests/delete_friend_request.md @@ -0,0 +1,58 @@ +# Delete Friend Request + +*Deletes a friend request.* + +## Endpoint + +| method | endpoint | +|--------|--------------------------------| +| `POST` | `deleteGJFriendRequests20.php` | + +## Parameters + +| name | description +|-------------------|-----------------------------------------------------------------------------------| +| `accountID` | The account ID of the user who is deleting the friend request. | +| `gjp` | The [encoded password][passwords] of the user who is deleting the friend request. | +| `targetAccountID` | The account ID of the person whose friend request is being deleted. | +| `isSender` | `1` if the user who deleted the friend request is the sender, otherwise `0`. | +| `secret` | The [common secret][secrets]. | +| `gameVersion`? | The current [game version][versions]. | +| `binaryVersion`? | The current [binary version][versions]. | +| `gdw`? | Whether the friend request is in *Geometry Dash World*. | + +## Response + +Always returns `1`, regardless of whether the request exists or not. + +## Example + +### Code + +```python +import requests + +# With this code, DevExit is deleting a friend request to the person with ID 314159 + +data = { + "accountID": 173831, # DevExit's account ID + "gjp": "********", # this would be DevExit's encoded password + "targetAccountID": 314159, # person's account ID + "isSender": 1, # DevExit sent the friend request, so this is 1 + "secret": "Wmfd2893gb7", # common secret +} + +response = requests.post("http://boomlings.com/database/deleteGJFriendRequests20.php", data=data) + +print(response.text) +``` + +### Output + +```console +1 +``` + +[passwords]: /server/topics/passwords +[secrets]: /server/topics/secrets +[versions]: /server/topics/versions diff --git a/docs/endpoints/getGJAccountComments20.md b/docs/server/endpoints/get_account_comments.md similarity index 100% rename from docs/endpoints/getGJAccountComments20.md rename to docs/server/endpoints/get_account_comments.md diff --git a/docs/endpoints/getAccountURL.md b/docs/server/endpoints/get_account_url.md similarity index 100% rename from docs/endpoints/getAccountURL.md rename to docs/server/endpoints/get_account_url.md diff --git a/docs/endpoints/getGJRewards.md b/docs/server/endpoints/get_chests.md similarity index 100% rename from docs/endpoints/getGJRewards.md rename to docs/server/endpoints/get_chests.md diff --git a/docs/endpoints/getGJCommentHistory.md b/docs/server/endpoints/get_comment_history.md similarity index 100% rename from docs/endpoints/getGJCommentHistory.md rename to docs/server/endpoints/get_comment_history.md diff --git a/docs/endpoints/getGJFriendRequests20.md b/docs/server/endpoints/get_friend_requests.md similarity index 100% rename from docs/endpoints/getGJFriendRequests20.md rename to docs/server/endpoints/get_friend_requests.md diff --git a/docs/endpoints/getGJGauntlets21.md b/docs/server/endpoints/get_gauntlets.md similarity index 100% rename from docs/endpoints/getGJGauntlets21.md rename to docs/server/endpoints/get_gauntlets.md diff --git a/docs/endpoints/getGJScores20.md b/docs/server/endpoints/get_leaderboard.md similarity index 100% rename from docs/endpoints/getGJScores20.md rename to docs/server/endpoints/get_leaderboard.md diff --git a/docs/endpoints/getGJComments21.md b/docs/server/endpoints/get_level_comments.md similarity index 100% rename from docs/endpoints/getGJComments21.md rename to docs/server/endpoints/get_level_comments.md diff --git a/docs/endpoints/getGJLevelScores211.md b/docs/server/endpoints/get_level_leaderboard.md similarity index 100% rename from docs/endpoints/getGJLevelScores211.md rename to docs/server/endpoints/get_level_leaderboard.md diff --git a/docs/endpoints/getGJLevels21.md b/docs/server/endpoints/get_levels.md similarity index 100% rename from docs/endpoints/getGJLevels21.md rename to docs/server/endpoints/get_levels.md diff --git a/docs/endpoints/getGJMapPacks21.md b/docs/server/endpoints/get_map_packs.md similarity index 100% rename from docs/endpoints/getGJMapPacks21.md rename to docs/server/endpoints/get_map_packs.md diff --git a/docs/endpoints/getGJMessages20.md b/docs/server/endpoints/get_messages.md similarity index 100% rename from docs/endpoints/getGJMessages20.md rename to docs/server/endpoints/get_messages.md diff --git a/docs/endpoints/getGJChallenges.md b/docs/server/endpoints/get_quests.md similarity index 100% rename from docs/endpoints/getGJChallenges.md rename to docs/server/endpoints/get_quests.md diff --git a/docs/endpoints/getGJSongInfo.md b/docs/server/endpoints/get_song.md similarity index 100% rename from docs/endpoints/getGJSongInfo.md rename to docs/server/endpoints/get_song.md diff --git a/docs/endpoints/getGJDailyLevel.md b/docs/server/endpoints/get_timely.md similarity index 100% rename from docs/endpoints/getGJDailyLevel.md rename to docs/server/endpoints/get_timely.md diff --git a/docs/endpoints/getTop1000.md b/docs/server/endpoints/get_top_1000.md similarity index 100% rename from docs/endpoints/getTop1000.md rename to docs/server/endpoints/get_top_1000.md diff --git a/docs/endpoints/getGJTopArtists.md b/docs/server/endpoints/get_top_artists.md similarity index 100% rename from docs/endpoints/getGJTopArtists.md rename to docs/server/endpoints/get_top_artists.md diff --git a/docs/endpoints/getGJUserInfo20.md b/docs/server/endpoints/get_user.md similarity index 100% rename from docs/endpoints/getGJUserInfo20.md rename to docs/server/endpoints/get_user.md diff --git a/docs/endpoints/getGJUserList20.md b/docs/server/endpoints/get_user_list.md similarity index 100% rename from docs/endpoints/getGJUserList20.md rename to docs/server/endpoints/get_user_list.md diff --git a/docs/server/endpoints/levels/delete_level.md b/docs/server/endpoints/levels/delete_level.md new file mode 100644 index 000000000..e9c06a76e --- /dev/null +++ b/docs/server/endpoints/levels/delete_level.md @@ -0,0 +1,56 @@ +# Delete Level + +*Deletes a level.* + +## Endpoint + +| method | endpoint | +|--------|---------------------------| +| `POST` | `deleteGJLevelUser20.php` | + +## Parameters + +| name | description | +|------------------|----------------------------------------------------| +| `accountID` | The level creator's account ID. | +| `gjp` | The level creator's [encoded password][passwords]. | +| `levelID` | The ID of the level being deleted. | +| `secret` | The [common secret][secrets]. | +| `gameVersion`? | The current [game version][versions]. | +| `binaryVersion`? | The current [binary version][versions]. | +| `gdw`? | Whether the level is in *Geometry Dash World*. | + +## Response + +Returns `1` if deleted or `-1` if failed or the level does not exist. + +## Example + +### Code + +```python +import requests + +# with this code, DevExit is deleting one of her levels + +data = { + "accountID": 173831, # DevExit's account ID + "gjp": "********", # this would be DevExit's encoded password + "levelID": 62689548, # level ID + "secret": "Wmfv2898gc9", # common secret +} + +response = requests.post("http://boomlings.com/database/deleteGJLevelUser20.php", data=data) + +print(response.text) +``` + +### Output + +```console +1 +``` + +[passwords]: /server/topics/passwords +[secrets]: /server/topics/secrets +[versions]: /server/topics/versions diff --git a/docs/server/endpoints/levels/get_level.md b/docs/server/endpoints/levels/get_level.md new file mode 100644 index 000000000..a07453dd8 --- /dev/null +++ b/docs/server/endpoints/levels/get_level.md @@ -0,0 +1,62 @@ +# Get Level + +*Fetches a level and its related information.* + +## Parameters + +| name | description | +|------------------|---------------------------------------------------------------------------------------| +| `levelID` | The ID of the level to download. See [special level IDs][special_level_ids] for more. | +| `secret` | The [common secret][secrets]. | +| `gameVersion`? | The current [game version][versions]. | +| `binaryVersion`? | The current [binary version][versions]. | +| `gdw`? | Whether the level is in *Geometry Dash World*. | +| `accountID`? | The account ID of the user downloading the level. | +| `gjp`? | The [encoded password][passwords] of the user downloading the level. | +| `udid`? | The [UDID][udid] of the user who is downloading the level. | +| `uuid`? | The [UUID][uuid] of the downloading the level. | +| `inc`? | Whether to count the download towards total downloads. Usually set to `1`. | +| `extras`? | Currently not used. Set to `0`. | +| `rs`? | Random string. See [here][random_string]. | +| `chk`? | Check. See [here][download_level]. | + +## Response + +Returns a [level][levels]. + +## Example + +### Code + +```python +import requests + +# with this code we are getting the level Test by DevExit + +data = { + "levelID": 62687277, # level ID + "secret": "Wmfd2893gb7", # common secret +} + +response = requests.post("http://boomlings.com/database/downloadGJLevel22.php", data=data) + +print(response.text) +``` + +### Output + +```console +1:62687277:2:Test:3:QSB0ZXN0IGxldmVsIGZvciB0aGUgR0QgRG9jcyE=:4:H4sIAAAAAAAAC6WQwQ3DIAxFF3IlfxsIUU6ZIQP8AbJChy_GPSZqpF7-A4yfDOfhXcCiNMIqnVYrgYQl8rDwBTZCVbkQRI3oVHbiDU6F2jMF_lesl4q4kw2PJMbovxLBQxTpM3-I6q0oHmXjzx7N0240cu5w0UBNtESRkble8uSLHjh8nTubmYJZ2MvMrEITEN0gEJMxlLiMZ28frmj:5:1:6:3935672:8:0:9:0:10:1:12:0:13:21:14:0:17::43:0:25::18:0:19:0:42:0:45:1:15:0:30:55610687:31:0:28:1 hour:29:1 hour:35:546561:36::37:0:38:0:39:50:46::47::40::27:AQcHBwEL#1bae6491cc87c72326abcbc0a7afaee139aa7088#f17c5a61f4ba1c7512081132459ddfaaa7c6f716 +``` + +[special_level_ids]: /server/topics/special_level_ids +[secrets]: /server/topics/secrets +[versions]: /server/topics/versions +[passwords]: /server/topics/passwords + +[levels]: /server/models/levels + +[udid]: /encoding/ids#udid +[uuid]: /encoding/ids#uuid +[random_string]: /encoding/ids#random-string +[download_level]: /encoding/checks#get-level diff --git a/docs/endpoints/likeGJItem211.md b/docs/server/endpoints/like_item.md similarity index 100% rename from docs/endpoints/likeGJItem211.md rename to docs/server/endpoints/like_item.md diff --git a/docs/endpoints/getSaveData.md b/docs/server/endpoints/load.md similarity index 100% rename from docs/endpoints/getSaveData.md rename to docs/server/endpoints/load.md diff --git a/docs/server/endpoints/messages/delete_message.md b/docs/server/endpoints/messages/delete_message.md new file mode 100644 index 000000000..c1958ed5e --- /dev/null +++ b/docs/server/endpoints/messages/delete_message.md @@ -0,0 +1,57 @@ +# Delete Message + +*Deletes a message between two users.* + +## Endpoint + +| method | endpoint | +|--------|--------------------------| +| `POST` | `deleteGJMessages20.php` | + +## Parameters + +| name | description | +|------------------|---------------------------------------------------------------------| +| `accountID` | The account ID of the user who is deleting the message. | +| `gjp` | The [encoded password][passwords] of the user deleting the message. | +| `messageID` | The ID of the message being deleted. | +| `secret` | The [common secret][secrets]. | +| `isSender`? | Whether the user is the sender. | +| `gameVersion`? | The current [game version][versions]. | +| `binaryVersion`? | The current [binary version][versions]. | +| `gdw`? | Whether the message is in *Geometry Dash World*. | + +## Response + +Always returns `1`, regardless of whether the message was deleted or not. + +## Example + +### Code + +```python +import requests + +# with this code, DevExit is deleting one of her recievied messages + +data = { + "accountID": 173831, # DevExit's account ID + "gjp": "********", # this would be DevExit's encoded password + "messageID": 3141592, # message ID + "secret": "Wmfd2893gb7", # common secret +} + +response = requests.post("http://boomlings.com/database/deleteGJMessages20.php", data=data) + +print(response.text) +``` + +### Output + +```console +1 +``` + +[passwords]: /server/topics/passwords +[secrets]: /server/topics/secrets +[versions]: /server/topics/versions diff --git a/docs/server/endpoints/messages/get_message.md b/docs/server/endpoints/messages/get_message.md new file mode 100644 index 000000000..404d4fadb --- /dev/null +++ b/docs/server/endpoints/messages/get_message.md @@ -0,0 +1,58 @@ +# Get Message + +*Fetches a message, effectively reading it.* + +## Endpoint + +| method | endpoint | +|--------|---------------------------| +| `POST` | `downloadGJMessage20.php` | + +## Parameters + +| name | description | +|------------------|--------------------------------------------------| +| `accountID` | The user's account ID. | +| `gjp` | The user's [encoded password][passwords]. | +| `message` | The ID of the message to read. | +| `secret` | The [common secret][secrets]. | +| `gameVersion`? | The current [game version][versions]. | +| `binaryVersion`? | The current [binary version][versions]. | +| `gdw`? | Whether the message is in *Geometry Dash World*. | + +## Response + +Returns a [message][messages]. + +## Example + +### Code + +```python +import requests + +# with this code we are downloading the message with a given ID + +data = { + "accountID": 173831, # DevExit's account ID + "gjp": "********", # this would be DevExit's encoded password + "messageID": 54109536, # message ID + "secret": "Wmfd2893gb7", # common secret +} + +response = requests.post("http://boomlings.com/database/downloadGJMessage20.php", data=data) + +print(response.text) +``` + +### Output + +```console +6:DevExit:3:3935672:2:173831:1:54109536:4:WW91J3JlIGR1bWIgbG9s:8:1:9:0:5:TWhtIHllcCB5b3UncmUgcCBkdW1iIGxtYW8=:7:19 minutes +``` + +[secrets]: /server/topics/secrets +[versions]: /server/topics/versions +[passwords]: /server/topics/passwords + +[messages]: /server/models/messages diff --git a/docs/endpoints/uploadGJAccComment20.md b/docs/server/endpoints/post_comment.md similarity index 100% rename from docs/endpoints/uploadGJAccComment20.md rename to docs/server/endpoints/post_comment.md diff --git a/docs/endpoints/rateGJDemon21.md b/docs/server/endpoints/rate_demon.md similarity index 100% rename from docs/endpoints/rateGJDemon21.md rename to docs/server/endpoints/rate_demon.md diff --git a/docs/endpoints/rateGJStars211.md b/docs/server/endpoints/rate_level.md similarity index 100% rename from docs/endpoints/rateGJStars211.md rename to docs/server/endpoints/rate_level.md diff --git a/docs/endpoints/suggestGJStars.md b/docs/server/endpoints/rate_stars.md similarity index 100% rename from docs/endpoints/suggestGJStars.md rename to docs/server/endpoints/rate_stars.md diff --git a/docs/endpoints/readGJFriendRequest20.md b/docs/server/endpoints/read_friend_request.md similarity index 100% rename from docs/endpoints/readGJFriendRequest20.md rename to docs/server/endpoints/read_friend_request.md diff --git a/docs/endpoints/removeGJFriend20.md b/docs/server/endpoints/remove_friend.md similarity index 100% rename from docs/endpoints/removeGJFriend20.md rename to docs/server/endpoints/remove_friend.md diff --git a/docs/endpoints/reportGJLevel.md b/docs/server/endpoints/report_level.md similarity index 100% rename from docs/endpoints/reportGJLevel.md rename to docs/server/endpoints/report_level.md diff --git a/docs/endpoints/request.md b/docs/server/endpoints/request.md similarity index 99% rename from docs/endpoints/request.md rename to docs/server/endpoints/request.md index 317cc963a..95548956c 100644 --- a/docs/endpoints/request.md +++ b/docs/server/endpoints/request.md @@ -132,7 +132,7 @@ public class Main { ``` -### **NodeJS** +### **Node JS** ```js const http = require("http"); diff --git a/docs/endpoints/requestUserAccess.md b/docs/server/endpoints/request_access.md similarity index 100% rename from docs/endpoints/requestUserAccess.md rename to docs/server/endpoints/request_access.md diff --git a/docs/endpoints/restoreGJItems.md b/docs/server/endpoints/restore_items.md similarity index 100% rename from docs/endpoints/restoreGJItems.md rename to docs/server/endpoints/restore_items.md diff --git a/docs/endpoints/getGJUsers20.md b/docs/server/endpoints/search_users.md similarity index 100% rename from docs/endpoints/getGJUsers20.md rename to docs/server/endpoints/search_users.md diff --git a/docs/endpoints/uploadFriendRequest20.md b/docs/server/endpoints/send_friend_request.md similarity index 100% rename from docs/endpoints/uploadFriendRequest20.md rename to docs/server/endpoints/send_friend_request.md diff --git a/docs/endpoints/uploadGJComment21.md b/docs/server/endpoints/send_level_comment.md similarity index 100% rename from docs/endpoints/uploadGJComment21.md rename to docs/server/endpoints/send_level_comment.md diff --git a/docs/endpoints/uploadGJMessage20.md b/docs/server/endpoints/send_message.md similarity index 100% rename from docs/endpoints/uploadGJMessage20.md rename to docs/server/endpoints/send_message.md diff --git a/docs/endpoints/unblockGJUser20.md b/docs/server/endpoints/unblock_user.md similarity index 100% rename from docs/endpoints/unblockGJUser20.md rename to docs/server/endpoints/unblock_user.md diff --git a/docs/endpoints/updateGJDesc20.md b/docs/server/endpoints/update_level_description.md similarity index 100% rename from docs/endpoints/updateGJDesc20.md rename to docs/server/endpoints/update_level_description.md diff --git a/docs/endpoints/updateGJUserScore22.md b/docs/server/endpoints/update_profile.md similarity index 100% rename from docs/endpoints/updateGJUserScore22.md rename to docs/server/endpoints/update_profile.md diff --git a/docs/endpoints/updateGJAccSettings20.md b/docs/server/endpoints/update_settings.md similarity index 100% rename from docs/endpoints/updateGJAccSettings20.md rename to docs/server/endpoints/update_settings.md diff --git a/docs/endpoints/uploadGJLevel21.md b/docs/server/endpoints/upload_level.md similarity index 100% rename from docs/endpoints/uploadGJLevel21.md rename to docs/server/endpoints/upload_level.md diff --git a/docs/server/endpoints/users/block_user.md b/docs/server/endpoints/users/block_user.md new file mode 100644 index 000000000..5772911d6 --- /dev/null +++ b/docs/server/endpoints/users/block_user.md @@ -0,0 +1,56 @@ +# Block User + +*Blocks a given user.* + +## Endpoint + +| method | endpoint | +|--------|---------------------| +| `POST` | `blockGJUser20.php` | + +## Parameters + +| name | description | +|-------------------|------------------------------------------------------| +| `accountID` | The blocking person's account ID. | +| `gjp` | The blocking person's [encoded password][passwords]. | +| `targetAccountID` | The account ID of the person being blocked. | +| `secret` | The [common secret][secrets]. | +| `gameVersion`? | The current [game version][versions]. | +| `binaryVersion`? | The current [binary version][versions]. | +| `gdw`? | Whether the users are in *Geometry Dash World*. | + +## Response + +Always returns `1`, regardless of whether the target account exists or not. + +## Example + +### Code + +```python +import requests + +# with this code, DevExit is blocking RobTop + +data = { + "accountID": 173831, # DevExit's account ID + "gjp": "********", # this would be DevExit's encoded password + "targetAccountID": 71, # RobTop's account ID + "secret": "Wmfd2893gb7", # common secret +} + +response = requests.post("http://boomlings.com/database/blockGJUser20.php", data=data) + +print(response.text) +``` + +### Output + +```console +1 +``` + +[passwords]: /server/topics/passwords +[secrets]: /server/topics/secrets +[versions]: /server/topics/versions diff --git a/docs/server/models/comments.md b/docs/server/models/comments.md new file mode 100644 index 000000000..05d7801e3 --- /dev/null +++ b/docs/server/models/comments.md @@ -0,0 +1,92 @@ +# Server Comment Resource + +## Comment + +A Comment is a message that the player can create inside of Geometry Dash. There are **Two** types of comments: `Level Comments` and `Account Comments` + +> - `Level Comments` can be found after pressing the `i` button which is located on the right side of the level menu which then opens the Comment Menu - you can also view comments by clicking on the comment icon on the player Profile. To Post a comment, the player has to click on the speech bubble icon and they can type their comment. Without any external tools, a comment can be up to **100** Characters in length

+> - `Account Comments` can be found on a user's profile. `Account Comments` are exactly the same as `Level Comments` however the following keys will not affect it: `10, 11, 12`
To Upload an Account Comment the player must click the speech bubble icon on their profile and they can type their comment. Without any external tools, a comment can be up to **140** Characters in length + +### Comment Object + +A comment object is split into two sections: a `Comment String` and an `Author String`. these two strings are divided by a `:` + +> - The `Comment String` contains all the data regarding the comment itself

+> - The `User String` contains all the data regarding the user who is commenting + +The `Comment String` and `User String` are both structured with a `key~value~key~value` pairing. Here is some examples of raw responses from the server + + + + +#### **Level Comment Example** +```md +2~R0QgRG9jcyBhcmUgZXBpYw==~3~84696119~4~0~7~0~10~0~9~2 seconds~6~12872819:1~TheWylieMaster~9~1~10~4~11~16~14~3~15~2~16~9276649 +``` + +#### **Account Comment Example** +```md +2~R0QgRG9jcyBhcmUgZXBpYw==~4~11~9~3 months~6~18083050 +``` + + + +Each `key` is tied to a component within the client and the `value` sets data for the specific component. +A list of all known keys can be found in the table below + +### Comment Structure + +**Note:** Keys marked with an asterisk `*` do not affect `Account Comments` + +| Key | Name/Value | Type | Description +|-----|---------------------------|----------------------------------------------|-------------------------------------------------------------------------- +| 1 | levelID | **Integer** | The levelID linked to the comment +| 2 | comment | **String** | The comment left by the user, encoded in [base64](/topics/encryption/base64.md) +| 3 | authorPlayerID | **Integer** | The player ID of the comment author | +| 4 | likes | **Integer** | The amount of likes the comment has +| 5 | dislikes | **Integer** | The amount of dislikes the comment has -> unused +| 6 | messageID | **Integer** | The message ID. Account comments have different IDs than level comments +| 7 | spam | **Bool** | If a comment has been flagged as spam +| 8 | authorAccountID | **Integer** | The accountID of the comment author | +| 9 | age | **String** | How long ago the comment was posted (e.g. "2 months") +| 10 | percent* | **Integer** | The percent the player put in their comment +| 11 | modBadge* | **Integer** | The Mod Badge of a moderator commenting +| 12 | moderatorChatColor* | **String** | Comma separated list of the RGB values of the moderator's chat color - only appears if the players `modBadge > 0` + +### User Structure + +**Note:** These values are only returned through `Level Comments` + +| Key | Name/Value | Type | Description +|-----|---------------------------|----------------------------------------------|-------------------------------------------------------------------------- +| 1 | userName | **String** | Author's username +| 9 | icon | **Integer** | Which icon the player is using, starting with 1 as the first icon +| 10 | playerColor | **Integer** | Author's primary player color, presumably ordered cronologically from left to right per update +| 11 | playerColor2 | **Integer** | Author's secondary player color, presumably ordered cronologically from left to right per update +| 14 | iconType | **Integer** | Author's icon type indexing an array of `icon, ship, ball, ufo, wave, robot, spider` +| 15 | glow | **Integer** | 0 = no glow, 2 = glow +| 16 | accountID | **Integer** | Author's account ID. **This is different than the player ID** + +### Comment Bans + +If a user violates [the commenting rules](https://imgur.com/a/US0Biaj), they can be banned from posting comments. +> As of Geometry Dash version 2.11, there are 2 different types of bans
+> - Permanent Bans - Only way to recieve one is by RobTop directly. The server response to trigger this is `-10` +> - Temporary Bans - Elder Moderators and RobTop are able to enforce these onto people. The server response to trigger temporary bans is split into 3 components `temp_{length}_{reason}` + +#### Temporary Ban Structure + +| Component | Description | +|:----------|:------------| +| `temp` | is used for the game to identify if the user is banned | +| `length` | The duration of the ban in seconds | +| `reason` | The reason the user was banned | + +### Trivia + +- The `User String` uses the same response parser that [player profiles](/resources/server/user) use + +- The only example of `Account Comments` where it was able to display a colour is with [RobTop's](https://gdbrowser.com/u/71) profile, this is because RobTop hardcoded the account colour into the accountID of `71` + + + diff --git a/docs/server/models/friend_requests.md b/docs/server/models/friend_requests.md new file mode 100644 index 000000000..c915465b6 --- /dev/null +++ b/docs/server/models/friend_requests.md @@ -0,0 +1,41 @@ +# Server Friend Request Resource + +## Friend Request + +One of the features in Geometry Dash is the friend system which allows players to add each other as a friend. It is part of a poorly developed social System in which players can send messages to each other. + +The server response returns a [User String](/resources/server/user) in a response which is structured with a `key:value:key:value` pairing. Each friend request string is then split with a `|` + + + +#### **Friend Request Example** +```md +1:TheWylieMaster:2:84696119:9:9:10:5:11:3:14:1:15:0:16:9276649:32:45272143:35:aGVsbG8=:41:1:37:1 week +``` + + +Each `key` is tied to a component within the client and the `value` sets data for the specific component. +A list of all known keys can be found in the table below + +#### Friend Request Structure + +**Note:** We will use "other user" to describe the user on the other side of the friend request, be it the receiving end or the sending end. + +| Key | Name/Value | Type | Description +|-----|---------------------------|----------------------------------------------|-------------------------------------------------------------------------- +| 1 | userName | **String** | The username of the other user +| 2 | playerID | **Integer** | The player ID of the other user. **This is different than the account ID** +| 9 | icon | **Integer** | Which icon the other user is using, starting with 1 as the first icon +| 10 | playerColor | **Integer** | The other user's primary player color, presumably ordered cronologically from left to right per update +| 11 | playerColor2 | **Integer** | The other user's secondary player color, presumably ordered cronologically from left to right per update +| 14 | iconType | **Integer** | The other user's icon type indexing an array of `icon, ship, ball, ufo, wave, robot, spider` +| 15 | glow | **Integer** | Either 0 or 2, might be related to glow +| 16 | accountID | **Integer** | The other user's account ID. **This is different than the player ID** +| 32 | friendRequestID | **Integer** | An ID unique to each friend request. (I'm not 100% certain on this) +| 35 | message | **String** | The friend requests's message, encoded in [base64](/topics/encryption/base64.md) +| 37 | age | **String** | How long ago the friend request was sent (e.g. "2 months") +| 41 | NewFriendRequest | **Bool** | if the friend request is new + +### Trivia + +- By sending yourself a friend request through 3rd party tools, you can actually block yourself. Doing so doesn't have any serious consequences as you can see in this [video by Cvolton](https://www.youtube.com/watch?v=R18tKYFrIqE) diff --git a/docs/server/models/gauntlets.md b/docs/server/models/gauntlets.md new file mode 100644 index 000000000..3b4292a4c --- /dev/null +++ b/docs/server/models/gauntlets.md @@ -0,0 +1,86 @@ +# Server Gauntlet Resource + +## Gauntlet Info + +Gauntlets are a collection of themed levels created by the users of Geometry Dash which were hand-picked by RobTop. + + - As of Geometry Dash 2.11, There are `15 gauntlets` + + - According to the [December 2019 2.2 leaks](https://www.reddit.com/r/geometrydash/comments/e9b0y6/update_22_leaks_megathread/), 2.2 will include `44 Gauntlets` + - **A list of the Gauntlet Names can be found [here](/resources/server/gauntlet?id=gauntlet-names)**
*Keep in mind that these are subject to change* + +A typical gauntlet server response is structured with a `key:value:key:value` pairing and is then split with a `|` + + +#### **Gauntlet Example Response** +```md +1:1:3:27732941,28200611,27483789,28225110,27448202|1:2:3:20635816,28151870,25969464,24302376,27399722 +``` + + +Each `key` is tied to a component within the client and the `value` sets data for the specific component. +A list of all known keys can be found in the table below + +### Gauntlet Structure + +| Key | Name/Value | Type | Description | +| --- | ---------- | ---------- | ------------------------------------- | +| 1 | gauntletID | **Integer**| the Gauntlet ID, starting at 1 | +| 3 | levels | **String** | List of gauntlet level IDs seperated by `,`| + +### Gauntlet names + +Here is a table which shows which `gauntletID` corresponds to a specific gauntlet + + + +| ID ⠀| Name | +|:---|:-----| + | 1| Fire| + | 2| Ice| + | 3| Poison| + | 4| Shadow| + | 5| Lava| + | 6| Bonus| + | 7| Chaos| + | 8| Demon| + | 9| Time| + | 10| Crystal| + | 11| Magic| + | 12| spike| + | 13| Monster| + | 14| Doom| + | 15| Death| + | 16| Forest| + | 17| Rune| + | 18| Force| + | 19| Spooky| + | 20| Dragon| + | 21| Water| + | 22| Haunted| + | 23| Acid| + | 24| Witch| + | 25| Power| + | 26| Potion| + | 27| Snake| + | 28| Toxic| + | 29| Halloween| + | 30| Treasure| + | 31| Ghost| + | 32| Gem| + | 33| Inferno| + | 34| Portal| + | 35| Strange| + | 36| Fantasy| + | 37| Christmas| + | 38| Surprise| + | 39| Mystery| + | 40| Cursed| + | 41| Cyborg| + | 42| Castle| + | 43| Grave| + | 44| Temple| + +### Trivia + +- Gauntlets use the same response parser as [MapPacks](/resources/server/mappack) but they do not share the full range of features mappacks have \ No newline at end of file diff --git a/docs/server/models/leaderboards.md b/docs/server/models/leaderboards.md new file mode 100644 index 000000000..4f7dc05cb --- /dev/null +++ b/docs/server/models/leaderboards.md @@ -0,0 +1,57 @@ +# Server Leaderboard Score Resource + +## Leaderboard Score + +Leaderboards are the in-game ranking system for Geometry Dash. There are `7` types of leaderboards that are used as of version `2.11` +> - `Star Top 100` - The top 100 best star grinders +> - `Star Friends` - The relative leaderboards between the user and his friends +> - `Relative Star` - The players position on the global leaderboards along with 100 other players that have a rank relative to the player +> - `Creator Top 100` - The top 100 creator point grinders +> - `Global Level Scores` - The fastest victors to a specific level since the level was uploaded to the servers +> - `Global Weekly Level Scores` - The fastest victors to a specific level since the last `604800` seconds +> - `Friend Level Scores` - The fastest victors to a specific level between the user and his friends since the level was uploaded to the servers + +A typical leaderboard server response is structured with a `key:value:key:value` pairing and is then split with a `|` + + + + +### **Level Leaderboard Example** + +```md +1:TheWylieMaster:2:84696119:9:1:10:4:11:16:14:3:15:2:16:9276649:3:34:6:1:13:0:42:1 second +``` + +### **Top Leaderboard Example** + +```md +1:xMiguel007:2:2866103:13:149:17:7219:6:1:9:37:10:35:11:3:14:0:15:2:16:70846:3:65710:8:0:46:12879:4:1073 +``` + + + +Each `key` is tied to a component within the client and the `value` sets data for the specific component. +A list of all known keys can be found in the table below + +### Leaderboard Score Structure + +**Note:** keys marked by a `*` are only used for level leaderboards + +| Key | Name/Value | Type | Description +|-----|---------------------------|----------------------------------------------|-------------------------------------------------------------------------- +| 1 | userName | **String** | The username of the user +| 2 | playerID | **Integer** | The player ID of the user. **This is different than the account ID** +| 3 | percentage* | **Integer** | Percentage the user has on the level +| 6 | ranking | **Integer** | What rank they are (e.g. Viprin would have 1 in the creating leaderboard) +| 9 | Icon | **Integer** | Which icon the user is using, starting with 1 as the first icon +| 10 | playerColor | **Integer** | The user's primary player color, presumably ordered cronologically from left to right per update +| 11 | playerColor2 | **Integer** | The user's secondary player color, presumably ordered cronologically from left to right per update +| 13 | coins | **Integer** | Secret coins/number of usercoins you get on a level* +| 14 | iconType | **Integer** | The user's icon type indexing an array of `icon, ship, ball, ufo, wave, robot, spider` +| 15 | special | **Integer** | functions the same as glow however it returns a 2 rather than a 1 +| 16 | accountID | **Integer** | The user's account ID. **This is different than the player ID** +| 42 | age | **String** | How long ago the score was set (e.g. "2 months") + +### Trivia + +- The key structure that leaderboards follow are exactly the same as the structure used for [Player Profiles](/resources/server/user.md) \ No newline at end of file diff --git a/docs/server/models/levels.md b/docs/server/models/levels.md new file mode 100644 index 000000000..78448fd49 --- /dev/null +++ b/docs/server/models/levels.md @@ -0,0 +1,77 @@ +# Server Level Resource + +## Level + +A level is a playable object in Geometry Dash, namely coming with data that explains on what it is, and the string that the client interprets, known as a [level string](/topics/levelstring_encoding_decoding). + + +A typical level server response is structured with a `key:value:key:value` pairing and is then split with a `|` + +*keep in mind that the value for key `4` will be replaced with `{levelString}` as it is too big to show* + + +#### **Level Example Response** +```md +1:6508283:2:ReTraY:3:VGhhbmtzIGZvciBwbGF5aW5nIEdlb21ldHJ5IERhc2g=:4:{levelString}:5:3:6:4993756:8:10:9:10:10:39431612:12:0:13:21:14:4125578:17::43:3:25::18:2:19:7730:42:0:45:20000:15:3:30:0:31:0:28:5 years:29:1 year:35:557117:36:0_733_0_0_0_0_574_716_0_0_352_78_729_0_42_0_833_68_0_347_0_38_240_205_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0_0:37:3:38:1:39:2:46:7729:47:13773:40:0:27:AwMABAYDBw==#eb541c03f8355c0709f8007a1d9a595ae5bedc5d#291568b26b08d70a198fca10a87c736a2823be0c +``` + + +Each `key` is tied to a component within the client and the `value` sets data for the specific component. +A list of all known keys can be found in the table below + +### Level Object + +Keys indicated with an asterisk (\*) are only returned from the downloadGJLevel22 endpoint. + +#### Level Structure + +| Key | Name/Value | Type | Description +|-----|---------------------------|----------------------------------------------|-------------------------------------------------------------------------- +| 1 | levelID | **Integer** | The id of the level +| 2 | levelName | **String** | The name of the level +| 3 | description | **String** | The level description, encoded in [base64](/topics/encryption/base64.md) +| 4* | levelString | **[Level String](/topics/levelstring_encoding_decoding)**| All the data for the level +| 5 | version | **Integer** | The version of the level published +| 6 | playerID | **Integer** | The player ID of the level author +| 8 | difficultyDenominator | **Integer** | Returns 0 if the level is N/A, returns 10 if a difficulty is assigned. Historically used to be the amount of people who have voted on the difficulty. +| 9 | difficultyNumerator | **Integer** | The nominator used for calculating the level difficulty. Divided by the denominator to get the difficulty icon. Nowadays just 0 = unrated, 10 = easy, 20 = normal, 30 = hard, 40 = harder, 50 = insane. Can be also used to determine the demon difficulty as a side-effect of the voting system. Historically used to be the sum of stars from all votes | +| 10 | downloads | **Integer** | The amount of times the level has been downloaded +| 11 | setCompletes | **Integer** | The Number of people who have completed a specific level removed in update 2.1 +| 12 | officialSong | **Integer** | The official song number used by the level, if applicable +| 13 | gameVersion | **Integer** | The GD version the level was uploaded in. Versions 1.0 to 1.6 use version numbers 1 to 7 respectively. Version 10 is 1.7. Otherwise, divide the version number by ten to get the correct number. +| 14 | likes | **Integer** | likes - dislikes | +| 15 | length | **Integer** | A number from 0-4, where 0 is tiny and 4 is XL | +| 16 | dislikes | **Integer** | dislikes - likes | +| 17 | demon | **Bool** | If the level's difficulty is demon +| 18 | stars | **Integer** | The amount of stars rewarded for completing the level +| 19 | featureScore | **Integer** | 0 if the level is not featured, otherwise a positive number. The higher it is, the higher the level appears on the featured levels list. +| 25 | auto | **Bool** | If the level's difficulty is auto +| 26 | recordString | **String** | appears in the [GJGameLevel parser](https://imgur.com/a/S2bWLCC) but is unused +| 27* | password | **Encrypted String** | The password required to copy the level. It is XOR encrypted with a key of 26364 +| 28* | uploadDate | **String** | The approximate date the level was uploaded on +| 29* | updateDate | **String** | The approximate date the level was last updated on +| 30 | copiedID | **Integer** | The ID the of the original level (if the level was copied) +| 31 | twoPlayer | **Bool** | Whether the level uses two player mode +| 35 | customSongID | **Integer** | The ID of the custom Newgrounds song used in the level +| 36 | extraString | **String** | The extraString passed when uploading the level. Its use is currently unknown +| 37 | coins | **Integer** | The number of user coins placed in the level +| 38 | verifiedCoins | **Bool** | If the level's user coins are verified (silver) +| 39 | starsRequested | **Integer** | The star value requested for the level +| 40* | lowDetailMode | **Bool** | If the level has a low detail checkbox +| 41* | dailyNumber | **Integer** | Daily/weekly levels only. Returns which daily/weekly the level was (e.g. the 500th daily level). Subtract 100,000 if the level is weekly +| 42 | epic | **Integer** | If the level has an epic rating +| 43 | demon Difficulty | **Integer** | The difficulty of the demon rating. 3 = easy, 4 = medium, 0 = hard, 5 = insane, 6 = extreme. Can also be used to determine the level difficulty non-demons had before rating as a side-effect of the voting system. +| 44 | isGauntlet | **Bool** | if the level is in a gauntlet | +| 45 | objects | **Integer** | The amount of objects in the level, used to determine if the level is considered "large". It caps at 65535 +| 46 | editorTime | **Integer** | the total number of seconds spend on the current copy of a level +| 47 | editorTime(Copies) | **Integer** | The accumulative total of seconds spend on previous copies of the level +| 48 | settingsString [Unused] | **String** | It was found in early 2.1 coming from the servers and was removed shortly after. The `December 2019 2.2 Leaks` however have information regarding it showing that it is called `settingsString` but, there is no information regarding its usage | + +### Trivia + +- The getGJLevels endpoint returns the keys `46` and `47` however they aren't actually correct + +- key `45` caps at the 16-bit integer limit so any level with more objects won't be accurate + +- Surprisingly, key `42` is classified as an `Integer` rather than a `Bool` + diff --git a/docs/server/models/map_packs.md b/docs/server/models/map_packs.md new file mode 100644 index 000000000..925ad75e2 --- /dev/null +++ b/docs/server/models/map_packs.md @@ -0,0 +1,55 @@ +# Server Map Pack Resource + +#### Map Pack + +A map pack is a series of 3 levels handpicked by Robtop. They preceded Gauntlets and can be seen as the predecessor to them. Upon completion, Map Packs can reward up to `10` stars and `2` secret coins. + +A typical map pack server response is structured with a `key:value:key:value` pairing and is then split with a `|` + + + +### **Map Pack Example** +```md +1:59:2:Cyclone Pack:3:1566116,946020,1100161:4:8:5:1:6:5:7:255,75,255:8:255,75,255|1:60:2:Colossus Pack:3:1350389,1215630,1724579:4:8:5:1:6:5:7:100,255,175:8:100,255,175|1:61:2:Diamond Pack:3:1267316,1670283,1205277:4:8:5:1:6:5:7:255,255,255:8:255,255,255|1:11:2:Chaos Pack:3:329929,188909,340602:4:9:5:1:6:5:7:255,125,0:8:255,125,0|1:44:2:Magma Pack:3:882417,884256,551979:4:9:5:1:6:5:7:255,100,50:8:255,100,50|1:62:2:Paradox Pack:3:1447246,1132530,1683722:4:9:5:1:6:5:7:50,255,75:8:50,255,75|1:63:2:Funky Pack:3:1728550,1799065,1311773:4:9:5:1:6:5:7:50,175,255:8:50,175,255|1:19:2:Remix Pack 4:3:341613,358750,369294:4:10:5:2:6:6:7:255,255,0:8:255,255,0|1:20:2:Demon Pack 1:3:70059,10109,135561:4:10:5:2:6:6:7:255,0,125:8:255,0,125|1:21:2:Demon Pack 2:3:57730,308891,102765:4:10:5:2:6:6:7:255,0,0:8:255,0,0#65:40:10#79c437d2cf75d2edf36a5094e0cc650c54440ba3 +``` + + +Each `key` is tied to a component within the client and the `value` sets data for the specific component. +A list of all known keys can be found in the table below + +### Map Pack Structure + +| Key | Name/Value | Type | Description | +| --- | ---------- | ---- | ----------- | +| 1 | packID | **Integer** | the ID for the specified Map Pack +| 2 | packName | **String** | Name of the map pack +| 3 | levels | **String** | List of level IDs separated by a `,` +| 4 | stars | **Integer** | How many stars the map pack should give +| 5 | coins | **Integer** | How many coins the map pack should give +| 6 | [difficulty](enumerations.md) | **Integer** | Difficulty ranging from `0->10` +| 7 | textColor | **String** | RGB color for the title text separated by `,` +| 8 | barColor | **String** | RGB color for the completion bar separated by `,` + + +### Trivia + +- Map packs use the same response parser as gauntlets + +- Although Map Packs only show a hard demon in-game, they can actually display each demon difficulty by using a specific value in key `6` + +#### Difficulty possible values + +| Value | Difficulty | +|:------|:-----------| +| 0 | auto | +| 1 | easy | +| 2 | normal | +| 3 | hard | +| 4 | harder | +| 5 | insane | +| 6 | hard demon | +| 7 | easy demon | +| 8 | medium demon | +| 9 | insane demon | +| 10 | extreme demon | + diff --git a/docs/server/models/messages.md b/docs/server/models/messages.md new file mode 100644 index 000000000..520936c94 --- /dev/null +++ b/docs/server/models/messages.md @@ -0,0 +1,43 @@ +# Server Message Resource + +## Message + +Messages are a feature in Geometry dash where you can send messages to other players online if they have their messages open. There are two fields you can control within a message: `Subject` and `Message` + +> `Subject` can be viewed in a list in the messages menu - without any external tools, the `Subject` field only supports 35 characters + +> `Message` can be viewed only if you download the message by clicking on the `view` button in the messages menu - without any external tools, the `Messages` field only supports 200 characters + +A typical message server response is structured with a `key:value:key:value` pairing and is then split with a `|` + + +#### **Message Example Response** +```md +6:DevExit:3:3935672:2:173831:1:54109536:4:WW91J3JlIGR1bWIgbG9s:8:1:9:0:5:TWhtIHllcCB5b3UncmUgcCBkdW1iIGxtYW8=:7:19 minutes +``` + + +Each `key` is tied to a component within the client and the `value` sets data for the specific component. +A list of all known keys can be found in the table below + +### Message Structure + +**Note:** We will use "other user" to describe the user on the other side of the message, be it the receiving end or the sending end. + +| Key | Name/Value | Type | Description | +| --- | ---------- | ---- | ----------- | +| 1 | messageID | **Integer** | The message ID +| 2 | accountID | **Integer** | The other user's account ID +| 3 | playerID | **Integer** | The other user's player ID +| 4 | title | **String** | The title encoded in [Base64](/topics/encryption/base64.md) +| 5 | messageContent | **String** | The message which has been [Xor'd](/topics/encryption/xor.md) with a key of `14251` and then encoded in [base64](/topics/encryption/base64.md) +| 6 | userName | **String** | The other user's username +| 7 | age | **String** | How long ago the message was sent (e.g. "2 months") +| 8 | read | **Bool** | 0 if the message hasn't been read, 1 if it has +| 9 | sender | **Bool** | 0 if the user is receiving the message, 1 if they sent it + +### Trivia + +- The current message system has a bug in which replying to a message will fail. This is because the client does not have any checks to see if the other user has their messages open when replying so if you send a reply to a user who has their messages closed, the request will return the error code `-1` resulting in it failing + +- Due to an oversight, you are able to block yourself if you send yourself a message. [Cvolton](https://github.com/Cvolton) explains this oversight in one of his [videos](https://www.youtube.com/watch?v=R18tKYFrIqE) \ No newline at end of file diff --git a/docs/server/models/restore.md b/docs/server/models/restore.md new file mode 100644 index 000000000..24088bf5b --- /dev/null +++ b/docs/server/models/restore.md @@ -0,0 +1,32 @@ +# Server Restore Resource + +## RestoreGJItems + +`Restore` was a feature used in Geometry dash from versions `1.7 - 2.0` and it was used as an alternative to the [Account System](/topics/accounts.md) that is currently used as of 2.11 + +A typical Gauntlet Server response is structured with a `key:value:key:value` pairing +*Official Levels behave a bit differently as you will find out further into his page* + +> - Due to lack of resources about RestoreGJItems, most information has been lost to time.
The only remaining archived response that we know about can be found [here](https://imgur.com/a/pPUu933) + +### Restore Items Structure + +| Key | Name/Value | Type |Description | +| --- | -------------- | ---------- | -------------------------------------| +| 1 | officalLevels | **String** | Please refer to [Official Level Structure](/resources/server/restore?id=official-level-structure) | +| 2 | stars | **Integer** | This is how many stars that should be given to your account | +| 3 | demons | **Integer** | This is how many demons that should be added to your account | +| 4 | jumps | **Integer** | This is how many jumps you have made on your account of its lifetime| +| 5 | attempts | **Integer** | This is how many attempts you have spent on levels on your accounts lifetime | +| 6 | onlineLevels | **String** | These are the ID's of online levels you have beaten. seperated by `,` | + +#### Official Level Structure + +There are three sections in regards to the `Official Level State` from the restore endpoint. The data is sent as `{NormalCompleted},{PracticeComepleted},{SecretCoins}` + +> - `{NormalCompleted}` is a `Bool` which denotes if you have completed the level in normal Mode

+> - `{PracticeComepleted}` is a `Bool` which denotes if you have completed the level in practice Mode

+> - `{SecretCoins}` is an `Integer` which includes the ammount of Secret Coins you collected during the completion of the official level + +**

This structure is then iterated for each official level in the update and is split with a `;`** + diff --git a/docs/server/models/songs.md b/docs/server/models/songs.md new file mode 100644 index 000000000..d8ffc899b --- /dev/null +++ b/docs/server/models/songs.md @@ -0,0 +1,41 @@ +# Server Song Resource + +## Song + +Songs in Geometry Dash are supplied through a partnership with a website called [Newgrounds](https://www.newgrounds.com/audio). To be used in community made levels, a song must pass **3** requirements + +> - The Song must be scouted by another artist from newgrounds +> - The Song must be whitelisted either by Robtop or an [Elder Moderator](/topics/moderators.md) +> - The artist must enable external API use in their song settings + +The songs can be downloaded and used via a private API that only RobTop has access to + + +A typical song server response is structured with a `key~|~value~|~key~|~value` pairing and is then split with a `:` + + + +#### **Song Example** +```md +1~|~803223~|~2~|~Xtrullor - Arcana~|~3~|~2159~|~4~|~Xtrullor~|~5~|~8.81~|~6~|~~|~10~|~https%3A%2F%2Faudio.ngfiles.com%2F803000%2F803223_Xtrullor---Arcana.mp3%3Ff1524940372~|~7~|~UCejLri1RVC7kj8ZVNX2a53g +``` + + +Each `key` is tied to a component within the client and the `value` sets data for the specific component. +A list of all known keys can be found in the table below + +#### Song Structure + +| Key | Name/Value | Type | Description +|-----|---------------------------|----------------------------------------------|-------------------------------------------------------------------------- +| 1 | ID | **Integer** | The ID of the song on Newgrounds +| 2 | name | **String** | The name of the song +| 3 | artistID | **Integer** | Newgrounds ArtistID +| 4 | artistName | **String** | The name of the artist who made the song +| 5 | size | **Integer** | Size of the song in MB, rounded to two decimal places +| 6 | videoID | **String** | the Video ID for the songs YouTube Video +| 7 | youtubeURL | **String** | The URL of the newgrounds user's youtube channel +| 8 | isVerified | **Bool** | if the song artist is scouted on newgrounds +| 9 | songPriority | **Integer** | priority over the song list +| 10 | link | **String** | Link to the song's mp3 + diff --git a/docs/server/models/users.md b/docs/server/models/users.md new file mode 100644 index 000000000..9fc247bf8 --- /dev/null +++ b/docs/server/models/users.md @@ -0,0 +1,69 @@ +# Server User Resource + +## Users + +Each player of Geometry Dash has their own profile which includes various different elements such as in-game stats, icons and even socials. + +A typical user server response is structured with a `key:value:key:value` pairing and is then split with a `|` + + + +#### **User Example Response** +```md +1:TheWylieMaster:2:84696119:13:67:17:176:10:4:11:16:3:1725:46:2991:4:33:8:0:18:0:19:0:50:0:20:../watch?v=dQw4w9WgXcQ:21:31:22:10:23:30:24:1:25:35:26:23:28:1:43:11:48:1:30:0:16:9276649:31:0:44:TheWylieMaster:45::49:0:38:0:39:0:40:0:41:1:29:1 +``` + + +Each `key` is tied to a component within the client and the `value` sets data for the specific component. +A list of all known keys can be found in the table below + +| Key | Name/Value | Type | Description | +| --- | ---------- | ---- | ----------- | +| 1 | userName | **String** | The name of player | +| 2 | userID | **Integer** | The ID of player | +| 3 | stars | **Integer** | The count of stars player have | +| 4 | demons | **Integer** | The count of demons player have | +| 6 | ranking | **Integer** | the global leaderboard position of the player | +| 7 | accountHighlight | **Integer** | The accountID of the player. Is used for highlighting the player on the leaderboards | +| 8 | creatorpoints | **Integer** | The count of creatorpoints player have | +| 9 | iconID | **Integer** | maybe... [link](https://github.com/gd-programming/gddocs/pull/16/files#r417926661) | +| 10 | playerColor | **Integer** | First color of the player use | +| 11 | playerColor2 | **Integer** | Second color of the player use | +| 13 | secretCoins | **Integer** | The count of coins player have | +| 14 | iconType | **Integer** | The iconType of the player use | +| 15 | special | **Integer** | The special number of the player use | +| 16 | accountID | **Integer** | The accountid of this player | +| 17 | usercoins | **Integer** | The count of usercoins player have | +| 18 | messageState | **Integer** | 0: All, 1: Only friends, 2: None | +| 19 | friendsState | **Integer** | 0: All, 1: None | +| 20 | youTube | **String** | The youtubeurl of player | +| 21 | accIcon | **Integer** | The icon number of the player use | +| 22 | accShip | **Integer** | The ship number of the player use | +| 23 | accBall | **Integer** | The ball number of the player use | +| 24 | accBird | **Integer** | The bird number of the player use | +| 25 | accDart(wave) | **Integer** | The dart(wave) number of the player use | +| 26 | accRobot | **Integer** | The robot number of the player use | +| 27 | accStreak | **Integer** | The streak of the user | +| 28 | accGlow | **Integer** | The glow number of the player use | +| 29 | isRegistered | **Integer** | if an account is registered or not | +| 30 | globalRank | **Integer** | The global rank of this player | +| 31 | friendstate | **Integer** | 0: None, 1: already is friend, 3: send request to target, but target haven't accept, 4: target send request, but haven't accept +| 38 | messages | **Integer** | How many new messages the user has (shown in-game as a notification) | +| 39 | friendRequests | **Integer** | How many new friend requests the user has (shown in-game as a notificaiton) | +| 40 | newFriends | **Integer** | How many new Friends the user has (shown in-game as a notificaiton) | +| 41 | NewFriendRequest | **Bool** | appears on userlist endpoint to show if the friend request is new | +| 42 | age | **String** | the time since you submitted a levelScore | +| 43 | accSpider | **Integer** | The spider number of the player use | +| 44 | twitter| **String** | The twitter of player | +| 45 | twitch | **String** | The twitch of player | +| 46 | diamonds | **Integer** | The count of diamonds player have | +| 48 | accExplosion | **Integer** | The explosion number of the player use | +| 49 | modlevel | **Integer** | 0: None, 1: Normal Mod(yellow), 2: Elder Mod(orange) | +| 50 | commentHistoryState | **Integer** | 0: All, 1: Only friends, 2: None | + +### Trivia + +- Setting Key `29` to `0` stops most aspects of your profile from loading + +- Key `27` is impossible to recieve from the server as there is no way for the server to know what the player's `streak` is + diff --git a/docs/server/topics/error_codes.md b/docs/server/topics/error_codes.md new file mode 100644 index 000000000..aefa06ade --- /dev/null +++ b/docs/server/topics/error_codes.md @@ -0,0 +1,68 @@ +# Error Codes + +Geometry Dash servers usually send an error code denoting an error either on the servers' +or the client's side. + +## General Error Codes + +| code | name | +|------|-------------------| +| `-1` | General (Generic) | +| `-2` | No Result / Taken | + +## Specific Error Codes + +### [Register][register] + +| code | name | description | +|-------|--------------------|---------------------------------------------------| +| `-2` | Name Taken | The name is taken. | +| `-3` | Email Used | The email is already used. | +| `-4` | Invalid Name | The name is invalid. | +| `-5` | Invalid Password | The password is invalid. | +| `-6` | Invalid Email | The email is invalid. | +| `-7` | Password Mismatch | The passwords do not match. | +| `-8` | Password Too Short | The password is too short (minimum 6 characters). | +| `-9` | Name Too Short | The name is too short (minimum 3 characters). | +| `-99` | Email Mismatch | The emails do not match. | + +### [Login][login] + +| code | name | description | +|-------|-----------------------------|--------------------------------------------------------| +| `-8` | Password Too Short | The password is less than 6 characters long. | +| `-9` | Name Too Short | The name is less than 3 characters long. | +| `-10` | Linked to Different Account | Already logged into a different account. | +| `-11` | Login Failed | Login credentials are incorrect. | +| `-12` | Account Disabled | The account has been disabled. | +| `-13` | Linked to Different Steam | One account is allowed per one steam account (unused). | + +### [Save][save] + +| code | name | description | +|------|----------------------|-------------------------------------------| +| `-2` | Login Failed | Login credentials are wrong. | +| `-4` | Request Too Large | Request to the server is too large. | +| `-5` | Bad Login Info | Invalid login information was provided. | +| `-6` | Something Went Wrong | Something went wrong on the servers' end. | + +### [Suggest Level][suggest_level] + +| code | name | description | +|------|---------------------|----------------------------------------| +| `-2` | Missing Permissions | Missing permissions to suggest levels. | + +### [Comment Level][comment_level] + +| code | name | description | +|-----------------------------|-----------------------|-----------------------------------------------| +| `-10` | Permanent Comment Ban | Permanently banned from commenting on levels. | +| `temp_{timeout}_{reason}`\* | Temporary Comment Ban | Temporarily banned from commenting on levels. | + +\* `timeout` is the remaining duration of the ban in seconds, `reason` is the reason for getting banned. + +[register]: /server/endpoints/accounts/register +[login]: /server/endpoints/accounts/login +[save]: /server/endpoints/accounts/save +[suggest_level]: /server/endpoints/levels/suggest_level +[comment_level]: /server/endpoints/levels/comment_level diff --git a/docs/server/topics/secrets.md b/docs/server/topics/secrets.md new file mode 100644 index 000000000..94c235db2 --- /dev/null +++ b/docs/server/topics/secrets.md @@ -0,0 +1,8 @@ +# Secrets + +| name | value | description | +|-------------------|---------------|----------------------------------------| +| Common Secret | `Wmfd2893gb7` | Used in the majority of endpoints. | +| Account Secret | `Wmfv3899gc9` | Used in all account-related endpoints. | +| Level Secret | `Wmfv2898gc9` | Used in level deletion endpoint. | +| Moderation Secret | `Wmfp3879gc3` | Used in moderator-only endpoints. | diff --git a/docs/server/topics/songs.md b/docs/server/topics/songs.md new file mode 100644 index 000000000..dce51d6c0 --- /dev/null +++ b/docs/server/topics/songs.md @@ -0,0 +1,45 @@ +# Geometry Dash Songs + +Song IDs are represented in *server-style*; for *client-style*, simply add one to the ID. + +| Level ID | Song ID | Name | Artist | +|----------|---------|----------------------------|----------------| +| `None` | `-1` | `Practice: Stay Inside Me` | `OcularNebula` | +| `1` | `0` | `Stereo Madness` | `Foreverbound` | +| `2` | `1` | `Back on Track` | `DJVI` | +| `3` | `2` | `Polargeist` | `Step` | +| `4` | `3` | `Dry Out` | `DJVI` | +| `5` | `4` | `Base after Base` | `DJVI` | +| `6` | `5` | `Can't Let Go` | `DJVI` | +| `7` | `6` | `Jumper` | `Waterflame` | +| `8` | `7` | `Time Machine` | `Waterflame` | +| `9` | `8` | `Cycles` | `DJVI` | +| `10` | `9` | `xStep` | `DJVI` | +| `11` | `10` | `Clutterfunk` | `Waterflame` | +| `12` | `11` | `Theory of Everything` | `DJ-Nate` | +| `13` | `12` | `Electroman Adventures` | `Waterflame` | +| `14` | `13` | `Clubstep` | `DJ-Nate` | +| `15` | `14` | `Electrodynamix` | `DJ-Nate` | +| `16` | `15` | `Hexagon Force` | `Waterflame` | +| `17` | `16` | `Blast Processing` | `Waterflame` | +| `18` | `17` | `Theory of Everything 2` | `DJ-Nate` | +| `19` | `18` | `Geometrical Dominator` | `Waterflame` | +| `20` | `19` | `Deadlocked` | `F-777` | +| `21` | `20` | `Fingerdash` | `MDK` | +| `1001` | `21` | `The Seven Seas` | `F-777` | +| `1002` | `22` | `Viking Arena` | `F-777` | +| `1003` | `23` | `Airborne Robots` | `F-777` | +| `3001` | `24` | `The Challenge` | `RobTop` | +| `2001` | `25` | `Payload` | `Dex Arson` | +| `2002` | `26` | `Beast Mode` | `Dex Arson` | +| `2003` | `27` | `Machina` | `Dex Arson` | +| `2004` | `28` | `Years` | `Dex Arson` | +| `2005` | `29` | `Frontlines` | `Dex Arson` | +| `2006` | `30` | `Space Pirates` | `Waterflame` | +| `2007` | `31` | `Striker` | `Waterflame` | +| `2008` | `32` | `Embers` | `Dex Arson` | +| `2009` | `33` | `Round 1` | `Dex Arson` | +| `2010` | `34` | `Monster Dance Off` | `F-777` | +| `4001` | `35` | `Press Start` | `MDK` | +| `4002` | `36` | `Nock Em` | `Bossfight` | +| `4003` | `37` | `Power Trip` | `Boom Kitty` | diff --git a/docs/server/topics/versions.md b/docs/server/topics/versions.md new file mode 100644 index 000000000..8b5e46344 --- /dev/null +++ b/docs/server/topics/versions.md @@ -0,0 +1,6 @@ +# Versions + +| name | current | +|----------------|---------| +| Game Version | `21` | +| Binary Version | `35` | diff --git a/docs/topics/encryption/base64.md b/docs/topics/encryption/base64.md deleted file mode 100644 index 7de27ae92..000000000 --- a/docs/topics/encryption/base64.md +++ /dev/null @@ -1,33 +0,0 @@ -# Base64 - -Base64 encoding is widely used amongst different endpoints in Geometry Dash. - -It is used to encode fields like level data, level descriptions, comments, etc. - -GD uses *URL-safe* Base64 encoding, which uses A-Z and a-z letters, along with `_` and `-` as special characters. (Main Base64 uses `+` and `/` special characters) - -Here is an example of using Base64 decoding and encoding: - - - -### **Python** - -```py -import base64 - -# For unknown reasons, people tend to use base64.b64(decode|encode) functions -# and replace "+" with "-" and "/" with "_" manually, -# even though "base64" module implements base64.urlsafe_b64(decode|encode). - -# encode and decode functions return "bytes" type in python so we might want to use -# bytes.decode() to convert them to "str" type. - -def base64_encode(string: str) -> str: - return base64.urlsafe_b64encode(string.encode()).decode() - - -def base64_decode(string: str) -> str: - return base64.urlsafe_b64decode(string.encode()).decode() -``` - - diff --git a/docs/topics/encryption/chk.md b/docs/topics/encryption/chk.md deleted file mode 100644 index d2184bcb2..000000000 --- a/docs/topics/encryption/chk.md +++ /dev/null @@ -1,185 +0,0 @@ -# CHK - -CHK is a common parameter in requests, which is intended to improve security. -CHK is sent in request often as `chk`. - -CHK is generated like so: - -1. Take arbitrary amount of values. -2. Combine them and add *salt* if there is one. -3. Apply [SHA-1](https://en.wikipedia.org/wiki/SHA-1) hashing to combined values and get its hexdigest. -4. Apply [XOR-Cipher](topics/encryption/xor.md) to the hexdigest with desired key. -5. [Base64](topics/encryption/base64.md) encode the result. - -CHK generator can be implemented like this: - - - -### **Python** - -```py -import base64 -import hashlib # sha1() lives there - - -def generate_chk(values: [int, str] = [], key: str = "", salt: str = "") -> str: - values.append(salt) - - string = ("").join(map(str, values)) # assure "str" type and connect values - - hashed = hashlib.sha1(string.encode()).hexdigest() - xored = xor_cipher(hashed, key) # we discuss this one in encryption/xor - final = base64.urlsafe_b64encode(xored.encode()).decode() - - return final -``` - - - -XOR keys can be found [here](topics/encryption/xor.md?id=xor-keys). - -Here is a list of CHK values and explanations on their generation: - -## Download level - -- LevelID -- Inc -- [RS](topics/encryption/id.md?id=rs) -- AccountID -- [UDID](topics/encryption/id.md?id=udid) -- [UUID](topics/encryption/id.md?id=uuid) - -## Upload level - -- seed2 - -seed2 is generated from level data: - - - -### **Pseudocode** - -```plain -seed2 = "" -space = length of levelString / 50 - -for i in range 50: - seed2 += levelString[space * i] - -seed2 += "xI25fpAapCQg" -sha1 encode seed2 -xor encrypt seed2 with key 41274 -``` - -### **Python** - -```py -def generate_upload_seed(data: str, chars: int = 50) -> str: - # GD currently uses 50 characters for level upload seed - if len(data) < chars: - return data # not enough data to generate - step = len(data) // chars - return data[::step][:chars] -``` - - - -## Comment - -- Username -- Comment Content -- LevelID -- Percentage -- Comment Type (0 = Level, 1 = User). - -## Challenges - -- Random Number - -Random number consisting of *5* digits. - -## Rewards - -- Random Number - -Random number consisting of *5* digits. - -## Like - -- Special (0 = Level, LevelID = Level Comment, CommentID = Other Comment) -- ItemID -- Like (0 = dislike, 1 = like) -- Type (1 = Level, 2 = Level Comment, 3 = Other Comment) -- [RS](topics/encryption/id.md?id=rs) -- AccountID -- [UDID](topics/encryption/id.md?id=udid) -- [UUID](topics/encryption/id.md?id=uuid) - -## User Profile - -- AccountID -- UserCoins -- Demons -- Stars -- Coins -- IconType -- Icon -- Diamonds -- CubeID -- ShipID -- BallID -- UFOID -- WaveID -- RobotID -- Glow (0 = disabled, 1 = enabled) -- SpiderID -- ExplosionID - -## Level Leaderboard - -- AccountID -- LevelID -- Percentage -- Jumps -- Attempts -- Seed - -Seed can be generated like this: - - - -### **Python** - -```py -def generate_leaderboard_seed( - jumps: int, percentage: int, seconds: int, has_played: bool = True -) -> int: - - return ( - 1482 * (has_played + 1) - + (jumps + 3991) * (percentage + 8354) - + ((seconds + 4085) ** 2) - 50028039 - ) -``` - - - -- Best Differences - -For example, `0%` - `13%` - `100%` -> `(13 - 0), (100 - 13)` -> `13,87` - -- Unknown (always 1) - -- Coins -- TimelyID -- [RS](topics/encryption/id.md?id=rs) - -## Salts - -| Value | Type | -|--------------|-------------------| -| xI25fpAapCQg | Level | -| xPT6iUrtws0J | Comment | -| ysg6pUrtjn0J | Like or Rate | -| xI35fsAapCRg | User Profile | -| yPg6pUrtWn0J | Level Leaderboard | diff --git a/docs/topics/encryption/id.md b/docs/topics/encryption/id.md deleted file mode 100644 index c8bf5fcd8..000000000 --- a/docs/topics/encryption/id.md +++ /dev/null @@ -1,71 +0,0 @@ -# RS, UUID and UDID - -These are the parameters that can be frequently noticed when sending a request. - -## RS - -RS stands for Random Seed, or Random String, which is essentially just a string containing *n* (often *10*) random alphanumeric characters. -RS is mainly sent as `rs` in requests. - -Generating RS is quite simple: - - - -### **Python** - -```py -import random -from string import ascii_letters, digits # so we don't have to type [A-Za-z0-9] by hand - -# this code works only on python 3.6 and above - -possible_letters = ascii_letters + digits - - -def generate_rs(n: int) -> str: - return ("").join(random.choices(possible_letters, k=n)) -``` - - - -## UUID - -[UUID](https://en.wikipedia.org/wiki/Universally_unique_identifier) stands for Universally Unique IDentifier. -It has format of `aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeee` and is sent as `uuid` in requests. - -It can be randomly generated using our `generate_rs()` function: - - - -### **Python** - -```py -def generate_uuid(parts: [int] = (8, 4, 4, 4, 10)) -> str: - # apply generate_rs to each number in parts, then join results - return ("-").join(map(generate_rs, parts)) -``` - - - -## UDID - -[UDID](https://en.wikipedia.org/wiki/UDID) is an abbreviation for Unique Device IDentifier that is sent as `udid` in requests. -It does not really have a defined format, -but frequently has structure like `Sxxx...` where `x` are digits, -or it is the same as PlayerID of a user. - -Generating UDID should be simpler because we can just generate a random integer: - - - -### **Python** - -```py -import random - - -def generate_udid(start: int = 100_000, end: int = 100_000_000) -> str: - return "S" + str(random.randint(start, end)) -``` - - diff --git a/docs/topics/encryption/xor.md b/docs/topics/encryption/xor.md deleted file mode 100644 index 96d4d141e..000000000 --- a/docs/topics/encryption/xor.md +++ /dev/null @@ -1,104 +0,0 @@ -# XOR - -[XOR](https://en.wikipedia.org/wiki/Bitwise_operation#XOR) is a _bit-wise_ binary operation that is commonly written as `^` in programming languages. - -Each character in a string is essentially represented by a number, -so-called _codepoint_, to which XOR operation can be applied. - - - -### **Python** - -In python, you can use `ord()` function to get the codepoint of a character, -and `chr()` to convert the codepoint to a character. - -```py ->>> ord("N") -78 ->>> chr(78) -"N" -``` - - - -## XOR Cipher - -**XOR-Cipher** elaborates on the idea of applying _XOR_ to each to characters, -one in the string and one in the key. - -Here is our **XOR-Cipher** stub (empty) function: - - - -### **Python** - -```py -def xor_cipher(string: str, key: str) -> str: ... -``` - - - -Suppose we have a string `"GD"` (how original), and key `"42069"` (rather original as well). - -Here is what will happen to our string if we apply **XOR-Cipher**: - - - -### **Python** - -```py ->>> chr(ord("G") ^ ord("4")) + chr(ord("D") ^ ord("2")) -"sv" -``` - - - -**XOR-Cipher** connects each character in given string with character in key (key is cycled), then applies _XOR_ operation on each pair. - -Returning back to the function: - - - -### **Python** - -```py -import itertools - -# we are going to use itertools.cycle() on our key, which will basically -# repeatedly yield "1234512345..." for key "12345" - -def xor_cipher(string: str, key: str) -> str: - result = "" - for string_char, key_char in zip(string, itertools.cycle(key)): - result += chr(ord(string_char) ^ ord(key_char)) - return result -``` - -This function is quite good, but adding new characters to strings in python is quite slow. -Here is a better function that implements **XOR-Cipher** (and hey, it is written in one line!): - -```py -def xor_cipher(string: str, key: str) -> str: - return ("").join(chr(ord(x) ^ ord(y)) for x, y in zip(string, itertools.cycle(key))) -``` - - - -## XOR Keys - -Here is a list of XOR keys currently used in GD: - -| Key | Usage | -| ----- | ----------------- | -| 14251 | Messages | -| 26364 | Level Password | -| 37526 | Account Password | -| 39673 | Level Leaderboard | -| 41274 | Level Seed | -| 29481 | Comment CHK | -| 19847 | Challenges | -| 59182 | Rewards | -| 58281 | Like and Rate | -| 85271 | User Profile | -| 19283 | Vault Codes | -| 48291 | Load data | diff --git a/docs/topics/encryption/zip.md b/docs/topics/encryption/zip.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/docs/topics/level_passwords.md b/docs/topics/level_passwords.md deleted file mode 100644 index 2d06186ed..000000000 --- a/docs/topics/level_passwords.md +++ /dev/null @@ -1,31 +0,0 @@ -# Level Passwords - -Level passwords are byte arrays at a 4 or 6 number length that can be set when a level is published. They are used for setting a way for adding a security to copying levels without making them free, alongside the implemented **Unlisted** property. Over the server, level passwords are encoded in a way that makes it more difficult for people to normally read, to prevent people from directly copying them from the response given from the server. - -The property is also used to determine whether a level is set for free copy, or not; with the values `0` not being able to be copied, and `1` being free copy. - -## Decoding - -The passwords used to copy levels that have such set aren't plain string, and are encoded in a method commonly seen for values like these. Like most of the base64, it's done in [URL Encoded Base64](/topics/encryption/base64.md) The method of decryption is as follows: - -`Decode Base64` -> `Xor Cipher (key "26364")` -> `Level Password` - -**The following code demonstrates this process programmatically:** - - - -### **Python** - -```py -import base64 - -def decode_level_password(password: str) -> str: - # decode the password from base64 - decoded_base64 = base64.b64decode(password.encode()).decode() - # put it through the xor cipher with the key "26364") - decoded = xor_cipher(decoded_base64, "26364") - - return decoded -``` - - diff --git a/docs/topics/levelstring_encoding_decoding.md b/docs/topics/levelstring_encoding_decoding.md deleted file mode 100644 index 2e5fe960b..000000000 --- a/docs/topics/levelstring_encoding_decoding.md +++ /dev/null @@ -1,54 +0,0 @@ -# Level encoding/decoding -Despite Geometry Dash levels being stored in a plaintext, human-readable format, the game will resort to storing level data in a compressed binary format when storing them in the game's memory or files(albeit for compatibility reasons levels can also be loaded directly in a uncompressed format). - -Official levels are stored in `\Resources\LevelData.plist` (filename depends on game, `LevelDataSubzero.plist` for *Geometry Dash Subzero*, etc.) - -Compressed levels are actually composed out of two things: [Base64](topics/encryption/base64) encoding and [ZLIB](https://zlib.net) compression. - -## Encoding -To encode a level you take first the level string and `compress()` it, afterwards you need to encode the resulting byte sequence with Base64 encoding. - -If you are encoding an official level and want to put it in `LevelData.plist`, you need to remove the first 13 characters in the beginning of the base64 encoded string. - - - -### **Python** - -```py -import base64 -import gzip - -def encode_level(level_string: str, is_official_level: bool) -> str: - gzipped = gzip.compress(level_string.encode()) - base64_encoded = base64.urlsafe_b64encode(gzipped) - if is_official_level: - base64_encoded = base64_encoded[13:] - return base64_encoded.decode() -``` - - - -## Decoding -To decompress the level you'll first need to decode the compressed string in it's B64 encoded form, then you need to `decompress()` the resulting bytes to obtain a valid level string which can be read by the game. - -If you are decoding an official level, you need to add `H4sIAAAAAAAAA` at the beginning of the compressed string. - - - -### **Python** - -```py -import base64 -import zlib - - -def decode_level(level_data: str, is_official_level: bool) -> str: - if is_official_level: - level_data = 'H4sIAAAAAAAAA' + level_data - base64_decoded = base64.urlsafe_b64decode(level_data.encode()) - # window_bits = 15 | 32 will autodetect gzip or not - decompressed = zlib.decompress(base64_decoded, 15 | 32) - return decompressed.decode() -``` - - diff --git a/docs/topics/localfiles_encrypt_decrypt.md b/docs/topics/localfiles_encrypt_decrypt.md deleted file mode 100644 index b3c7a3223..000000000 --- a/docs/topics/localfiles_encrypt_decrypt.md +++ /dev/null @@ -1,142 +0,0 @@ -# Game Files - Encryption and Decryption - -Although Geometry Dash's install path is usually inside the user's `steamapps/common` folder (if the game was bought from Steam) the game will actually store all relevant user data inside the `AppData/Local` directory, in which a new folder will be created under the name of `GeometryDash`. This folder contains all custom songs that the user has downloaded but it also contains 2 important files, which are *CCGameManager.dat* and *CCLocalLevels.dat*; the first one contains all the information regarding the player's in-game stats and preferences while the latter contains the data for the game's user created levels. - -On MacOS, saves are placed under `~/Library/Application Support/GeometryDash`, and use completely different encoding from Windows one. - -However when these files are written to the disk they are encrypted and have to be decrypted before they can be read or modified. -Both files share the same process for decryption and encryption. - -## Decryption - -### Windows - -Local game files are decrypted in the following order: Apply XOR function with key `0xB` (`11`), then apply [B64 decoding](topics/encryption/base64), the resulting byte sequence will be a [gzip](https://zlib.net) compressed string which needs to be decompressed/inflated. - -Simple XOR function differs can be written like this: - - - -### **Python** - -```py -def xor(string: str, key: int) -> str: - return ("").join(chr(ord(char) ^ key) for char in string) -``` - - - -Programmatically decryption can be implemented like so: - - - -### **Python** - -```py -import base64 -import gzip - - -def decrypt_data(data: str) -> str: - base64_decoded = base64.urlsafe_b64decode(xor(data, key=11).encode()) - decompressed = gzip.decompress(base64_decoded) - return decompressed.decode() -``` - - - -### MacOS - -On MacOS, decryption is quite simpler. Saves are encrypted with -[AES](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard), using `ECB` mode. - -256-bit key for encryption looks like this: - - - -### **Plain** - -```plain -69 70 75 39 54 55 76 35 34 79 76 5d 69 73 46 4d 68 35 40 3b 74 2e 35 77 33 34 45 32 52 79 40 7b -``` - -### **Python** - -```py -KEY = ( # python will automatically concatenate two parts - b"\x69\x70\x75\x39\x54\x55\x76\x35\x34\x79\x76\x5d\x69\x73\x46\x4d" - b"\x68\x35\x40\x3b\x74\x2e\x35\x77\x33\x34\x45\x32\x52\x79\x40\x7b" -) -``` - - - -Here is how actual decryption would be implemented: - - - -### **Python** - -```py -from Crypto.Cipher import AES - - -def remove_pad(data: bytes) -> bytes: - last = data[-1] - if last < 16: - data = data[:-last] - return data - - -def mac_decrypt(data: bytes) -> str: - cipher = AES.new(KEY, AES.MODE_ECB) - return remove_pad(cipher.decrypt(data)).decode() -``` - - - -## Encryption - -### Windows - -Encryption is done pretty much the same way but with opposite operations and order. So the sequence for encrypting can be defined as: [gzip](https://zlib.net) compress/deflate -> [Base64](topics/encryption/base64) encode -> XOR using `0xb` (`11`) as a key. - - - -### **Python** - -```py -def encrypt_data(data: str) -> str: - gzipped = gzip.compress(data.encode()) - base64_encoded = base64.urlsafe_b64encode(gzipped) - return xor(base64_encoded.decode(), key=11) -``` - - - -### MacOS - -Like on Windows, encryption and decrypion are almost the same: - - - -### **Python** - -```py -from Crypto.Cipher import AES - - -def add_pad(data: bytes) -> bytes: - len_r = len(data) % 16 - if len_r: - to_add = 16 - len_r - data += to_add.to_bytes(1, "little") * to_add - return data - - -def mac_encrypt(data: str) -> bytes: - cipher = AES.new(KEY, AES.MODE_ECB) - return cipher.encrypt(add_pad(data.encode())) -``` - - diff --git a/docs/topics/shop.md b/docs/topics/shop.md deleted file mode 100644 index 47bf83fcf..000000000 --- a/docs/topics/shop.md +++ /dev/null @@ -1,126 +0,0 @@ -# Shops - -There are 3 different shops in Geometry Dash which allow the player to purchase various icons. Below is a table which contains every shop item in the game - -**Note:** ItemID refers to the ID of the item Type. - -| listingID | itemID | Item Type | cost | Shop Type | -|:-------|:-------|:----------|:-----|:----------| -| 34 | 79 | Cube | 500 | Shopkeeper | -| 1 | 77 | Cube | 1000 | Shopkeeper | -| 2 | 86 | Cube | 1000 | Shopkeeper | -| 3 | 73 | Cube | 1000 | Shopkeeper | -| 4 | 102 | Cube | 1000 | Shopkeeper | -| 5 | 107 | Cube | 1000 | Shopkeeper | -| 6 | 27 | Ship | 2000 | Shopkeeper | -| 7 | 25 | UFO | 2000 | Shopkeeper | -| 8 | 23 | UFO | 2500 | Shopkeeper | -| 9 | 20 | Ball | 1000 | Shopkeeper | -| 10 | 19 | Ball | 1500 | Shopkeeper | -| 11 | 21 | Wave | 500 | Shopkeeper | -| 12 | 2 | Spider | 2000 | Shopkeeper | -| 13 | 12 | Robot | 3000 | Shopkeeper | -| 14 | 8 | Explosion | 7000 | Shopkeeper | -| 15 | 11 | Explosion | 7000 | Shopkeeper | -| 16 | 18 | Wave | 2000 | Scratch | -| 17 | 94 | Cube | 3000 | Scratch | -| 18 | 85 | Cube | 2500 | Scratch | -| 19 | 96 | Cube | 2000 | Scratch | -| 20 | 4 | Master Emblem | 1000 | Scratch | -| 21 | 14 | Robot | 3000 | Scratch | -| 22 | 21 | UFO | 4000 | Scratch | -| 23 | 3 | Spider | 3000 | Scratch | -| 24 | 25 | Ball | 2000 | Scratch | -| 25 | 13 | Explosion | 10000 | Scratch | -| 26 | 35 | Colour 1 | 1000 | Shopkeeper | -| 27 | 36 | Colour 1 | 1000 | Shopkeeper | -| 28 | 39 | Colour 1 | 1000 | Scratch | -| 29 | 40 | Colour 1 | 1000 | Scratch | -| 30 | 39 | Colour 2 | 1000 | Shopkeeper | -| 32 | 32 | Colour 2 | 1000 | Scratch | -| 33 | 41 | Colour 2 | 1000 | Scratch | -| 35 | 5 | Streak | 4000 | Shopkeeper | -| 36 | 6 | Streak | 4000 | Shopkeeper | -| 37 | 7 | Streak | 4000 | Scratch | -| 38 | 117 | Cube | 4000 | PotBor | -| 39 | 118 | Cube | 2000 | PotBor | -| 40 | 119 | Cube | 2000 | PotBor | -| 41 | 120 | Cube | 4000 | PotBor | -| 42 | 121 | Cube | 2000 | PotBor | -| 43 | 122 | Cube | 2000 | PotBor | -| 44 | 123 | Cube | 6000 | PotBor | -| 45 | 124 | Cube | 8000 | PotBor | -| 46 | 125 | Cube | 4000 | PotBor | -| 47 | 126 | Cube | 2000 | PotBor | -| 48 | 127 | Cube | 6000 | PotBor | -| 49 | 128 | Cube | 8000 | PotBor | -| 50 | 129 | Cube | 6000 | PotBor | -| 51 | 130 | Cube | 4000 | PotBor | -| 52 | 131 | Cube | 4000 | PotBor | -| 53 | 132 | Cube | 4000 | PotBor | -| 54 | 133 | Cube | 8000 | PotBor | -| 55 | 134 | Cube | 6000 | PotBor | -| 56 | 135 | Cube | 6000 | PotBor | -| 57 | 30 | Ball | 4000 | PotBor | -| 58 | 31 | Ball | 6000 | PotBor | -| 59 | 32 | Ball | 6000 | PotBor | -| 60 | 33 | Ball | 2000 | PotBor | -| 61 | 34 | Ball | 4000 | PotBor | -| 62 | 35 | Ball | 8000 | PotBor | -| 63 | 36 | Ball | 6000 | PotBor | -| 64 | 37 | Ball | 2000 | PotBor | -| 65 | 38 | Ball | 2000 | PotBor | -| 66 | 36 | Ship | 2000 | PotBor | -| 67 | 37 | Ship | 2000 | PotBor | -| 68 | 38 | Ship | 6000 | PotBor | -| 69 | 39 | Ship | 2000 | PotBor | -| 70 | 40 | Ship | 4000 | PotBor | -| 71 | 41 | Ship | 4000 | PotBor | -| 72 | 42 | Ship | 6000 | PotBor | -| 73 | 43 | Ship | 2000 | PotBor | -| 74 | 44 | Ship | 6000 | PotBor | -| 75 | 45 | Ship | 8000 | PotBor | -| 76 | 46 | Ship | 4000 | PotBor | -| 77 | 47 | Ship | 6000 | PotBor | -| 78 | 48 | Ship | 4000 | PotBor | -| 79 | 29 | UFO | 6000 | PotBor | -| 80 | 30 | UFO | 6000 | PotBor | -| 81 | 31 | UFO | 4000 | PotBor | -| 82 | 32 | UFO | 6000 | PotBor | -| 83 | 33 | UFO | 4000 | PotBor | -| 84 | 34 | UFO | 2000 | PotBor | -| 85 | 35 | UFO | 2000 | PotBor | -| 86 | 24 | Wave | 2000 | PotBor | -| 87 | 25 | Wave | 4000 | PotBor | -| 88 | 26 | Wave | 2000 | PotBor | -| 89 | 27 | Wave | 2000 | PotBor | -| 90 | 28 | Wave | 6000 | PotBor | -| 91 | 29 | Wave | 6000 | PotBor | -| 92 | 30 | Wave | 4000 | PotBor | -| 93 | 31 | Wave | 6000 | PotBor | -| 94 | 32 | Wave | 2000 | PotBor | -| 95 | 33 | Wave | 6000 | PotBor | -| 96 | 18 | Robot | 2000 | PotBor | -| 97 | 19 | Robot | 6000 | PotBor | -| 98 | 20 | Robot | 2000 | PotBor | -| 99 | 21 | Robot | 4000 | PotBor | -| 100 | 22 | Robot | 6000 | PotBor | -| 101 | 23 | Robot | 2000 | PotBor | -| 102 | 24 | Robot | 6000 | PotBor | -| 103 | 25 | Robot | 4000 | PotBor | -| 104 | 11 | Spider | 4000 | PotBor | -| 105 | 12 | Spider | 6000 | PotBor | -| 106 | 13 | Spider | 4000 | PotBor | -| 107 | 14 | Spider | 8000 | PotBor | -| 108 | 15 | Spider | 2000 | PotBor | -| 109 | 16 | Spider | 6000 | PotBor | -| 111 | 140 | Cube | 3000 | Shopkeeper | -| 112 | 109 | Cube | 4000 | Shopkeeper | -| 113 | 113 | Cube | 4000 | Shopkeeper | -| 114 | 40 | Ball | 4000 | Shopkeeper | -| 115 | 35 | Wave | 4000 | Shopkeeper | -| 116 | 33 | Colour 1 | 1000 | Shopkeeper | -| 117 | 28 | Colour 2 | 1000 | Shopkeeper | -| 118 | 136 | Cube | 5000 | Scratch | -| 119 | 110 | Cube | 5000 | Scratch | -| 120 | 16 | Explosion | 15000 | Scratch | diff --git a/docs/topics/status_codes.md b/docs/topics/status_codes.md deleted file mode 100644 index d20fcd7a7..000000000 --- a/docs/topics/status_codes.md +++ /dev/null @@ -1,67 +0,0 @@ -# Status Codes - -## Server - -Events over the Geometry Dash servers usually send an error code denoting that the server either had an error, or you sent an invalid request. - -### Server Status Codes - -| Code | Name | Description | -|------|------------------------------------------------------------------|-------------------------------------------------------------------------------------| -| -1 | Invalid Request | A parameter in your [HTTP request](/endpoints/request.md) to the server was invalid.| -| -2 | [Common](/topics/status_codes?id=endpoint-specific-status-codes) | This status code is commonly used in multiple endpoints either for `taken` things, or theres none of something. | - -### Endpoint-specific Status Codes - -#### registerGJAccount - -| Code | Name | Description | -|:-----|:-----|:------------| -| `-2` | Taken UserName | If the username you are trying to register with is taken | -| `-3` | Email is in use | If an account with that already email exists | -| `-4` | Username is invalid | If the username is invalid | -| `-5` | Password is invalid | If the password is invalid | -| `-6` | Email is invalid | If the email is invalid | -| `-7` | Passwords do not match | If the passwords don't match | -| `-8` | Too short. Minimum 6 characters | If the password is less than 6 characters long | -| `-9` | Too short. Minimum 3 characters | If the name is less than 3 characters long | -| `-99` | Emails do not match | if emails do not match | - -#### loginGJAccount - -| Code | Name | Description | -|:-----|:-----|:------------| -| `-8` | Too short. Minimum 6 characters | If the password is less than 6 characters long | -| `-9` | Too short. Minimum 3 characters | If the name is less than 3 characters long | -| `-10`| Already linked to a different account | If you are already logged into a different account (refresh login) | -| `-11`| Login Failed | Your login credentials are incorrect | -| `-12`| Account Disabled | Your account has been disabled | -| `-13`| Account already linked to a steam account | An unused error code which supposedly only allowed a single account per steam account | - -#### syncGJAccount/backupGJAccount - -| Code | Name | Description | -|:-----|:-----|:------------| -| `-2` | Login Failed | Your login credentials were wrong and you need to log back in | -| `-4` | Request is too large | Your request to the server was too large | -| `-5` | Bad login info | Invalid login info was provided | -| `-6` | Something went wrong | Something went wrong on the servers' end | - - -#### suggestGJStars/rateGJDemon - -| Code | Name | Description | -|:-----|:-----|:------------| -| `-2` | Not a Moderator | If you try to send a level despite not being a moderator | - -#### uploadGJComment/uploadGJAccComment - -| Code | Name | Description | -|:-----|:-----|:------------| -| `-10` | Permanent comment ban | If Robtop has deemed you worthy of a permanent comment ban | -| `temp_{time}_{reason}` | Temporary Comment Ban | If you have recieved a temporary ban from Robtop or an [Elder Moderator](/topics/moderators.md) - -| Key | description | -|:----|:------------| -| `{time}` | The duration of your ban left in seconds | -| `{reason}` | The reason behind your ban | diff --git a/docs/topics/tags.md b/docs/topics/tags.md deleted file mode 100644 index f5669ec32..000000000 --- a/docs/topics/tags.md +++ /dev/null @@ -1,33 +0,0 @@ -# Tags - -Throughout Geometry Dash there are various interfaces in which the player an see specialised text. Specialised text is created using a custom tag which Robtop has created. As of Geometry Dash 2.11, there are 3 different types of tags. - -> - `` tags assign a specific colour depending on the letter you give you give it. All `` tags must be closed with `` otherwise the game will crash.

-> - `` tags manipulate the delay before a piece of text is sent within a dialog box. The speed you can set is within a range of `000` to `999` ms.

-> - `` tags are the simplest tags out of everything and all they do is make text appear immediately. `` tags must be closed with `` otherwise the game will crash. - -## \ Tags - -There are `9` different colour tags that are usable in Geometry Dash. below is a table of them all - -**Note:** The `\` in the examples are **not** a part of a tag! It has been placed there to show the colour of the tag with the game still showing the tag as plain text. - -| tag | Colour | Hex Code | -|:----|:-------|:---------| -| `` | ![Orange](https://raw.githubusercontent.com/Wyliemaster/gddocs/client/assets/examples/tags/orange.png) | `0xFFA54B` | -| `` | ![Yellow](https://raw.githubusercontent.com/Wyliemaster/gddocs/client/assets/examples/tags/yellow.png) | `0xFFFF48` -| `` | ![Green](https://raw.githubusercontent.com/Wyliemaster/gddocs/client/assets/examples/tags/green.png) | `0x40E348` | -| `` | ![Light Blue](https://raw.githubusercontent.com/Wyliemaster/gddocs/client/assets/examples/tags/lightBlue.png) | `0x32C8FF` | -| `` | ![Blue](https://raw.githubusercontent.com/Wyliemaster/gddocs/client/assets/examples/tags/blue.png) | `0x4A52E1` | -| `` | ![Purple](https://raw.githubusercontent.com/Wyliemaster/gddocs/client/assets/examples/tags/purple.png) | `0xFF00FF` -| `` | ![Very Light Blue](https://raw.githubusercontent.com/Wyliemaster/gddocs/client/assets/examples/tags/veryLightBlue.png) | `0x60ABEF` | -| `` | ![Red](https://raw.githubusercontent.com/Wyliemaster/gddocs/client/assets/examples/tags/red.png) | `0xFFA548` | -| `` | ![dark Red](https://raw.githubusercontent.com/Wyliemaster/gddocs/client/assets/examples/tags/any.png) | `0xFF0000` | - -## \ Tags - -`` tags are used to create a delay before a specific string in dialog boxes. The game detects a `Delay Tag` if the string contains a ` Tags - -`` tags are the complete opposite to `Delay Tags` as they display text instantly rather than after a delay. `` tags also require a closing tag which is `` so the game does not crash when parsing the string. An example of an `` tag can be found [here](https://github.com/Wyliemaster/gddocs/blob/client/assets/examples/tags/I%20tags%20example.mp4?raw=true) \ No newline at end of file diff --git a/docs/topics/vault_codes.md b/docs/topics/vault_codes.md deleted file mode 100644 index 5375d8fc2..000000000 --- a/docs/topics/vault_codes.md +++ /dev/null @@ -1,38 +0,0 @@ -# Vault Codes - -In Geometry Dash 2.1 there are three different vaults you can access. The Vault, Vault of Secrets and the Chamber of Time. Each vault has a select number of passwords that you can enter to unlock icons and colors. - -## Vault Code Encryption - -The Vault: Codes are in plaintext and arent encrypted - -Vault of Secrets and Chamber of time: [VaultCode] + ask2fpcaqCQ2 -> Xor with a key of 19283 -> base64 encode - -### Table of Vault codes - -| Vault Type | Code | Rewards | notes | -|------------|----------------|---------|-------| -| The Vault | spooky | Cube -| The Vault | lenny | Cube -| The Vault | your in-game name | Cube -| The Vault | mule | ship -| The Vault | blockbite | ufo -| The Vault | neverending | ufo -| The Vault | ahead | wave -| The Vault | 8, 16, 30, 32, 46, 84 | wave | (you enter 1 at a time consecutively) -| The Vault | robotop | robot -| The Vault | gandalfpotter | trail -| The Vault | sparky | coin -| Vault of Secrets | your star count | cube -| Vault of Secrets | CodeBreaker | cube | you are given a sequence of numbers you have to subtract the numbers from each other and the code is all the numbers subtracted combined if the numbers were 1,2,4,8,16,32 then you would do 2-1, 4-2, 8-4, 16-8, 32-16 and the code would then be 124816 -| Vault of Secrets | brainpower | cube -| Vault of Secrets | octocube | cube -| Vault of Secrets | seven | cube -| Vault of Secrets | thechickenisonfire | colour2 -| Vault of Secrets | gimmethecolor | color1 -| Vault of Secrets | glubflub | coin -| Chamber Of Time | silence | cube -| Chamber Of Time | hunger | cube -| Chamber Of Time | darkness | cube -| Chamber Of Time | volcano | wave | 'a volcano' also works -| Chamber Of Time | river | color2 | 'a river' also works diff --git a/generator.js b/generator.js deleted file mode 100644 index d166c0e1a..000000000 --- a/generator.js +++ /dev/null @@ -1,19 +0,0 @@ -/* eslint no-console: ["error", { allow: ["log", "warn", "error"] }] */ -const childProcess = require("child_process"); -const chalk = require("chalk"); -const os = require("os"); - -require("./scripts/installPackages.js"); // install packages - -// serve data -let command = "node ./node_modules/docsify-cli/bin/docsify serve ./docs --port 9505"; - -if (os.platform() === "win32") { - command = "node \"./node_modules/docsify-cli/bin/docsify\" serve ./docs --port 9505"; -} - -console.log(`${chalk.hex("#66d9ff")("Running Command: ")} ${command}\n`); - -const docsProcess = childProcess.exec(command); - -docsProcess.on("exit", () => process.exit(0)); \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 000000000..93e65fe57 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,85 @@ +site_name: gd.docs +site_author: GD Programming +site_description: Documentation for Geometry Dash. + +repo_name: gd-programming/gd.docs +repo_url: https://github.com/gd-programming/gd.docs + +remote_branch: github-pages + +watch: + - docs + +nav: + - Index: "index.md" + + - Server: + - Endpoints: + - Comments: + - Delete Level Comment: "server/endpoints/comments/delete_level_comment.md" + - Delete User Comment: "server/endpoints/comments/delete_user_comment.md" + - Friend Requests: + - Accept Friend Request: "server/endpoints/friend_requests/accept_friend_request.md" + - Delete Friend Request: "server/endpoints/friend_requests/delete_friend_request.md" + - Levels: + - Get Level: "server/endpoints/levels/get_level.md" + - Delete Level: "server/endpoints/levels/delete_level.md" + - Messages: + - Delete Message: "server/endpoints/messages/delete_message.md" + - Get Message: "server/endpoints/messages/get_message.md" + - Users: + - Block User: "server/endpoints/users/block_user.md" + + - Topics: + - Error Codes: "server/topics/error_codes.md" + - Secrets: "server/topics/secrets.md" + - Songs: "server/topics/songs.md" + - Versions: "server/topics/versions.md" + + - Client: + - Topics: + - Vault Codes: "client/topics/vault_codes.md" + + - Encoding: + - AES: "encoding/aes.md" + - Base64: "encoding/base64.md" + - Checks: "encoding/checks.md" + - Random String, UUID and UDID: "encoding/ids.md" + - RobTop Encoding: "encoding/robtop.md" + - Seeds: "encoding/seeds.md" + - XOR: "encoding/xor.md" + - ZIP: "encoding/zip.md" + + - Code of Conduct: "code_of_conduct.md" + +theme: + name: material + palette: + - media: "(prefers-color-scheme: dark)" + scheme: slate + + primary: deep purple + accent: light blue + + toggle: + icon: material/toggle-switch-off-outline + name: Switch to light mode + + - media: "(prefers-color-scheme: light)" + scheme: default + + primary: light blue + accent: deep purple + + toggle: + icon: material/toggle-switch + name: Switch to dark mode + +plugins: + - search + +markdown_extensions: + - pymdownx.highlight + - pymdownx.inlinehilite + - pymdownx.snippets + - pymdownx.superfences diff --git a/package.json b/package.json deleted file mode 100644 index 3039af308..000000000 --- a/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "gddocs", - "version": "0.0.1", - "description": "GD Documentation", - "main": "generator.js", - "scripts": { - "run": "node generator.js" - }, - "repository": { - "type": "git", - "url": "git+https://github.com/gd-programming/gddocs.git" - }, - "keywords": [ - "gd" - ], - "author": "GD Programming", - "license": "MIT", - "bugs": { - "url": "https://github.com/gd-programming/gddocs/issues" - }, - "homepage": "https://github.com/gd-programming/gddocs#readme", - "dependencies": { - "chalk": "^4.0.0", - "docsify-cli": "^4.4.0" - } -} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..441c8340e --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,34 @@ +[tool.poetry] +name = "gd.docs" +version = "0.1.0" +description = "Documentation for Geometry Dash." +authors = ["gd-programming"] +license = "MIT" + +readme = "README.md" + +homepage = "https://docs.gd-programming.org/" +repository = "https://github.com/gd-programming/gd.docs" + +keywords = ["gd", "docs", "documentation"] + +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Operating System :: OS Independent", + "Topic :: Documentation", +] + +[tool.poetry.urls] +Discord = "https://gd-programming.org/discord" +Issues = "https://github.com/gd-programming/gd.docs/issues" + +[tool.poetry.dependencies] +python = ">= 3.7" + +mkdocs = ">= 1.4.2" +mkdocs-material = ">= 9.1.6" + +[build-system] +requires = ["poetry-core >= 1.5.2"] +build-backend = "poetry.core.masonry.api" diff --git a/scripts/installPackages.js b/scripts/installPackages.js deleted file mode 100644 index abd31377f..000000000 --- a/scripts/installPackages.js +++ /dev/null @@ -1,14 +0,0 @@ -// install_packages.js -// made by Homura -const chalk = require("chalk"); -const fs = require("fs"); -const childProcess = require("child_process"); - -const package = require("../package.json"); -const missing = Object.keys(package.dependencies) - .filter((package) => !fs.existsSync(`../node_modules/${package}`)); - -if (missing.length > 0) { - console.log(chalk.hex("#79b0fc")("Installing Packages: ") + missing.join(", ")); - childProcess.exec(`npm i --save ${missing.join(" ")}`); -} \ No newline at end of file