Move Chunks things from Client to Player
Also made Chunk handling more robust
This commit is contained in:
parent
ba6f50aae0
commit
e0dd8d6b61
23
.github/workflows/rust.yml
vendored
23
.github/workflows/rust.yml
vendored
@ -6,6 +6,7 @@ on:
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
RUSTFLAGS: "-Dwarnings"
|
||||
|
||||
jobs:
|
||||
format:
|
||||
@ -15,12 +16,9 @@ jobs:
|
||||
matrix:
|
||||
toolchain:
|
||||
- stable
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
|
||||
|
||||
- run: cargo fmt --check
|
||||
clippy:
|
||||
name: Run lints
|
||||
@ -29,27 +27,21 @@ jobs:
|
||||
matrix:
|
||||
toolchain:
|
||||
- stable
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
|
||||
|
||||
- run: cargo clippy --all-targets --all-features --no-default-features -- -D warnings
|
||||
- run: cargo clippy --all-targets --all-features --no-default-features
|
||||
build_and_test:
|
||||
name: Build project and test
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
toolchain:
|
||||
- stable
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
|
||||
|
||||
- run: cargo build --verbose
|
||||
- run: cargo test --verbose
|
||||
build_release:
|
||||
name: Build project in release
|
||||
@ -59,12 +51,10 @@ jobs:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
toolchain:
|
||||
- stable
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
|
||||
|
||||
- run: cargo build --verbose --release
|
||||
- name: Export executable
|
||||
uses: actions/upload-artifact@v4
|
||||
@ -79,10 +69,7 @@ jobs:
|
||||
matrix:
|
||||
toolchain:
|
||||
- stable
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- run: rustup update ${{ matrix.toolchain }} && rustup default ${{ matrix.toolchain }}
|
||||
|
||||
- run: cargo clippy --release --all-targets --all-features --no-default-features -- -D warnings
|
||||
- run: cargo clippy --release --all-targets --all-features --no-default-features
|
||||
|
||||
222
package-lock.json
generated
222
package-lock.json
generated
@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "Pumpkin",
|
||||
"name": "pumpkin",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
@ -848,9 +848,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz",
|
||||
"integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==",
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.2.tgz",
|
||||
"integrity": "sha512-ufoveNTKDg9t/b7nqI3lwbCG/9IJMhADBNjjz/Jn6LxIZxD7T5L8l2uO/wD99945F1Oo8FvgbbZJRguyk/BdzA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@ -862,9 +862,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz",
|
||||
"integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==",
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.2.tgz",
|
||||
"integrity": "sha512-iZoYCiJz3Uek4NI0J06/ZxUgwAfNzqltK0MptPDO4OR0a88R4h0DSELMsflS6ibMCJ4PnLvq8f7O1d7WexUvIA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -876,9 +876,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz",
|
||||
"integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==",
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.2.tgz",
|
||||
"integrity": "sha512-/UhrIxobHYCBfhi5paTkUDQ0w+jckjRZDZ1kcBL132WeHZQ6+S5v9jQPVGLVrLbNUebdIRpIt00lQ+4Z7ys4Rg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -890,9 +890,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz",
|
||||
"integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==",
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.2.tgz",
|
||||
"integrity": "sha512-1F/jrfhxJtWILusgx63WeTvGTwE4vmsT9+e/z7cZLKU8sBMddwqw3UV5ERfOV+H1FuRK3YREZ46J4Gy0aP3qDA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -903,10 +903,38 @@
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.2.tgz",
|
||||
"integrity": "sha512-1YWOpFcGuC6iGAS4EI+o3BV2/6S0H+m9kFOIlyFtp4xIX5rjSnL3AwbTBxROX0c8yWtiWM7ZI6mEPTI7VkSpZw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.2.tgz",
|
||||
"integrity": "sha512-3qAqTewYrCdnOD9Gl9yvPoAoFAVmPJsBvleabvx4bnu1Kt6DrB2OALeRVag7BdWGWLhP1yooeMLEi6r2nYSOjg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz",
|
||||
"integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==",
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.2.tgz",
|
||||
"integrity": "sha512-ArdGtPHjLqWkqQuoVQ6a5UC5ebdX8INPuJuJNWRe0RGa/YNhVvxeWmCTFQ7LdmNCSUzVZzxAvUznKaYx645Rig==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@ -918,9 +946,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz",
|
||||
"integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==",
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.2.tgz",
|
||||
"integrity": "sha512-B6UHHeNnnih8xH6wRKB0mOcJGvjZTww1FV59HqJoTJ5da9LCG6R4SEBt6uPqzlawv1LoEXSS0d4fBlHNWl6iYw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@ -932,9 +960,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz",
|
||||
"integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==",
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.2.tgz",
|
||||
"integrity": "sha512-kr3gqzczJjSAncwOS6i7fpb4dlqcvLidqrX5hpGBIM1wtt0QEVtf4wFaAwVv8QygFU8iWUMYEoJZWuWxyua4GQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -946,9 +974,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz",
|
||||
"integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==",
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.2.tgz",
|
||||
"integrity": "sha512-TDdHLKCWgPuq9vQcmyLrhg/bgbOvIQ8rtWQK7MRxJ9nvaxKx38NvY7/Lo6cYuEnNHqf6rMqnivOIPIQt6H2AoA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -960,9 +988,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz",
|
||||
"integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==",
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.2.tgz",
|
||||
"integrity": "sha512-xv9vS648T3X4AxFFZGWeB5Dou8ilsv4VVqJ0+loOIgDO20zIhYfDLkk5xoQiej2RiSQkld9ijF/fhLeonrz2mw==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
@ -974,9 +1002,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz",
|
||||
"integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==",
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.2.tgz",
|
||||
"integrity": "sha512-tbtXwnofRoTt223WUZYiUnbxhGAOVul/3StZ947U4A5NNjnQJV5irKMm76G0LGItWs6y+SCjUn/Q0WaMLkEskg==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
@ -988,9 +1016,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz",
|
||||
"integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==",
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.2.tgz",
|
||||
"integrity": "sha512-gc97UebApwdsSNT3q79glOSPdfwgwj5ELuiyuiMY3pEWMxeVqLGKfpDFoum4ujivzxn6veUPzkGuSYoh5deQ2Q==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
@ -1002,9 +1030,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz",
|
||||
"integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==",
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.2.tgz",
|
||||
"integrity": "sha512-jOG/0nXb3z+EM6SioY8RofqqmZ+9NKYvJ6QQaa9Mvd3RQxlH68/jcB/lpyVt4lCiqr04IyaC34NzhUqcXbB5FQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -1016,9 +1044,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz",
|
||||
"integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==",
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.2.tgz",
|
||||
"integrity": "sha512-XAo7cJec80NWx9LlZFEJQxqKOMz/lX3geWs2iNT5CHIERLFfd90f3RYLLjiCBm1IMaQ4VOX/lTC9lWfzzQm14Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -1030,9 +1058,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz",
|
||||
"integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==",
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.2.tgz",
|
||||
"integrity": "sha512-A+JAs4+EhsTjnPQvo9XY/DC0ztaws3vfqzrMNMKlwQXuniBKOIIvAAI8M0fBYiTCxQnElYu7mLk7JrhlQ+HeOw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@ -1044,9 +1072,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz",
|
||||
"integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==",
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.2.tgz",
|
||||
"integrity": "sha512-ZhcrakbqA1SCiJRMKSU64AZcYzlZ/9M5LaYil9QWxx9vLnkQ9Vnkve17Qn4SjlipqIIBFKjBES6Zxhnvh0EAEw==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@ -1058,9 +1086,9 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz",
|
||||
"integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==",
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.2.tgz",
|
||||
"integrity": "sha512-2mLH46K1u3r6uwc95hU+OR9q/ggYMpnS7pSp83Ece1HUQgF9Nh/QwTK5rcgbFnV9j+08yBrU5sA/P0RK2MSBNA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@ -1072,57 +1100,57 @@
|
||||
]
|
||||
},
|
||||
"node_modules/@shikijs/core": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.1.tgz",
|
||||
"integrity": "sha512-bqAhT/Ri5ixV4oYsvJNH8UJjpjbINWlWyXY6tBTsP4OmD6XnFv43nRJ+lTdxd2rmG5pgam/x+zGR6kLRXrpEKA==",
|
||||
"version": "1.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.22.2.tgz",
|
||||
"integrity": "sha512-bvIQcd8BEeR1yFvOYv6HDiyta2FFVePbzeowf5pPS1avczrPK+cjmaxxh0nx5QzbON7+Sv0sQfQVciO7bN72sg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@shikijs/engine-javascript": "1.22.1",
|
||||
"@shikijs/engine-oniguruma": "1.22.1",
|
||||
"@shikijs/types": "1.22.1",
|
||||
"@shikijs/engine-javascript": "1.22.2",
|
||||
"@shikijs/engine-oniguruma": "1.22.2",
|
||||
"@shikijs/types": "1.22.2",
|
||||
"@shikijs/vscode-textmate": "^9.3.0",
|
||||
"@types/hast": "^3.0.4",
|
||||
"hast-util-to-html": "^9.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@shikijs/engine-javascript": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.1.tgz",
|
||||
"integrity": "sha512-540pyoy0LWe4jj2BVbgELwOFu1uFvRI7lg4hdsExrSXA9x7gqfzZ/Nnh4RfX86aDAgJ647gx4TCmRwACbnQSvw==",
|
||||
"version": "1.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-1.22.2.tgz",
|
||||
"integrity": "sha512-iOvql09ql6m+3d1vtvP8fLCVCK7BQD1pJFmHIECsujB0V32BJ0Ab6hxk1ewVSMFA58FI0pR2Had9BKZdyQrxTw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@shikijs/types": "1.22.1",
|
||||
"@shikijs/types": "1.22.2",
|
||||
"@shikijs/vscode-textmate": "^9.3.0",
|
||||
"oniguruma-to-js": "0.4.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@shikijs/engine-oniguruma": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.1.tgz",
|
||||
"integrity": "sha512-L+1Vmd+a2kk8HtogUFymQS6BjUfJnzcWoUp1BUgxoDiklbKSMvrsMuLZGevTOP1m0rEjgnC5MsDmsr8lX1lC+Q==",
|
||||
"version": "1.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.22.2.tgz",
|
||||
"integrity": "sha512-GIZPAGzQOy56mGvWMoZRPggn0dTlBf1gutV5TdceLCZlFNqWmuc7u+CzD0Gd9vQUTgLbrt0KLzz6FNprqYAxlA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@shikijs/types": "1.22.1",
|
||||
"@shikijs/types": "1.22.2",
|
||||
"@shikijs/vscode-textmate": "^9.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@shikijs/transformers": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-1.22.1.tgz",
|
||||
"integrity": "sha512-KvG49YFV6gV116sC4L3Sn1Rp6HXsioMKBBG373j088rw849440hm8s2r+/dgjsGLvT4p+QB7newev+5a3ARM6w==",
|
||||
"version": "1.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@shikijs/transformers/-/transformers-1.22.2.tgz",
|
||||
"integrity": "sha512-8f78OiBa6pZDoZ53lYTmuvpFPlWtevn23bzG+azpPVvZg7ITax57o/K3TC91eYL3OMJOO0onPbgnQyZjRos8XQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"shiki": "1.22.1"
|
||||
"shiki": "1.22.2"
|
||||
}
|
||||
},
|
||||
"node_modules/@shikijs/types": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.1.tgz",
|
||||
"integrity": "sha512-+45f8mu/Hxqs6Kyhfm98Nld5n7Q7lwhjU8UtdQwrOPs7BnM4VAb929O3IQ2ce+4D7SlNFlZGd8CnKRSnwbQreQ==",
|
||||
"version": "1.22.2",
|
||||
"resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.22.2.tgz",
|
||||
"integrity": "sha512-NCWDa6LGZqTuzjsGfXOBWfjS/fDIbDdmVDug+7ykVe1IKT4c1gakrvlfFYp5NhAXH/lyqLM8wsAPo5wNy73Feg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -2136,9 +2164,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.24.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz",
|
||||
"integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==",
|
||||
"version": "4.24.2",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.2.tgz",
|
||||
"integrity": "sha512-do/DFGq5g6rdDhdpPq5qb2ecoczeK6y+2UAjdJ5trjQJj5f1AiVdLRWRc9A9/fFukfvJRgM0UXzxBIYMovm5ww==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@ -2152,22 +2180,24 @@
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.24.0",
|
||||
"@rollup/rollup-android-arm64": "4.24.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.24.0",
|
||||
"@rollup/rollup-darwin-x64": "4.24.0",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.24.0",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.24.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.24.0",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.24.0",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.24.0",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.24.0",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.24.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.24.0",
|
||||
"@rollup/rollup-linux-x64-musl": "4.24.0",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.24.0",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.24.0",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.24.0",
|
||||
"@rollup/rollup-android-arm-eabi": "4.24.2",
|
||||
"@rollup/rollup-android-arm64": "4.24.2",
|
||||
"@rollup/rollup-darwin-arm64": "4.24.2",
|
||||
"@rollup/rollup-darwin-x64": "4.24.2",
|
||||
"@rollup/rollup-freebsd-arm64": "4.24.2",
|
||||
"@rollup/rollup-freebsd-x64": "4.24.2",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.24.2",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.24.2",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.24.2",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.24.2",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.24.2",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.24.2",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.24.2",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.24.2",
|
||||
"@rollup/rollup-linux-x64-musl": "4.24.2",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.24.2",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.24.2",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.24.2",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
@ -2180,16 +2210,16 @@
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/shiki": {
|
||||
"version": "1.22.1",
|
||||
"resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.1.tgz",
|
||||
"integrity": "sha512-PbJ6XxrWLMwB2rm3qdjIHNm3zq4SfFnOx0B3rEoi4AN8AUngsdyZ1tRe5slMPtn6jQkbUURLNZPpLR7Do3k78g==",
|
||||
"version": "1.22.2",
|
||||
"resolved": "https://registry.npmjs.org/shiki/-/shiki-1.22.2.tgz",
|
||||
"integrity": "sha512-3IZau0NdGKXhH2bBlUk4w1IHNxPh6A5B2sUpyY+8utLu2j/h1QpFkAaUA1bAMxOWWGtTWcAh531vnS4NJKS/lA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@shikijs/core": "1.22.1",
|
||||
"@shikijs/engine-javascript": "1.22.1",
|
||||
"@shikijs/engine-oniguruma": "1.22.1",
|
||||
"@shikijs/types": "1.22.1",
|
||||
"@shikijs/core": "1.22.2",
|
||||
"@shikijs/engine-javascript": "1.22.2",
|
||||
"@shikijs/engine-oniguruma": "1.22.2",
|
||||
"@shikijs/types": "1.22.2",
|
||||
"@shikijs/vscode-textmate": "^9.3.0",
|
||||
"@types/hast": "^3.0.4"
|
||||
}
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
use thiserror::Error;
|
||||
|
||||
use super::block_registry::get_block;
|
||||
|
||||
#[derive(Clone)]
|
||||
@ -10,26 +8,32 @@ pub struct BlockState {
|
||||
impl BlockState {
|
||||
pub const AIR: BlockState = BlockState { state_id: 0 };
|
||||
|
||||
pub fn new(registry_id: &str) -> Result<Self, BlockStateError> {
|
||||
let block_registry = get_block(registry_id).ok_or(
|
||||
BlockStateError::BlockIdentifierNotFound(registry_id.to_string()),
|
||||
)?;
|
||||
Ok(Self {
|
||||
state_id: block_registry.default_state_id,
|
||||
/// Get a Block from the Vanilla Block registry at Runtime
|
||||
pub fn new(registry_id: &str) -> Option<Self> {
|
||||
let block = get_block(registry_id);
|
||||
block.map(|block| Self {
|
||||
state_id: block.default_state_id,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_id(&self) -> u16 {
|
||||
self.state_id
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_id_mojang_repr(&self) -> i32 {
|
||||
self.state_id as i32
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::BlockState;
|
||||
|
||||
#[test]
|
||||
fn not_existing() {
|
||||
let result = BlockState::new("this_block_does_not_exist");
|
||||
assert!(result.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn does_exist() {
|
||||
let result = BlockState::new("minecraft:dirt");
|
||||
assert!(result.is_some());
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum BlockStateError {
|
||||
#[error("The requested block identifier does not exist {0}")]
|
||||
BlockIdentifierNotFound(String),
|
||||
}
|
||||
|
||||
@ -91,10 +91,7 @@ impl ChunkReader for AnvilChunkReader {
|
||||
save_file: &SaveFile,
|
||||
at: &pumpkin_core::math::vector2::Vector2<i32>,
|
||||
) -> Result<super::ChunkData, ChunkReadingError> {
|
||||
let region = (
|
||||
((at.x as f32) / 32.0).floor() as i32,
|
||||
((at.z as f32) / 32.0).floor() as i32,
|
||||
);
|
||||
let region = (at.x >> 5, at.z >> 5);
|
||||
|
||||
let mut region_file = OpenOptions::new()
|
||||
.read(true)
|
||||
@ -162,3 +159,28 @@ impl ChunkReader for AnvilChunkReader {
|
||||
ChunkData::from_bytes(decompressed_chunk, *at).map_err(ChunkReadingError::ParsingError)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::PathBuf;
|
||||
|
||||
use pumpkin_core::math::vector2::Vector2;
|
||||
|
||||
use crate::{
|
||||
chunk::{anvil::AnvilChunkReader, ChunkReader, ChunkReadingError},
|
||||
level::SaveFile,
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn not_existing() {
|
||||
let region_path = PathBuf::from("not_existing");
|
||||
let result = AnvilChunkReader::new().read_chunk(
|
||||
&SaveFile {
|
||||
root_folder: PathBuf::from(""),
|
||||
region_folder: region_path,
|
||||
},
|
||||
&Vector2::new(0, 0),
|
||||
);
|
||||
assert!(matches!(result, Err(ChunkReadingError::ChunkNotExist)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::{
|
||||
block::{block_state::BlockStateError, BlockId, BlockState},
|
||||
block::{BlockId, BlockState},
|
||||
coordinates::{ChunkRelativeBlockCoordinates, Height},
|
||||
level::SaveFile,
|
||||
WORLD_HEIGHT,
|
||||
@ -223,7 +223,8 @@ impl Index<ChunkRelativeBlockCoordinates> for ChunkBlocks {
|
||||
|
||||
impl ChunkData {
|
||||
pub fn from_bytes(chunk_data: Vec<u8>, at: Vector2<i32>) -> Result<Self, ChunkParsingError> {
|
||||
if fastnbt::from_bytes::<ChunkStatus>(&chunk_data).expect("Failed reading chunk status.")
|
||||
if fastnbt::from_bytes::<ChunkStatus>(&chunk_data)
|
||||
.map_err(|_| ChunkParsingError::FailedReadStatus)?
|
||||
!= ChunkStatus::Full
|
||||
{
|
||||
return Err(ChunkParsingError::ChunkNotGenerated);
|
||||
@ -247,8 +248,8 @@ impl ChunkData {
|
||||
.iter()
|
||||
.map(|entry| match BlockState::new(&entry.name) {
|
||||
// Block not found, Often the case when World has an newer or older version then block registry
|
||||
Err(_) => BlockState::AIR,
|
||||
Ok(state) => state,
|
||||
None => BlockState::AIR,
|
||||
Some(state) => state,
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
@ -309,8 +310,8 @@ impl ChunkData {
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ChunkParsingError {
|
||||
#[error("BlockState error: {0}")]
|
||||
BlockStateError(BlockStateError),
|
||||
#[error("Failed reading chunk status")]
|
||||
FailedReadStatus,
|
||||
#[error("The chunk isn't generated yet")]
|
||||
ChunkNotGenerated,
|
||||
#[error("Error deserializing chunk: {0}")]
|
||||
|
||||
@ -37,8 +37,7 @@ pub struct Level {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SaveFile {
|
||||
#[expect(dead_code)]
|
||||
root_folder: PathBuf,
|
||||
pub root_folder: PathBuf,
|
||||
pub region_folder: PathBuf,
|
||||
}
|
||||
|
||||
@ -63,10 +62,6 @@ impl Level {
|
||||
chunk_watchers: Arc::new(DashMap::new()),
|
||||
}
|
||||
} else {
|
||||
log::warn!(
|
||||
"Pumpkin currently only supports Superflat World generation. Use a vanilla ./world folder to play in a normal world."
|
||||
);
|
||||
|
||||
Self {
|
||||
world_gen,
|
||||
save_file: None,
|
||||
|
||||
@ -3,7 +3,7 @@ use pumpkin_core::math::vector3::Vector3;
|
||||
use crate::block::block_state::BlockState;
|
||||
|
||||
pub struct ProtoChunk {
|
||||
state: GenerationState,
|
||||
// may want to use chunk status
|
||||
}
|
||||
|
||||
impl ProtoChunk {
|
||||
@ -11,19 +11,3 @@ impl ProtoChunk {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, PartialOrd)]
|
||||
pub enum GenerationState {
|
||||
Empty,
|
||||
StructureStart,
|
||||
StructureRef,
|
||||
Biome,
|
||||
Noise,
|
||||
Surface,
|
||||
Carver,
|
||||
Feature,
|
||||
InitLight,
|
||||
Light,
|
||||
Spawn,
|
||||
Full,
|
||||
}
|
||||
|
||||
@ -42,7 +42,7 @@ rsa = "0.9.6"
|
||||
rsa-der = "0.3.0"
|
||||
|
||||
# authentication
|
||||
reqwest = { version = "0.12.8", default-features = false, features = [
|
||||
reqwest = { version = "0.12.9", default-features = false, features = [
|
||||
"http2",
|
||||
"json",
|
||||
"macos-system-configuration",
|
||||
|
||||
@ -141,7 +141,7 @@ pub enum AuthError {
|
||||
DisallowedAction,
|
||||
#[error("Failed to parse JSON into Game Profile")]
|
||||
FailedParse,
|
||||
#[error("Unknown Status Code")]
|
||||
#[error("Unknown Status Code {0}")]
|
||||
UnknownStatusCode(StatusCode),
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
collections::VecDeque,
|
||||
net::SocketAddr,
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicI32},
|
||||
@ -16,7 +16,7 @@ use authentication::GameProfile;
|
||||
use crossbeam::atomic::AtomicCell;
|
||||
use num_traits::FromPrimitive;
|
||||
use pumpkin_config::compression::CompressionInfo;
|
||||
use pumpkin_core::{math::vector2::Vector2, text::TextComponent};
|
||||
use pumpkin_core::text::TextComponent;
|
||||
use pumpkin_protocol::{
|
||||
bytebuf::DeserializerError,
|
||||
client::{config::CConfigDisconnect, login::CLoginDisconnect, play::CPlayDisconnect},
|
||||
@ -36,12 +36,8 @@ use pumpkin_protocol::{
|
||||
},
|
||||
ClientPacket, ConnectionState, PacketError, RawPacket, ServerPacket,
|
||||
};
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::sync::Mutex;
|
||||
use tokio::{
|
||||
io::{AsyncReadExt, AsyncWriteExt},
|
||||
sync::Notify,
|
||||
task::JoinHandle,
|
||||
};
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
@ -93,42 +89,6 @@ impl Default for PlayerConfig {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ChunkHandleWrapper {
|
||||
handle: Option<JoinHandle<()>>,
|
||||
aborted: bool,
|
||||
}
|
||||
|
||||
impl ChunkHandleWrapper {
|
||||
#[must_use]
|
||||
pub fn new(handle: JoinHandle<()>) -> Self {
|
||||
Self {
|
||||
handle: Some(handle),
|
||||
aborted: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn abort(&mut self) {
|
||||
self.aborted = true;
|
||||
if let Some(handle) = &self.handle {
|
||||
handle.abort();
|
||||
} else {
|
||||
log::error!("Trying to abort without a handle!");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn take_handle(&mut self) -> JoinHandle<()> {
|
||||
self.handle.take().unwrap()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn aborted(&self) -> bool {
|
||||
self.aborted
|
||||
}
|
||||
}
|
||||
|
||||
pub type PlayerPendingChunks =
|
||||
Arc<parking_lot::Mutex<HashMap<Vector2<i32>, VecDeque<ChunkHandleWrapper>>>>;
|
||||
|
||||
/// Everything which makes a Connection with our Server is a `Client`.
|
||||
/// Client will become Players when they reach the `Play` state
|
||||
pub struct Client {
|
||||
@ -164,18 +124,6 @@ pub struct Client {
|
||||
pub client_packets_queue: Arc<Mutex<VecDeque<RawPacket>>>,
|
||||
/// Indicates whether the client should be converted into a player.
|
||||
pub make_player: AtomicBool,
|
||||
|
||||
//TODO: Is there a way to consolidate these two?
|
||||
//Need to lookup by chunk, but also would be need to contain all the stuff
|
||||
//In a PendingBatch struct. Is there a cheap way to map multiple keys to a single element?
|
||||
//
|
||||
/// Individual chunk tasks that this client is waiting for
|
||||
pub pending_chunks: PlayerPendingChunks,
|
||||
/// Chunk batches that this client is waiting for
|
||||
pub pending_chunk_batch: parking_lot::Mutex<HashMap<uuid::Uuid, JoinHandle<()>>>,
|
||||
|
||||
/// Tell tasks to stop if we are closing
|
||||
cancel_tasks: Notify,
|
||||
}
|
||||
|
||||
impl Client {
|
||||
@ -199,9 +147,6 @@ impl Client {
|
||||
closed: AtomicBool::new(false),
|
||||
client_packets_queue: Arc::new(Mutex::new(VecDeque::new())),
|
||||
make_player: AtomicBool::new(false),
|
||||
pending_chunks: Arc::new(parking_lot::Mutex::new(HashMap::new())),
|
||||
pending_chunk_batch: parking_lot::Mutex::new(HashMap::new()),
|
||||
cancel_tasks: Notify::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -299,10 +244,6 @@ impl Client {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn await_cancel(&self) {
|
||||
self.cancel_tasks.notified().await;
|
||||
}
|
||||
|
||||
/// Processes all packets send by the client
|
||||
pub async fn process_packets(&self, server: &Arc<Server>) {
|
||||
let mut packet_queue = self.client_packets_queue.lock().await;
|
||||
@ -311,23 +252,15 @@ impl Client {
|
||||
log::debug!("Canceling client packet processing (pre)");
|
||||
return;
|
||||
}
|
||||
tokio::select! {
|
||||
() = self.cancel_tasks.notified() => {
|
||||
log::debug!("Canceling client packet processing (interrupt)");
|
||||
return;
|
||||
},
|
||||
packet_result = self.handle_packet(server, &mut packet) => {
|
||||
if let Err(error) = packet_result {
|
||||
let text = format!("Error while reading incoming packet {error}");
|
||||
log::error!(
|
||||
"Failed to read incoming packet with id {}: {}",
|
||||
i32::from(packet.id),
|
||||
error
|
||||
);
|
||||
self.kick(&text).await;
|
||||
};
|
||||
}
|
||||
}
|
||||
if let Err(error) = self.handle_packet(server, &mut packet).await {
|
||||
let text = format!("Error while reading incoming packet {error}");
|
||||
log::error!(
|
||||
"Failed to read incoming packet with id {}: {}",
|
||||
i32::from(packet.id),
|
||||
error
|
||||
);
|
||||
self.kick(&text).await;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -562,26 +495,8 @@ impl Client {
|
||||
pub fn close(&self) {
|
||||
self.closed
|
||||
.store(true, std::sync::atomic::Ordering::Relaxed);
|
||||
|
||||
// Abort pending chunks here too because we might clean up before chunk tasks are done
|
||||
self.abort_chunks("closed");
|
||||
|
||||
self.cancel_tasks.notify_waiters();
|
||||
|
||||
log::debug!("Closed connection for {}", self.id);
|
||||
}
|
||||
|
||||
pub fn abort_chunks(&self, reason: &str) {
|
||||
let mut pending_chunks = self.pending_chunks.lock();
|
||||
pending_chunks.iter_mut().for_each(|(chunk, handles)| {
|
||||
handles.iter_mut().enumerate().for_each(|(count, handle)| {
|
||||
if !handle.aborted() {
|
||||
log::debug!("Aborting chunk {:?} ({}) ({})", chunk, count, reason);
|
||||
handle.abort();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
|
||||
@ -78,7 +78,7 @@ impl Player {
|
||||
pos.clamp(-2.0E7, 2.0E7)
|
||||
}
|
||||
|
||||
pub async fn handle_position(&self, position: SPlayerPosition) {
|
||||
pub async fn handle_position(self: &Arc<Self>, position: SPlayerPosition) {
|
||||
if position.x.is_nan() || position.feet_y.is_nan() || position.z.is_nan() {
|
||||
self.kick(TextComponent::text("Invalid movement")).await;
|
||||
return;
|
||||
@ -133,7 +133,10 @@ impl Player {
|
||||
player_chunker::update_position(self).await;
|
||||
}
|
||||
|
||||
pub async fn handle_position_rotation(&self, position_rotation: SPlayerPositionRotation) {
|
||||
pub async fn handle_position_rotation(
|
||||
self: &Arc<Self>,
|
||||
position_rotation: SPlayerPositionRotation,
|
||||
) {
|
||||
if position_rotation.x.is_nan()
|
||||
|| position_rotation.feet_y.is_nan()
|
||||
|| position_rotation.z.is_nan()
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicI32, AtomicI64, AtomicU32, AtomicU8},
|
||||
Arc,
|
||||
@ -31,14 +32,15 @@ use pumpkin_protocol::{
|
||||
},
|
||||
RawPacket, ServerPacket, VarInt,
|
||||
};
|
||||
use tokio::sync::Mutex;
|
||||
use tokio::sync::{Mutex, Notify};
|
||||
use tokio::task::JoinHandle;
|
||||
|
||||
use pumpkin_protocol::server::play::SKeepAlive;
|
||||
use pumpkin_world::{cylindrical_chunk_iterator::Cylindrical, item::ItemStack};
|
||||
|
||||
use super::Entity;
|
||||
use crate::{
|
||||
client::{authentication::GameProfile, ChunkHandleWrapper, Client, PlayerConfig},
|
||||
client::{authentication::GameProfile, Client, PlayerConfig},
|
||||
server::Server,
|
||||
world::World,
|
||||
};
|
||||
@ -46,6 +48,42 @@ use crate::{error::PumpkinError, world::player_chunker::get_view_distance};
|
||||
|
||||
use super::living::LivingEntity;
|
||||
|
||||
pub struct ChunkHandleWrapper {
|
||||
handle: Option<JoinHandle<()>>,
|
||||
aborted: bool,
|
||||
}
|
||||
|
||||
impl ChunkHandleWrapper {
|
||||
#[must_use]
|
||||
pub fn new(handle: JoinHandle<()>) -> Self {
|
||||
Self {
|
||||
handle: Some(handle),
|
||||
aborted: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn abort(&mut self) {
|
||||
self.aborted = true;
|
||||
if let Some(handle) = &self.handle {
|
||||
handle.abort();
|
||||
} else {
|
||||
log::error!("Trying to abort without a handle!");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn take_handle(&mut self) -> JoinHandle<()> {
|
||||
self.handle.take().unwrap()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn aborted(&self) -> bool {
|
||||
self.aborted
|
||||
}
|
||||
}
|
||||
|
||||
pub type PlayerPendingChunks =
|
||||
Arc<parking_lot::Mutex<HashMap<Vector2<i32>, VecDeque<ChunkHandleWrapper>>>>;
|
||||
|
||||
/// Represents a Minecraft player entity.
|
||||
///
|
||||
/// A `Player` is a special type of entity that represents a human player connected to the server.
|
||||
@ -99,6 +137,18 @@ pub struct Player {
|
||||
pub last_keep_alive_time: AtomicCell<Instant>,
|
||||
/// Amount of ticks since last attack
|
||||
pub last_attacked_ticks: AtomicU32,
|
||||
|
||||
//TODO: Is there a way to consolidate these two?
|
||||
//Need to lookup by chunk, but also would be need to contain all the stuff
|
||||
//In a PendingBatch struct. Is there a cheap way to map multiple keys to a single element?
|
||||
//
|
||||
/// Individual chunk tasks that this client is waiting for
|
||||
pub pending_chunks: PlayerPendingChunks,
|
||||
/// Chunk batches that this client is waiting for
|
||||
pub pending_chunk_batch: parking_lot::Mutex<HashMap<uuid::Uuid, JoinHandle<()>>>,
|
||||
|
||||
/// Tell tasks to stop if we are closing
|
||||
cancel_tasks: Notify,
|
||||
}
|
||||
|
||||
impl Player {
|
||||
@ -148,6 +198,9 @@ impl Player {
|
||||
keep_alive_id: AtomicI64::new(0),
|
||||
last_keep_alive_time: AtomicCell::new(std::time::Instant::now()),
|
||||
last_attacked_ticks: AtomicU32::new(0),
|
||||
pending_chunks: Arc::new(parking_lot::Mutex::new(HashMap::new())),
|
||||
pending_chunk_batch: parking_lot::Mutex::new(HashMap::new()),
|
||||
cancel_tasks: Notify::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,6 +208,10 @@ impl Player {
|
||||
#[allow(unused_variables)]
|
||||
pub async fn remove(&self) {
|
||||
let world = &self.living_entity.entity.world;
|
||||
// Abort pending chunks here too because we might clean up before chunk tasks are done
|
||||
self.abort_chunks("closed");
|
||||
|
||||
self.cancel_tasks.notify_waiters();
|
||||
|
||||
world.remove_player(self).await;
|
||||
|
||||
@ -177,7 +234,7 @@ impl Player {
|
||||
);
|
||||
|
||||
let (watched_chunks, to_await) = {
|
||||
let mut pending_chunks = self.client.pending_chunks.lock();
|
||||
let mut pending_chunks = self.pending_chunks.lock();
|
||||
|
||||
// Don't try to clean chunks that dont exist yet
|
||||
// If they are still pending, we never sent the client the chunk,
|
||||
@ -230,7 +287,7 @@ impl Player {
|
||||
// Allow the batch jobs to properly cull stragglers before we do our clean up
|
||||
log::debug!("Collecting chunk batches...");
|
||||
let batches = {
|
||||
let mut chunk_batches = self.client.pending_chunk_batch.lock();
|
||||
let mut chunk_batches = self.pending_chunk_batch.lock();
|
||||
let keys = chunk_batches.keys().copied().collect_vec();
|
||||
let handles = keys
|
||||
.iter()
|
||||
@ -274,6 +331,10 @@ impl Player {
|
||||
//self.living_entity.entity.world.level.list_cached();
|
||||
}
|
||||
|
||||
pub async fn await_cancel(&self) {
|
||||
self.cancel_tasks.notified().await;
|
||||
}
|
||||
|
||||
pub async fn tick(&self) {
|
||||
if self
|
||||
.client
|
||||
@ -469,6 +530,18 @@ impl Player {
|
||||
.send_packet(&CSystemChatMessage::new(text, false))
|
||||
.await;
|
||||
}
|
||||
|
||||
pub fn abort_chunks(&self, reason: &str) {
|
||||
let mut pending_chunks = self.pending_chunks.lock();
|
||||
pending_chunks.iter_mut().for_each(|(chunk, handles)| {
|
||||
handles.iter_mut().enumerate().for_each(|(count, handle)| {
|
||||
if !handle.aborted() {
|
||||
log::debug!("Aborting chunk {:?} ({}) ({})", chunk, count, reason);
|
||||
handle.abort();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl Player {
|
||||
@ -478,7 +551,7 @@ impl Player {
|
||||
#[cfg(debug_assertions)]
|
||||
let inst = std::time::Instant::now();
|
||||
tokio::select! {
|
||||
() = self.client.await_cancel() => {
|
||||
() = self.await_cancel() => {
|
||||
log::debug!("Canceling player packet processing");
|
||||
return;
|
||||
},
|
||||
|
||||
@ -5,9 +5,9 @@ use std::{
|
||||
|
||||
pub mod player_chunker;
|
||||
|
||||
use crate::{
|
||||
client::{ChunkHandleWrapper, Client},
|
||||
entity::{player::Player, Entity},
|
||||
use crate::entity::{
|
||||
player::{ChunkHandleWrapper, Player},
|
||||
Entity,
|
||||
};
|
||||
use num_traits::ToPrimitive;
|
||||
use pumpkin_config::BasicConfiguration;
|
||||
@ -337,8 +337,13 @@ impl World {
|
||||
self.level.loaded_chunk_count()
|
||||
}
|
||||
|
||||
fn spawn_world_chunks(&self, client: Arc<Client>, chunks: &[Vector2<i32>]) {
|
||||
if client.closed.load(std::sync::atomic::Ordering::Relaxed) {
|
||||
#[expect(clippy::too_many_lines)]
|
||||
fn spawn_world_chunks(&self, player: Arc<Player>, chunks: &[Vector2<i32>]) {
|
||||
if player
|
||||
.client
|
||||
.closed
|
||||
.load(std::sync::atomic::Ordering::Relaxed)
|
||||
{
|
||||
log::info!("The connection has closed before world chunks were spawned",);
|
||||
return;
|
||||
}
|
||||
@ -349,13 +354,13 @@ impl World {
|
||||
|
||||
let (pending, mut receiver) = self.receive_chunks(chunks);
|
||||
{
|
||||
let mut pending_chunks = client.pending_chunks.lock();
|
||||
let mut pending_chunks = player.pending_chunks.lock();
|
||||
|
||||
for chunk in chunks {
|
||||
if pending_chunks.contains_key(chunk) {
|
||||
log::debug!(
|
||||
"Client id {} is requesting chunk {:?} but its already pending!",
|
||||
client.id,
|
||||
player.client.id,
|
||||
chunk
|
||||
);
|
||||
}
|
||||
@ -376,9 +381,9 @@ impl World {
|
||||
};
|
||||
}
|
||||
}
|
||||
let pending_chunks = client.pending_chunks.clone();
|
||||
let pending_chunks = player.pending_chunks.clone();
|
||||
let level = self.level.clone();
|
||||
let retained_client = client.clone();
|
||||
let retained_player = player.clone();
|
||||
let batch_id = id;
|
||||
|
||||
let handle = tokio::spawn(async move {
|
||||
@ -434,13 +439,17 @@ impl World {
|
||||
level.mark_chunk_as_newly_watched(chunk_data.position);
|
||||
};
|
||||
|
||||
if !client.closed.load(std::sync::atomic::Ordering::Relaxed) {
|
||||
client.send_packet(&packet).await;
|
||||
if !player
|
||||
.client
|
||||
.closed
|
||||
.load(std::sync::atomic::Ordering::Relaxed)
|
||||
{
|
||||
player.client.send_packet(&packet).await;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
let mut batch = client.pending_chunk_batch.lock();
|
||||
let mut batch = player.pending_chunk_batch.lock();
|
||||
batch.remove(&batch_id);
|
||||
}
|
||||
#[cfg(debug_assertions)]
|
||||
@ -452,7 +461,7 @@ impl World {
|
||||
});
|
||||
|
||||
{
|
||||
let mut batch_handles = retained_client.pending_chunk_batch.lock();
|
||||
let mut batch_handles = retained_player.pending_chunk_batch.lock();
|
||||
batch_handles.insert(id, handle);
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,10 +47,10 @@ pub async fn player_join(world: &World, player: Arc<Player>) {
|
||||
let new_cylindrical = Cylindrical::new(Vector2::new(chunk_pos.x, chunk_pos.z), view_distance);
|
||||
let loading_chunks = new_cylindrical.all_chunks_within();
|
||||
|
||||
world.spawn_world_chunks(player.client.clone(), &loading_chunks);
|
||||
world.spawn_world_chunks(player, &loading_chunks);
|
||||
}
|
||||
|
||||
pub async fn update_position(player: &Player) {
|
||||
pub async fn update_position(player: &Arc<Player>) {
|
||||
let entity = &player.living_entity.entity;
|
||||
let current_watched = player.watched_section.load();
|
||||
let new_watched = chunk_section_from_pos(&entity.block_pos.load());
|
||||
@ -93,7 +93,7 @@ pub async fn update_position(player: &Player) {
|
||||
//let inst = std::time::Instant::now();
|
||||
entity
|
||||
.world
|
||||
.spawn_world_chunks(player.client.clone(), &loading_chunks);
|
||||
.spawn_world_chunks(player.clone(), &loading_chunks);
|
||||
//log::debug!("Loading chunks took {:?}", inst.elapsed());
|
||||
}
|
||||
|
||||
@ -104,7 +104,7 @@ pub async fn update_position(player: &Player) {
|
||||
//let inst = std::time::Instant::now();
|
||||
|
||||
let watched_chunks: Vec<_> = {
|
||||
let mut pending_chunks = player.client.pending_chunks.lock();
|
||||
let mut pending_chunks = player.pending_chunks.lock();
|
||||
unloading_chunks
|
||||
.into_iter()
|
||||
.filter(|chunk| {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user