diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml
index e80b7100..f913b9b6 100644
--- a/.github/workflows/benchmark.yml
+++ b/.github/workflows/benchmark.yml
@@ -26,7 +26,7 @@ jobs:
uses: pnpm/action-setup@v4
- uses: actions/setup-node@v4
with:
- node-version: 22
+ node-version: 18
cache: "pnpm"
- name: Move Cypress to dependencies
run: |
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 3e8c4136..cbf52251 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -49,20 +49,6 @@ jobs:
publish_dir: .vercel/output/static
force_orphan: true
- # Create CNAME file for custom domain
- - name: Create CNAME file
- run: echo "github.mcraft.fun" > .vercel/output/static/CNAME
-
- - name: Deploy to mwc-mcraft-pages repository
- uses: peaceiris/actions-gh-pages@v3
- with:
- personal_token: ${{ secrets.MCW_MCRAFT_PAGE_DEPLOY_TOKEN }}
- external_repository: ${{ github.repository_owner }}/mwc-mcraft-pages
- publish_dir: .vercel/output/static
- publish_branch: main
- destination_dir: docs
- force_orphan: true
-
- name: Change index.html title
run: |
# change
Minecraft Web Client to Minecraft Web Client — Free Online Browser Version
diff --git a/README.MD b/README.MD
index 018784e3..7978cee5 100644
--- a/README.MD
+++ b/README.MD
@@ -78,8 +78,6 @@ There is a builtin proxy, but you can also host your one! Just clone the repo, r
[](https://app.koyeb.com/deploy?name=minecraft-web-client&type=git&repository=zardoy%2Fminecraft-web-client&branch=next&builder=dockerfile&env%5B%5D=&ports=8080%3Bhttp%3B%2F)
-> **Note**: If you want to make **your own** Minecraft server accessible to web clients (without our proxies), you can use [mwc-proxy](https://github.com/zardoy/mwc-proxy) - a lightweight JS WebSocket proxy that runs on the same server as your Minecraft server, allowing players to connect directly via `wss://play.example.com`. `?client_mcraft` is added to the URL, so the proxy will know that it's this client.
-
Proxy servers are used to connect to Minecraft servers which use TCP protocol. When you connect connect to a server with a proxy, websocket connection is created between you (browser client) and the proxy server located in Europe, then the proxy connects to the Minecraft server and sends the data to the client (you) without any packet deserialization to avoid any additional delays. That said all the Minecraft protocol packets are processed by the client, right in your browser.
```mermaid
@@ -178,7 +176,6 @@ Server specific:
- `?lockConnect=true` - Only works then `ip` parameter is set. Disables cancel/save buttons and all inputs in the connect screen already set as parameters. Useful for integrates iframes.
- `?autoConnect=true` - Only works then `ip` and `version` parameters are set and `allowAutoConnect` is `true` in config.json! Directly connects to the specified server. Useful for integrates iframes.
- `?serversList=` - `` can be a list of servers in the format `ip:version,ip` or a url to a json file with the same format (array) or a txt file with line-delimited list of server IPs.
-- `?addPing=` - Add a latency to both sides of the connection. Useful for testing ping issues. For example `?addPing=100` will add 200ms to your ping.
Single player specific:
@@ -235,4 +232,3 @@ Only during development:
- [https://github.com/ClassiCube/ClassiCube](ClassiCube - Better C# Rewrite) [DEMO](https://www.classicube.net/server/play/?warned=true)
- [https://m.eaglercraft.com/](EaglerCraft) - Eaglercraft runnable on mobile (real Minecraft in the browser)
-- [js-minecraft](https://github.com/LabyStudio/js-minecraft) - An insanely well done clone from the graphical side that inspired many features here
diff --git a/config.json b/config.json
index 2bfa9cfe..940fb738 100644
--- a/config.json
+++ b/config.json
@@ -10,10 +10,6 @@
{
"ip": "wss://play.mcraft.fun"
},
- {
- "ip": "wss://play.webmc.fun",
- "name": "WebMC"
- },
{
"ip": "wss://ws.fuchsmc.net"
},
diff --git a/package.json b/package.json
index ff673726..a8c2c4e7 100644
--- a/package.json
+++ b/package.json
@@ -80,14 +80,14 @@
"esbuild-plugin-polyfill-node": "^0.3.0",
"express": "^4.18.2",
"filesize": "^10.0.12",
- "flying-squid": "npm:@zardoy/flying-squid@^0.0.104",
+ "flying-squid": "npm:@zardoy/flying-squid@^0.0.62",
"framer-motion": "^12.9.2",
"fs-extra": "^11.1.1",
"google-drive-browserfs": "github:zardoy/browserfs#google-drive",
"jszip": "^3.10.1",
"lodash-es": "^4.17.21",
"mcraft-fun-mineflayer": "^0.1.23",
- "minecraft-data": "3.98.0",
+ "minecraft-data": "3.92.0",
"minecraft-protocol": "github:PrismarineJS/node-minecraft-protocol#master",
"mineflayer-item-map-downloader": "github:zardoy/mineflayer-item-map-downloader",
"mojangson": "^2.0.4",
@@ -157,7 +157,7 @@
"mc-assets": "^0.2.62",
"minecraft-inventory-gui": "github:zardoy/minecraft-inventory-gui#next",
"mineflayer": "github:zardoy/mineflayer#gen-the-master",
- "mineflayer-mouse": "^0.1.21",
+ "mineflayer-mouse": "^0.1.17",
"npm-run-all": "^4.1.5",
"os-browserify": "^0.3.0",
"path-browserify": "^1.0.1",
@@ -205,7 +205,7 @@
"diamond-square": "github:zardoy/diamond-square",
"prismarine-block": "github:zardoy/prismarine-block#next-era",
"prismarine-world": "github:zardoy/prismarine-world#next-era",
- "minecraft-data": "3.98.0",
+ "minecraft-data": "3.92.0",
"prismarine-provider-anvil": "github:zardoy/prismarine-provider-anvil#everything",
"prismarine-physics": "github:zardoy/prismarine-physics",
"minecraft-protocol": "github:PrismarineJS/node-minecraft-protocol#master",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 5bcd74a0..8acb9681 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -13,7 +13,7 @@ overrides:
diamond-square: github:zardoy/diamond-square
prismarine-block: github:zardoy/prismarine-block#next-era
prismarine-world: github:zardoy/prismarine-world#next-era
- minecraft-data: 3.98.0
+ minecraft-data: 3.92.0
prismarine-provider-anvil: github:zardoy/prismarine-provider-anvil#everything
prismarine-physics: github:zardoy/prismarine-physics
minecraft-protocol: github:PrismarineJS/node-minecraft-protocol#master
@@ -121,8 +121,8 @@ importers:
specifier: ^10.0.12
version: 10.1.6
flying-squid:
- specifier: npm:@zardoy/flying-squid@^0.0.104
- version: '@zardoy/flying-squid@0.0.104(encoding@0.1.13)'
+ specifier: npm:@zardoy/flying-squid@^0.0.62
+ version: '@zardoy/flying-squid@0.0.62(encoding@0.1.13)'
framer-motion:
specifier: ^12.9.2
version: 12.9.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
@@ -140,13 +140,13 @@ importers:
version: 4.17.21
mcraft-fun-mineflayer:
specifier: ^0.1.23
- version: 0.1.23(encoding@0.1.13)(mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/dd3b1ff38506d6f72d90e8444186e4e75fe82659(encoding@0.1.13))
+ version: 0.1.23(encoding@0.1.13)(mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/86e65631e79c490021afc63c80091a7bb6019fa8(encoding@0.1.13))
minecraft-data:
- specifier: 3.98.0
- version: 3.98.0
+ specifier: 3.92.0
+ version: 3.92.0
minecraft-protocol:
specifier: github:PrismarineJS/node-minecraft-protocol#master
- version: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/bf89f7e86526c54d8c43f555d8f6dfa4948fd2d9(patch_hash=4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b)(encoding@0.1.13)
+ version: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/c561917bf7e7966911321512c2a6895a3f9da074(patch_hash=4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b)(encoding@0.1.13)
mineflayer-item-map-downloader:
specifier: github:zardoy/mineflayer-item-map-downloader
version: https://codeload.github.com/zardoy/mineflayer-item-map-downloader/tar.gz/a8d210ecdcf78dd082fa149a96e1612cc9747824(patch_hash=a731ebbace2d8790c973ab3a5ba33494a6e9658533a9710dd8ba36f86db061ad)(encoding@0.1.13)
@@ -155,7 +155,7 @@ importers:
version: 2.0.4
net-browserify:
specifier: github:zardoy/prismarinejs-net-browserify
- version: https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/e754999ffdea67853bc9b10553b5e9908b40f618
+ version: https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/17fb901e8ea480a52c8fd46373695be172be8aa5
node-gzip:
specifier: ^1.1.2
version: 1.1.2
@@ -170,7 +170,7 @@ importers:
version: 6.1.1
prismarine-provider-anvil:
specifier: github:zardoy/prismarine-provider-anvil#everything
- version: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.98.0)
+ version: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.92.0)
prosemirror-example-setup:
specifier: ^1.2.2
version: 1.2.3
@@ -345,10 +345,10 @@ importers:
version: https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/89c33d396f3fde4804c71f4be3c203ade1833b41(@types/react@18.3.18)(react@18.3.1)
mineflayer:
specifier: github:zardoy/mineflayer#gen-the-master
- version: https://codeload.github.com/zardoy/mineflayer/tar.gz/dd3b1ff38506d6f72d90e8444186e4e75fe82659(encoding@0.1.13)
+ version: https://codeload.github.com/zardoy/mineflayer/tar.gz/86e65631e79c490021afc63c80091a7bb6019fa8(encoding@0.1.13)
mineflayer-mouse:
- specifier: ^0.1.21
- version: 0.1.21
+ specifier: ^0.1.17
+ version: 0.1.17
npm-run-all:
specifier: ^4.1.5
version: 4.1.5
@@ -436,7 +436,7 @@ importers:
version: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9
prismarine-chunk:
specifier: github:zardoy/prismarine-chunk#master
- version: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.98.0)
+ version: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.92.0)
prismarine-schematic:
specifier: ^1.2.0
version: 1.2.3
@@ -3387,13 +3387,13 @@ packages:
resolution: {integrity: sha512-6xm38yGVIa6mKm/DUCF2zFFJhERh/QWp1ufm4cNUvxsONBmfPg8uZ9pZBdOmF6qFGr/HlT6ABBkCSx/dlEtvWg==}
engines: {node: '>=12 <14 || 14.2 - 14.9 || >14.10.0'}
- '@zardoy/flying-squid@0.0.104':
- resolution: {integrity: sha512-jGhQ7fn7o8UN+mUwZbt9674D37YLuBi+Au4TwKcopCA6huIQdHTFNl2e+0ZSTI5mnhN+NpyVoR3vmtH6L58vHQ==}
+ '@zardoy/flying-squid@0.0.49':
+ resolution: {integrity: sha512-Kt4wr5/R+44tcLU9gjuNG2an9weWeKEpIoKXfsgJN2GGQqdnbd5nBpxfGDdgZ9aMdFugsVW8BsyPZNhj9vbMXA==}
engines: {node: '>=8'}
hasBin: true
- '@zardoy/flying-squid@0.0.49':
- resolution: {integrity: sha512-Kt4wr5/R+44tcLU9gjuNG2an9weWeKEpIoKXfsgJN2GGQqdnbd5nBpxfGDdgZ9aMdFugsVW8BsyPZNhj9vbMXA==}
+ '@zardoy/flying-squid@0.0.62':
+ resolution: {integrity: sha512-M6icydO/yrmwevBhmgKcqEPC63AhWfU/Es9N/uadVrmKaxGm2FQMMLcybbutRYm1xZ6qsdxDUOUZnN56PsVwfQ==}
engines: {node: '>=8'}
hasBin: true
@@ -6444,12 +6444,6 @@ packages:
resolution: {integrity: sha512-RYZeD1+joNlPuUpi+tIWkbP0ieVJr+R6IFkI6/8juhSxx9zE4osoSmteybrfspGm8A6u+YbbY1epqRKEMwVR6Q==}
engines: {node: '>=18.0.0'}
- mc-bridge@0.1.3:
- resolution: {integrity: sha512-H9jPt2xEU77itC27dSz3qazHYqN9qVsv4HgMPozg7RqQ1uwgXmEa+ojKIlDtXf/TLJsG6Kv4EbzGa8a1Wh72uA==}
- engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- peerDependencies:
- minecraft-data: 3.98.0
-
mcraft-fun-mineflayer@0.1.23:
resolution: {integrity: sha512-qmI1rQQ0Ro5zJdi99rClWLF+mS9JZffgNX2vyWWesS3Hsk3Xblp/8swYTJKHSaFpNgzkVfXV92fEIrBqeH6iKA==}
version: 0.1.23
@@ -6658,8 +6652,8 @@ packages:
resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==}
engines: {node: '>=4'}
- minecraft-data@3.98.0:
- resolution: {integrity: sha512-JAPqJ/TZoxMUlAPPdWUh1v5wdqvYGFSZ4rW9bUtmaKBkGpomDSjw4V02ocBqbxKJvcTtmc5nM/LfN9/0DDqHrQ==}
+ minecraft-data@3.92.0:
+ resolution: {integrity: sha512-CGfO50svzm+pSRa4Mbq4owsmRKbPCNkSZ3MCOyH+epC7yNjh+PUhPQFHWq72O51qsY7pAB5qM/bJn1ncwG1J5g==}
minecraft-folder-path@1.2.0:
resolution: {integrity: sha512-qaUSbKWoOsH9brn0JQuBhxNAzTDMwrOXorwuRxdJKKKDYvZhtml+6GVCUrY5HRiEsieBEjCUnhVpDuQiKsiFaw==}
@@ -6668,9 +6662,9 @@ packages:
resolution: {tarball: https://codeload.github.com/zardoy/minecraft-inventory-gui/tar.gz/89c33d396f3fde4804c71f4be3c203ade1833b41}
version: 1.0.1
- minecraft-protocol@https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/bf89f7e86526c54d8c43f555d8f6dfa4948fd2d9:
- resolution: {tarball: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/bf89f7e86526c54d8c43f555d8f6dfa4948fd2d9}
- version: 1.62.0
+ minecraft-protocol@https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/c561917bf7e7966911321512c2a6895a3f9da074:
+ resolution: {tarball: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/c561917bf7e7966911321512c2a6895a3f9da074}
+ version: 1.61.0
engines: {node: '>=22'}
minecraft-wrap@1.6.0:
@@ -6684,12 +6678,12 @@ packages:
resolution: {tarball: https://codeload.github.com/zardoy/mineflayer-item-map-downloader/tar.gz/a8d210ecdcf78dd082fa149a96e1612cc9747824}
version: 1.2.0
- mineflayer-mouse@0.1.21:
- resolution: {integrity: sha512-1XTVuw3twIrEcqQ1QRSB8NcStIUEZ+tbxiAG6rOrN/9M4thhtlS5PTJzFdmdrcYgWEBLvuOdJszaKE5zFfiXhg==}
+ mineflayer-mouse@0.1.17:
+ resolution: {integrity: sha512-0eCR8pnGb42Qd9QmAxOjl0PhA5Fa+9+6H1G/YsbsO5rg5mDf94Tusqp/8NAGLPQCPVDzbarLskXdjR3h0E0bEQ==}
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
- mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/dd3b1ff38506d6f72d90e8444186e4e75fe82659:
- resolution: {tarball: https://codeload.github.com/zardoy/mineflayer/tar.gz/dd3b1ff38506d6f72d90e8444186e4e75fe82659}
+ mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/86e65631e79c490021afc63c80091a7bb6019fa8:
+ resolution: {tarball: https://codeload.github.com/zardoy/mineflayer/tar.gz/86e65631e79c490021afc63c80091a7bb6019fa8}
version: 8.0.0
engines: {node: '>=22'}
@@ -6855,8 +6849,8 @@ packages:
neo-async@2.6.2:
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
- net-browserify@https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/e754999ffdea67853bc9b10553b5e9908b40f618:
- resolution: {tarball: https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/e754999ffdea67853bc9b10553b5e9908b40f618}
+ net-browserify@https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/17fb901e8ea480a52c8fd46373695be172be8aa5:
+ resolution: {tarball: https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/17fb901e8ea480a52c8fd46373695be172be8aa5}
version: 0.2.4
nice-try@1.0.5:
@@ -7387,7 +7381,7 @@ packages:
prismarine-biome@1.3.0:
resolution: {integrity: sha512-GY6nZxq93mTErT7jD7jt8YS1aPrOakbJHh39seYsJFXvueIOdHAmW16kYQVrTVMW5MlWLQVxV/EquRwOgr4MnQ==}
peerDependencies:
- minecraft-data: 3.98.0
+ minecraft-data: 3.92.0
prismarine-registry: ^1.1.0
prismarine-block@https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9:
@@ -11343,8 +11337,8 @@ snapshots:
'@nxg-org/mineflayer-trajectories@1.2.0(encoding@0.1.13)':
dependencies:
'@nxg-org/mineflayer-util-plugin': 1.8.4
- minecraft-data: 3.98.0
- mineflayer: https://codeload.github.com/zardoy/mineflayer/tar.gz/dd3b1ff38506d6f72d90e8444186e4e75fe82659(encoding@0.1.13)
+ minecraft-data: 3.92.0
+ mineflayer: https://codeload.github.com/zardoy/mineflayer/tar.gz/86e65631e79c490021afc63c80091a7bb6019fa8(encoding@0.1.13)
prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9
prismarine-item: 1.17.0
prismarine-physics: https://codeload.github.com/zardoy/prismarine-physics/tar.gz/353e25b800149393f40539ec381218be44cbb03b
@@ -13094,7 +13088,7 @@ snapshots:
'@types/emscripten': 1.40.0
tslib: 1.14.1
- '@zardoy/flying-squid@0.0.104(encoding@0.1.13)':
+ '@zardoy/flying-squid@0.0.49(encoding@0.1.13)':
dependencies:
'@tootallnate/once': 2.0.0
chalk: 5.4.1
@@ -13104,18 +13098,16 @@ snapshots:
exit-hook: 2.2.1
flatmap: 0.0.3
long: 5.3.1
- mc-bridge: 0.1.3(minecraft-data@3.98.0)
- minecraft-data: 3.98.0
- minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/bf89f7e86526c54d8c43f555d8f6dfa4948fd2d9(patch_hash=4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b)(encoding@0.1.13)
+ minecraft-data: 3.92.0
+ minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/c561917bf7e7966911321512c2a6895a3f9da074(patch_hash=4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b)(encoding@0.1.13)
mkdirp: 2.1.6
node-gzip: 1.1.2
node-rsa: 1.1.1
- prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9
- prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.98.0)
+ prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.92.0)
prismarine-entity: 2.5.0
prismarine-item: 1.17.0
prismarine-nbt: 2.7.0
- prismarine-provider-anvil: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.98.0)
+ prismarine-provider-anvil: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.92.0)
prismarine-windows: 2.9.0
prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/ab2146c9933eef3247c3f64446de4ccc2c484c7c
rambda: 9.4.2
@@ -13132,7 +13124,7 @@ snapshots:
- encoding
- supports-color
- '@zardoy/flying-squid@0.0.49(encoding@0.1.13)':
+ '@zardoy/flying-squid@0.0.62(encoding@0.1.13)':
dependencies:
'@tootallnate/once': 2.0.0
chalk: 5.4.1
@@ -13142,16 +13134,16 @@ snapshots:
exit-hook: 2.2.1
flatmap: 0.0.3
long: 5.3.1
- minecraft-data: 3.98.0
- minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/bf89f7e86526c54d8c43f555d8f6dfa4948fd2d9(patch_hash=4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b)(encoding@0.1.13)
+ minecraft-data: 3.92.0
+ minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/c561917bf7e7966911321512c2a6895a3f9da074(patch_hash=4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b)(encoding@0.1.13)
mkdirp: 2.1.6
node-gzip: 1.1.2
node-rsa: 1.1.1
- prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.98.0)
+ prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.92.0)
prismarine-entity: 2.5.0
prismarine-item: 1.17.0
prismarine-nbt: 2.7.0
- prismarine-provider-anvil: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.98.0)
+ prismarine-provider-anvil: https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.92.0)
prismarine-windows: 2.9.0
prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/ab2146c9933eef3247c3f64446de4ccc2c484c7c
rambda: 9.4.2
@@ -14542,8 +14534,8 @@ snapshots:
diamond-square@https://codeload.github.com/zardoy/diamond-square/tar.gz/cfaad2d1d5909fdfa63c8cc7bc05fb5e87782d71:
dependencies:
- minecraft-data: 3.98.0
- prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.98.0)
+ minecraft-data: 3.92.0
+ prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.92.0)
prismarine-registry: 1.11.0
random-seed: 0.3.0
vec3: 0.1.10
@@ -16986,16 +16978,12 @@ snapshots:
maxrects-packer: '@zardoy/maxrects-packer@2.7.4'
zod: 3.24.2
- mc-bridge@0.1.3(minecraft-data@3.98.0):
- dependencies:
- minecraft-data: 3.98.0
-
- mcraft-fun-mineflayer@0.1.23(encoding@0.1.13)(mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/dd3b1ff38506d6f72d90e8444186e4e75fe82659(encoding@0.1.13)):
+ mcraft-fun-mineflayer@0.1.23(encoding@0.1.13)(mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/86e65631e79c490021afc63c80091a7bb6019fa8(encoding@0.1.13)):
dependencies:
'@zardoy/flying-squid': 0.0.49(encoding@0.1.13)
exit-hook: 2.2.1
- minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/bf89f7e86526c54d8c43f555d8f6dfa4948fd2d9(patch_hash=4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b)(encoding@0.1.13)
- mineflayer: https://codeload.github.com/zardoy/mineflayer/tar.gz/dd3b1ff38506d6f72d90e8444186e4e75fe82659(encoding@0.1.13)
+ minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/c561917bf7e7966911321512c2a6895a3f9da074(patch_hash=4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b)(encoding@0.1.13)
+ mineflayer: https://codeload.github.com/zardoy/mineflayer/tar.gz/86e65631e79c490021afc63c80091a7bb6019fa8(encoding@0.1.13)
prismarine-item: 1.17.0
ws: 8.18.1
transitivePeerDependencies:
@@ -17302,7 +17290,7 @@ snapshots:
min-indent@1.0.1: {}
- minecraft-data@3.98.0: {}
+ minecraft-data@3.92.0: {}
minecraft-folder-path@1.2.0: {}
@@ -17313,7 +17301,7 @@ snapshots:
- '@types/react'
- react
- minecraft-protocol@https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/bf89f7e86526c54d8c43f555d8f6dfa4948fd2d9(patch_hash=4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b)(encoding@0.1.13):
+ minecraft-protocol@https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/c561917bf7e7966911321512c2a6895a3f9da074(patch_hash=4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b)(encoding@0.1.13):
dependencies:
'@types/node-rsa': 1.1.4
'@types/readable-stream': 4.0.18
@@ -17322,7 +17310,7 @@ snapshots:
debug: 4.4.0(supports-color@8.1.1)
endian-toggle: 0.0.0
lodash.merge: 4.6.2
- minecraft-data: 3.98.0
+ minecraft-data: 3.92.0
minecraft-folder-path: 1.2.0
node-fetch: 2.7.0(encoding@0.1.13)
node-rsa: 0.4.2
@@ -17365,13 +17353,13 @@ snapshots:
mineflayer-item-map-downloader@https://codeload.github.com/zardoy/mineflayer-item-map-downloader/tar.gz/a8d210ecdcf78dd082fa149a96e1612cc9747824(patch_hash=a731ebbace2d8790c973ab3a5ba33494a6e9658533a9710dd8ba36f86db061ad)(encoding@0.1.13):
dependencies:
- mineflayer: https://codeload.github.com/zardoy/mineflayer/tar.gz/dd3b1ff38506d6f72d90e8444186e4e75fe82659(encoding@0.1.13)
+ mineflayer: https://codeload.github.com/zardoy/mineflayer/tar.gz/86e65631e79c490021afc63c80091a7bb6019fa8(encoding@0.1.13)
sharp: 0.30.7
transitivePeerDependencies:
- encoding
- supports-color
- mineflayer-mouse@0.1.21:
+ mineflayer-mouse@0.1.17:
dependencies:
change-case: 5.4.4
debug: 4.4.1
@@ -17380,15 +17368,15 @@ snapshots:
transitivePeerDependencies:
- supports-color
- mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/dd3b1ff38506d6f72d90e8444186e4e75fe82659(encoding@0.1.13):
+ mineflayer@https://codeload.github.com/zardoy/mineflayer/tar.gz/86e65631e79c490021afc63c80091a7bb6019fa8(encoding@0.1.13):
dependencies:
'@nxg-org/mineflayer-physics-util': 1.8.10
- minecraft-data: 3.98.0
- minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/bf89f7e86526c54d8c43f555d8f6dfa4948fd2d9(patch_hash=4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b)(encoding@0.1.13)
- prismarine-biome: 1.3.0(minecraft-data@3.98.0)(prismarine-registry@1.11.0)
+ minecraft-data: 3.92.0
+ minecraft-protocol: https://codeload.github.com/PrismarineJS/node-minecraft-protocol/tar.gz/c561917bf7e7966911321512c2a6895a3f9da074(patch_hash=4ebdae314c68d01ce7879445c0b8bde5f90373abba8b66ed00d42e7a5f542f8b)(encoding@0.1.13)
+ prismarine-biome: 1.3.0(minecraft-data@3.92.0)(prismarine-registry@1.11.0)
prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9
prismarine-chat: 1.11.0
- prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.98.0)
+ prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.92.0)
prismarine-entity: 2.5.0
prismarine-item: 1.17.0
prismarine-nbt: 2.7.0
@@ -17586,7 +17574,7 @@ snapshots:
neo-async@2.6.2: {}
- net-browserify@https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/e754999ffdea67853bc9b10553b5e9908b40f618:
+ net-browserify@https://codeload.github.com/zardoy/prismarinejs-net-browserify/tar.gz/17fb901e8ea480a52c8fd46373695be172be8aa5:
dependencies:
body-parser: 1.20.3
express: 4.21.2
@@ -18174,15 +18162,15 @@ snapshots:
transitivePeerDependencies:
- supports-color
- prismarine-biome@1.3.0(minecraft-data@3.98.0)(prismarine-registry@1.11.0):
+ prismarine-biome@1.3.0(minecraft-data@3.92.0)(prismarine-registry@1.11.0):
dependencies:
- minecraft-data: 3.98.0
+ minecraft-data: 3.92.0
prismarine-registry: 1.11.0
prismarine-block@https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9:
dependencies:
- minecraft-data: 3.98.0
- prismarine-biome: 1.3.0(minecraft-data@3.98.0)(prismarine-registry@1.11.0)
+ minecraft-data: 3.92.0
+ prismarine-biome: 1.3.0(minecraft-data@3.92.0)(prismarine-registry@1.11.0)
prismarine-chat: 1.11.0
prismarine-item: 1.17.0
prismarine-nbt: 2.7.0
@@ -18194,9 +18182,9 @@ snapshots:
prismarine-nbt: 2.7.0
prismarine-registry: 1.11.0
- prismarine-chunk@https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.98.0):
+ prismarine-chunk@https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.92.0):
dependencies:
- prismarine-biome: 1.3.0(minecraft-data@3.98.0)(prismarine-registry@1.11.0)
+ prismarine-biome: 1.3.0(minecraft-data@3.92.0)(prismarine-registry@1.11.0)
prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9
prismarine-nbt: 2.7.0
prismarine-registry: 1.11.0
@@ -18225,14 +18213,14 @@ snapshots:
prismarine-physics@https://codeload.github.com/zardoy/prismarine-physics/tar.gz/353e25b800149393f40539ec381218be44cbb03b:
dependencies:
- minecraft-data: 3.98.0
+ minecraft-data: 3.92.0
prismarine-nbt: 2.7.0
vec3: 0.1.10
- prismarine-provider-anvil@https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.98.0):
+ prismarine-provider-anvil@https://codeload.github.com/zardoy/prismarine-provider-anvil/tar.gz/1d548fac63fe977c8281f0a9a522b37e4d92d0b7(minecraft-data@3.92.0):
dependencies:
prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9
- prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.98.0)
+ prismarine-chunk: https://codeload.github.com/zardoy/prismarine-chunk/tar.gz/c5feac83b61d95feb4d4f22c063dacfb8c192a9f(minecraft-data@3.92.0)
prismarine-nbt: 2.7.0
prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/ab2146c9933eef3247c3f64446de4ccc2c484c7c
uint4: 0.1.2
@@ -18254,13 +18242,13 @@ snapshots:
prismarine-registry@1.11.0:
dependencies:
- minecraft-data: 3.98.0
+ minecraft-data: 3.92.0
prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9
prismarine-nbt: 2.7.0
prismarine-schematic@1.2.3:
dependencies:
- minecraft-data: 3.98.0
+ minecraft-data: 3.92.0
prismarine-block: https://codeload.github.com/zardoy/prismarine-block/tar.gz/853c559bff2b402863ee9a75b125a3ca320838f9
prismarine-nbt: 2.7.0
prismarine-world: https://codeload.github.com/zardoy/prismarine-world/tar.gz/ab2146c9933eef3247c3f64446de4ccc2c484c7c
diff --git a/renderer/viewer/lib/createPlayerObject.ts b/renderer/viewer/lib/createPlayerObject.ts
deleted file mode 100644
index 836c8062..00000000
--- a/renderer/viewer/lib/createPlayerObject.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-import { PlayerObject, PlayerAnimation } from 'skinview3d'
-import * as THREE from 'three'
-import { WalkingGeneralSwing } from '../three/entity/animations'
-import { loadSkinImage, stevePngUrl } from './utils/skins'
-
-export type PlayerObjectType = PlayerObject & {
- animation?: PlayerAnimation
- realPlayerUuid: string
- realUsername: string
-}
-
-export function createPlayerObject (options: {
- username?: string
- uuid?: string
- scale?: number
-}): {
- playerObject: PlayerObjectType
- wrapper: THREE.Group
- } {
- const wrapper = new THREE.Group()
- const playerObject = new PlayerObject() as PlayerObjectType
-
- playerObject.realPlayerUuid = options.uuid ?? ''
- playerObject.realUsername = options.username ?? ''
- playerObject.position.set(0, 16, 0)
-
- // fix issues with starfield
- playerObject.traverse((obj) => {
- if (obj instanceof THREE.Mesh && obj.material instanceof THREE.MeshStandardMaterial) {
- obj.material.transparent = true
- }
- })
-
- wrapper.add(playerObject as any)
- const scale = options.scale ?? (1 / 16)
- wrapper.scale.set(scale, scale, scale)
- wrapper.rotation.set(0, Math.PI, 0)
-
- // Set up animation
- playerObject.animation = new WalkingGeneralSwing()
- ;(playerObject.animation as WalkingGeneralSwing).isMoving = false
- playerObject.animation.update(playerObject, 0)
-
- return { playerObject, wrapper }
-}
-
-export const applySkinToPlayerObject = async (playerObject: PlayerObjectType, skinUrl: string) => {
- return loadSkinImage(skinUrl || stevePngUrl).then(({ canvas }) => {
- const skinTexture = new THREE.CanvasTexture(canvas)
- skinTexture.magFilter = THREE.NearestFilter
- skinTexture.minFilter = THREE.NearestFilter
- skinTexture.needsUpdate = true
- playerObject.skin.map = skinTexture as any
- }).catch(console.error)
-}
diff --git a/renderer/viewer/lib/worldDataEmitter.ts b/renderer/viewer/lib/worldDataEmitter.ts
index dfbdb35c..86a85f77 100644
--- a/renderer/viewer/lib/worldDataEmitter.ts
+++ b/renderer/viewer/lib/worldDataEmitter.ts
@@ -7,7 +7,6 @@ import { Vec3 } from 'vec3'
import { BotEvents } from 'mineflayer'
import { proxy } from 'valtio'
import TypedEmitter from 'typed-emitter'
-import { Biome } from 'minecraft-data'
import { delayedIterator } from '../../playground/shared'
import { chunkPos } from './simpleUtils'
@@ -29,8 +28,6 @@ export type WorldDataEmitterEvents = {
updateLight: (data: { pos: Vec3 }) => void
onWorldSwitch: () => void
end: () => void
- biomeUpdate: (data: { biome: Biome }) => void
- biomeReset: () => void
}
export class WorldDataEmitterWorker extends (EventEmitter as new () => TypedEmitter) {
@@ -363,37 +360,8 @@ export class WorldDataEmitter extends (EventEmitter as new () => TypedEmitter {
export const worldCleanup = buildCleanupDecorator('resetWorld')
export const defaultWorldRendererConfig = {
- // Debug settings
showChunkBorders: false,
- enableDebugOverlay: false,
-
- // Performance settings
mesherWorkers: 4,
- addChunksBatchWaitTime: 200,
- _experimentalSmoothChunkLoading: true,
- _renderByChunks: false,
-
- // Rendering engine settings
- dayCycle: true,
+ isPlayground: false,
+ renderEars: true,
+ skinTexturesProxy: undefined as string | undefined,
+ // game renderer setting actually
+ showHand: false,
+ viewBobbing: false,
+ extraBlockRenderers: true,
+ clipWorldBelowY: undefined as number | undefined,
smoothLighting: true,
enableLighting: true,
starfield: true,
- defaultSkybox: true,
- renderEntities: true,
- extraBlockRenderers: true,
- foreground: true,
- fov: 75,
- volume: 1,
-
- // Camera visual related settings
- showHand: false,
- viewBobbing: false,
- renderEars: true,
- highlightBlockColor: 'blue',
-
- // Player models
- fetchPlayerSkins: true,
- skinTexturesProxy: undefined as string | undefined,
-
- // VR settings
+ addChunksBatchWaitTime: 200,
vrSupport: true,
vrPageGameRendering: true,
-
- // World settings
- clipWorldBelowY: undefined as number | undefined,
- isPlayground: false
+ renderEntities: true,
+ fov: 75,
+ fetchPlayerSkins: true,
+ highlightBlockColor: 'blue',
+ foreground: true,
+ enableDebugOverlay: false,
+ _experimentalSmoothChunkLoading: true,
+ _renderByChunks: false,
+ volume: 1
}
export type WorldRendererConfig = typeof defaultWorldRendererConfig
@@ -510,10 +496,6 @@ export abstract class WorldRendererCommon
timeUpdated? (newTime: number): void
- biomeUpdated? (biome: any): void
-
- biomeReset? (): void
-
updateViewerPosition (pos: Vec3) {
this.viewerChunkPosition = pos
for (const [key, value] of Object.entries(this.loadedChunks)) {
@@ -835,9 +817,12 @@ export abstract class WorldRendererCommon
})
worldEmitter.on('time', (timeOfDay) => {
- if (!this.worldRendererConfig.dayCycle) return
this.timeUpdated?.(timeOfDay)
+ if (timeOfDay < 0 || timeOfDay > 24_000) {
+ throw new Error('Invalid time of day. It should be between 0 and 24000.')
+ }
+
this.timeOfTheDay = timeOfDay
// if (this.worldRendererConfig.skyLight === skyLight) return
@@ -846,14 +831,6 @@ export abstract class WorldRendererCommon
// (this).rerenderAllChunks?.()
// }
})
-
- worldEmitter.on('biomeUpdate', ({ biome }) => {
- this.biomeUpdated?.(biome)
- })
-
- worldEmitter.on('biomeReset', () => {
- this.biomeReset?.()
- })
}
setBlockStateIdInner (pos: Vec3, stateId: number | undefined, needAoRecalculation = true) {
diff --git a/renderer/viewer/three/cameraShake.ts b/renderer/viewer/three/cameraShake.ts
index 7b159509..593b4628 100644
--- a/renderer/viewer/three/cameraShake.ts
+++ b/renderer/viewer/three/cameraShake.ts
@@ -80,12 +80,8 @@ export class CameraShake {
camera.setRotationFromQuaternion(yawQuat)
} else {
// For regular camera, apply all rotations
- // Add tiny offsets to prevent z-fighting at ideal angles (90, 180, 270 degrees)
- const pitchOffset = this.addAntiZfightingOffset(this.basePitch)
- const yawOffset = this.addAntiZfightingOffset(this.baseYaw)
-
- const pitchQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), pitchOffset)
- const yawQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), yawOffset)
+ const pitchQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(1, 0, 0), this.basePitch)
+ const yawQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), this.baseYaw)
const rollQuat = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 0, 1), THREE.MathUtils.degToRad(this.rollAngle))
// Combine rotations in the correct order: pitch -> yaw -> roll
const finalQuat = yawQuat.multiply(pitchQuat).multiply(rollQuat)
@@ -100,21 +96,4 @@ export class CameraShake {
private easeInOut (t: number): number {
return t < 0.5 ? 2 * t * t : 1 - (-2 * t + 2) ** 2 / 2
}
-
- private addAntiZfightingOffset (angle: number): number {
- const offset = 0.001 // Very small offset in radians (about 0.057 degrees)
-
- // Check if the angle is close to ideal angles (0, π/2, π, 3π/2)
- const normalizedAngle = ((angle % (Math.PI * 2)) + Math.PI * 2) % (Math.PI * 2)
- const tolerance = 0.01 // Tolerance for considering an angle "ideal"
-
- if (Math.abs(normalizedAngle) < tolerance ||
- Math.abs(normalizedAngle - Math.PI / 2) < tolerance ||
- Math.abs(normalizedAngle - Math.PI) < tolerance ||
- Math.abs(normalizedAngle - 3 * Math.PI / 2) < tolerance) {
- return angle + offset
- }
-
- return angle
- }
}
diff --git a/renderer/viewer/three/entities.ts b/renderer/viewer/three/entities.ts
index fad30182..7849686b 100644
--- a/renderer/viewer/three/entities.ts
+++ b/renderer/viewer/three/entities.ts
@@ -20,7 +20,6 @@ import { ItemSpecificContextProperties } from '../lib/basePlayerState'
import { loadSkinFromUsername, loadSkinImage, stevePngUrl } from '../lib/utils/skins'
import { renderComponent } from '../sign-renderer'
import { createCanvas } from '../lib/utils'
-import { PlayerObjectType } from '../lib/createPlayerObject'
import { getBlockMeshFromModel } from './holdingBlock'
import { createItemMesh } from './itemMesh'
import * as Entity from './entity/EntityMesh'
@@ -34,6 +33,12 @@ export const steveTexture = loadThreeJsTextureFromUrl(stevePngUrl)
export const TWEEN_DURATION = 120
+type PlayerObjectType = PlayerObject & {
+ animation?: PlayerAnimation
+ realPlayerUuid: string
+ realUsername: string
+}
+
function convert2sComplementToHex (complement: number) {
if (complement < 0) {
complement = (0xFF_FF_FF_FF + complement + 1) >>> 0
diff --git a/renderer/viewer/three/skyboxRenderer.ts b/renderer/viewer/three/skyboxRenderer.ts
index fb9edae6..294c72aa 100644
--- a/renderer/viewer/three/skyboxRenderer.ts
+++ b/renderer/viewer/three/skyboxRenderer.ts
@@ -1,51 +1,10 @@
import * as THREE from 'three'
-import { DebugGui } from '../lib/DebugGui'
-
-export const DEFAULT_TEMPERATURE = 0.75
export class SkyboxRenderer {
private texture: THREE.Texture | null = null
private mesh: THREE.Mesh | null = null
- private skyMesh: THREE.Mesh | null = null
- private voidMesh: THREE.Mesh | null = null
- // World state
- private worldTime = 0
- private partialTicks = 0
- private viewDistance = 4
- private temperature = DEFAULT_TEMPERATURE
- private inWater = false
- private waterBreathing = false
- private fogBrightness = 0
- private prevFogBrightness = 0
- private readonly fogOrangeness = 0 // Debug property to control sky color orangeness
- private readonly distanceFactor = 2.7
-
- private readonly brightnessAtPosition = 1
- debugGui: DebugGui
-
- constructor (private readonly scene: THREE.Scene, public defaultSkybox: boolean, public initialImage: string | null) {
- this.debugGui = new DebugGui('skybox_renderer', this, [
- 'temperature',
- 'worldTime',
- 'inWater',
- 'waterBreathing',
- 'fogOrangeness',
- 'brightnessAtPosition',
- 'distanceFactor'
- ], {
- brightnessAtPosition: { min: 0, max: 1, step: 0.01 },
- temperature: { min: 0, max: 1, step: 0.01 },
- worldTime: { min: 0, max: 24_000, step: 1 },
- fogOrangeness: { min: -1, max: 1, step: 0.01 },
- distanceFactor: { min: 0, max: 5, step: 0.01 },
- })
-
- if (!initialImage) {
- this.createGradientSky()
- }
- // this.debugGui.activate()
- }
+ constructor (private readonly scene: THREE.Scene, public initialImage: string | null) {}
async init () {
if (this.initialImage) {
@@ -99,290 +58,12 @@ export class SkyboxRenderer {
}
}
- update (cameraPosition: THREE.Vector3, newViewDistance: number) {
- if (newViewDistance !== this.viewDistance) {
- this.viewDistance = newViewDistance
- this.updateSkyColors()
- }
-
+ update (cameraPosition: THREE.Vector3) {
if (this.mesh) {
- // Update skybox position
this.mesh.position.copy(cameraPosition)
- } else if (this.skyMesh) {
- // Update gradient sky position
- this.skyMesh.position.copy(cameraPosition)
- this.voidMesh?.position.copy(cameraPosition)
- this.updateSkyColors() // Update colors based on time of day
}
}
- // Update world time
- updateTime (timeOfDay: number, partialTicks = 0) {
- if (this.debugGui.visible) return
- this.worldTime = timeOfDay
- this.partialTicks = partialTicks
- this.updateSkyColors()
- }
-
- // Update view distance
- updateViewDistance (viewDistance: number) {
- this.viewDistance = viewDistance
- this.updateSkyColors()
- }
-
- // Update temperature (for biome support)
- updateTemperature (temperature: number) {
- if (this.debugGui.visible) return
- this.temperature = temperature
- this.updateSkyColors()
- }
-
- // Update water state
- updateWaterState (inWater: boolean, waterBreathing: boolean) {
- if (this.debugGui.visible) return
- this.inWater = inWater
- this.waterBreathing = waterBreathing
- this.updateSkyColors()
- }
-
- // Update default skybox setting
- updateDefaultSkybox (defaultSkybox: boolean) {
- if (this.debugGui.visible) return
- this.defaultSkybox = defaultSkybox
- this.updateSkyColors()
- }
-
- private createGradientSky () {
- const size = 64
- const scale = 256 / size + 2
-
- {
- const geometry = new THREE.PlaneGeometry(size * scale * 2, size * scale * 2)
- geometry.rotateX(-Math.PI / 2)
- geometry.translate(0, 16, 0)
-
- const material = new THREE.MeshBasicMaterial({
- color: 0xff_ff_ff,
- side: THREE.DoubleSide,
- depthTest: false
- })
-
- this.skyMesh = new THREE.Mesh(geometry, material)
- this.scene.add(this.skyMesh)
- }
-
- {
- const geometry = new THREE.PlaneGeometry(size * scale * 2, size * scale * 2)
- geometry.rotateX(-Math.PI / 2)
- geometry.translate(0, -16, 0)
-
- const material = new THREE.MeshBasicMaterial({
- color: 0xff_ff_ff,
- side: THREE.DoubleSide,
- depthTest: false
- })
-
- this.voidMesh = new THREE.Mesh(geometry, material)
- this.scene.add(this.voidMesh)
- }
-
- this.updateSkyColors()
- }
-
- private getFogColor (partialTicks = 0): THREE.Vector3 {
- const angle = this.getCelestialAngle(partialTicks)
- let rotation = Math.cos(angle * Math.PI * 2) * 2 + 0.5
- rotation = Math.max(0, Math.min(1, rotation))
-
- let x = 0.752_941_2
- let y = 0.847_058_83
- let z = 1
-
- x *= (rotation * 0.94 + 0.06)
- y *= (rotation * 0.94 + 0.06)
- z *= (rotation * 0.91 + 0.09)
-
- return new THREE.Vector3(x, y, z)
- }
-
- private getSkyColor (x = 0, z = 0, partialTicks = 0): THREE.Vector3 {
- const angle = this.getCelestialAngle(partialTicks)
- let brightness = Math.cos(angle * 3.141_593 * 2) * 2 + 0.5
-
- if (brightness < 0) brightness = 0
- if (brightness > 1) brightness = 1
-
- const temperature = this.getTemperature(x, z)
- const rgb = this.getSkyColorByTemp(temperature)
-
- const red = ((rgb >> 16) & 0xff) / 255
- const green = ((rgb >> 8) & 0xff) / 255
- const blue = (rgb & 0xff) / 255
-
- return new THREE.Vector3(
- red * brightness,
- green * brightness,
- blue * brightness
- )
- }
-
- private calculateCelestialAngle (time: number, partialTicks: number): number {
- const modTime = (time % 24_000)
- let angle = (modTime + partialTicks) / 24_000 - 0.25
-
- if (angle < 0) {
- angle++
- }
- if (angle > 1) {
- angle--
- }
-
- angle = 1 - ((Math.cos(angle * Math.PI) + 1) / 2)
- angle += (angle - angle) / 3
-
- return angle
- }
-
- private getCelestialAngle (partialTicks: number): number {
- return this.calculateCelestialAngle(this.worldTime, partialTicks)
- }
-
- private getTemperature (x: number, z: number): number {
- return this.temperature
- }
-
- private getSkyColorByTemp (temperature: number): number {
- temperature /= 3
- if (temperature < -1) temperature = -1
- if (temperature > 1) temperature = 1
-
- // Apply debug fog orangeness to hue - positive values make it more orange, negative make it less orange
- const baseHue = 0.622_222_2 - temperature * 0.05
- // Orange is around hue 0.08-0.15, so we need to shift from blue-purple (0.62) toward orange
- // Use a more dramatic shift and also increase saturation for more noticeable effect
- const orangeHue = 0.12 // Orange hue value
- const hue = this.fogOrangeness > 0
- ? baseHue + (orangeHue - baseHue) * this.fogOrangeness * 0.8 // Blend toward orange
- : baseHue + this.fogOrangeness * 0.1 // Subtle shift for negative values
- const saturation = 0.5 + temperature * 0.1 + Math.abs(this.fogOrangeness) * 0.3 // Increase saturation with orangeness
- const brightness = 1
-
- return this.hsbToRgb(hue, saturation, brightness)
- }
-
- private hsbToRgb (hue: number, saturation: number, brightness: number): number {
- let r = 0; let g = 0; let b = 0
- if (saturation === 0) {
- r = g = b = Math.floor(brightness * 255 + 0.5)
- } else {
- const h = (hue - Math.floor(hue)) * 6
- const f = h - Math.floor(h)
- const p = brightness * (1 - saturation)
- const q = brightness * (1 - saturation * f)
- const t = brightness * (1 - (saturation * (1 - f)))
- switch (Math.floor(h)) {
- case 0:
- r = Math.floor(brightness * 255 + 0.5)
- g = Math.floor(t * 255 + 0.5)
- b = Math.floor(p * 255 + 0.5)
- break
- case 1:
- r = Math.floor(q * 255 + 0.5)
- g = Math.floor(brightness * 255 + 0.5)
- b = Math.floor(p * 255 + 0.5)
- break
- case 2:
- r = Math.floor(p * 255 + 0.5)
- g = Math.floor(brightness * 255 + 0.5)
- b = Math.floor(t * 255 + 0.5)
- break
- case 3:
- r = Math.floor(p * 255 + 0.5)
- g = Math.floor(q * 255 + 0.5)
- b = Math.floor(brightness * 255 + 0.5)
- break
- case 4:
- r = Math.floor(t * 255 + 0.5)
- g = Math.floor(p * 255 + 0.5)
- b = Math.floor(brightness * 255 + 0.5)
- break
- case 5:
- r = Math.floor(brightness * 255 + 0.5)
- g = Math.floor(p * 255 + 0.5)
- b = Math.floor(q * 255 + 0.5)
- break
- }
- }
- return 0xff_00_00_00 | (r << 16) | (g << 8) | (Math.trunc(b))
- }
-
- private updateSkyColors () {
- if (!this.skyMesh || !this.voidMesh) return
-
- // If default skybox is disabled, hide the skybox meshes
- if (!this.defaultSkybox) {
- this.skyMesh.visible = false
- this.voidMesh.visible = false
- if (this.mesh) {
- this.mesh.visible = false
- }
- return
- }
-
- // Show skybox meshes when default skybox is enabled
- this.skyMesh.visible = true
- this.voidMesh.visible = true
- if (this.mesh) {
- this.mesh.visible = true
- }
-
- // Update fog brightness with smooth transition
- this.prevFogBrightness = this.fogBrightness
- const renderDistance = this.viewDistance / 32
- const targetBrightness = this.brightnessAtPosition * (1 - renderDistance) + renderDistance
- this.fogBrightness += (targetBrightness - this.fogBrightness) * 0.1
-
- // Handle water fog
- if (this.inWater) {
- const waterViewDistance = this.waterBreathing ? 100 : 5
- this.scene.fog = new THREE.Fog(new THREE.Color(0, 0, 1), 0.0025, waterViewDistance)
- this.scene.background = new THREE.Color(0, 0, 1)
-
- // Update sky and void colors for underwater effect
- ;(this.skyMesh.material as THREE.MeshBasicMaterial).color.set(new THREE.Color(0, 0, 1))
- ;(this.voidMesh.material as THREE.MeshBasicMaterial).color.set(new THREE.Color(0, 0, 0.6))
- return
- }
-
- // Normal sky colors
- const viewDistance = this.viewDistance * 16
- const viewFactor = 1 - (0.25 + 0.75 * this.viewDistance / 32) ** 0.25
-
- const angle = this.getCelestialAngle(this.partialTicks)
- const skyColor = this.getSkyColor(0, 0, this.partialTicks)
- const fogColor = this.getFogColor(this.partialTicks)
-
- const brightness = Math.cos(angle * Math.PI * 2) * 2 + 0.5
- const clampedBrightness = Math.max(0, Math.min(1, brightness))
-
- // Interpolate fog brightness
- const interpolatedBrightness = this.prevFogBrightness + (this.fogBrightness - this.prevFogBrightness) * this.partialTicks
-
- const red = (fogColor.x + (skyColor.x - fogColor.x) * viewFactor) * clampedBrightness * interpolatedBrightness
- const green = (fogColor.y + (skyColor.y - fogColor.y) * viewFactor) * clampedBrightness * interpolatedBrightness
- const blue = (fogColor.z + (skyColor.z - fogColor.z) * viewFactor) * clampedBrightness * interpolatedBrightness
-
- this.scene.background = new THREE.Color(red, green, blue)
- this.scene.fog = new THREE.Fog(new THREE.Color(red, green, blue), 0.0025, viewDistance * this.distanceFactor)
-
- ;(this.skyMesh.material as THREE.MeshBasicMaterial).color.set(new THREE.Color(skyColor.x, skyColor.y, skyColor.z))
- ;(this.voidMesh.material as THREE.MeshBasicMaterial).color.set(new THREE.Color(
- skyColor.x * 0.2 + 0.04,
- skyColor.y * 0.2 + 0.04,
- skyColor.z * 0.6 + 0.1
- ))
- }
-
dispose () {
if (this.texture) {
this.texture.dispose()
@@ -392,15 +73,5 @@ export class SkyboxRenderer {
;(this.mesh.material as THREE.Material).dispose()
this.scene.remove(this.mesh)
}
- if (this.skyMesh) {
- this.skyMesh.geometry.dispose()
- ;(this.skyMesh.material as THREE.Material).dispose()
- this.scene.remove(this.skyMesh)
- }
- if (this.voidMesh) {
- this.voidMesh.geometry.dispose()
- ;(this.voidMesh.material as THREE.Material).dispose()
- this.scene.remove(this.voidMesh)
- }
}
}
diff --git a/renderer/viewer/three/waypointSprite.ts b/renderer/viewer/three/waypointSprite.ts
index 6a30e6db..7c8cf1f6 100644
--- a/renderer/viewer/three/waypointSprite.ts
+++ b/renderer/viewer/three/waypointSprite.ts
@@ -16,7 +16,7 @@ export const WAYPOINT_CONFIG = {
CANVAS_SCALE: 2,
ARROW: {
enabledDefault: false,
- pixelSize: 50,
+ pixelSize: 30,
paddingPx: 50,
},
}
@@ -50,7 +50,6 @@ export function createWaypointSprite (options: {
depthTest?: boolean,
// Y offset in world units used by updateScaleWorld only (screen-pixel API ignores this)
labelYOffset?: number,
- metadata?: any,
}): WaypointSprite {
const color = options.color ?? 0xFF_00_00
const depthTest = options.depthTest ?? false
@@ -132,22 +131,16 @@ export function createWaypointSprite (options: {
canvas.height = size
const ctx = canvas.getContext('2d')!
ctx.clearRect(0, 0, size, size)
-
- // Draw arrow shape
ctx.beginPath()
- ctx.moveTo(size * 0.15, size * 0.5)
- ctx.lineTo(size * 0.85, size * 0.5)
- ctx.lineTo(size * 0.5, size * 0.15)
+ ctx.moveTo(size * 0.2, size * 0.5)
+ ctx.lineTo(size * 0.8, size * 0.5)
+ ctx.lineTo(size * 0.5, size * 0.2)
ctx.closePath()
-
- // Use waypoint color for arrow
- const colorHex = `#${color.toString(16).padStart(6, '0')}`
- ctx.lineWidth = 6
+ ctx.lineWidth = 4
ctx.strokeStyle = 'black'
ctx.stroke()
- ctx.fillStyle = colorHex
+ ctx.fillStyle = 'white'
ctx.fill()
-
const texture = new THREE.CanvasTexture(canvas)
const material = new THREE.SpriteMaterial({ map: texture, transparent: true, depthTest: false, depthWrite: false })
arrowSprite = new THREE.Sprite(material)
@@ -176,9 +169,6 @@ export function createWaypointSprite (options: {
ensureArrow()
if (!arrowSprite) return true
- // Check if onlyLeftRight is enabled in metadata
- const onlyLeftRight = options.metadata?.onlyLeftRight === true
-
// Build camera basis using camera.up to respect custom orientations
const forward = new THREE.Vector3()
camera.getWorldDirection(forward) // camera look direction
@@ -223,20 +213,6 @@ export function createWaypointSprite (options: {
}
}
- // Apply onlyLeftRight logic - restrict arrows to left/right edges only
- if (onlyLeftRight) {
- // Force the arrow to appear only on left or right edges
- if (Math.abs(rx) > Math.abs(ry)) {
- // Horizontal direction is dominant, keep it
- ry = 0
- } else {
- // Vertical direction is dominant, but we want only left/right
- // So choose left or right based on the sign of rx
- rx = rx >= 0 ? 1 : -1
- ry = 0
- }
- }
-
// Place on the rectangle border [-1,1]x[-1,1]
const s = Math.max(Math.abs(rx), Math.abs(ry)) || 1
let ndcX = rx / s
diff --git a/renderer/viewer/three/waypoints.ts b/renderer/viewer/three/waypoints.ts
index 256ca6df..cebd779a 100644
--- a/renderer/viewer/three/waypoints.ts
+++ b/renderer/viewer/three/waypoints.ts
@@ -17,7 +17,6 @@ interface WaypointOptions {
color?: number
label?: string
minDistance?: number
- metadata?: any
}
export class WaypointsRenderer {
@@ -72,14 +71,13 @@ export class WaypointsRenderer {
this.removeWaypoint(id)
const color = options.color ?? 0xFF_00_00
- const { label, metadata } = options
+ const { label } = options
const minDistance = options.minDistance ?? 0
const sprite = createWaypointSprite({
position: new THREE.Vector3(x, y, z),
color,
label: (label || id),
- metadata,
})
sprite.enableOffscreenArrow(true)
sprite.setArrowParent(this.waypointScene)
diff --git a/renderer/viewer/three/world/cursorBlock.ts b/renderer/viewer/three/world/cursorBlock.ts
index a03a6999..b71c1b8d 100644
--- a/renderer/viewer/three/world/cursorBlock.ts
+++ b/renderer/viewer/three/world/cursorBlock.ts
@@ -28,7 +28,7 @@ export class CursorBlock {
}
cursorLineMaterial: LineMaterial
- interactionLines: null | { blockPos: Vec3, mesh: THREE.Group, shapePositions: BlocksShapes | undefined } = null
+ interactionLines: null | { blockPos: Vec3, mesh: THREE.Group } = null
prevColor: string | undefined
blockBreakMesh: THREE.Mesh
breakTextures: THREE.Texture[] = []
@@ -62,13 +62,6 @@ export class CursorBlock {
this.worldRenderer.onReactivePlayerStateUpdated('gameMode', () => {
this.updateLineMaterial()
})
- // todo figure out why otherwise fog from skybox breaks it
- setTimeout(() => {
- this.updateLineMaterial()
- if (this.interactionLines) {
- this.setHighlightCursorBlock(this.interactionLines.blockPos, this.interactionLines.shapePositions, true)
- }
- })
}
// Update functions
@@ -76,9 +69,6 @@ export class CursorBlock {
const inCreative = this.worldRenderer.playerStateReactive.gameMode === 'creative'
const pixelRatio = this.worldRenderer.renderer.getPixelRatio()
- if (this.cursorLineMaterial) {
- this.cursorLineMaterial.dispose()
- }
this.cursorLineMaterial = new LineMaterial({
color: (() => {
switch (this.worldRenderer.worldRendererConfig.highlightBlockColor) {
@@ -125,8 +115,8 @@ export class CursorBlock {
}
}
- setHighlightCursorBlock (blockPos: Vec3 | null, shapePositions?: BlocksShapes, force = false): void {
- if (blockPos && this.interactionLines && blockPos.equals(this.interactionLines.blockPos) && !force) {
+ setHighlightCursorBlock (blockPos: Vec3 | null, shapePositions?: BlocksShapes): void {
+ if (blockPos && this.interactionLines && blockPos.equals(this.interactionLines.blockPos)) {
return
}
if (this.interactionLines !== null) {
@@ -150,7 +140,7 @@ export class CursorBlock {
}
this.worldRenderer.scene.add(group)
group.visible = !this.cursorLinesHidden
- this.interactionLines = { blockPos, mesh: group, shapePositions }
+ this.interactionLines = { blockPos, mesh: group }
}
render () {
diff --git a/renderer/viewer/three/worldrendererThree.ts b/renderer/viewer/three/worldrendererThree.ts
index 1b4e6152..fb6c8e11 100644
--- a/renderer/viewer/three/worldrendererThree.ts
+++ b/renderer/viewer/three/worldrendererThree.ts
@@ -3,7 +3,6 @@ import { Vec3 } from 'vec3'
import nbt from 'prismarine-nbt'
import PrismarineChatLoader from 'prismarine-chat'
import * as tweenJs from '@tweenjs/tween.js'
-import { Biome } from 'minecraft-data'
import { renderSign } from '../sign-renderer'
import { DisplayWorldOptions, GraphicsInitOptions } from '../../../src/appViewer'
import { chunkPos, sectionPos } from '../lib/simpleUtils'
@@ -25,7 +24,7 @@ import { CameraShake } from './cameraShake'
import { ThreeJsMedia } from './threeJsMedia'
import { Fountain } from './threeJsParticles'
import { WaypointsRenderer } from './waypoints'
-import { DEFAULT_TEMPERATURE, SkyboxRenderer } from './skyboxRenderer'
+import { SkyboxRenderer } from './skyboxRenderer'
type SectionKey = string
@@ -98,7 +97,7 @@ export class WorldRendererThree extends WorldRendererCommon {
this.holdingBlockLeft = new HoldingBlock(this, true)
// Initialize skybox renderer
- this.skyboxRenderer = new SkyboxRenderer(this.scene, this.worldRendererConfig.defaultSkybox, null)
+ this.skyboxRenderer = new SkyboxRenderer(this.scene, null)
void this.skyboxRenderer.init()
this.addDebugOverlay()
@@ -174,10 +173,7 @@ export class WorldRendererThree extends WorldRendererCommon {
override watchReactivePlayerState () {
super.watchReactivePlayerState()
this.onReactivePlayerStateUpdated('inWater', (value) => {
- this.skyboxRenderer.updateWaterState(value, this.playerStateReactive.waterBreathing)
- })
- this.onReactivePlayerStateUpdated('waterBreathing', (value) => {
- this.skyboxRenderer.updateWaterState(this.playerStateReactive.inWater, value)
+ this.scene.fog = value ? new THREE.Fog(0x00_00_ff, 0.1, this.playerStateReactive.waterBreathing ? 100 : 20) : null
})
this.onReactivePlayerStateUpdated('ambientLight', (value) => {
if (!value) return
@@ -206,9 +202,6 @@ export class WorldRendererThree extends WorldRendererCommon {
this.onReactiveConfigUpdated('showChunkBorders', (value) => {
this.updateShowChunksBorder(value)
})
- this.onReactiveConfigUpdated('defaultSkybox', (value) => {
- this.skyboxRenderer.updateDefaultSkybox(value)
- })
}
changeHandSwingingState (isAnimationPlaying: boolean, isLeft = false) {
@@ -271,19 +264,6 @@ export class WorldRendererThree extends WorldRendererCommon {
} else {
this.starField.remove()
}
-
- this.skyboxRenderer.updateTime(newTime)
- }
-
- biomeUpdated (biome: Biome): void {
- if (biome?.temperature !== undefined) {
- this.skyboxRenderer.updateTemperature(biome.temperature)
- }
- }
-
- biomeReset (): void {
- // Reset to default temperature when biome is unknown
- this.skyboxRenderer.updateTemperature(DEFAULT_TEMPERATURE)
}
getItemRenderData (item: Record, specificProps: ItemSpecificContextProperties) {
@@ -736,7 +716,7 @@ export class WorldRendererThree extends WorldRendererCommon {
// Update skybox position to follow camera
const cameraPos = this.getCameraPosition()
- this.skyboxRenderer.update(cameraPos, this.viewDistance)
+ this.skyboxRenderer.update(cameraPos)
const sizeOrFovChanged = sizeChanged || this.displayOptions.inWorldRenderingConfig.fov !== this.camera.fov
if (sizeOrFovChanged) {
@@ -787,17 +767,12 @@ export class WorldRendererThree extends WorldRendererCommon {
}
renderHead (position: Vec3, rotation: number, isWall: boolean, blockEntity) {
- let textureData: string
- if (blockEntity.SkullOwner) {
- textureData = blockEntity.SkullOwner.Properties?.textures?.[0]?.Value
- } else {
- textureData = blockEntity.profile?.properties?.find(p => p.name === 'textures')?.value
- }
- if (!textureData) return
+ const textures = blockEntity.SkullOwner?.Properties?.textures[0]
+ if (!textures) return
try {
- const decodedData = JSON.parse(Buffer.from(textureData, 'base64').toString())
- let skinUrl = decodedData.textures?.SKIN?.url
+ const textureData = JSON.parse(Buffer.from(textures.Value, 'base64').toString())
+ let skinUrl = textureData.textures?.SKIN?.url
const { skinTexturesProxy } = this.worldRendererConfig
if (skinTexturesProxy) {
skinUrl = skinUrl?.replace('http://textures.minecraft.net/', skinTexturesProxy)
diff --git a/scripts/makeOptimizedMcData.mjs b/scripts/makeOptimizedMcData.mjs
index a572d067..76e0f1c2 100644
--- a/scripts/makeOptimizedMcData.mjs
+++ b/scripts/makeOptimizedMcData.mjs
@@ -371,7 +371,6 @@ console.log('size', fs.lstatSync(filePath).size / 1000 / 1000, gzipSizeFromFileS
const { defaultVersion } = MCProtocol
const data = MinecraftData(defaultVersion)
-console.log('defaultVersion', defaultVersion, !!data)
const initialMcData = {
[defaultVersion]: {
version: data.version,
diff --git a/src/appConfig.ts b/src/appConfig.ts
index c29d74e8..92fde21a 100644
--- a/src/appConfig.ts
+++ b/src/appConfig.ts
@@ -35,7 +35,7 @@ export type AppConfig = {
// defaultVersion?: string
peerJsServer?: string
peerJsServerFallback?: string
- promoteServers?: Array<{ ip, description, name?, version?, }>
+ promoteServers?: Array<{ ip, description, version? }>
mapsProvider?: string
appParams?: Record // query string params
diff --git a/src/appParams.ts b/src/appParams.ts
index 4c8ca186..8d487f8d 100644
--- a/src/appParams.ts
+++ b/src/appParams.ts
@@ -47,7 +47,6 @@ export type AppQsParams = {
connectText?: string
freezeSettings?: string
testIosCrash?: string
- addPing?: string
// Replay params
replayFilter?: string
diff --git a/src/basicSounds.ts b/src/basicSounds.ts
index 54af0d35..37f8dccd 100644
--- a/src/basicSounds.ts
+++ b/src/basicSounds.ts
@@ -7,12 +7,7 @@ let audioContext: AudioContext
const sounds: Record = {}
// Track currently playing sounds and their gain nodes
-const activeSounds: Array<{
- source: AudioBufferSourceNode;
- gainNode: GainNode;
- volumeMultiplier: number;
- isMusic: boolean;
-}> = []
+const activeSounds: Array<{ source: AudioBufferSourceNode; gainNode: GainNode; volumeMultiplier: number }> = []
window.activeSounds = activeSounds
// load as many resources on page load as possible instead on demand as user can disable internet connection after he thinks the page is loaded
@@ -48,7 +43,7 @@ export async function loadSound (path: string, contents = path) {
}
}
-export const loadOrPlaySound = async (url, soundVolume = 1, loadTimeout = options.remoteSoundsLoadTimeout, loop = false, isMusic = false) => {
+export const loadOrPlaySound = async (url, soundVolume = 1, loadTimeout = options.remoteSoundsLoadTimeout, loop = false) => {
const soundBuffer = sounds[url]
if (!soundBuffer) {
const start = Date.now()
@@ -56,11 +51,11 @@ export const loadOrPlaySound = async (url, soundVolume = 1, loadTimeout = option
if (cancelled || Date.now() - start > loadTimeout) return
}
- return playSound(url, soundVolume, loop, isMusic)
+ return playSound(url, soundVolume, loop)
}
-export async function playSound (url, soundVolume = 1, loop = false, isMusic = false) {
- const volume = soundVolume * (options.volume / 100) * (isMusic ? options.musicVolume / 100 : 1)
+export async function playSound (url, soundVolume = 1, loop = false) {
+ const volume = soundVolume * (options.volume / 100)
if (!volume) return
@@ -87,7 +82,7 @@ export async function playSound (url, soundVolume = 1, loop = false, isMusic = f
source.start(0)
// Add to active sounds
- activeSounds.push({ source, gainNode, volumeMultiplier: soundVolume, isMusic })
+ activeSounds.push({ source, gainNode, volumeMultiplier: soundVolume })
const callbacks = [] as Array<() => void>
source.onended = () => {
@@ -115,7 +110,6 @@ export async function playSound (url, soundVolume = 1, loop = false, isMusic = f
console.warn('Failed to stop sound:', err)
}
},
- gainNode,
}
}
@@ -143,11 +137,11 @@ export function stopSound (url: string) {
}
}
-export function changeVolumeOfCurrentlyPlayingSounds (newVolume: number, newMusicVolume: number) {
+export function changeVolumeOfCurrentlyPlayingSounds (newVolume: number) {
const normalizedVolume = newVolume / 100
- for (const { gainNode, volumeMultiplier, isMusic } of activeSounds) {
+ for (const { gainNode, volumeMultiplier } of activeSounds) {
try {
- gainNode.gain.value = normalizedVolume * volumeMultiplier * (isMusic ? newMusicVolume / 100 : 1)
+ gainNode.gain.value = normalizedVolume * volumeMultiplier
} catch (err) {
console.warn('Failed to change sound volume:', err)
}
@@ -155,9 +149,5 @@ export function changeVolumeOfCurrentlyPlayingSounds (newVolume: number, newMusi
}
subscribeKey(options, 'volume', () => {
- changeVolumeOfCurrentlyPlayingSounds(options.volume, options.musicVolume)
-})
-
-subscribeKey(options, 'musicVolume', () => {
- changeVolumeOfCurrentlyPlayingSounds(options.volume, options.musicVolume)
+ changeVolumeOfCurrentlyPlayingSounds(options.volume)
})
diff --git a/src/chatUtils.ts b/src/chatUtils.ts
index 849d5847..88437bc3 100644
--- a/src/chatUtils.ts
+++ b/src/chatUtils.ts
@@ -118,14 +118,6 @@ export const formatMessage = (message: MessageInput, mcData: IndexedData = globa
return msglist
}
-export const messageToString = (message: MessageInput | string) => {
- if (typeof message === 'string') {
- return message
- }
- const msglist = formatMessage(message)
- return msglist.map(msg => msg.text).join('')
-}
-
const blockToItemRemaps = {
water: 'water_bucket',
lava: 'lava_bucket',
diff --git a/src/customChannels.ts b/src/customChannels.ts
index 506ea776..717c7c93 100644
--- a/src/customChannels.ts
+++ b/src/customChannels.ts
@@ -7,15 +7,18 @@ import { registerIdeChannels } from './core/ideChannels'
export default () => {
customEvents.on('mineflayerBotCreated', async () => {
if (!options.customChannels) return
- bot.once('login', () => {
- registerBlockModelsChannel()
- registerMediaChannels()
- registerSectionAnimationChannels()
- registeredJeiChannel()
- registerBlockInteractionsCustomizationChannel()
- registerWaypointChannels()
- registerIdeChannels()
+ await new Promise(resolve => {
+ bot.once('login', () => {
+ resolve(true)
+ })
})
+ registerBlockModelsChannel()
+ registerMediaChannels()
+ registerSectionAnimationChannels()
+ registeredJeiChannel()
+ registerBlockInteractionsCustomizationChannel()
+ registerWaypointChannels()
+ registerIdeChannels()
})
}
@@ -47,7 +50,19 @@ const registerBlockInteractionsCustomizationChannel = () => {
registerChannel(CHANNEL_NAME, packetStructure, (data) => {
const config = JSON.parse(data.newConfiguration)
- bot.mouse.setConfigFromPacket(config)
+ if (config.customBreakTime !== undefined && Object.values(config.customBreakTime).every(x => typeof x === 'number')) {
+ bot.mouse.customBreakTime = config.customBreakTime
+ }
+ if (config.customBreakTimeToolAllowance !== undefined) {
+ bot.mouse.customBreakTimeToolAllowance = new Set(config.customBreakTimeToolAllowance)
+ }
+
+ if (config.blockPlacePrediction !== undefined) {
+ bot.mouse.settings.blockPlacePrediction = config.blockPlacePrediction
+ }
+ if (config.blockPlacePredictionDelay !== undefined) {
+ bot.mouse.settings.blockPlacePredictionDelay = config.blockPlacePredictionDelay
+ }
}, true)
}
@@ -82,30 +97,15 @@ const registerWaypointChannels = () => {
{
name: 'color',
type: 'i32'
- },
- {
- name: 'metadataJson',
- type: ['pstring', { countType: 'i16' }]
}
]
]
registerChannel('minecraft-web-client:waypoint-add', packetStructure, (data) => {
- // Parse metadata if provided
- let metadata: any = {}
- if (data.metadataJson && data.metadataJson.trim() !== '') {
- try {
- metadata = JSON.parse(data.metadataJson)
- } catch (error) {
- console.warn('Failed to parse waypoint metadataJson:', error)
- }
- }
-
getThreeJsRendererMethods()?.addWaypoint(data.id, data.x, data.y, data.z, {
minDistance: data.minDistance,
label: data.label || undefined,
- color: data.color || undefined,
- metadata
+ color: data.color || undefined
})
})
diff --git a/src/dayCycle.ts b/src/dayCycle.ts
new file mode 100644
index 00000000..50e63a21
--- /dev/null
+++ b/src/dayCycle.ts
@@ -0,0 +1,46 @@
+import { options } from './optionsStorage'
+import { assertDefined } from './utils'
+import { updateBackground } from './water'
+
+export default () => {
+ const timeUpdated = () => {
+ // 0 morning
+ const dayTotal = 24_000
+ const evening = 11_500
+ const night = 13_500
+ const morningStart = 23_000
+ const morningEnd = 23_961
+ const timeProgress = options.dayCycleAndLighting ? bot.time.timeOfDay : 0
+
+ // todo check actual colors
+ const dayColorRainy = { r: 111 / 255, g: 156 / 255, b: 236 / 255 }
+ // todo yes, we should make animations (and rain)
+ // eslint-disable-next-line unicorn/numeric-separators-style
+ const dayColor = bot.isRaining ? dayColorRainy : { r: 0.6784313725490196, g: 0.8470588235294118, b: 0.9019607843137255 } // lightblue
+ // let newColor = dayColor
+ let int = 1
+ if (timeProgress < evening) {
+ // stay dayily
+ } else if (timeProgress < night) {
+ const progressNorm = timeProgress - evening
+ const progressMax = night - evening
+ int = 1 - progressNorm / progressMax
+ } else if (timeProgress < morningStart) {
+ int = 0
+ } else if (timeProgress < morningEnd) {
+ const progressNorm = timeProgress - morningStart
+ const progressMax = night - morningEnd
+ int = progressNorm / progressMax
+ }
+ // todo need to think wisely how to set these values & also move directional light around!
+ const colorInt = Math.max(int, 0.1)
+ updateBackground({ r: dayColor.r * colorInt, g: dayColor.g * colorInt, b: dayColor.b * colorInt })
+ if (!options.newVersionsLighting && bot.supportFeature('blockStateId')) {
+ appViewer.playerState.reactive.ambientLight = Math.max(int, 0.25)
+ appViewer.playerState.reactive.directionalLight = Math.min(int, 0.5)
+ }
+ }
+
+ bot.on('time', timeUpdated)
+ timeUpdated()
+}
diff --git a/src/defaultOptions.ts b/src/defaultOptions.ts
index 48c1cfad..6045e70b 100644
--- a/src/defaultOptions.ts
+++ b/src/defaultOptions.ts
@@ -16,8 +16,7 @@ export const defaultOptions = {
chatOpacityOpened: 100,
messagesLimit: 200,
volume: 50,
- enableMusic: true,
- musicVolume: 50,
+ enableMusic: false,
// fov: 70,
fov: 75,
defaultPerspective: 'first_person' as 'first_person' | 'third_person_back' | 'third_person_front',
@@ -42,7 +41,6 @@ export const defaultOptions = {
renderEars: true,
lowMemoryMode: false,
starfieldRendering: true,
- defaultSkybox: true,
enabledResourcepack: null as string | null,
useVersionsTextures: 'latest',
serverResourcePacks: 'prompt' as 'prompt' | 'always' | 'never',
@@ -85,7 +83,6 @@ export const defaultOptions = {
localServerOptions: {
gameMode: 1
} as any,
- saveLoginPassword: 'prompt' as 'prompt' | 'never' | 'always',
preferLoadReadonly: false,
experimentalClientSelfReload: false,
remoteSoundsSupport: false,
diff --git a/src/devtools.ts b/src/devtools.ts
index 1f8ef8e8..6c47f73d 100644
--- a/src/devtools.ts
+++ b/src/devtools.ts
@@ -5,17 +5,6 @@ import { WorldRendererThree } from 'renderer/viewer/three/worldrendererThree'
import { enable, disable, enabled } from 'debug'
import { Vec3 } from 'vec3'
-customEvents.on('mineflayerBotCreated', () => {
- window.debugServerPacketNames = Object.fromEntries(Object.keys(loadedData.protocol.play.toClient.types).map(name => {
- name = name.replace('packet_', '')
- return [name, name]
- }))
- window.debugClientPacketNames = Object.fromEntries(Object.keys(loadedData.protocol.play.toServer.types).map(name => {
- name = name.replace('packet_', '')
- return [name, name]
- }))
-})
-
window.Vec3 = Vec3
window.cursorBlockRel = (x = 0, y = 0, z = 0) => {
const newPos = bot.blockAtCursor(5)?.position.offset(x, y, z)
diff --git a/src/entities.ts b/src/entities.ts
index 674f91ef..dcec6143 100644
--- a/src/entities.ts
+++ b/src/entities.ts
@@ -246,29 +246,22 @@ customEvents.on('gameLoaded', () => {
}
}
// even if not found, still record to cache
- void getThreeJsRendererMethods()!.updatePlayerSkin(entityId, player.username, player.uuid, skinUrl ?? true, capeUrl)
+ void getThreeJsRendererMethods()?.updatePlayerSkin(entityId, player.username, player.uuid, skinUrl ?? true, capeUrl)
} catch (err) {
- reportError(new Error('Error applying skin texture:', { cause: err }))
+ console.error('Error decoding player texture:', err)
}
}
bot.on('playerJoined', updateSkin)
bot.on('playerUpdated', updateSkin)
- for (const entity of Object.values(bot.players)) {
- updateSkin(entity)
- }
- const teamUpdated = (team: Team) => {
+ bot.on('teamUpdated', (team: Team) => {
for (const entity of Object.values(bot.entities)) {
if (entity.type === 'player' && entity.username && team.members.includes(entity.username) || entity.uuid && team.members.includes(entity.uuid)) {
bot.emit('entityUpdate', entity)
}
}
- }
- bot.on('teamUpdated', teamUpdated)
- for (const team of Object.values(bot.teams)) {
- teamUpdated(team)
- }
+ })
const updateEntityNameTags = (team: Team) => {
for (const entity of Object.values(bot.entities)) {
diff --git a/src/index.ts b/src/index.ts
index 7764188f..4a118cee 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -56,6 +56,7 @@ import { isCypress } from './standaloneUtils'
import { startLocalServer, unsupportedLocalServerFeatures } from './createLocalServer'
import defaultServerOptions from './defaultLocalServerOptions'
+import dayCycle from './dayCycle'
import { onAppLoad, resourcepackReload, resourcePackState } from './resourcePack'
import { ConnectPeerOptions, connectToPeer } from './localServerMultiplayer'
@@ -304,7 +305,7 @@ export async function connect (connectOptions: ConnectOptions) {
if (connectOptions.server && !connectOptions.viewerWsConnect && !parsedServer.isWebSocket) {
console.log(`using proxy ${proxy.host}:${proxy.port || location.port}`)
- net['setProxy']({ hostname: proxy.host, port: proxy.port, headers: { Authorization: `Bearer ${new URLSearchParams(location.search).get('token') ?? ''}` }, artificialDelay: appQueryParams.addPing ? Number(appQueryParams.addPing) : undefined })
+ net['setProxy']({ hostname: proxy.host, port: proxy.port, headers: { Authorization: `Bearer ${new URLSearchParams(location.search).get('token') ?? ''}` } })
}
const renderDistance = singleplayer ? renderDistanceSingleplayer : multiplayerRenderDistance
@@ -793,6 +794,7 @@ export async function connect (connectOptions: ConnectOptions) {
}
initMotionTracking()
+ dayCycle()
// Bot position callback
const botPosition = () => {
diff --git a/src/inventoryWindows.ts b/src/inventoryWindows.ts
index d40260df..a9f89d1b 100644
--- a/src/inventoryWindows.ts
+++ b/src/inventoryWindows.ts
@@ -12,7 +12,6 @@ import PrismarineChatLoader from 'prismarine-chat'
import * as nbt from 'prismarine-nbt'
import { BlockModel } from 'mc-assets'
import { renderSlot } from 'renderer/viewer/three/renderSlot'
-import { loadSkinFromUsername } from 'renderer/viewer/lib/utils/skins'
import Generic95 from '../assets/generic_95.png'
import { appReplacableResources } from './generated/resources'
import { activeModalStack, hideCurrentModal, hideModal, miscUiState, showModal } from './globalState'
@@ -24,7 +23,6 @@ import { getItemDescription } from './itemsDescriptions'
import { MessageFormatPart } from './chatUtils'
import { GeneralInputItem, getItemMetadata, getItemModelName, getItemNameRaw, RenderItem } from './mineflayer/items'
import { playerState } from './mineflayer/playerState'
-import { modelViewerState } from './react/OverlayModelViewer'
const loadedImagesCache = new Map()
const cleanLoadedImagesCache = () => {
@@ -42,34 +40,6 @@ export const jeiCustomCategories = proxy({
value: [] as Array<{ id: string, categoryTitle: string, items: any[] }>
})
-let remotePlayerSkin: string | undefined | Promise
-
-export const showInventoryPlayer = () => {
- modelViewerState.model = {
- positioning: {
- windowWidth: 176,
- windowHeight: 166,
- x: 25,
- y: 8,
- width: 50,
- height: 70,
- scaled: true,
- onlyInitialScale: true,
- followCursor: true,
- },
- // models: ['https://bucket.mcraft.fun/sitarbuckss.glb'],
- // debug: true,
- steveModelSkin: appViewer.playerState.reactive.playerSkin ?? (typeof remotePlayerSkin === 'string' ? remotePlayerSkin : ''),
- }
- if (remotePlayerSkin === undefined && !appViewer.playerState.reactive.playerSkin) {
- remotePlayerSkin = loadSkinFromUsername(bot.username, 'skin').then(a => {
- setTimeout(() => { showInventoryPlayer() }, 0) // todo patch instead and make reactive
- remotePlayerSkin = a ?? ''
- return remotePlayerSkin
- })
- }
-}
-
export const onGameLoad = () => {
version = bot.version
@@ -87,23 +57,12 @@ export const onGameLoad = () => {
return type
}
- const maybeParseNbtJson = (data: any) => {
- if (typeof data === 'string') {
- try {
- data = JSON.parse(data)
- } catch (err) {
- // ignore
- }
- }
- return nbt.simplify(data) ?? data
- }
-
bot.on('windowOpen', (win) => {
const implementedWindow = implementedContainersGuiMap[mapWindowType(win.type as string, win.inventoryStart)]
if (implementedWindow) {
- openWindow(implementedWindow, maybeParseNbtJson(win.title))
+ openWindow(implementedWindow, nbt.simplify(win.title as any))
} else if (options.unimplementedContainers) {
- openWindow('ChestWin', maybeParseNbtJson(win.title))
+ openWindow('ChestWin', nbt.simplify(win.title as any))
} else {
// todo format
displayClientChat(`[client error] cannot open unimplemented window ${win.id} (${win.type}). Slots: ${win.slots.map(item => getItemName(item)).filter(Boolean).join(', ')}`)
@@ -422,12 +381,7 @@ const openWindow = (type: string | undefined, title: string | any = undefined) =
miscUiState.displaySearchInput = false
destroyFn()
skipClosePacketSending = false
-
- modelViewerState.model = undefined
})
- if (type === undefined) {
- showInventoryPlayer()
- }
cleanLoadedImagesCache()
const inv = openItemsCanvas(type)
inv.canvasManager.children[0].mobileHelpers = miscUiState.currentTouch
@@ -470,7 +424,6 @@ const openWindow = (type: string | undefined, title: string | any = undefined) =
const isRightClick = type === 'rightclick'
const isLeftClick = type === 'leftclick'
if (isLeftClick || isRightClick) {
- modelViewerState.model = undefined
inv.canvasManager.children[0].showRecipesOrUsages(isLeftClick, item)
}
} else {
@@ -502,7 +455,6 @@ const openWindow = (type: string | undefined, title: string | any = undefined) =
if (freeSlot === null) return
void bot.creative.setInventorySlot(freeSlot, item)
} else {
- modelViewerState.model = undefined
inv.canvasManager.children[0].showRecipesOrUsages(!isRightclick, mapSlots([item], true)[0])
}
}
diff --git a/src/mineflayer/mc-protocol.ts b/src/mineflayer/mc-protocol.ts
index cd21d01f..0171387a 100644
--- a/src/mineflayer/mc-protocol.ts
+++ b/src/mineflayer/mc-protocol.ts
@@ -130,8 +130,7 @@ export const setProxy = (proxyParams: ProxyParams) => {
net['setProxy']({
hostname: proxy.host,
port: proxy.port,
- headers: proxyParams.headers,
- artificialDelay: appQueryParams.addPing ? Number(appQueryParams.addPing) : undefined
+ headers: proxyParams.headers
})
return {
proxy
diff --git a/src/mineflayer/plugins/mouse.ts b/src/mineflayer/plugins/mouse.ts
index 14e19345..fc1ce0fd 100644
--- a/src/mineflayer/plugins/mouse.ts
+++ b/src/mineflayer/plugins/mouse.ts
@@ -110,7 +110,7 @@ const domListeners = (bot: Bot) => {
}, { signal: abortController.signal })
bot.mouse.beforeUpdateChecks = () => {
- if (!document.hasFocus() || !isGameActive(true)) {
+ if (!document.hasFocus()) {
// deactive all buttons
bot.mouse.buttons.fill(false)
}
diff --git a/src/mineflayer/websocket-core.ts b/src/mineflayer/websocket-core.ts
index f8163102..0edd2497 100644
--- a/src/mineflayer/websocket-core.ts
+++ b/src/mineflayer/websocket-core.ts
@@ -15,12 +15,9 @@ class CustomDuplex extends Duplex {
}
export const getWebsocketStream = async (host: string) => {
- const baseProtocol = host.startsWith('ws://') ? 'ws' : 'wss'
+ const baseProtocol = location.protocol === 'https:' ? 'wss' : host.startsWith('ws://') ? 'ws' : 'wss'
const hostClean = host.replace('ws://', '').replace('wss://', '')
- const hostURL = new URL(`${baseProtocol}://${hostClean}`)
- const hostParams = hostURL.searchParams
- hostParams.append('client_mcraft', '')
- const ws = new WebSocket(`${baseProtocol}://${hostURL.host}${hostURL.pathname}?${hostParams.toString()}`)
+ const ws = new WebSocket(`${baseProtocol}://${hostClean}`)
const clientDuplex = new CustomDuplex(undefined, data => {
ws.send(data)
})
diff --git a/src/optionsGuiScheme.tsx b/src/optionsGuiScheme.tsx
index 0cb0fe1e..b03db37d 100644
--- a/src/optionsGuiScheme.tsx
+++ b/src/optionsGuiScheme.tsx
@@ -480,24 +480,6 @@ export const guiOptionsScheme: {
],
sound: [
{ volume: {} },
- {
- custom () {
- return {
- options.musicVolume = value
- }}
- item={{
- type: 'slider',
- id: 'musicVolume',
- text: 'Music Volume',
- min: 0,
- max: 100,
- unit: '%',
- }}
- />
- },
- },
{
custom () {
return