{"id":24703741,"url":"https://github.com/airvzxf/sniparinject","last_synced_at":"2026-05-18T00:34:54.989Z","repository":{"id":57468905,"uuid":"376885948","full_name":"airvzxf/sniparinject","owner":"airvzxf","description":"SniPar Inject is the abbreviation of these three word: Sniffer, Parser and Inject. Intercept and read the network packets to find information about the game, but it could be useful for any network sniffer.","archived":false,"fork":false,"pushed_at":"2026-01-29T09:52:33.000Z","size":93,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-01-29T21:17:24.903Z","etag":null,"topics":["game","games","hack","hacking","inject","monitor","monitoring","network","networking","packet","packets","parse","parser","sniff","sniffer","video-game","video-games"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/airvzxf.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"docs/CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"docs/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-06-14T16:19:43.000Z","updated_at":"2026-01-29T09:33:42.000Z","dependencies_parsed_at":"2022-09-19T14:00:14.647Z","dependency_job_id":null,"html_url":"https://github.com/airvzxf/sniparinject","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/airvzxf/sniparinject","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/airvzxf%2Fsniparinject","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/airvzxf%2Fsniparinject/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/airvzxf%2Fsniparinject/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/airvzxf%2Fsniparinject/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/airvzxf","download_url":"https://codeload.github.com/airvzxf/sniparinject/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/airvzxf%2Fsniparinject/sbom","scorecard":{"id":173776,"data":{"date":"2025-08-11","repo":{"name":"github.com/airvzxf/sniparinject","commit":"b82bff0c6c78c84094b7735407bb004e2dadbd9a"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.7,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":10,"reason":"SAST tool detected: CodeQL","details":["Info: SAST configuration detected: CodeQL","Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/code-ql.yml:1","Warn: no topLevel permission defined: .github/workflows/python-app.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/code-ql.yml:16: update your workflow using https://app.stepsecurity.io/secureworkflow/airvzxf/sniparinject/code-ql.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/code-ql.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/airvzxf/sniparinject/code-ql.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/code-ql.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/airvzxf/sniparinject/code-ql.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/code-ql.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/airvzxf/sniparinject/code-ql.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-app.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/airvzxf/sniparinject/python-app.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-app.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/airvzxf/sniparinject/python-app.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-app.yml:47: update your workflow using https://app.stepsecurity.io/secureworkflow/airvzxf/sniparinject/python-app.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-app.yml:50: update your workflow using https://app.stepsecurity.io/secureworkflow/airvzxf/sniparinject/python-app.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-app.yml:77: update your workflow using https://app.stepsecurity.io/secureworkflow/airvzxf/sniparinject/python-app.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-app.yml:80: update your workflow using https://app.stepsecurity.io/secureworkflow/airvzxf/sniparinject/python-app.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-app.yml:107: update your workflow using https://app.stepsecurity.io/secureworkflow/airvzxf/sniparinject/python-app.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/python-app.yml:110: update your workflow using https://app.stepsecurity.io/secureworkflow/airvzxf/sniparinject/python-app.yml/main?enable=pin","Warn: pipCommand not pinned by hash: script/pypi-build.bash:10","Warn: pipCommand not pinned by hash: script/pypi-upload.bash:10","Warn: pipCommand not pinned by hash: script/pypitest-upload.bash:11","Warn: pipCommand not pinned by hash: script/setup-dev.bash:11","Warn: pipCommand not pinned by hash: script/setup-dev.bash:12","Warn: pipCommand not pinned by hash: script/setup-dev.bash:13","Warn: pipCommand not pinned by hash: script/setup.bash:11","Warn: pipCommand not pinned by hash: script/setup.bash:12","Warn: pipCommand not pinned by hash: .github/workflows/python-app.yml:26","Warn: pipCommand not pinned by hash: .github/workflows/python-app.yml:30","Warn: pipCommand not pinned by hash: .github/workflows/python-app.yml:34","Warn: pipCommand not pinned by hash: .github/workflows/python-app.yml:56","Warn: pipCommand not pinned by hash: .github/workflows/python-app.yml:60","Warn: pipCommand not pinned by hash: .github/workflows/python-app.yml:64","Warn: pipCommand not pinned by hash: .github/workflows/python-app.yml:86","Warn: pipCommand not pinned by hash: .github/workflows/python-app.yml:90","Warn: pipCommand not pinned by hash: .github/workflows/python-app.yml:94","Warn: pipCommand not pinned by hash: .github/workflows/python-app.yml:116","Warn: pipCommand not pinned by hash: .github/workflows/python-app.yml:120","Warn: pipCommand not pinned by hash: .github/workflows/python-app.yml:124","Info:   0 out of  12 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of  20 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU General Public License v3.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":6,"reason":"4 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2023-228 / GHSA-mq26-g339-26xf","Warn: Project is vulnerable to: PYSEC-2025-49 / GHSA-5rjg-fvgr-3xxf","Warn: Project is vulnerable to: GHSA-cx63-2mw6-8hw5","Warn: Project is vulnerable to: PYSEC-2022-43012 / GHSA-r9hx-vwmv-q579"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-16T17:12:27.444Z","repository_id":57468905,"created_at":"2025-08-16T17:12:27.445Z","updated_at":"2025-08-16T17:12:27.445Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33160519,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-17T22:39:12.733Z","status":"ssl_error","status_checked_at":"2026-05-17T22:39:10.741Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["game","games","hack","hacking","inject","monitor","monitoring","network","networking","packet","packets","parse","parser","sniff","sniffer","video-game","video-games"],"created_at":"2025-01-27T05:59:20.827Z","updated_at":"2026-05-18T00:34:54.983Z","avatar_url":"https://github.com/airvzxf.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SniParInject\n\nIt is the abbreviation of these three word: Sniffer, Parser and Inject.\nIntercept and read the network packets to find information about the game, but\nit could be useful for any network sniffer purpose. The injection is coming\nsoon.\n\nThis project is work in progress. Reefer to the [To-Do's][todo] list to check\nwhat is done and what is coming.\n\n## Run it\n\n### Locally\n\nFor more information go to the [package's page in PyPi][pypi].\n\nInstall the package.\n\n```bash\npython3 -m pip install sniparinject\n```\n\n### As a developer\n\nThe only two special Python's packages that you need are `scapy` and\n`PyYAML`, the suggested version of `Python` is `\u003e= 3.10`. Follow the commands to\nset up and install this package.\n\n```bash\ngit clone https://github.com/airvzxf/sniparinject.git\ncd sniparinject || exit 123\n./script/setup-dev.bash\n```\n\nAfter this setup, it could be easy to activate the vEnv and start to work.\n\n```bash\n# Inside of the GitHub cloned directory.\nsource ./venv/bin/activate\ncd src/sniparinject || exit 123\n# Make modification to the source code files.\n# Run your changes.\n# Finally deactivate the vEnv.\ndeactivate\n```\n\n## Usage\n\nThe most basic setup is creating one Python file, and the settings file.\n\n`main.py`\n\n```python\n#!/usr/bin/env python3\n# -*- coding: UTF-8 -*-\n\"\"\"\nThe most basic example of SniParInject.\n\"\"\"\nfrom sniparinject.network_sniffer import NetworkSniffer\n\nif __name__ == '__main__':\n    SETTINGS_PATH = 'settings.yml'\n    NetworkSniffer(SETTINGS_PATH).start()\n```\n\n`settings.yml`\n\n```yaml\n%YAML 1.1\n---\nNetwork:\n  interface: enp4s0\n\nServer:\n  ip: 52.174.196.146\n  port: 5122\n\nGame:\n  node:\n    actions:\n      0x7d:\n        title: Scenario change\n      0x85:\n        title: Player move to\n        display_message: Yes\n        structs:\n          - type: chars\n            size: 3\n            output:\n              type: hex\n  host:\n    actions:\n      0x78:\n        title: NPC Info\n        structs:\n          - name: ID\n            type: unsigned int\n            output:\n              type: hex\n              auto_zero_fill: Yes\n          - type: chars\n            size: 1\n            output:\n              type: hex\n          - name: HP\n            type: unsigned short\n          - name: Max HP\n            type: unsigned short\n```\n\nThe settings, needs to set the network interface which could get by the\ncommand `ip addr` or `ls -1 /sys/class/net`. The next two are the host IP and\nits port, in our case we will use the game IP and port. You could use this\ncommand `lsof -i` to show all the process which has connection to the network,\ncheck the column `NAME` to review the connection\n`manaplus   5563 wolf ... MSIGT73EVR7RF:55238-\u003e52.174.196.146:5122\n(ESTABLISHED)`. Also, another command is\n`sudo netstat -nap | grep -i NAME_OF_GAME_PROCESS`.\n\nExecute the application:\n\n```bash\n# Execute with root permissions the main script.\nsudo python3 main.py\n```\n\n### Example\n\nThis example is for the game `Mana Plus`.\n\n[![asciicast][ascii-mana-image]][ascii-mana-link]\n\n## Settings\n\nThis software **does not need** to **modify** any file in the **source code**.\nCreate a `settings.yml` file which is able to add, modify or remove any parse\nrules.\n\n### Examples\n\nThe required fields for the `Server` information are `ip`, `port` or both.\n\n```yaml\nNetwork:\n  interface: enp4s0\n\nServer:\n  ip: 52.174.196.146\n  port: 5122\n```\n\n---\n\nThe default protocol is `TCP` but you can assign the `UDP`.\n\n```yaml\nNetwork:\n  interface: enp4s0\n\nServer:\n  protocol: UDP\n  port: 6666\n```\n\n---\n\nThis is the basic structure without any rule.\n\n```yaml\nGame:\n  node:\n  host:\n```\n\n---\n\nExample for node, which is the raw data send from your computer to the server.\n\nHere will capture all the packets which start with the id `0x7d` equal to the\nraw data `\\x00\\x7d`. It will print in your console:\n`--\u003e Scenario change |` every time your computer send to the server this\npacket.\n\nThe action `0x85` equal to the raw data `\\x00\\x85`. It will print in your\nconsole: `--\u003e Player move to | a07f18 |`. Means the player communicate to the\nserver that it is moving to this position.\n\n```yaml\nGame:\n  node:\n    actions:\n      0x7d:\n        title: Scenario change\n      0x85:\n        title: Player move to\n        structs:\n          - type: chars\n            size: 3\n            output:\n              type: hex\n```\n\n---\n\nSame example as above, but we do not want to print the action `Player move to`.\nAdd `display_message: No` in the action which want to avoid the print.\n\n```yaml\nGame:\n  node:\n    actions:\n      0x7d:\n        title: Scenario change\n      0x85:\n        title: Player move to\n        display_message: No\n        structs:\n          - type: chars\n            size: 3\n            output:\n              type: hex\n```\n\n---\n\nSame example as above, but we do not want to print any node action, it means\nthe actions sent by you computer to the server. It will print only the host's\nactions. The default value for the node/host or actions is always\n`display_message: Yes`, it does need to set explicitly.\n\n```yaml\nGame:\n  node:\n    display_message: No\n    actions:\n      0x7d:\n        title: Scenario change\n  host:\n    actions:\n      0xad:\n        title: Scenario change\n```\n\n---\n\nWhat are the structs? It is the way that it will parse the data. Basically,\nsplit the raw data based on the Python Structs which are C Types. They are\nwell-known as an integer, char, long, float, etc. You will find information in\nthe official web page [Python Structs][structs]. In the game the function which\ncontains this logic is\n`def _get_struct(self, struct_type: str, repeat_count: int = 1)`\nin `./core/game.py`.\n\n```python\n# 'ID': ('Python struct symbol', Size in bytes)\nstructs = {\n    'char': ('c', 1),\n    'signed char': ('b', 1),\n    'unsigned char': ('B', 1),\n    'bool': ('?', 1),\n    'short': ('h', 2),\n    'unsigned short': ('H', 2),\n    'int': ('i', 4),\n    'unsigned int': ('I', 4),\n    'long': ('q', 8),\n    'unsigned long': ('Q', 8),\n    'half precision': ('e', 2),\n    'float': ('f', 4),\n    'double': ('d', 6),\n    'chars': ('s', 0),\n}\n```\n\n---\n\nThe option `size` returns the number of repeats of this struct. One example is\nif the setting's action has `type: int` and `size: 8`, it will returns\n`4i` and it is exactly the same to write `iiii`. The example below will\nreturn `5s`.\n\n```yaml\nstructs:\n  - type: chars\n    size: 5\n```\n\n---\n\nIn this example it will take the raw data and split in two. The first is an\n`unsigned int` with `4 bytes` of size and the `char` with `1 byte` of size. The\nraw data could be `\\x00\\x80 \\x0f\\x00\\x00\\x00 \\xf8`, I split intentional with\nspaces to be more clear. The rule in the example take the first\n`unsigned short` value as an action ID (`\\x00\\x80` equal to `0x80`), then\nextract as a `unsigned int` the monster ID, and the last byte as an unknown.\nThe output will be `---\u003e NPC Monster Check | ID 0x0000000f | 0xf8 |`. Note in\nthe monster ID that the raw data, and the output is different:\n`\\x0f\\x00\\x00\\x00` vs `0x0000000f`. It is because the network data is coming\nin `big-endian` and the human / machine-readable for numbers is\nin `little-endian`.\n\n```yaml\nGame:\n  node:\n    actions:\n      0x80:\n        title: NPC Monster Check\n        structs:\n          - name: ID\n            type: unsigned int\n            output:\n              type: hex\n              auto_zero_fill: Yes\n          - type: chars\n            size: 1\n            output:\n              type: hex\n```\n\n---\n\nIn every struct there is an option to add the name which will display before\nthe value. In the follow example the first struct does not have the name, and\nthe second has the name id. The output will be\n`---\u003e NPC Monster Check | 56 | ID 78 |`.\n\n```yaml\nGame:\n  node:\n    actions:\n      0x80:\n        title: NPC Monster Check\n        structs:\n          - type: unsigned int\n          - name: ID\n            type: unsigned int\n```\n\n---\n\nWhat happen if I do not use the `output` as an `hex`? It will show the raw\ndata: `---\u003e NPC Monster Check | ID b'\\x00\\x00\\x00\\x0f' |`\n\n```yaml\nGame:\n  node:\n    actions:\n      0x80:\n        title: NPC Monster Check\n        structs:\n          - name: ID\n            type: chars\n            size: 4\n```\n\n---\n\nTake a little break for output and check the `reference` option. In the middle\ntime that you are parsing the data, some findings will be discovered for\nexample the ID types of the shop options. It is possible to map this\ninformation and display as a text in the output. Adding `reference:\n*node_shop_options` to your settings, it will take the section referring with\nthe ID `shop_options: \u0026node_shop_options`. If the value is not in the map, it\nwill print as usual.\n\nGiven the raw data `\\x00\\xc5 \\x00`, the output will be\n`---\u003e Shop store | ID Buy |`.\n\nGiven the raw data `\\x00\\xc5 \\x01`, the output will be\n`---\u003e Shop store | ID Sell |`.\n\nGiven the raw data `\\x00\\xc5 \\x5a`, the output will be\n`---\u003e Shop store | ID 0x5a |`.\n\n```yaml\nGame:\n  node:\n    references:\n      shop_options: \u0026node_shop_options\n        0x0: 'Buy'\n        0x1: 'Sell'\n    actions:\n      0xc5:\n        title: Shop store\n        structs:\n          - name: ID\n            type: unsigned char\n            reference: *node_shop_options\n            output:\n              type: hex\n              auto_zero_fill: Yes\n```\n\n---\n\nFormatting the `output` is possible with these options `zero_fill`,\n`auto_zero_fill`, `fill` and `fill_left`.\n\n- `zero_fill` - Add zeros to the left for example if you have for digits as an\n  output `0x12` and the property set to `8`, it will display:\n  `00000x12`.\n- `auto_zero_fill` - Add zeros to the left taking the type of the structure.\n  For example if you have an `integer` with `byte size of 4`, but the value\n  is `5`. The output without this option will be `0x05`, then if your next\n  value is `123456789` the output will be `0x75bcd15`. Keep aligned the output\n  and using the property `auto_zero_fill: Yes` it will display both numbers\n  as`0000000x05` and `00x75bcd15` because the\n  `integer` is `4 bytes` equal to `00 00 00 00` plus the pre-fix `0x`, it means\n  10 digits.\n- `fill` - Same as `zero_fill` but add blank spaces to the right of the value.\n- `fill_left` - Same as the previous option but add blank spaces to the left of\n  the value.\n\n```yaml\nGame:\n  node:\n    actions:\n      0x146:\n        title: NPC Dialog close\n        structs:\n          - type: unsigned int\n            output:\n              type: hex\n              zero_fill: 20\n          - type: unsigned int\n            output:\n              type: hex\n              auto_zero_fill: Yes\n          - type: unsigned int\n            output:\n              type: hex\n              fill: 9\n          - type: unsigned int\n            output:\n              type: hex\n              fill_left: 17\n```\n\n## Endian\n\nAll the data coming from the network or server usually is big-endian, to read\nthis as the game interpretation needs to convert to little-endian. In this\nexample if you receive a raw data `ff 00 ab 14 36 f0 1f`. The parse should be:\n\n- ID Action package: `ff 00` = `0x00ff` = `255`.\n- ID Monster: `ab 14 36 f0` = `0xf03614ab`.\n- Unknown: `1f` = `0x1f` = `31`.\n\nEnjoy!\n\n\n[pypi]: https://pypi.org/project/sniparinject/\n\n[todo]: https://github.com/airvzxf/sniparinject/blob/main/TODO.md\n\n[ascii-mana-image]: https://asciinema.org/a/R0mxcmrpWHzX96NDJyc7kyTDB.svg\n\n[ascii-mana-link]: https://asciinema.org/a/R0mxcmrpWHzX96NDJyc7kyTDB\n\n[structs]: https://docs.python.org/3/library/struct.html#format-characters\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fairvzxf%2Fsniparinject","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fairvzxf%2Fsniparinject","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fairvzxf%2Fsniparinject/lists"}