Merge branch 'beta' into localization-md

This commit is contained in:
Bertie690 2025-06-24 10:27:06 -04:00 committed by GitHub
commit 64f045c0ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
470 changed files with 79962 additions and 25917 deletions

View File

@ -1,6 +1,19 @@
/** @type {import('dependency-cruiser').IConfiguration} */
module.exports = {
forbidden: [
{
name: "no-non-type-@type-exports",
severity: "error",
comment:
"Files in @types should not export anything but types and interfaces. " +
"The folder is intended to house imports that are removed at runtime, " +
"and thus should not contain anything with a bearing on runtime code.",
from: {},
to: {
path: "(^|/)src/@types",
dependencyTypesNot: ["type-only"],
},
},
{
name: "only-type-imports",
severity: "error",
@ -310,7 +323,7 @@ module.exports = {
conditionNames: ["import", "require", "node", "default", "types"],
/*
The extensions, by default are the same as the ones dependency-cruiser
can access (run `npx depcruise --info` to see which ones that are in
can access (run `pnpm exec depcruise --info` to see which ones that are in
_your_ environment). If that list is larger than you need you can pass
the extensions you actually use (e.g. [".js", ".jsx"]). This can speed
up module resolution, which is the most expensive step.

View File

@ -68,8 +68,8 @@ Do the reviewers need to do something special in order to test your changes?
- [ ] The PR is self-contained and cannot be split into smaller PRs?
- [ ] Have I provided a clear explanation of the changes?
- [ ] Have I tested the changes manually?
- [ ] Are all unit tests still passing? (`npm run test:silent`)
- [ ] Have I created new automated tests (`npm run test:create`) or updated existing tests related to the PR's changes?
- [ ] Are all unit tests still passing? (`pnpm test:silent`)
- [ ] Have I created new automated tests (`pnpm test:create`) or updated existing tests related to the PR's changes?
- [ ] Have I provided screenshots/videos of the changes (if applicable)?
- [ ] Have I made sure that any UI change works for both UI themes (default and legacy)?

View File

@ -18,15 +18,24 @@ jobs:
with:
submodules: "recursive"
ref: ${{ vars.BETA_DEPLOY_BRANCH || 'beta'}}
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"
- name: Install dependencies
run: npm ci
run: pnpm i
- name: Build
run: npm run build:beta
run: pnpm build:beta
env:
NODE_ENV: production
- name: Set up SSH
run: |
mkdir ~/.ssh
@ -34,6 +43,7 @@ jobs:
echo "${{ secrets.BETA_SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/*
ssh-keyscan -H ${{ secrets.BETA_SSH_HOST }} >> ~/.ssh/known_hosts
- name: Deploy build on server
run: |
rsync --del --no-times --checksum -vrm dist/* ${{ secrets.BETA_SSH_USER }}@${{ secrets.BETA_SSH_HOST }}:${{ secrets.BETA_DESTINATION_DIR }}

View File

@ -16,15 +16,24 @@ jobs:
- uses: actions/checkout@v4
with:
submodules: 'recursive'
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
- name: Install dependencies
run: npm ci
run: pnpm i
- name: Build
run: npm run build
run: pnpm build
env:
NODE_ENV: production
- name: Set up SSH
if: github.event_name == 'push' && github.ref_name == 'main'
run: |
@ -33,11 +42,13 @@ jobs:
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/*
ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts
- name: Deploy build on server
if: github.event_name == 'push' && github.ref_name == 'main'
run: |
rsync --del --no-times --checksum -vrm dist/* ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:${{ secrets.DESTINATION_DIR }}
ssh -t ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} "~/prmanifest --inpath ${{ secrets.DESTINATION_DIR }} --outpath ${{ secrets.DESTINATION_DIR }}/manifest.json"
- name: Purge Cloudflare Cache
if: github.event_name == 'push' && github.ref_name == 'main'
id: purge-cache

View File

@ -34,6 +34,11 @@ jobs:
sudo apt update
sudo apt install -y git openssh-client
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Setup Node 22.14.1
uses: actions/setup-node@v4
with:
@ -50,13 +55,13 @@ jobs:
working-directory: ${{env.api-dir}}
run: |
cd pokerogue_docs
npm ci
pnpm i
- name: Generate Typedoc docs
working-directory: ${{env.api-dir}}
run: |
cd pokerogue_docs
npm run docs -- --out /tmp/docs --githubPages false --entryPoints ./src/
pnpm exec typedoc --out /tmp/docs --githubPages false --entryPoints ./src/
- name: Commit & Push docs
if: github.event_name == 'push'

View File

@ -23,20 +23,22 @@ jobs:
with:
submodules: 'recursive'
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version-file: '.nvmrc'
cache: 'npm'
cache: 'pnpm'
- name: Install Node.js dependencies
run: npm ci
- name: Run ESLint
run: npm run eslint-ci
run: pnpm i
- name: Lint with Biome
run: npm run biome-ci
run: pnpm biome-ci
- name: Check dependencies with depcruise
run: npm run depcruise
run: pnpm depcruise

View File

@ -28,12 +28,20 @@ jobs:
uses: actions/checkout@v4.2.2
with:
submodules: "recursive"
- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version-file: ".nvmrc"
cache: "npm"
cache: "pnpm"
- name: Install Node.js dependencies
run: npm ci
run: pnpm i
- name: Run tests
run: npx vitest --project ${{ inputs.project }} --no-isolate --shard=${{ inputs.shard }}/${{ inputs.totalShards }} ${{ !runner.debug && '--silent' || '' }}
run: pnpm exec vitest --project ${{ inputs.project }} --no-isolate --shard=${{ inputs.shard }}/${{ inputs.totalShards }} ${{ !runner.debug && '--silent' || '' }}

View File

@ -1,16 +1,14 @@
name: Tests
on:
# Trigger the workflow on push or pull request,
# but only for the main branch
push:
branches:
- main # Trigger on push events to the main branch
- beta # Trigger on push events to the beta branch
- main
- beta
pull_request:
branches:
- main # Trigger on pull request events targeting the main branch
- beta # Trigger on pull request events targeting the beta branch
- main
- beta
merge_group:
types: [checks_requested]
@ -24,6 +22,7 @@ jobs:
steps:
- name: checkout
uses: actions/checkout@v4
- uses: dorny/paths-filter@de90cc6fb38fc0963ad72b210f1f284cd68cea36
id: filter
with:

164
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,164 @@
# Contributing to PokéRogue
Thank you for taking the time to contribute, every little bit helps. This project is entirely open-source and unmonetized - community contributions are what keep it alive!
Please make sure you understand everything relevant to your changes from the [Table of Contents](#-table-of-contents), and absolutely *feel free to reach out reach out in the **#dev-corner** channel on [Discord](https://discord.gg/pokerogue)*. We are here to help and the better you understand what you're working on, the easier it will be for it to find its way into the game.
## 📄 Table of Contents
- [Development Basics](#-development-basics)
- [Environment Setup](#-environment-setup)
- [Getting Started](#-getting-started)
- [Documentation](#-documentation)
- [Testing Your Changes](#-testing-your-changes)
- [Localization](#-localization)
- [Development Save File (Unlock Everything)](#-development-save-file)
## 🛠️ Development Basics
PokéRogue is built with [Typescript](https://www.typescriptlang.org/docs/handbook/intro.html), using the [Phaser](https://github.com/phaserjs/phaser) game framework.
If you have the motivation and experience with Typescript/Javascript (or are willing to learn) you can contribute by forking the repository and making pull requests with contributions.
## 💻 Environment Setup
### Prerequisites
- node: >=22.14.0 - [manage with pnpm](https://pnpm.io/cli/env) | [manage with fnm](https://github.com/Schniz/fnm) | [manage with nvm](https://github.com/nvm-sh/nvm)
- pnpm: 10.x - [how to install](https://pnpm.io/installation) (not recommended to install via `npm` on Windows native) | [alternate method - volta.sh](https://volta.sh/)
### Running Locally
1. Clone the repo and in the root directory run `pnpm install`
- *if you run into any errors, reach out in the **#dev-corner** channel on Discord*
2. Run `pnpm start:dev` to locally run the project at `localhost:8000`
### Linting
Check out our [in-depth file](./docs/linting.md) on linting and formatting!
## 🚀 Getting Started
A great way to develop an understanding of how the project works is to look at test cases (located in [the `test` folder](./test/)).
Tests show you both how things are supposed to work and the expected "flow" to get from point A to point B in battles.
*This is a big project and you will be confused at times - never be afraid to reach out and ask questions in **#dev-corner***!
### Where to Look
Once you have your feet under you, check out the [Issues](https://github.com/pagefaultgames/pokerogue/issues) page to see how you can help us!
Most issues are bugs and are labeled with their area, such as `Move`, `Ability`, `UI/UX`, etc. There are also priority labels:
- `P0`: Completely gamebreaking (very rare)
- `P1`: Major - Game crash
- `P2`: Minor - Incorrect (but non-crashing) move/ability/interaction
- `P3`: No gameplay impact - typo, minor graphical error, etc.
Also under issues, you can take a look at the [List of Partial / Unimplemented Moves and Abilities](https://github.com/pagefaultgames/pokerogue/issues/3503) and the [Bug Board](https://github.com/orgs/pagefaultgames/projects/3) (the latter is essentially the same as the issues page but easier to work with).
You are free to comment on any issue so that you may be assigned to it and we can avoid multiple people working on the same thing.
## 📚 Documentation
You can find the auto-generated documentation [here](https://pagefaultgames.github.io/pokerogue/main/index.html).
For information on enemy AI, check out the [enemy-ai.md](./docs/enemy-ai.md) file.
For detailed guidelines on documenting your code, refer to the [comments.md](./docs/comments.md) file.
Again, if you have unanswered questions please feel free to ask!
## 🧪 Testing Your Changes
You've just made a change - how can you check if it works? You have two areas to hit:
### 1 - Manual Testing
> This will likely be your first stop. After making a change, you'll want to spin the game up and make sure everything is as you expect. To do this, you will need a way to manipulate the game to produce the situation you're looking to test.
[src/overrides.ts](../src/overrides.ts) contains overrides for most values you'll need to change for testing, controlled through the `overrides` object.
For example, here is how you could test a scenario where the player Pokemon has the ability Drought and the enemy Pokemon has the move Water Gun:
```typescript
const overrides = {
ABILITY_OVERRIDE: AbilityId.DROUGHT,
OPP_MOVESET_OVERRIDE: MoveId.WATER_GUN,
} satisfies Partial<InstanceType<typeof DefaultOverrides>>;
```
Read through `src/overrides.ts` file to find the override that fits your needs - there are a lot of them!
If the situation you're trying to test can't be created using existing overrides (or with the [Dev Save](#-development-save-file)), reach out in **#dev-corner**.
You can get help testing your specific changes, and you might have found a new override that needs to be created!
### 2 - Automatic Testing
> PokéRogue uses [Vitest](https://vitest.dev/) for automatic testing. Checking out the existing tests in the [test](./test/) folder is a great way to understand how this works, and to get familiar with the project as a whole.
To make sure your changes didn't break any existing test cases, run `pnpm test:silent` in your terminal. You can also provide an argument to the command: to run only the Dancer (ability) tests, you could write `pnpm test:silent dancer`.
- __Note that passing all test cases does *not* guarantee that everything is working properly__. The project does not have complete regression testing.
Most non-trivial changes (*especially bug fixes*) should come along with new test cases.
- To make a new test file, run `pnpm test:create` and follow the prompts. If the move/ability/etc. you're modifying already has tests, simply add new cases to the end of the file. As mentioned before, the easiest way to get familiar with the system and understand how to write your own tests is simply to read the existing tests, particularly ones similar to the tests you intend to write.
- Ensure that new tests:
- Are deterministic. In other words, the test should never pass or fail when it shouldn't due to randomness. This involves primarily ensuring that abilities and moves are never randomly selected.
- As much as possible, are unit tests. If you have made two distinct changes, they should be tested in two separate cases.
- Test edge cases. A good strategy is to think of edge cases beforehand and create tests for them using `it.todo`. Once the edge case has been handled, you can remove the `todo` marker.
## 📜 Localization
The project intends for all text to be localized. That is, strings are pulled from translation files using keys (depending on the current language) and *never* hardcoded as a particular language. Note that there is a PDF in a message pinned in **#dev-corner** which gives the following information in greater detail.
### Setting Up and Updating the Locales Submodule
> The locales (translation) files are set up as a git submodule. A project-in-a-project, if you will.
To fetch translations when you first start development in your fork or to update them on your local branch, run:
```bash
git submodule update --progress --init --recursive
```
### How Localizations Work
> This project uses the [i18next](https://www.i18next.com/) library to integrate translations from public/locales
into the source code based on the user's settings or location. The basic process for
fetching translated text is as follows:
1. The source code fetches text by a given key, e.g.
```ts
i18next.t("fileName:keyName", { arg1: "Hello", arg2: "an example", ... })
```
2. The game looks up the key in the corresponding JSON file in the user's
language, e.g.
```ts
// from "en/file-name.json"...
"keyName": "{{arg1}}! This is {{arg2}} of translated text!"
```
If the key doesn't exist for the user's language, the game will default to the
corresponding English key (in the case of LATAM Spanish, it will first default to ES Spanish).
3. The game shows the text to the user:
```ts
"Hello! This is an example of translated text!"
```
### Adding Translated Text
> If your feature involves new or modified text in any form, then you will be modifying the [locales](https://github.com/pagefaultgames/pokerogue-locales) repository. ***Never hardcode new text in any language!***
The workflow is:
1. Make a pull request to the main repository for your new feature.
If this feature requires new text, the text should be integrated into the code with a new i18next key pointing to where you plan to add it into the pokerogue-locales repository.
2. Make another pull request -- this time to the [pokerogue-locales](https://github.com/pagefaultgames/pokerogue-locales)
repository -- adding a new entry to the English locale with text for each key
you added to your main PR. You *only* need to add the English key and value - the translation team will handle the rest.
3. If your feature is pulled from the mainline Pokémon games (e.g. a Move or Ability implementation), add a source link for any added text within the locale PR.
[Poké Corpus](https://abcboy101.github.io/poke-corpus) is a great resource for finding text from the latest mainline games; otherwise, a YouTube video link showing the text in mainline is sufficient.
4. Ping @lugiadrien in **#dev-corner** or the current callout thread to make sure your locales PR is seen.
It'll be merged into the locales repository after any necessary corrections, at which point you can test it in your main PR (after updating locales from remote)
5. The Dev team will approve your main PR, and your changes will be in the beta environment!
## 😈 Development Save File
> Some issues may require you to have unlocks on your save file which go beyond normal overrides. For this reason, the repository contains a [save file](../test/testUtils/saves/everything.psrv) with _everything_ unlocked (even ones not legitimately obtainable, like unimplemented variant shinies).
1. Start the game up locally and navigate to `Menu -> Manage Data -> Import Data`
2. Select [everything.prsv](test/testUtils/saves/everything.prsv) (`test/testUtils/saves/everything.prsv`) and confirm.

View File

@ -4,64 +4,7 @@ PokéRogue is a browser based Pokémon fangame heavily inspired by the roguelite
# Contributing
## 🛠️ Development
If you have the motivation and experience with Typescript/Javascript (or are willing to learn) please feel free to fork the repository and make pull requests with contributions. If you don't know what to work on but want to help, reference the below **To-Do** section or the **#feature-vote** channel in the discord.
### 💻 Environment Setup
#### Prerequisites
- node: 22.14.0
- npm: [how to install](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
#### Running Locally
1. Clone the repository through Git by running the following command in your desired directory:
   ``bash
   git clone --recurse-submodules https://github.com/pagefaultgames/pokerogue
   ```
   [^1]
2. Run `npm install` in the newly cloned folder to download required dependencies.
3. Run `npm run start:dev` to locally run the project in `localhost:8000`
If you run into any errors, reach out in the **#dev-corner** channel in discord
[^1]: If you forget to use the `--recurse-submodules` flag when cloning initially, consult [localization.md](./docs/localization.md) \
for instructions on how to clone the `locales` submodule manually.
#### Linting
<!-- TODO: Mention linting.md -->
We're using Biome as our common linter and formatter. \
It will run automatically during the pre-commit hook, or can be done manually via `npm run biome`. \
To view the complete rules, check out the [biome.jsonc](./biome.jsonc) file.
### 📚 Documentation
You can find the auto-generated documentation [here](https://pagefaultgames.github.io/pokerogue/main/index.html).
Additionally, the [docs folder](./docs) contains a variety of documents and guides useful for aspiring contributors. \
Notable topics include:
- [Commenting your code](./docs/comments.md)
- [Linting & Formatting](./docs/linting.md)
- [Localization](./docs/localization.md)
- [Enemy AI move selection](./docs/enemy-ai.md)
### ❔ FAQ
**How do I test a new _______?**
- In the `src/overrides.ts` file there are overrides for most values you'll need to change for testing
**How do I retrieve the translations?**
- See [localization.md](./docs/localization.md) for detailed info on everything to do with translations, \
from cloning the `locales` repository to adding new entries and submitting changes.
## 🪧 To Do
Check out [Github Issues](https://github.com/pagefaultgames/pokerogue/issues) to see how can you help us!
See [CONTRIBUTING.md](./CONTRIBUTING.md), this includes instructions on how to set up the game locally.
# 📝 Credits
>

View File

@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
"vcs": {
"enabled": false,
"clientKind": "git",
@ -10,35 +10,47 @@
"enabled": true,
"useEditorconfig": true,
"indentStyle": "space",
"ignore": ["src/enums/*", "src/data/balance/*"],
"includes": ["**", "!**/src/enums/**/*", "!**/src/data/balance/**/*"],
"lineWidth": 120
},
"files": {
"ignoreUnknown": true,
// Adding folders to the ignore list is GREAT for performance because it prevents biome from descending into them
// and having to verify whether each individual file is ignored
"ignore": [
"**/*.d.ts",
"dist/*",
"build/*",
"coverage/*",
"public/*",
".github/*",
"node_modules/*",
".vscode/*",
"*.css", // TODO?
"*.html", // TODO?
// TODO: these files are too big and complex, ignore them until their respective refactors
"src/data/moves/move.ts",
// this file is just too big:
"src/data/balance/tms.ts"
"includes": [
"**",
"!**/*.d.ts",
"!**/dist/**/*",
"!**/build/**/*",
"!**/coverage/**/*",
"!**/public/**/*",
"!**/.github/**/*",
"!**/node_modules/**/*",
"!**/.vscode/**/*",
"!**/typedoc/**/*",
// TODO: lint css and html?
"!**/*.css",
"!**/*.html",
// TODO: enable linting this file
"!**/src/data/moves/move.ts",
// this file is too big
"!**/src/data/balance/tms.ts"
]
},
// While it'd be nice to enable consistent sorting, enabling this causes issues due to circular import resolution order
// TODO: Remove if we ever get down to 0 circular imports
"organizeImports": { "enabled": false },
// TODO: Configure and enable import sorting
"assist": {
"actions": {
"source": {
"organizeImports": {
"level": "off",
"options": {
"groups": []
}
}
}
}
},
"linter": {
"enabled": true,
"rules": {
@ -48,10 +60,15 @@
"noUnusedVariables": "error",
"noSwitchDeclarations": "error",
"noVoidTypeReturn": "error",
"noUnusedImports": "error"
"noUnusedImports": {
"level": "error",
"fix": "safe"
},
"noUnusedFunctionParameters": "error",
"noUnusedLabels": "error",
"noPrivateImports": "error"
},
"style": {
"noVar": "error",
"useEnumInitializers": "off", // large enums like Moves/Species would make this cumbersome
"useBlockStatements": "error",
"useConst": "error",
@ -59,11 +76,31 @@
"noNonNullAssertion": "off", // TODO: Turn this on ASAP and fix all non-null assertions in non-test files
"noParameterAssign": "off",
"useExponentiationOperator": "off", // Too typo-prone and easy to mixup with standard multiplication (* vs **)
"useDefaultParameterLast": "off", // TODO: Fix spots in the codebase where this flag would be triggered, and then enable
"useDefaultParameterLast": {
// TODO: Fix spots in the codebase where this flag would be triggered
// and then set to "error" and re-enable the fixer
"level": "warn",
"fix": "none"
},
"useSingleVarDeclarator": "off",
"useNodejsImportProtocol": "off",
"useTemplate": "off", // string concatenation is faster: https://stackoverflow.com/questions/29055518/are-es6-template-literals-faster-than-string-concatenation
"noNamespaceImport": "error"
"useAsConstAssertion": "error",
"noUnusedTemplateLiteral": "error",
"useNumberNamespace": "error",
"noInferrableTypes": "error",
"noUselessElse": "error",
"noRestrictedTypes": {
"level": "error",
"options": {
"types": {
"integer": {
"message": "This is an alias for 'number' that can provide false impressions of what values can actually be contained in this variable. Use 'number' instead.",
"use": "number"
}
}
}
}
},
"suspicious": {
"noDoubleEquals": "error",
@ -77,45 +114,62 @@
"noImplicitAnyLet": "warn", // TODO: Refactor and make this an error
"noRedeclare": "info", // TODO: Refactor and make this an error
"noGlobalIsNan": "off",
"noAsyncPromiseExecutor": "warn" // TODO: Refactor and make this an error
"noAsyncPromiseExecutor": "warn", // TODO: Refactor and make this an error
"noVar": "error",
"noDocumentCookie": "off" // Firefox has minimal support for the "Cookie Store API"
},
"complexity": {
"noExcessiveCognitiveComplexity": "warn", // TODO: Refactor and make this an error
"noExcessiveCognitiveComplexity": "info", // TODO: Refactor and make this an error
"useLiteralKeys": "off",
"noForEach": "off", // Foreach vs for of is not that simple.
"noUselessSwitchCase": "off", // Explicit > Implicit
"noUselessConstructor": "error",
"noBannedTypes": "warn" // TODO: Refactor and make this an error
"noBannedTypes": "warn", // TODO: Refactor and make this an error
"noThisInStatic": "error",
"noUselessThisAlias": "error",
"noUselessTernary": "error"
},
"performance": {
"noNamespaceImport": "error",
"noDelete": "error"
},
"nursery": {
"noRestrictedTypes": {
"level": "error",
"options": {
"types": {
"integer": {
"message": "This is an alias for 'number' that can provide false impressions of what values can actually be contained in this variable. Use 'number' instead.",
"use": "number"
}
}
}
}
"useAdjacentGetterSetter": "error",
"noConstantBinaryExpression": "error",
"noTsIgnore": "error",
"noAwaitInLoop": "warn",
"useJsonImportAttribute": "off", // "Import attributes are only supported when the '--module' option is set to 'esnext', 'node18', 'nodenext', or 'preserve'. ts(2823)"
"useIndexOf": "error",
"useObjectSpread": "error",
"useNumericSeparators": "off", // TODO: enable?
"useIterableCallbackReturn": "warn", // TODO: refactor and make "error"
"noShadow": "warn" // TODO: refactor and make "error"
}
}
},
"javascript": {
"formatter": { "quoteStyle": "double", "arrowParentheses": "asNeeded" }
"formatter": {
"quoteStyle": "double",
"arrowParentheses": "asNeeded"
},
"parser": {
"jsxEverywhere": false
}
},
"overrides": [
{
"include": ["test/**/*.test.ts"],
"javascript": { "globals": [] },
"includes": ["**/test/**/*.test.ts"],
"linter": {
"rules": {
"performance": {
"noDelete": "off" // TODO: evaluate if this is necessary for the test(s) to function
"noDelete": "off", // TODO: evaluate if this is necessary for the test(s) to function
"noNamespaceImport": "off" // this is required for `vi.spyOn` to work in some tests
},
"style": {
"noNamespaceImport": "off" // this is required for `vi.spyOn` to work in some tests
"noNonNullAssertion": "off"
},
"nursery": {
"noFloatingPromises": "error"
}
}
}
@ -123,7 +177,7 @@
// Overrides to prevent unused import removal inside `overrides.ts` and enums files (for TSDoc linkcodes)
{
"include": ["src/overrides.ts", "src/enums/*"],
"includes": ["**/src/overrides.ts", "**/src/enums/**/*"],
"linter": {
"rules": {
"correctness": {
@ -133,7 +187,7 @@
}
},
{
"include": ["src/overrides.ts"],
"includes": ["**/src/overrides.ts"],
"linter": {
"rules": {
"style": {

View File

@ -23,7 +23,7 @@ When formatted correctly, these comments are shown within VS Code or similar IDE
- Functions also show the comment for each parameter as you type them, making keeping track of arguments inside lengthy functions much more clear.
They can also be used to generate a commentated overview of the codebase. There is a GitHub action that automatically updates [this docs site](https://pagefaultgames.github.io/pokerogue/main/index.html)
and you can generate it locally as well via `npm run docs` which will generate into the `typedoc/` directory.
and you can generate it locally as well via `pnpm run docs` which will generate into the `typedoc/` directory.
## Syntax
For an example of how TSDoc comments work, here are some TSDoc comments taken from `src/data/moves/move.ts`:

View File

@ -1,14 +1,10 @@
# Linting & Formatting
> "Any fool can write code that a computer can understand. Good programmers write code that humans can understand."
>
> — Martin Fowler
Writing clean, readable code is important, and linters and formatters are an integral part of ensuring code quality and readability.
It is for this reason we are using [Biome](https://biomejs.dev), an opinionated linter/formatter (akin to Prettier) with a heavy focus on speed and performance.
### Installation
You probably installed Biome already without noticing it - it's included inside `package.json` and should've been downloaded when you ran `npm install` after cloning the repo (assuming you followed proper instructions, that is). If you haven't done that yet, go do it.
You probably installed Biome already without noticing it - it's included inside `package.json` and should've been downloaded when you ran `pnpm install` after cloning the repo. If you haven't done that yet, go do it.
# Using Biome
@ -24,17 +20,11 @@ You will **not** be able to push code with `error`-level linting problems - fix
We also have a [Github Action](../.github/workflows/quality.yml) to verify code quality each time a PR is updated, preventing bad code from inadvertently making its way upstream.
### Why am I getting errors for code I didn't write?
<!-- TODO: Remove this if/when we perform a project wide linting spree -->
To save time and minimize friction with existing code, both the pre-commit hook and workflow run will only check files **directly changed** by a given PR or commit.
As a result, changes to files not updated since Biome's introduction can cause any _prior_ linting errors in them to resurface and get flagged.
This should occur less and less often as time passes and more files are updated to the new standard.
## Running Biome via CLI
If you want Biome to check your files manually, you can run it from the command line like so:
```sh
npx biome check --[flags]
pnpm exec biome check --[flags]
```
A full list of flags and options can be found on [their website](https://biomejs.dev/reference/cli/), but here's a few useful ones to keep in mind:
@ -56,10 +46,3 @@ Some things to consider:
Any questions about linting rules should be brought up in the `#dev-corner` channel in the discord.
[^1]: A complete list of rules can be found in the `biome.jsonc` file in the project root.
## What about ESLint?
<!-- Remove if/when we finally ditch eslint for good -->
Our project migrated away from ESLint around March 2025 due to it simply not scaling well enough with the codebase's ever-growing size. The [existing eslint rules](../eslint.config.js) are considered _deprecated_, only kept due to Biome lacking the corresponding rules in its current ruleset.
No additional ESLint rules should be added under any circumstances - even the few currently in circulation take longer to run than the entire Biome formatting/linting suite combined.

View File

@ -1,43 +0,0 @@
/** @ts-check */
import tseslint from "typescript-eslint";
import stylisticTs from "@stylistic/eslint-plugin-ts";
import parser from "@typescript-eslint/parser";
import importX from "eslint-plugin-import-x";
export default tseslint.config(
{
name: "eslint-config",
files: ["src/**/*.{ts,tsx,js,jsx}", "test/**/*.{ts,tsx,js,jsx}"],
ignores: ["dist/*", "build/*", "coverage/*", "public/*", ".github/*", "node_modules/*", ".vscode/*"],
languageOptions: {
parser: parser,
},
plugins: {
"import-x": importX,
"@stylistic/ts": stylisticTs,
"@typescript-eslint": tseslint.plugin,
},
rules: {
"no-undef": "off", // Disables the rule that disallows the use of undeclared variables (TypeScript handles this)
"no-extra-semi": "error", // Disallows unnecessary semicolons for TypeScript-specific syntax
"import-x/extensions": ["error", "never", { json: "always" }], // Enforces no extension for imports unless json
},
},
{
name: "eslint-tests",
files: ["test/**/**.test.ts"],
languageOptions: {
parser: parser,
parserOptions: {
project: ["./tsconfig.json"],
},
},
plugins: {
"@typescript-eslint": tseslint.plugin,
},
rules: {
"@typescript-eslint/no-floating-promises": "error", // Require Promise-like statements to be handled appropriately. - https://typescript-eslint.io/rules/no-floating-promises/
"@typescript-eslint/no-misused-promises": "error", // Disallow Promises in places not designed to handle them. - https://typescript-eslint.io/rules/no-misused-promises/
},
},
);

View File

@ -1,8 +1,7 @@
pre-commit:
parallel: true
commands:
biome-lint:
run: npx biome check --write --reporter=summary --staged --no-errors-on-unmatched
run: pnpm exec biome check --write --reporter=summary --staged --no-errors-on-unmatched
stage_fixed: true
skip:
- merge

8029
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
{
"name": "pokemon-rogue-battle",
"private": true,
"version": "1.9.5",
"version": "1.9.6",
"type": "module",
"scripts": {
"start": "vite",
@ -22,24 +22,19 @@
"docs": "typedoc",
"depcruise": "depcruise src test",
"depcruise:graph": "depcruise src --output-type dot | node dependency-graph.js > dependency-graph.svg",
"postinstall": "npx lefthook install && npx lefthook run post-merge",
"update-version:patch": "npm version patch --force --no-git-tag-version",
"update-version:minor": "npm version minor --force --no-git-tag-version",
"postinstall": "lefthook install && lefthook run post-merge",
"update-version:patch": "pnpm version patch --force --no-git-tag-version",
"update-version:minor": "pnpm version minor --force --no-git-tag-version",
"update-locales:remote": "git submodule update --progress --init --recursive --force --remote"
},
"devDependencies": {
"@biomejs/biome": "1.9.4",
"@eslint/js": "^9.23.0",
"@biomejs/biome": "2.0.0",
"@hpcc-js/wasm": "^2.22.4",
"@stylistic/eslint-plugin-ts": "^4.1.0",
"@types/jsdom": "^21.1.7",
"@types/node": "^22.13.14",
"@typescript-eslint/eslint-plugin": "^8.28.0",
"@typescript-eslint/parser": "^8.28.0",
"@vitest/coverage-istanbul": "^3.0.9",
"chalk": "^5.4.1",
"dependency-cruiser": "^16.3.10",
"eslint": "^9.23.0",
"eslint-plugin-import-x": "^4.9.4",
"inquirer": "^12.4.2",
"jsdom": "^26.0.0",
"lefthook": "^1.11.5",
@ -47,7 +42,6 @@
"phaser3spectorjs": "^0.0.8",
"typedoc": "^0.28.1",
"typescript": "^5.8.2",
"typescript-eslint": "^8.28.0",
"vite": "^6.3.4",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.0.9",

3910
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

View File

@ -595,6 +595,20 @@
"774-yellow",
"774",
"774",
"774-blue-meteor",
"774-blue-meteor",
"774-green-meteor",
"774-green-meteor",
"774-indigo-meteor",
"774-indigo-meteor",
"774-orange-meteor",
"774-orange-meteor",
"774-red-meteor",
"774-red-meteor",
"774-violet-meteor",
"774-violet-meteor",
"774-yellow-meteor",
"774-yellow-meteor",
"775",
"775",
"776",
@ -1705,6 +1719,20 @@
"774b-violet",
"774b-yellow",
"774b-yellow",
"774b-blue-meteor",
"774b-blue-meteor",
"774b-green-meteor",
"774b-green-meteor",
"774b-indigo-meteor",
"774b-indigo-meteor",
"774b-orange-meteor",
"774b-orange-meteor",
"774b-red-meteor",
"774b-red-meteor",
"774b-violet-meteor",
"774b-violet-meteor",
"774b-yellow-meteor",
"774b-yellow-meteor",
"774b",
"774b",
"775b",
@ -2817,6 +2845,20 @@
"774sb-violet",
"774sb-yellow",
"774sb-yellow",
"774sb-blue-meteor",
"774sb-blue-meteor",
"774sb-green-meteor",
"774sb-green-meteor",
"774sb-indigo-meteor",
"774sb-indigo-meteor",
"774sb-orange-meteor",
"774sb-orange-meteor",
"774sb-red-meteor",
"774sb-red-meteor",
"774sb-violet-meteor",
"774sb-violet-meteor",
"774sb-yellow-meteor",
"774sb-yellow-meteor",
"774sb",
"774sb",
"775sb",
@ -3934,6 +3976,20 @@
"774s-violet",
"774s-yellow",
"774s-yellow",
"774s-blue-meteor",
"774s-blue-meteor",
"774s-green-meteor",
"774s-green-meteor",
"774s-indigo-meteor",
"774s-indigo-meteor",
"774s-orange-meteor",
"774s-orange-meteor",
"774s-red-meteor",
"774s-red-meteor",
"774s-violet-meteor",
"774s-violet-meteor",
"774s-yellow-meteor",
"774s-yellow-meteor",
"774s",
"774s",
"775s",

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:566b51540ed595250ead15a4733d98d6:172aa05dcc207383119cd2f2f7977e0e:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 410 B

After

Width:  |  Height:  |  Size: 415 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:566b51540ed595250ead15a4733d98d6:172aa05dcc207383119cd2f2f7977e0e:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 410 B

After

Width:  |  Height:  |  Size: 415 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:566b51540ed595250ead15a4733d98d6:172aa05dcc207383119cd2f2f7977e0e:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 410 B

After

Width:  |  Height:  |  Size: 415 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:566b51540ed595250ead15a4733d98d6:172aa05dcc207383119cd2f2f7977e0e:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 410 B

After

Width:  |  Height:  |  Size: 415 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:566b51540ed595250ead15a4733d98d6:172aa05dcc207383119cd2f2f7977e0e:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 410 B

After

Width:  |  Height:  |  Size: 415 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:566b51540ed595250ead15a4733d98d6:172aa05dcc207383119cd2f2f7977e0e:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 410 B

After

Width:  |  Height:  |  Size: 415 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:566b51540ed595250ead15a4733d98d6:172aa05dcc207383119cd2f2f7977e0e:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 410 B

After

Width:  |  Height:  |  Size: 415 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 472 B

After

Width:  |  Height:  |  Size: 483 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 936 B

After

Width:  |  Height:  |  Size: 945 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:241dff4083e172e8503b54a7f0210f8d:982b194223ffeef2ba672b3c5979a426:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 374 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:241dff4083e172e8503b54a7f0210f8d:982b194223ffeef2ba672b3c5979a426:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 374 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:241dff4083e172e8503b54a7f0210f8d:982b194223ffeef2ba672b3c5979a426:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 374 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:241dff4083e172e8503b54a7f0210f8d:982b194223ffeef2ba672b3c5979a426:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 374 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:241dff4083e172e8503b54a7f0210f8d:982b194223ffeef2ba672b3c5979a426:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 374 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:241dff4083e172e8503b54a7f0210f8d:982b194223ffeef2ba672b3c5979a426:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 374 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:241dff4083e172e8503b54a7f0210f8d:982b194223ffeef2ba672b3c5979a426:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 470 B

After

Width:  |  Height:  |  Size: 491 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:241dff4083e172e8503b54a7f0210f8d:982b194223ffeef2ba672b3c5979a426:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

View File

@ -1,7 +1,7 @@
{
"textures": [
{
"image": "774-blue.png",
"image": "774-green.png",
"format": "RGBA8888",
"size": {
"w": 37,
@ -36,6 +36,6 @@
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:d2a43e44c5cc1c82f432212a17308d68:5faf838c8d06da9dcfb9b100f32b682b:0787168dbe37404ac3aa22b487979d47$"
"smartupdate": "$TexturePacker:SmartUpdate:15dc5fd6941072ff45be95ed6c7c8648:bc55f37f7cfc1778719aa7113bbfe914:e4b1fffb78b8c0cdc557670bcee043ca$"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 374 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:241dff4083e172e8503b54a7f0210f8d:982b194223ffeef2ba672b3c5979a426:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 374 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:241dff4083e172e8503b54a7f0210f8d:982b194223ffeef2ba672b3c5979a426:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

View File

@ -1,7 +1,7 @@
{
"textures": [
{
"image": "774-indigo.png",
"image": "774-green.png",
"format": "RGBA8888",
"size": {
"w": 37,
@ -36,6 +36,6 @@
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:98fb9e8a8436e2a8c9e7950a6cd9a86a:d89e965b091729dac43a3b5625521c2a:f6d3104f6cc09a16e2cbfcba30e4d78a$"
"smartupdate": "$TexturePacker:SmartUpdate:15dc5fd6941072ff45be95ed6c7c8648:bc55f37f7cfc1778719aa7113bbfe914:e4b1fffb78b8c0cdc557670bcee043ca$"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 374 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:241dff4083e172e8503b54a7f0210f8d:982b194223ffeef2ba672b3c5979a426:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

View File

@ -1,7 +1,7 @@
{
"textures": [
{
"image": "774-orange.png",
"image": "774-green.png",
"format": "RGBA8888",
"size": {
"w": 37,
@ -36,6 +36,6 @@
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:35a5ec7178c34950d39e76fac4d9c4e1:f0224f022e70f1f1ced7c450321b1ee7:44d5ed9bf64302a0edf6c65ea8033c12$"
"smartupdate": "$TexturePacker:SmartUpdate:15dc5fd6941072ff45be95ed6c7c8648:bc55f37f7cfc1778719aa7113bbfe914:e4b1fffb78b8c0cdc557670bcee043ca$"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 374 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:241dff4083e172e8503b54a7f0210f8d:982b194223ffeef2ba672b3c5979a426:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

View File

@ -1,7 +1,7 @@
{
"textures": [
{
"image": "774-red.png",
"image": "774-green.png",
"format": "RGBA8888",
"size": {
"w": 37,
@ -36,6 +36,6 @@
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:83c95663a6a4dd2327dd160efa96fc46:76b2340565400cf3b9209f1de35a8a7d:cda0147f4d676691e1699693bc0ee567$"
"smartupdate": "$TexturePacker:SmartUpdate:15dc5fd6941072ff45be95ed6c7c8648:bc55f37f7cfc1778719aa7113bbfe914:e4b1fffb78b8c0cdc557670bcee043ca$"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 374 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:241dff4083e172e8503b54a7f0210f8d:982b194223ffeef2ba672b3c5979a426:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

View File

@ -1,7 +1,7 @@
{
"textures": [
{
"image": "774-violet.png",
"image": "774-green.png",
"format": "RGBA8888",
"size": {
"w": 37,
@ -36,6 +36,6 @@
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:dd289c19ea84de5009d77b1701e0e91c:9e5c9078e416d3f1cee7d51e089a3ba3:cafe7bbce21f2b95187ef35011084eca$"
"smartupdate": "$TexturePacker:SmartUpdate:15dc5fd6941072ff45be95ed6c7c8648:bc55f37f7cfc1778719aa7113bbfe914:e4b1fffb78b8c0cdc557670bcee043ca$"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

After

Width:  |  Height:  |  Size: 374 B

View File

@ -0,0 +1,41 @@
{
"textures": [
{
"image": "774.png",
"format": "RGBA8888",
"size": {
"w": 37,
"h": 37
},
"scale": 1,
"frames": [
{
"filename": "0001.png",
"rotated": false,
"trimmed": false,
"sourceSize": {
"w": 37,
"h": 37
},
"spriteSourceSize": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
},
"frame": {
"x": 0,
"y": 0,
"w": 37,
"h": 37
}
}
]
}
],
"meta": {
"app": "https://www.codeandweb.com/texturepacker",
"version": "3.0",
"smartupdate": "$TexturePacker:SmartUpdate:241dff4083e172e8503b54a7f0210f8d:982b194223ffeef2ba672b3c5979a426:37281ac0aa1e619ef385b889b64064b7$"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 B

Some files were not shown because too many files have changed in this diff Show More