zhzabcd commited on
Commit
248d96b
·
verified ·
1 Parent(s): b1a94d0

Upload 64 files

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .dockerignore +5 -0
  2. .gitattributes +4 -0
  3. .gitignore +7 -0
  4. .gitpod +2 -0
  5. .npmignore +3 -0
  6. .npmrc +1 -0
  7. Dockerfile +9 -0
  8. HISTORY.md +43 -0
  9. LICENSE +21 -0
  10. README_PT.md +104 -0
  11. README_RU.md +105 -0
  12. assets/click_stereo.ogg +0 -0
  13. assets/favicon.ico +0 -0
  14. assets/favicon.png +0 -0
  15. assets/favicon.svg +1 -0
  16. assets/invsprite.png +3 -0
  17. assets/manifest.json +13 -0
  18. assets/minecraftia.woff +0 -0
  19. assets/mojangles.ttf +0 -0
  20. config.json +7 -0
  21. extra-textures/background/panorama_0.png +0 -0
  22. extra-textures/background/panorama_1.png +0 -0
  23. extra-textures/background/panorama_2.png +0 -0
  24. extra-textures/background/panorama_3.png +0 -0
  25. extra-textures/background/panorama_4.png +0 -0
  26. extra-textures/background/panorama_5.png +3 -0
  27. extra-textures/edition.png +0 -0
  28. extra-textures/gui.png +0 -0
  29. extra-textures/loading.png +0 -0
  30. extra-textures/loading.psd +3 -0
  31. index.html +30 -0
  32. index.js +466 -0
  33. lib/chat.js +361 -0
  34. lib/cursor.js +143 -0
  35. lib/dns.js +39 -0
  36. lib/invsprite.json +4812 -0
  37. lib/menus/components/bossbars_overlay.js +147 -0
  38. lib/menus/components/breath_bar.js +88 -0
  39. lib/menus/components/button.js +140 -0
  40. lib/menus/components/common.js +72 -0
  41. lib/menus/components/debug_overlay.js +146 -0
  42. lib/menus/components/edit_box.js +97 -0
  43. lib/menus/components/food_bar.js +117 -0
  44. lib/menus/components/health_bar.js +158 -0
  45. lib/menus/components/hotbar.js +210 -0
  46. lib/menus/components/playerlist_overlay.js +179 -0
  47. lib/menus/components/slider.js +176 -0
  48. lib/menus/hud.js +370 -0
  49. lib/menus/keybinds_screen.js +172 -0
  50. lib/menus/loading_screen.js +67 -0
.dockerignore ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ # we dont want default config to be loaded in the dockerfile, but rather using a volume
2
+ config.json
3
+ # build stuff
4
+ node_modules
5
+ public
.gitattributes CHANGED
@@ -33,3 +33,7 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ assets/invsprite.png filter=lfs diff=lfs merge=lfs -text
37
+ extra-textures/background/panorama_5.png filter=lfs diff=lfs merge=lfs -text
38
+ extra-textures/loading.psd filter=lfs diff=lfs merge=lfs -text
39
+ screenshot.png filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ node_modules/
2
+ package-lock.json
3
+ .vscode
4
+ public
5
+ .DS_Store
6
+ .idea/
7
+ *.iml
.gitpod ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ tasks:
2
+ - command: npm install
.npmignore ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ node_modules/
2
+ package-lock.json
3
+ .vscode
.npmrc ADDED
@@ -0,0 +1 @@
 
 
1
+ package-lock=false
Dockerfile ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ FROM node:14-alpine
2
+ # Without git installing the npm packages fails
3
+ RUN apk add git
4
+ RUN mkdir /app
5
+ WORKDIR /app
6
+ COPY . /app
7
+ RUN npm install
8
+ RUN npm run build
9
+ ENTRYPOINT ["npm", "run", "prod-start"]
HISTORY.md ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ## History
2
+
3
+ ### 1.6.0
4
+ * [bump pviewer](https://github.com/PrismarineJS/prismarine-web-client/commit/901242b33151ad70d651e18416bd67b9949cc117) (thanks @rom1504)
5
+ * [Remove incorrect signals + change server. (#361)](https://github.com/PrismarineJS/prismarine-web-client/commit/a243144a9802e569ef2ee31dce5379c2f2ba3951) (thanks @rom1504)
6
+ * [Create commands.yml](https://github.com/PrismarineJS/prismarine-web-client/commit/17548409c1fc881a899dcad0a67a7a1a0ecf9157) (thanks @rom1504)
7
+ * [avoid using @azure/msal-node (#358)](https://github.com/PrismarineJS/prismarine-web-client/commit/d441efaef504a22b31f7d5eca8af9a5591f22e32) (thanks @rom1504)
8
+ * [bump mineflayer](https://github.com/PrismarineJS/prismarine-web-client/commit/d4c0c0c6e610cb2d1f836acb800cfa38777fc50e) (thanks @rom1504)
9
+ * [Should show error screen on error (#350)](https://github.com/PrismarineJS/prismarine-web-client/commit/2fba863d662cb895339c3eda905a4f1edc8d5db6) (thanks @zardoy)
10
+ * [[ImgBot] Optimize images (#348)](https://github.com/PrismarineJS/prismarine-web-client/commit/856639d586f1647bccef7abffe20a218ab232ddf) (thanks @Rahib777-7)
11
+
12
+ ### 1.5.0
13
+
14
+ * Add BossBars @sverben (PrismarineJS#319)
15
+ * save all play screen options @Fury-101 (PrismarineJS#326)
16
+
17
+ ### 1.4.0
18
+
19
+ * so much
20
+
21
+ ### 1.3.0
22
+
23
+ * a lot
24
+
25
+ ### 1.2.0
26
+
27
+ * custom proxy selection (@Karang)
28
+ * loading screen (@AwesomestCode)
29
+ * better chat (@AwesomestCode)
30
+ * default random name (@rom1504)
31
+ * fix pixelated (@Karang)
32
+ * placing and breaking (@ShrimpyStuff)
33
+ * crosshairs (@AwesomestCode)
34
+
35
+ ### 1.1.0
36
+
37
+ * chat
38
+ * better font
39
+ * pitch fix
40
+
41
+ ### 1.0.1
42
+
43
+ * initial implementation
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2020 PrismarineJS
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README_PT.md ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # prismarine-web-client
2
+ [![NPM version](https://img.shields.io/npm/v/prismarine-web-client.svg)](http://npmjs.com/package/prismarine-web-client)
3
+ [![Build Status](https://github.com/PrismarineJS/prismarine-web-client/workflows/CI/badge.svg)](https://github.com/PrismarineJS/prismarine-web-client/actions?query=workflow%3A%22CI%22)
4
+ [![Discord](https://img.shields.io/badge/chat-on%20discord-brightgreen.svg)](https://discord.gg/GsEFRM8)
5
+ [![Try it on gitpod](https://img.shields.io/badge/try-on%20gitpod-brightgreen.svg)](https://gitpod.io/#https://github.com/PrismarineJS/prismarine-web-client)
6
+
7
+ | 🇺🇸 [English](README.md) | 🇷🇺 [Russian](README_RU.md) | 🇵🇹 [Portuguese](README_PT.md) |
8
+ | ----------------------- | -------------------------- | ---------------------------- |
9
+
10
+ Um cliente de Minecraft a funcionar numa página web. **Demostração em https://prismarinejs.github.io/prismarine-web-client/**
11
+
12
+ ## Como funciona
13
+ prismarine-web-client executa mineflayer e prismarine-viewer no teu navegador, que se conecta por WebSocket a uma proxy
14
+ que traduz o conexão do WebSocket em TCP para poderes conectar-te a servidores normais do Minecraft. Prismarine-web-client é basiado em:
15
+ * [prismarine-viewer](https://github.com/PrismarineJS/prismarine-viewer) para renderizar o mundo
16
+ * [mineflayer](https://github.com/PrismarineJS/mineflayer) um API incrível do cliente de Minecraft
17
+
18
+ Da uma olhada nestes módulos se quiseres entender mais sobre como isto funciona e poderes contribuir!
19
+
20
+ ## Captura de tela
21
+ ![Captura de tela do prismarine-web-client em ação](screenshot.png)
22
+
23
+ ## Demostração ao vivo
24
+ Clica neste endereço para o abrires no navegador, sem instalação necessária: https://prismarinejs.github.io/prismarine-web-client/
25
+
26
+ *Testado no Chrome & Firefox para plataformas desktop.*
27
+
28
+ ## Uso
29
+ Para hospedá-lo por si próprio, execute estes comandos no bash:
30
+ ```bash
31
+ $ npm install -g prismarine-web-client
32
+ $ prismarine-web-client
33
+ ```
34
+ Finalmente, abra `http://localhost:8080` no seu navigador.
35
+
36
+ ## Conteúdos
37
+
38
+ * Mostra criaturas e os jogadores
39
+ * Mostra os blocos
40
+ * Movimento (podes mover-te, e também ver entidades a mover-se em tempo real)
41
+ * Colocar e destruir blocos
42
+
43
+ ## Planeamentos
44
+ * Containers (inventário, baús, etc.)
45
+ * Sons
46
+ * Mais interações no mundo (atacar entidades, etc.)
47
+ * Renderizar cosméticos (ciclo dia-noite, nevoeiro, etc.)
48
+
49
+ ## Desenvolvimentos
50
+
51
+ Se estiveres a contribuir/fazer alterações, precisas intalá-lo de outra forma.
52
+
53
+ Primeiro, clona o repositório.
54
+
55
+ Depois, defina o seu diretório de trabalho para o do repositório. Por examplo:
56
+ ```bash
57
+ $ cd ~/prismarine-web-client/
58
+ ```
59
+
60
+ Finalmente, execute
61
+
62
+ ```bash
63
+ $ npm install
64
+ $ npm start
65
+ ```
66
+
67
+ Isto vai começar o express e webpack no modo de desenvolvimento; quando salvares um arquivo, o build vai ser executado de novo (demora 5s),
68
+ e podes atualizar a página para veres o novo resultado.
69
+
70
+ Conecta em http://localhost:8080 no teu navegador.
71
+
72
+ Poderás ter que desativar o auto salvar no teu IDE para evitar estar constantemente a reconstruir; see https://webpack.js.org/guides/development/#adjusting-your-text-editor.
73
+
74
+ Para conferir a build de produção (vai demorar alguns minutos para terminar), podes executar `npm run build-start`.
75
+
76
+ Se estiveres interessado em contribuir, podes dar uma vista de olhos nos projetos em https://github.com/PrismarineJS/prismarine-web-client/projects.
77
+
78
+ Algumas variáveis estão expostas no objeto global ``window`` para depuração:
79
+ * ``bot``
80
+ * ``viewer``
81
+ * ``mcData``
82
+ * ``worldView``
83
+ * ``Vec3``
84
+ * ``pathfinder``
85
+ * ``debugMenu``
86
+
87
+ ### Adicionar coisas no debugMenu
88
+
89
+ debugMenu.customEntries['myKey'] = 'myValue'
90
+ delete debugMenu.customEntries['myKey']
91
+
92
+ ### Alguns exemplos de depuração
93
+
94
+ Na devtools do chrome:
95
+
96
+ * `bot.chat('test')` permite usar o chat
97
+ * `bot.chat(JSON.stringify(Object.values(bot.players).map(({username, ping}) => ({username, ping}))))` display the ping of everyone
98
+ * `window.bot.entity.position.y += 5` saltar
99
+ * `bot.chat(JSON.stringify(bot.findBlock({matching:(block) => block.name==='diamond_ore', maxDistance:256}).position))` encontrar a posição de um bloco de diamante
100
+ * `bot.physics.stepHeight = 2` permite andar sobre os blocos
101
+ * `bot.physics.sprintSpeed = 5` andar mais rápido
102
+ * `bot.loadPlugin(pathfinder.pathfinder)` em seguida `bot.pathfinder.goto(new pathfinder.goals.GoalXZ(100, 100))` para ir para a posição 100, 100
103
+
104
+ Para mais ideas de depuração, leia o documento [mineflayer](https://github.com/PrismarineJS/mineflayer).
README_RU.md ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # prismarine-web-client
2
+ [![NPM version](https://img.shields.io/npm/v/prismarine-web-client.svg)](http://npmjs.com/package/prismarine-web-client)
3
+ [![Build Status](https://github.com/PrismarineJS/prismarine-web-client/workflows/CI/badge.svg)](https://github.com/PrismarineJS/prismarine-web-client/actions?query=workflow%3A%22CI%22)
4
+ [![Discord](https://img.shields.io/badge/chat-on%20discord-brightgreen.svg)](https://discord.gg/GsEFRM8)
5
+ [![Try it on gitpod](https://img.shields.io/badge/try-on%20gitpod-brightgreen.svg)](https://gitpod.io/#https://github.com/PrismarineJS/prismarine-web-client)
6
+
7
+ | 🇺🇸 [English](README.md) | 🇷🇺 [Russian](README_RU.md) | 🇵🇹 [Portuguese](README_PT.md) |
8
+ | ----------------------- | -------------------------- | ---------------------------- |
9
+
10
+ Клиент Minecraft, запущенный на веб-странице. **Демонстрация на https://prismarinejs.github.io/prismarine-web-client/**
11
+
12
+
13
+ ## Как это работает
14
+ prismarine-web-client запускает mineflayer и prismarine-viewer в вашем браузере, которые подключаются к прокси через WebSocket
15
+ который переводит соединение WebSocket в TCP для подключения к обычным серверам Minecraft. Prismarine-web-client основан на:
16
+ * [prismarine-viewer](https://github.com/PrismarineJS/prismarine-viewer) для рендера мира
17
+ * [mineflayer](https://github.com/PrismarineJS/mineflayer) для высокоуровневого API клиента minecraft
18
+
19
+ Проверьте эти модули, если вы хотите больше понять, как это работает, и внести свой вклад!
20
+
21
+ ## Скриншот
22
+ ![Screenshot of prismarine-web-client in action](screenshot.png)
23
+
24
+ ## Демонстация
25
+ Нажмите на эту ссылку, чтобы открыть ее в вашем браузере, установка не требуется: https://prismarinejs.github.io/prismarine-web-client/
26
+
27
+ *Протестировано в Chrome и Firefox для настольных платформ.*
28
+
29
+ ## Использование
30
+ Чтобы хостить его самостоятельно, выполните эти команды в bash:
31
+ ```bash
32
+ $ npm install -g prismarine-web-client
33
+ $ prismarine-web-client
34
+ ```
35
+ Наконец, откройте `http://localhost:8080` в вашем браузере.
36
+
37
+ ## Функции
38
+
39
+ * Показывание мобов и игроков
40
+ * Показывание блоков
41
+ * Передвижение (Вы можете двигаться, и вы можете видеть передвижение других сущностей)
42
+ * Установка и ломание блоков
43
+
44
+ ## Roadmap
45
+ * Контейнеры (Инвентарь, сундуки, и так далее.)
46
+ * Звуки
47
+ * Больше взаимодействий с Миром (Атаковать мобов и других игроков, и так далее.)
48
+ * Косметические особенности рендера (Цикл дня и ночи, fog, и так далее.)
49
+
50
+ ## Разработка
51
+
52
+ Если вы ввносите изменения, вам нужно установить его по-другому.
53
+
54
+ Во-первых, клонируйте репозиторий.
55
+
56
+ Затем установите свой рабочий каталог в каталог репозитория. Например:
57
+ ```bash
58
+ $ cd ~/prismarine-web-client/
59
+ ```
60
+
61
+ Наконец, запустите.
62
+
63
+ ```bash
64
+ $ npm install
65
+ $ npm start
66
+ ```
67
+
68
+ Это запустит express и webpack в режиме разработки: всякий раз, когда вы сохраняете файл, сборка будет переделана (это займет 5 секунд),
69
+ и вы можете обновить страницу, чтобы получить новый результат.
70
+
71
+ Для входа в Prismarine Web Client откройте http://localhost:8080 в вашем браузере.
72
+
73
+ Если вы захотите отключить автоматическое сохранение в своем IDE, чтобы избежать постоянной пересборки Web Client'а, смотрите: https://webpack.js.org/guides/development/#adjusting-your-text-editor
74
+
75
+ Чтобы проверить сборку Web Client'а (на сборку потребуется минута), вы можете запустить `npm run build-start`
76
+
77
+ Если вы заинтересованы в участии, вы можете проверить проекты [тут](https://github.com/PrismarineJS/prismarine-web-client/projects)
78
+
79
+ Некоторые переменные которые отображаются в окне для отладки:
80
+ * bot
81
+ * viewer
82
+ * mcData
83
+ * worldView
84
+ * Vec3
85
+ * pathfinder
86
+ * debugMenu
87
+
88
+ ### Как добавить дополнительные элементы в меню отладки ?
89
+
90
+ debugMenu.customEntries['myKey'] = 'myValue'
91
+ delete debugMenu.customEntries['myKey']
92
+
93
+ ### Некоторые примеры отладки
94
+
95
+ В инструментах chrome dev
96
+
97
+ * `bot.chat('test')` позволяет вам использовать чат
98
+ * `bot.chat(JSON.stringify(Object.values(bot.players).map(({username, ping}) => ({username, ping}))))` показывает пинг всех игроков
99
+ * `window.bot.entity.position.y += 5` прыжок
100
+ * `bot.chat(JSON.stringify(bot.findBlock({matching:(block) => block.name==='diamond_ore', maxDistance:256}).position))` ищет позицию алмазной руды
101
+ * `bot.physics.stepHeight = 2` позволяет вам взбиратся по блокам
102
+ * `bot.physics.sprintSpeed = 5` более быстрый бег
103
+ * `bot.loadPlugin(pathfinder.pathfinder)` затем `bot.pathfinder.goto(new pathfinder.goals.GoalXZ(100, 100))` идет к координатам 100, 100
104
+
105
+ Для получения дополнительных идей по отладке прочитайте [mineflayer](https://github.com/PrismarineJS/mineflayer) документацию
assets/click_stereo.ogg ADDED
Binary file (7.05 kB). View file
 
assets/favicon.ico ADDED
assets/favicon.png ADDED
assets/favicon.svg ADDED
assets/invsprite.png ADDED

Git LFS Details

  • SHA256: f1ac25723319eaf53490652f2255c7e82d3f06805946d558aca239ba843f76b6
  • Pointer size: 132 Bytes
  • Size of remote file: 2.85 MB
assets/manifest.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "Prismarine Web Client",
3
+ "short_name": "Prismarine Web Client",
4
+ "scope": "/",
5
+ "start_url": "/",
6
+ "icons": [{
7
+ "src": "favicon.png",
8
+ "sizes": "512x512"
9
+ }],
10
+ "background_color": "#349474",
11
+ "theme_color": "#349474",
12
+ "display": "standalone"
13
+ }
assets/minecraftia.woff ADDED
Binary file (6.41 kB). View file
 
assets/mojangles.ttf ADDED
Binary file (71.9 kB). View file
 
config.json ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ {
2
+ "defaultHost": "kaboom.pw",
3
+ "defaultHostPort": 25565,
4
+ "defaultProxy": "",
5
+ "defaultProxyPort": 0,
6
+ "defaultVersion": "1.18.2"
7
+ }
extra-textures/background/panorama_0.png ADDED
extra-textures/background/panorama_1.png ADDED
extra-textures/background/panorama_2.png ADDED
extra-textures/background/panorama_3.png ADDED
extra-textures/background/panorama_4.png ADDED
extra-textures/background/panorama_5.png ADDED

Git LFS Details

  • SHA256: 7888ab245c81f35c2e6c16d10872512e4c6fa7ab47a8f76063ef688213802007
  • Pointer size: 132 Bytes
  • Size of remote file: 1.12 MB
extra-textures/edition.png ADDED
extra-textures/gui.png ADDED
extra-textures/loading.png ADDED
extra-textures/loading.psd ADDED

Git LFS Details

  • SHA256: 35bb9df1485124bc896ba3d16033b7cb0dbb92b87c8aa98b0a8c3f1c0c1e051e
  • Pointer size: 132 Bytes
  • Size of remote file: 2.64 MB
index.html ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Prismarine Web Client</title>
5
+ <link rel="stylesheet" href="styles.css">
6
+ <link rel="favicon" href="favicon.ico">
7
+ <link rel="icon" type="image/png" href="favicon.png" />
8
+ <meta name="description" content="Minecraft web client running in your browser">
9
+ <meta name="keywords" content="Minecraft, Web, Voxel, Javascript, PrismarineJS">
10
+ <meta name="author" content="PrismarineJS">
11
+ <meta name="theme-color" content="#349474">
12
+ <meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0,user-scalable=0'>
13
+ <meta property="og:title" content="Prismarine Web Client" />
14
+ <meta property="og:type" content="website" />
15
+ <meta property="og:url" content="https://prismarinejs.github.io/prismarine-web-client/" />
16
+ <meta property="og:image" content="https://prismarinejs.github.io/prismarine-web-client/favicon.png" />
17
+ <link rel="manifest" href="manifest.json" crossorigin="use-credentials">
18
+ </head>
19
+ <body>
20
+ <div id="ui-root">
21
+ <pmui-hud id="hud" style="display: none;"></pmui-hud>
22
+ <pmui-pausescreen id="pause-screen" style="display: none;"></pmui-pausescreen>
23
+ <pmui-loadingscreen id="loading-screen" style="display: none;"></pmui-loadingscreen>
24
+ <pmui-playscreen id="play-screen" style="display: none;"></pmui-playscreen>
25
+ <pmui-keybindsscreen id="keybinds-screen" style="display: none;"></pmui-keybindsscreen>
26
+ <pmui-optionsscreen id="options-screen" style="display: none;"></pmui-optionsscreen>
27
+ <pmui-titlescreen id="title-screen" style="display: none;"></pmui-titlescreen>
28
+ </div>
29
+ </body>
30
+ </html>
index.js ADDED
@@ -0,0 +1,466 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* global THREE */
2
+ require('./lib/chat')
3
+
4
+ require('./lib/menus/components/button')
5
+ require('./lib/menus/components/edit_box')
6
+ require('./lib/menus/components/slider')
7
+ require('./lib/menus/components/hotbar')
8
+ require('./lib/menus/components/health_bar')
9
+ require('./lib/menus/components/food_bar')
10
+ require('./lib/menus/components/breath_bar')
11
+ require('./lib/menus/components/debug_overlay')
12
+ require('./lib/menus/components/playerlist_overlay')
13
+ require('./lib/menus/components/bossbars_overlay')
14
+ require('./lib/menus/hud')
15
+ require('./lib/menus/play_screen')
16
+ require('./lib/menus/pause_screen')
17
+ require('./lib/menus/loading_screen')
18
+ require('./lib/menus/keybinds_screen')
19
+ require('./lib/menus/options_screen')
20
+ require('./lib/menus/title_screen')
21
+
22
+ const net = require('net')
23
+ const Cursor = require('./lib/cursor')
24
+
25
+ // Workaround for process.versions.node not existing in the browser
26
+ process.versions.node = '14.0.0'
27
+
28
+ const mineflayer = require('mineflayer')
29
+ const { WorldView, Viewer } = require('prismarine-viewer/viewer')
30
+ const pathfinder = require('mineflayer-pathfinder')
31
+ const { Vec3 } = require('vec3')
32
+ global.THREE = require('three')
33
+ const { initVR } = require('./lib/vr')
34
+
35
+ if ('serviceWorker' in navigator) {
36
+ window.addEventListener('load', () => {
37
+ navigator.serviceWorker.register('/service-worker.js').then(registration => {
38
+ console.log('SW registered: ', registration)
39
+ }).catch(registrationError => {
40
+ console.log('SW registration failed: ', registrationError)
41
+ })
42
+ })
43
+ }
44
+
45
+ const maxPitch = 0.5 * Math.PI
46
+ const minPitch = -0.5 * Math.PI
47
+
48
+ // Create three.js context, add to page
49
+ const renderer = new THREE.WebGLRenderer()
50
+ renderer.setPixelRatio(window.devicePixelRatio || 1)
51
+ renderer.setSize(window.innerWidth, window.innerHeight)
52
+ document.body.appendChild(renderer.domElement)
53
+
54
+ // Create viewer
55
+ const viewer = new Viewer(renderer)
56
+
57
+ // Menu panorama background
58
+ function addPanoramaCubeMap () {
59
+ let time = 0
60
+ viewer.camera = new THREE.PerspectiveCamera(85, window.innerWidth / window.innerHeight, 0.05, 1000)
61
+ viewer.camera.updateProjectionMatrix()
62
+ viewer.camera.position.set(0, 0, 0)
63
+ viewer.camera.rotation.set(0, 0, 0)
64
+ const panorGeo = new THREE.BoxGeometry(1000, 1000, 1000)
65
+
66
+ const loader = new THREE.TextureLoader()
67
+ const panorMaterials = [
68
+ new THREE.MeshBasicMaterial({ map: loader.load('extra-textures/background/panorama_1.png'), transparent: true, side: THREE.DoubleSide }), // WS
69
+ new THREE.MeshBasicMaterial({ map: loader.load('extra-textures/background/panorama_3.png'), transparent: true, side: THREE.DoubleSide }), // ES
70
+ new THREE.MeshBasicMaterial({ map: loader.load('extra-textures/background/panorama_4.png'), transparent: true, side: THREE.DoubleSide }), // Up
71
+ new THREE.MeshBasicMaterial({ map: loader.load('extra-textures/background/panorama_5.png'), transparent: true, side: THREE.DoubleSide }), // Down
72
+ new THREE.MeshBasicMaterial({ map: loader.load('extra-textures/background/panorama_0.png'), transparent: true, side: THREE.DoubleSide }), // NS
73
+ new THREE.MeshBasicMaterial({ map: loader.load('extra-textures/background/panorama_2.png'), transparent: true, side: THREE.DoubleSide }) // SS
74
+ ]
75
+
76
+ const panoramaBox = new THREE.Mesh(panorGeo, panorMaterials)
77
+
78
+ panoramaBox.onBeforeRender = () => {
79
+ time += 0.01
80
+ panoramaBox.rotation.y = Math.PI + time * 0.01
81
+ panoramaBox.rotation.z = Math.sin(-time * 0.001) * 0.001
82
+ }
83
+
84
+ const group = new THREE.Object3D()
85
+ group.add(panoramaBox)
86
+
87
+ const Entity = require('prismarine-viewer/viewer/lib/entity/Entity')
88
+ for (let i = 0; i < 42; i++) {
89
+ const m = new Entity('1.16.4', 'squid').mesh
90
+ m.position.set(Math.random() * 30 - 15, Math.random() * 20 - 10, Math.random() * 10 - 17)
91
+ m.rotation.set(0, Math.PI + Math.random(), -Math.PI / 4, 'ZYX')
92
+ const v = Math.random() * 0.01
93
+ m.children[0].onBeforeRender = () => {
94
+ m.rotation.y += v
95
+ m.rotation.z = Math.cos(panoramaBox.rotation.y * 3) * Math.PI / 4 - Math.PI / 2
96
+ }
97
+ group.add(m)
98
+ }
99
+
100
+ viewer.scene.add(group)
101
+ return group
102
+ }
103
+
104
+ const panoramaCubeMap = addPanoramaCubeMap()
105
+
106
+ function removePanorama () {
107
+ viewer.camera = new THREE.PerspectiveCamera(document.getElementById('options-screen').fov, window.innerWidth / window.innerHeight, 0.1, 1000)
108
+ viewer.camera.updateProjectionMatrix()
109
+ viewer.scene.remove(panoramaCubeMap)
110
+ }
111
+
112
+ let animate = () => {
113
+ window.requestAnimationFrame(animate)
114
+ viewer.update()
115
+ renderer.render(viewer.scene, viewer.camera)
116
+ }
117
+ animate()
118
+
119
+ window.addEventListener('resize', () => {
120
+ viewer.camera.aspect = window.innerWidth / window.innerHeight
121
+ viewer.camera.updateProjectionMatrix()
122
+ renderer.setSize(window.innerWidth, window.innerHeight)
123
+ })
124
+
125
+ const showEl = (str) => { document.getElementById(str).style = 'display:block' }
126
+ async function main () {
127
+ const menu = document.getElementById('play-screen')
128
+
129
+ menu.addEventListener('connect', e => {
130
+ const options = e.detail
131
+ menu.style = 'display: none;'
132
+ showEl('loading-screen')
133
+ removePanorama()
134
+ connect(options)
135
+ })
136
+ }
137
+
138
+ async function connect (options) {
139
+ const loadingScreen = document.getElementById('loading-screen')
140
+
141
+ const hud = document.getElementById('hud')
142
+ const chat = hud.shadowRoot.querySelector('#chat')
143
+ const debugMenu = hud.shadowRoot.querySelector('#debug-overlay')
144
+ const optionsScrn = document.getElementById('options-screen')
145
+ const keyBindScrn = document.getElementById('keybinds-screen')
146
+ const gameMenu = document.getElementById('pause-screen')
147
+
148
+ const viewDistance = optionsScrn.renderDistance
149
+ const hostprompt = options.server
150
+ const proxyprompt = options.proxy
151
+ const username = options.username
152
+ const password = options.password
153
+
154
+ let host, port, proxy, proxyport
155
+ if (!hostprompt.includes(':')) {
156
+ host = hostprompt
157
+ port = 25565
158
+ } else {
159
+ [host, port] = hostprompt.split(':')
160
+ port = parseInt(port, 10)
161
+ }
162
+
163
+ if (!proxyprompt.includes(':')) {
164
+ proxy = proxyprompt
165
+ proxyport = undefined
166
+ } else {
167
+ [proxy, proxyport] = proxyprompt.split(':')
168
+ proxyport = parseInt(proxyport, 10)
169
+ }
170
+ console.log(`connecting to ${host} ${port} with ${username}`)
171
+
172
+ if (proxy) {
173
+ console.log(`using proxy ${proxy} ${proxyport}`)
174
+ net.setProxy({ hostname: proxy, port: proxyport })
175
+ }
176
+
177
+ loadingScreen.status = 'Logging in'
178
+
179
+ const errorAbortController = new AbortController()
180
+ window.addEventListener('unhandledrejection', (e) => {
181
+ handleError(e.reason)
182
+ })
183
+ window.addEventListener('error', (e) => {
184
+ handleError(e.message)
185
+ })
186
+ const bot = mineflayer.createBot({
187
+ host,
188
+ port,
189
+ version: options.botVersion === '' ? false : options.botVersion,
190
+ username,
191
+ password,
192
+ viewDistance: 'tiny',
193
+ checkTimeoutInterval: 240 * 1000,
194
+ noPongTimeout: 240 * 1000,
195
+ closeTimeout: 240 * 1000
196
+ })
197
+ hud.preload(bot)
198
+
199
+ const handleError = (err) => {
200
+ console.log('Encountered error!', err)
201
+ loadingScreen.status = `Error encountered. Error message: ${err}. Please reload the page`
202
+ loadingScreen.style = 'display: block;'
203
+ loadingScreen.hasError = true
204
+ }
205
+ bot.on('error', handleError)
206
+
207
+ bot.on('kicked', (kickReason) => {
208
+ console.log('User was kicked!', kickReason)
209
+ loadingScreen.status = `The Minecraft server kicked you. Kick reason: ${kickReason}. Please reload the page to rejoin`
210
+ loadingScreen.style = 'display: block;'
211
+ loadingScreen.hasError = true
212
+ })
213
+
214
+ bot.on('end', (endReason) => {
215
+ console.log('disconnected for', endReason)
216
+ loadingScreen.status = `You have been disconnected from the server. End reason: ${endReason}. Please reload the page to rejoin`
217
+ loadingScreen.style = 'display: block;'
218
+ loadingScreen.hasError = true
219
+ })
220
+
221
+ bot.once('login', () => {
222
+ loadingScreen.status = 'Loading world'
223
+ })
224
+
225
+ bot.once('spawn', () => {
226
+ const mcData = require('minecraft-data')(bot.version)
227
+
228
+ loadingScreen.status = 'Placing blocks (starting viewer)'
229
+
230
+ console.log('bot spawned - starting viewer')
231
+
232
+ const version = bot.version
233
+
234
+ const center = bot.entity.position
235
+
236
+ console.log(viewDistance)
237
+ const worldView = new WorldView(bot.world, viewDistance, center)
238
+
239
+ gameMenu.init(renderer)
240
+ optionsScrn.isInsideWorld = true
241
+ optionsScrn.addEventListener('fov_changed', (e) => {
242
+ viewer.camera.fov = e.detail.fov
243
+ viewer.camera.updateProjectionMatrix()
244
+ })
245
+
246
+ viewer.setVersion(version)
247
+
248
+ window.worldView = worldView
249
+ window.bot = bot
250
+ window.mcData = mcData
251
+ window.viewer = viewer
252
+ window.Vec3 = Vec3
253
+ window.pathfinder = pathfinder
254
+ window.debugMenu = debugMenu
255
+ window.settings = optionsScrn
256
+ window.renderer = renderer
257
+
258
+ initVR(bot, renderer, viewer)
259
+
260
+ const cursor = new Cursor(viewer, renderer, bot)
261
+ animate = () => {
262
+ window.requestAnimationFrame(animate)
263
+ viewer.update()
264
+ cursor.update(bot)
265
+ debugMenu.cursorBlock = cursor.cursorBlock
266
+ renderer.render(viewer.scene, viewer.camera)
267
+ }
268
+
269
+ // Link WorldView and Viewer
270
+ viewer.listen(worldView)
271
+ worldView.listenToBot(bot)
272
+ worldView.init(bot.entity.position)
273
+
274
+ // Bot position callback
275
+ function botPosition () {
276
+ viewer.setFirstPersonCamera(bot.entity.position, bot.entity.yaw, bot.entity.pitch)
277
+ worldView.updatePosition(bot.entity.position)
278
+ }
279
+ bot.on('move', botPosition)
280
+ botPosition()
281
+
282
+ loadingScreen.status = 'Setting callbacks'
283
+
284
+ function moveCallback (e) {
285
+ bot.entity.pitch -= e.movementY * optionsScrn.mouseSensitivityY * 0.0001
286
+ bot.entity.pitch = Math.max(minPitch, Math.min(maxPitch, bot.entity.pitch))
287
+ bot.entity.yaw -= e.movementX * optionsScrn.mouseSensitivityX * 0.0001
288
+
289
+ viewer.setFirstPersonCamera(null, bot.entity.yaw, bot.entity.pitch)
290
+ }
291
+
292
+ function changeCallback () {
293
+ if (document.pointerLockElement === renderer.domElement ||
294
+ document.mozPointerLockElement === renderer.domElement ||
295
+ document.webkitPointerLockElement === renderer.domElement) {
296
+ document.addEventListener('mousemove', moveCallback, false)
297
+ } else {
298
+ document.removeEventListener('mousemove', moveCallback, false)
299
+ }
300
+ }
301
+
302
+ document.addEventListener('pointerlockchange', changeCallback, false)
303
+ document.addEventListener('mozpointerlockchange', changeCallback, false)
304
+ document.addEventListener('webkitpointerlockchange', changeCallback, false)
305
+
306
+ let lastTouch
307
+ document.addEventListener('touchmove', (e) => {
308
+ window.scrollTo(0, 0)
309
+ e.preventDefault()
310
+ e.stopPropagation()
311
+ if (lastTouch !== undefined) {
312
+ moveCallback({ movementX: e.touches[0].pageX - lastTouch.pageX, movementY: e.touches[0].pageY - lastTouch.pageY })
313
+ }
314
+ lastTouch = e.touches[0]
315
+ }, { passive: false })
316
+
317
+ document.addEventListener('touchend', (e) => {
318
+ lastTouch = undefined
319
+ }, { passive: false })
320
+
321
+ renderer.domElement.requestPointerLock = renderer.domElement.requestPointerLock ||
322
+ renderer.domElement.mozRequestPointerLock ||
323
+ renderer.domElement.webkitRequestPointerLock
324
+ document.addEventListener('mousedown', (e) => {
325
+ if (!chat.inChat && !gameMenu.inMenu) {
326
+ renderer.domElement.requestPointerLock()
327
+ }
328
+ })
329
+
330
+ document.addEventListener('contextmenu', (e) => e.preventDefault(), false)
331
+
332
+ window.addEventListener('blur', (e) => {
333
+ bot.clearControlStates()
334
+ }, false)
335
+
336
+ document.addEventListener('keydown', (e) => {
337
+ if (chat.inChat) return
338
+ if (gameMenu.inMenu) return
339
+
340
+ keyBindScrn.keymaps.forEach(km => {
341
+ if (e.code === km.key) {
342
+ switch (km.defaultKey) {
343
+ case 'KeyQ':
344
+ if (bot.heldItem) bot.tossStack(bot.heldItem)
345
+ break
346
+ case 'ControlLeft':
347
+ bot.setControlState('sprint', true)
348
+ break
349
+ case 'ShiftLeft':
350
+ bot.setControlState('sneak', true)
351
+ break
352
+ case 'Space':
353
+ bot.setControlState('jump', true)
354
+ break
355
+ case 'KeyD':
356
+ bot.setControlState('left', true)
357
+ break
358
+ case 'KeyA':
359
+ bot.setControlState('right', true)
360
+ break
361
+ case 'KeyS':
362
+ bot.setControlState('back', true)
363
+ break
364
+ case 'KeyW':
365
+ bot.setControlState('forward', true)
366
+ break
367
+ }
368
+ }
369
+ })
370
+ }, false)
371
+
372
+ document.addEventListener('keyup', (e) => {
373
+ keyBindScrn.keymaps.forEach(km => {
374
+ if (e.code === km.key) {
375
+ switch (km.defaultKey) {
376
+ case 'ControlLeft':
377
+ bot.setControlState('sprint', false)
378
+ break
379
+ case 'ShiftLeft':
380
+ bot.setControlState('sneak', false)
381
+ break
382
+ case 'Space':
383
+ bot.setControlState('jump', false)
384
+ break
385
+ case 'KeyD':
386
+ bot.setControlState('left', false)
387
+ break
388
+ case 'KeyA':
389
+ bot.setControlState('right', false)
390
+ break
391
+ case 'KeyS':
392
+ bot.setControlState('back', false)
393
+ break
394
+ case 'KeyW':
395
+ bot.setControlState('forward', false)
396
+ break
397
+ }
398
+ }
399
+ })
400
+ }, false)
401
+
402
+ loadingScreen.status = 'Done!'
403
+ console.log(loadingScreen.status) // only do that because it's read in index.html and npm run fix complains.
404
+
405
+ hud.init(renderer, bot, host)
406
+ hud.style.display = 'block'
407
+
408
+ setTimeout(function () {
409
+ // game in playable state show errors in console instead
410
+ errorAbortController.abort()
411
+ if (loadingScreen.hasError) return
412
+ // remove loading screen, wait a second to make sure a frame has properly rendered
413
+ loadingScreen.style = 'display: none;'
414
+ }, 2500)
415
+ })
416
+ }
417
+
418
+ /**
419
+ * @param {URLSearchParams} params
420
+ */
421
+ async function fromTheOutside (params, addr) {
422
+ const opts = {}
423
+ const dfltConfig = await (await window.fetch('config.json')).json()
424
+
425
+ let server, port, proxy, proxyPort
426
+
427
+ if (address.includes(':')) {
428
+ const s = address.split(':')
429
+ server = s[0]
430
+ port = Number(s[1]) || 25565
431
+ } else {
432
+ server = address
433
+ port = Number(params.get('port')) || 25565
434
+ }
435
+
436
+ const proxyAddr = params.get('proxy')
437
+ if (proxyAddr) {
438
+ const s = proxyAddr.split(':')
439
+ proxy = s[0]
440
+ proxyPort = Number(s[1] ?? 'NaN') || 22
441
+ } else {
442
+ proxy = dfltConfig.defaultProxy
443
+ proxyPort = !dfltConfig.defaultProxy && !dfltConfig.defaultProxyPort ? '' : dfltConfig.defaultProxyPort ?? 443
444
+ }
445
+
446
+ opts.server = `${server}:${port}`
447
+ opts.proxy = `${proxy}:${proxyPort}`
448
+ opts.username = params.get('username') ?? `pviewer${Math.floor(Math.random() * 1000)}`
449
+ opts.password = params.get('password') ?? ''
450
+ opts.botVersion = params.get('version') ?? false
451
+
452
+ console.log(opts)
453
+
454
+ showEl('loading-screen')
455
+ removePanorama()
456
+ connect(opts)
457
+ }
458
+
459
+ const params = new URLSearchParams(window.location.search)
460
+ let address
461
+ if ((address = params.get('address'))) {
462
+ fromTheOutside(params, address)
463
+ } else {
464
+ showEl('title-screen')
465
+ main()
466
+ }
lib/chat.js ADDED
@@ -0,0 +1,361 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { LitElement, html, css } = require('lit')
2
+ const { isMobile } = require('./menus/components/common')
3
+
4
+ const styles = {
5
+ black: 'color:#000000',
6
+ dark_blue: 'color:#0000AA',
7
+ dark_green: 'color:#00AA00',
8
+ dark_aqua: 'color:#00AAAA',
9
+ dark_red: 'color:#AA0000',
10
+ dark_purple: 'color:#AA00AA',
11
+ gold: 'color:#FFAA00',
12
+ gray: 'color:#AAAAAA',
13
+ dark_gray: 'color:#555555',
14
+ blue: 'color:#5555FF',
15
+ green: 'color:#55FF55',
16
+ aqua: 'color:#55FFFF',
17
+ red: 'color:#FF5555',
18
+ light_purple: 'color:#FF55FF',
19
+ yellow: 'color:#FFFF55',
20
+ white: 'color:#FFFFFF',
21
+ bold: 'font-weight:900',
22
+ strikethrough: 'text-decoration:line-through',
23
+ underlined: 'text-decoration:underline',
24
+ italic: 'font-style:italic'
25
+ }
26
+
27
+ function colorShadow (hex, dim = 0.25) {
28
+ const color = parseInt(hex.replace('#', ''), 16)
29
+
30
+ const r = (color >> 16 & 0xFF) * dim | 0
31
+ const g = (color >> 8 & 0xFF) * dim | 0
32
+ const b = (color & 0xFF) * dim | 0
33
+
34
+ const f = (c) => ('00' + c.toString(16)).substr(-2)
35
+ return `#${f(r)}${f(g)}${f(b)}`
36
+ }
37
+
38
+ class ChatBox extends LitElement {
39
+ static get styles () {
40
+ return css`
41
+ .chat-wrapper {
42
+ position: fixed;
43
+ z-index: 10;
44
+ }
45
+
46
+ .chat-display-wrapper {
47
+ bottom: 40px;
48
+ padding: 4px;
49
+ padding-left: 0;
50
+ max-height: var(--chatHeight);
51
+ width: var(--chatWidth);
52
+ transform-origin: bottom left;
53
+ transform: scale(var(--chatScale));
54
+ }
55
+
56
+ .chat-input-wrapper {
57
+ bottom: 1px;
58
+ width: calc(100% - 3px);
59
+ position: absolute;
60
+ left: 1px;
61
+ box-sizing: border-box;
62
+ overflow: hidden;
63
+ background-color: rgba(0, 0, 0, 0);
64
+ }
65
+
66
+ .input-mobile {
67
+ top: 1px;
68
+ }
69
+
70
+ .display-mobile {
71
+ top: 40px;
72
+ }
73
+
74
+ .chat {
75
+ overflow: hidden;
76
+ color: white;
77
+ font-size: 10px;
78
+ margin: 0px;
79
+ line-height: 100%;
80
+ text-shadow: 1px 1px 0px #3f3f3f;
81
+ font-family: mojangles, minecraft, monospace;
82
+ width: 100%;
83
+ max-height: var(--chatHeight);
84
+ }
85
+
86
+ input[type=text], #chatinput {
87
+ background-color: rgba(0, 0, 0, 0.5);
88
+ border: 1px solid rgba(0, 0, 0, 0);
89
+ display: none;
90
+ outline: none;
91
+ }
92
+
93
+ #chatinput:focus {
94
+ border-color: white;
95
+ }
96
+
97
+ .chat-message {
98
+ display: block;
99
+ padding-left: 4px;
100
+ background-color: rgba(0, 0, 0, 0.5);
101
+ }
102
+
103
+ .chat-message-fadeout {
104
+ opacity: 1;
105
+ transition: all 3s;
106
+ }
107
+
108
+ .chat-message-fade {
109
+ opacity: 0;
110
+ }
111
+
112
+ .chat-message-faded {
113
+ transition: none !important;
114
+ }
115
+
116
+ .chat-message-chat-opened {
117
+ opacity: 1 !important;
118
+ transition: none !important;
119
+ }
120
+ `
121
+ }
122
+
123
+ render () {
124
+ return html`
125
+ <div id="chat-wrapper" class="chat-wrapper chat-display-wrapper">
126
+ <div class="chat" id="chat">
127
+ <li class="chat-message chat-message-fade chat-message-faded">Welcome to prismarine-web-client! Chat appears here.</li>
128
+ </div>
129
+ </div>
130
+ <div id="chat-wrapper2" class="chat-wrapper chat-input-wrapper">
131
+ <div class="chat" id="chat-input">
132
+ <input type="text" class="chat" id="chatinput" spellcheck="false" autocomplete="off"></input>
133
+ </div>
134
+ </div>
135
+ `
136
+ }
137
+
138
+ constructor () {
139
+ super()
140
+ this.chatHistoryPos = 0
141
+ this.chatHistory = []
142
+ }
143
+
144
+ enableChat (isCommand) {
145
+ const chat = this.shadowRoot.querySelector('#chat')
146
+ const chatInput = this.shadowRoot.querySelector('#chatinput')
147
+
148
+ this.shadowRoot.querySelector('#chat-wrapper2').classList.toggle('input-mobile', isMobile())
149
+ this.shadowRoot.querySelector('#chat-wrapper').classList.toggle('display-mobile', isMobile())
150
+
151
+ // Set inChat value
152
+ this.inChat = true
153
+ // Exit the pointer lock
154
+ document.exitPointerLock()
155
+ // Show chat input
156
+ chatInput.style.display = 'block'
157
+ // Show extended chat history
158
+ chat.style.maxHeight = 'var(--chatHeight)'
159
+ chat.scrollTop = chat.scrollHeight // Stay bottom of the list
160
+ if (isCommand) { // handle commands
161
+ chatInput.value = '/'
162
+ }
163
+ // Focus element
164
+ chatInput.focus()
165
+ this.chatHistoryPos = this.chatHistory.length
166
+ document.querySelector('#hud').shadowRoot.querySelector('#chat').shadowRoot.querySelectorAll('.chat-message').forEach(e => e.classList.add('chat-message-chat-opened'))
167
+ }
168
+
169
+ /**
170
+ * @param {globalThis.THREE.Renderer} client
171
+ * @param {import('minecraft-protocol').Client} renderer
172
+ */
173
+ init (client, renderer) {
174
+ this.inChat = false
175
+ const chat = this.shadowRoot.querySelector('#chat')
176
+ const gameMenu = document.getElementById('pause-screen')
177
+ const chatInput = this.shadowRoot.querySelector('#chatinput')
178
+
179
+ renderer.domElement.requestPointerLock = renderer.domElement.requestPointerLock ||
180
+ renderer.domElement.mozRequestPointerLock ||
181
+ renderer.domElement.webkitRequestPointerLock
182
+
183
+ // Show chat
184
+ chat.style.display = 'block'
185
+
186
+ // Esc event - Doesnt work with onkeypress?! - keypressed is deprecated uk
187
+ document.addEventListener('keydown', e => {
188
+ if (gameMenu.inMenu) return
189
+ if (!this.inChat) return
190
+ e = e || window.event
191
+ if (e.code === 'Escape') {
192
+ disableChat()
193
+ } else if (e.code === 'ArrowUp') {
194
+ if (this.chatHistoryPos === 0) return
195
+ chatInput.value = this.chatHistory[--this.chatHistoryPos] !== undefined ? this.chatHistory[this.chatHistoryPos] : ''
196
+ setTimeout(() => { chatInput.setSelectionRange(-1, -1) }, 0)
197
+ } else if (e.code === 'ArrowDown') {
198
+ if (this.chatHistoryPos === this.chatHistory.length) return
199
+ chatInput.value = this.chatHistory[++this.chatHistoryPos] !== undefined ? this.chatHistory[this.chatHistoryPos] : ''
200
+ setTimeout(() => { chatInput.setSelectionRange(-1, -1) }, 0)
201
+ }
202
+ })
203
+
204
+ const keyBindScrn = document.getElementById('keybinds-screen')
205
+
206
+ // Chat events
207
+ document.addEventListener('keypress', e => {
208
+ if (gameMenu.inMenu) return
209
+ e = e || window.event
210
+ if (this.inChat === false) {
211
+ keyBindScrn.keymaps.forEach(km => {
212
+ if (e.code === km.key) {
213
+ switch (km.defaultKey) {
214
+ case 'KeyT':
215
+ setTimeout(() => this.enableChat(false), 0)
216
+ break
217
+ case 'Slash':
218
+ setTimeout(() => this.enableChat(true), 0)
219
+ break
220
+ }
221
+ }
222
+ })
223
+
224
+ return false
225
+ }
226
+
227
+ if (!this.inChat) return
228
+
229
+ e.stopPropagation()
230
+
231
+ if (e.code === 'Enter') {
232
+ this.chatHistory.push(chatInput.value)
233
+ client.write('chat', { message: chatInput.value })
234
+ disableChat()
235
+ }
236
+ })
237
+
238
+ const disableChat = () => {
239
+ this.inChat = false
240
+ hideChat()
241
+ renderer.domElement.requestPointerLock()
242
+ }
243
+
244
+ const hideChat = () => {
245
+ // Clear chat input
246
+ chatInput.value = ''
247
+ // Unfocus it
248
+ chatInput.blur()
249
+ // Hide it
250
+ chatInput.style.display = 'none'
251
+ // Hide extended chat history
252
+ chat.style.maxHeight = 'var(--chatHeight)'
253
+ chat.scrollTop = chat.scrollHeight // Stay bottom of the list
254
+ document.querySelector('#hud').shadowRoot.querySelector('#chat').shadowRoot.querySelectorAll('.chat-message').forEach(e => e.classList.remove('chat-message-chat-opened'))
255
+ }
256
+
257
+ client.on('chat', (packet) => {
258
+ // Reading of chat message
259
+ const fullmessage = JSON.parse(packet.message.toString())
260
+ const msglist = []
261
+
262
+ const colorF = (color) => {
263
+ return color.trim().startsWith('#') ? `color:${color}` : styles[color] ?? undefined
264
+ }
265
+
266
+ const readMsg = (msglist, msg) => {
267
+ const styles = {
268
+ color: msg.color,
269
+ bold: !!msg.bold,
270
+ italic: !!msg.italic,
271
+ underlined: !!msg.underlined,
272
+ strikethrough: !!msg.strikethrough,
273
+ obfuscated: !!msg.obfuscated
274
+ }
275
+
276
+ if (msg.text) {
277
+ msglist.push({
278
+ text: msg.text,
279
+ ...styles
280
+ })
281
+ }
282
+
283
+ if (msg.translate) {
284
+ const tText = window.mcData.language[msg.translate] ?? msg.translate
285
+
286
+ if (msg.with) {
287
+ const splited = tText.split(/%s|%\d+\$s/g)
288
+
289
+ let i = 0
290
+ splited.forEach((spl, j, arr) => {
291
+ msglist.push({ text: spl, ...styles })
292
+
293
+ if (j + 1 < arr.length) {
294
+ if (msg.with[i]) {
295
+ if (typeof msg.with[i] === 'string') {
296
+ readMsg(msglist, {
297
+ ...styles,
298
+ text: msg.with[i]
299
+ })
300
+ } else {
301
+ readMsg(msglist, {
302
+ ...styles,
303
+ ...msg.with[i]
304
+ })
305
+ }
306
+ }
307
+ i++
308
+ }
309
+ })
310
+ } else {
311
+ msglist.push({
312
+ text: tText,
313
+ ...styles
314
+ })
315
+ }
316
+ }
317
+
318
+ if (msg.extra) {
319
+ msg.extra.forEach(ex => {
320
+ readMsg(msglist, { ...styles, ...ex })
321
+ })
322
+ }
323
+ }
324
+
325
+ readMsg(msglist, fullmessage)
326
+
327
+ const li = document.createElement('li')
328
+ msglist.forEach(msg => {
329
+ const span = document.createElement('span')
330
+ span.appendChild(document.createTextNode(msg.text))
331
+ span.setAttribute(
332
+ 'style',
333
+ `${msg.color ? colorF(msg.color.toLowerCase()) + `; text-shadow: 1px 1px 0px ${colorShadow(colorF(msg.color.toLowerCase()).replace('color:', ''))}` : styles.white}; ${
334
+ msg.bold ? styles.bold + ';' : ''
335
+ }${msg.italic ? styles.italic + ';' : ''}${
336
+ msg.strikethrough ? styles.strikethrough + ';' : ''
337
+ }${msg.underlined ? styles.underlined + ';' : ''}`
338
+ )
339
+ li.appendChild(span)
340
+ })
341
+ chat.appendChild(li)
342
+ chat.scrollTop = chat.scrollHeight // Stay bottom of the list
343
+ // fading
344
+ li.classList.add('chat-message')
345
+ if (this.inChat) {
346
+ li.classList.add('chat-message-chat-opened')
347
+ }
348
+ setTimeout(() => {
349
+ li.classList.add('chat-message-fadeout')
350
+ li.classList.add('chat-message-fade')
351
+ setTimeout(() => {
352
+ li.classList.add('chat-message-faded')
353
+ }, 3000)
354
+ }, 5000)
355
+ })
356
+
357
+ hideChat()
358
+ }
359
+ }
360
+
361
+ window.customElements.define('chat-box', ChatBox)
lib/cursor.js ADDED
@@ -0,0 +1,143 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* global THREE performance */
2
+
3
+ const { Vec3 } = require('vec3')
4
+
5
+ function getViewDirection (pitch, yaw) {
6
+ const csPitch = Math.cos(pitch)
7
+ const snPitch = Math.sin(pitch)
8
+ const csYaw = Math.cos(yaw)
9
+ const snYaw = Math.sin(yaw)
10
+ return new Vec3(-snYaw * csPitch, snPitch, -csYaw * csPitch)
11
+ }
12
+
13
+ class Cursor {
14
+ constructor (viewer, renderer, bot) {
15
+ // Init state
16
+ this.buttons = [false, false, false]
17
+ this.lastButtons = [false, false, false]
18
+ this.breakStartTime = 0
19
+ this.cursorBlock = null
20
+
21
+ // Setup graphics
22
+ const blockGeometry = new THREE.BoxGeometry(1.001, 1.001, 1.001)
23
+ this.cursorMesh = new THREE.LineSegments(new THREE.EdgesGeometry(blockGeometry), new THREE.LineBasicMaterial({ color: 0 }))
24
+ this.cursorMesh.visible = false
25
+ viewer.scene.add(this.cursorMesh)
26
+
27
+ const loader = new THREE.TextureLoader()
28
+ this.breakTextures = []
29
+ for (let i = 0; i < 10; i++) {
30
+ const texture = loader.load('textures/' + viewer.version + '/blocks/destroy_stage_' + i + '.png')
31
+ texture.magFilter = THREE.NearestFilter
32
+ texture.minFilter = THREE.NearestFilter
33
+ this.breakTextures.push(texture)
34
+ }
35
+ const breakMaterial = new THREE.MeshBasicMaterial({
36
+ transparent: true,
37
+ blending: THREE.MultiplyBlending
38
+ })
39
+ this.blockBreakMesh = new THREE.Mesh(blockGeometry, breakMaterial)
40
+ this.blockBreakMesh.visible = false
41
+ this.blockBreakMesh.renderOrder = 999
42
+ viewer.scene.add(this.blockBreakMesh)
43
+
44
+ // Setup events
45
+ document.addEventListener('mouseup', (e) => {
46
+ this.buttons[e.button] = false
47
+ })
48
+
49
+ document.addEventListener('mousedown', (e) => {
50
+ if (document.pointerLockElement !== renderer.domElement) return
51
+ this.buttons[e.button] = true
52
+
53
+ const entity = bot.nearestEntity((e) => {
54
+ if (e.position.distanceTo(bot.entity.position) <= (bot.player.gamemode === 1 ? 5 : 3)) {
55
+ const dir = getViewDirection(bot.entity.pitch, bot.entity.yaw)
56
+ const { width, height } = e
57
+ const { x: eX, y: eY, z: eZ } = e.position
58
+ const { x: bX, y: bY, z: bZ } = bot.entity.position
59
+ const box = new THREE.Box3(
60
+ new THREE.Vector3(eX - width / 2, eY, eZ - width / 2),
61
+ new THREE.Vector3(eX + width / 2, eY + height, eZ + width / 2)
62
+ )
63
+
64
+ const r = new THREE.Raycaster(
65
+ new THREE.Vector3(bX, bY + 1.52, bZ),
66
+ new THREE.Vector3(dir.x, dir.y, dir.z)
67
+ )
68
+ const int = r.ray.intersectBox(box, new THREE.Vector3(eX, eY, eZ))
69
+ return int !== null
70
+ }
71
+
72
+ return false
73
+ })
74
+
75
+ if (entity) {
76
+ bot.attack(entity)
77
+ }
78
+ })
79
+ this.lastPlaced = 4 // ticks since last placed
80
+ bot.on('physicsTick', () => { if (this.lastPlaced < 4) this.lastPlaced++ })
81
+ }
82
+
83
+ update (bot) {
84
+ let cursorBlock = bot.blockAtCursor(6)
85
+ if (!bot.canDigBlock(cursorBlock)) cursorBlock = null
86
+
87
+ let cursorChanged = !cursorBlock !== !this.cursorBlock
88
+ if (cursorBlock && this.cursorBlock) {
89
+ cursorChanged = !cursorBlock.position.equals(this.cursorBlock.position)
90
+ }
91
+
92
+ // Place
93
+ if (cursorBlock && this.buttons[2] && (!this.lastButtons[2] || cursorChanged) && this.lastPlaced >= 4) {
94
+ const vecArray = [new Vec3(0, -1, 0), new Vec3(0, 1, 0), new Vec3(0, 0, -1), new Vec3(0, 0, 1), new Vec3(-1, 0, 0), new Vec3(1, 0, 0)]
95
+ const delta = cursorBlock.intersect.minus(cursorBlock.position)
96
+ bot._placeBlockWithOptions(cursorBlock, vecArray[cursorBlock.face], { delta, forceLook: 'ignore' })
97
+ bot.lastPlaced = 0
98
+ }
99
+
100
+ // Start break
101
+ if (cursorBlock && this.buttons[0] && (!this.lastButtons[0] || cursorChanged)) {
102
+ this.breakStartTime = performance.now()
103
+ try {
104
+ bot.dig(cursorBlock, 'ignore')
105
+ } catch (e) {} // we don't care if its aborted
106
+ }
107
+
108
+ // Stop break
109
+ if (!this.buttons[0] && this.lastButtons[0]) {
110
+ try {
111
+ bot.stopDigging() // this shouldnt throw anything...
112
+ } catch (e) {} // to be reworked in mineflayer, then remove the try here
113
+ }
114
+
115
+ // Show break animation
116
+ if (cursorBlock && this.buttons[0]) {
117
+ const elapsed = performance.now() - this.breakStartTime
118
+ const time = bot.digTime(cursorBlock)
119
+ const state = Math.floor((elapsed / time) * 10)
120
+ this.blockBreakMesh.position.set(cursorBlock.position.x + 0.5, cursorBlock.position.y + 0.5, cursorBlock.position.z + 0.5)
121
+ this.blockBreakMesh.material.map = this.breakTextures[state]
122
+ this.blockBreakMesh.visible = true
123
+ } else {
124
+ this.blockBreakMesh.visible = false
125
+ }
126
+
127
+ // Show cursor
128
+ if (!cursorBlock) {
129
+ this.cursorMesh.visible = false
130
+ } else {
131
+ this.cursorMesh.visible = true
132
+ this.cursorMesh.position.set(cursorBlock.position.x + 0.5, cursorBlock.position.y + 0.5, cursorBlock.position.z + 0.5)
133
+ }
134
+
135
+ // Update state
136
+ this.cursorBlock = cursorBlock
137
+ this.lastButtons[0] = this.buttons[0]
138
+ this.lastButtons[1] = this.buttons[1]
139
+ this.lastButtons[2] = this.buttons[2]
140
+ }
141
+ }
142
+
143
+ module.exports = Cursor
lib/dns.js ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* global XMLHttpRequest */
2
+
3
+ // Custom DNS resolver made by SiebeDW. Powered by google dns.
4
+ // Supported: SRV (not all errors support)
5
+ module.exports.resolveSrv = function (hostname, callback) {
6
+ const Http = new XMLHttpRequest()
7
+ const url = `https://dns.google.com/resolve?name=${hostname}&type=SRV`
8
+ Http.open('GET', url)
9
+ Http.responseType = 'json'
10
+ Http.send()
11
+
12
+ Http.onload = function () {
13
+ const response = Http.response
14
+ if (response.Status === 3) {
15
+ const err = new Error('querySrv ENOTFOUND')
16
+ err.code = 'ENOTFOUND'
17
+ callback(err)
18
+ return
19
+ }
20
+ if (!response.Answer || response.Answer.length < 1) {
21
+ const err = new Error('querySrv ENODATA')
22
+ err.code = 'ENODATA'
23
+ callback(err)
24
+ return
25
+ }
26
+ const willreturn = []
27
+ response.Answer.forEach(function (object) {
28
+ const data = object.data.split(' ')
29
+ willreturn.push({
30
+ priority: data[0],
31
+ weight: data[1],
32
+ port: data[2],
33
+ name: data[3]
34
+ })
35
+ })
36
+ console.log(willreturn)
37
+ callback(null, willreturn)
38
+ }
39
+ }
lib/invsprite.json ADDED
@@ -0,0 +1,4812 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "air": {
3
+ "name": "Air",
4
+ "x": 832,
5
+ "y": 2336
6
+ },
7
+ "stone": {
8
+ "name": "Stone",
9
+ "x": 224,
10
+ "y": 992
11
+ },
12
+ "granite": {
13
+ "name": "Granite",
14
+ "x": 96,
15
+ "y": 3360
16
+ },
17
+ "polished_granite": {
18
+ "name": "Polished Granite",
19
+ "x": 384,
20
+ "y": 896
21
+ },
22
+ "diorite": {
23
+ "name": "Diorite",
24
+ "x": 64,
25
+ "y": 3360
26
+ },
27
+ "polished_diorite": {
28
+ "name": "Polished Diorite",
29
+ "x": 352,
30
+ "y": 896
31
+ },
32
+ "andesite": {
33
+ "name": "Andesite",
34
+ "x": 832,
35
+ "y": 3328
36
+ },
37
+ "polished_andesite": {
38
+ "name": "Polished Andesite",
39
+ "x": 320,
40
+ "y": 896
41
+ },
42
+ "grass_block": {
43
+ "name": "Grass Block",
44
+ "x": 640,
45
+ "y": 960
46
+ },
47
+ "dirt": {
48
+ "name": "Dirt",
49
+ "x": 576,
50
+ "y": 960
51
+ },
52
+ "coarse_dirt": {
53
+ "name": "Coarse Dirt",
54
+ "x": 416,
55
+ "y": 960
56
+ },
57
+ "podzol": {
58
+ "name": "Podzol",
59
+ "x": 352,
60
+ "y": 3360
61
+ },
62
+ "crimson_nylium": {
63
+ "name": "Crimson Nylium",
64
+ "x": 640,
65
+ "y": 128
66
+ },
67
+ "warped_nylium": {
68
+ "name": "Warped Nylium",
69
+ "x": 768,
70
+ "y": 128
71
+ },
72
+ "cobblestone": {
73
+ "name": "Cobblestone",
74
+ "x": 960,
75
+ "y": 3328
76
+ },
77
+ "oak_planks": {
78
+ "name": "Oak Planks",
79
+ "x": 192,
80
+ "y": 896
81
+ },
82
+ "spruce_planks": {
83
+ "name": "Spruce Planks",
84
+ "x": 0,
85
+ "y": 928
86
+ },
87
+ "birch_planks": {
88
+ "name": "Birch Planks",
89
+ "x": 832,
90
+ "y": 832
91
+ },
92
+ "jungle_planks": {
93
+ "name": "Jungle Planks",
94
+ "x": 992,
95
+ "y": 864
96
+ },
97
+ "acacia_planks": {
98
+ "name": "Acacia Planks",
99
+ "x": 672,
100
+ "y": 832
101
+ },
102
+ "dark_oak_planks": {
103
+ "name": "Dark Oak Planks",
104
+ "x": 512,
105
+ "y": 864
106
+ },
107
+ "crimson_planks": {
108
+ "name": "Crimson Planks",
109
+ "x": 544,
110
+ "y": 128
111
+ },
112
+ "warped_planks": {
113
+ "name": "Warped Planks",
114
+ "x": 576,
115
+ "y": 128
116
+ },
117
+ "oak_sapling": {
118
+ "name": "Oak Sapling",
119
+ "x": 192,
120
+ "y": 3424
121
+ },
122
+ "spruce_sapling": {
123
+ "name": "Spruce Sapling",
124
+ "x": 608,
125
+ "y": 3424
126
+ },
127
+ "birch_sapling": {
128
+ "name": "Birch Sapling",
129
+ "x": 416,
130
+ "y": 3392
131
+ },
132
+ "jungle_sapling": {
133
+ "name": "Jungle Sapling",
134
+ "x": 960,
135
+ "y": 3392
136
+ },
137
+ "acacia_sapling": {
138
+ "name": "Acacia Sapling",
139
+ "x": 224,
140
+ "y": 3392
141
+ },
142
+ "dark_oak_sapling": {
143
+ "name": "Dark Oak Sapling",
144
+ "x": 768,
145
+ "y": 3392
146
+ },
147
+ "bedrock": {
148
+ "name": "Bedrock",
149
+ "x": 320,
150
+ "y": 960
151
+ },
152
+ "sand": {
153
+ "name": "Sand",
154
+ "x": 480,
155
+ "y": 3360
156
+ },
157
+ "red_sand": {
158
+ "name": "Red Sand",
159
+ "x": 416,
160
+ "y": 3360
161
+ },
162
+ "gravel": {
163
+ "name": "Gravel",
164
+ "x": 128,
165
+ "y": 3360
166
+ },
167
+ "gold_ore": {
168
+ "name": "Gold Ore",
169
+ "x": 32,
170
+ "y": 3392
171
+ },
172
+ "iron_ore": {
173
+ "name": "Iron Ore",
174
+ "x": 64,
175
+ "y": 3392
176
+ },
177
+ "coal_ore": {
178
+ "name": "Coal Ore",
179
+ "x": 960,
180
+ "y": 3360
181
+ },
182
+ "nether_gold_ore": {
183
+ "name": "Nether Gold Ore",
184
+ "x": 288,
185
+ "y": 192
186
+ },
187
+ "oak_log": {
188
+ "name": "Oak Log",
189
+ "x": 160,
190
+ "y": 3424
191
+ },
192
+ "spruce_log": {
193
+ "name": "Spruce Log",
194
+ "x": 576,
195
+ "y": 3424
196
+ },
197
+ "birch_log": {
198
+ "name": "Birch Log",
199
+ "x": 384,
200
+ "y": 3392
201
+ },
202
+ "jungle_log": {
203
+ "name": "Jungle Log",
204
+ "x": 928,
205
+ "y": 3392
206
+ },
207
+ "acacia_log": {
208
+ "name": "Acacia Log",
209
+ "x": 192,
210
+ "y": 3392
211
+ },
212
+ "dark_oak_log": {
213
+ "name": "Dark Oak Log",
214
+ "x": 736,
215
+ "y": 3392
216
+ },
217
+ "crimson_stem": {
218
+ "name": "Crimson Stem",
219
+ "x": 672,
220
+ "y": 128
221
+ },
222
+ "warped_stem": {
223
+ "name": "Warped Stem",
224
+ "x": 800,
225
+ "y": 128
226
+ },
227
+ "stripped_oak_log": {
228
+ "name": "Stripped Oak Log",
229
+ "x": 288,
230
+ "y": 1664
231
+ },
232
+ "stripped_spruce_log": {
233
+ "name": "Stripped Spruce Log",
234
+ "x": 320,
235
+ "y": 1664
236
+ },
237
+ "stripped_birch_log": {
238
+ "name": "Stripped Birch Log",
239
+ "x": 192,
240
+ "y": 1664
241
+ },
242
+ "stripped_jungle_log": {
243
+ "name": "Stripped Jungle Log",
244
+ "x": 256,
245
+ "y": 1664
246
+ },
247
+ "stripped_acacia_log": {
248
+ "name": "Stripped Acacia Log",
249
+ "x": 160,
250
+ "y": 1664
251
+ },
252
+ "stripped_dark_oak_log": {
253
+ "name": "Stripped Dark Oak Log",
254
+ "x": 224,
255
+ "y": 1664
256
+ },
257
+ "stripped_crimson_stem": {
258
+ "name": "Stripped Crimson Stem",
259
+ "x": 448,
260
+ "y": 160
261
+ },
262
+ "stripped_warped_stem": {
263
+ "name": "Stripped Warped Stem",
264
+ "x": 480,
265
+ "y": 160
266
+ },
267
+ "stripped_oak_wood": {
268
+ "name": "Stripped Oak Wood",
269
+ "x": 576,
270
+ "y": 2080
271
+ },
272
+ "stripped_spruce_wood": {
273
+ "name": "Stripped Spruce Wood",
274
+ "x": 608,
275
+ "y": 2080
276
+ },
277
+ "stripped_birch_wood": {
278
+ "name": "Stripped Birch Wood",
279
+ "x": 640,
280
+ "y": 2080
281
+ },
282
+ "stripped_jungle_wood": {
283
+ "name": "Stripped Jungle Wood",
284
+ "x": 672,
285
+ "y": 2080
286
+ },
287
+ "stripped_acacia_wood": {
288
+ "name": "Stripped Acacia Wood",
289
+ "x": 704,
290
+ "y": 2080
291
+ },
292
+ "stripped_dark_oak_wood": {
293
+ "name": "Stripped Dark Oak Wood",
294
+ "x": 736,
295
+ "y": 2080
296
+ },
297
+ "stripped_crimson_hyphae": {
298
+ "name": "Stripped Crimson Hyphae",
299
+ "x": 224,
300
+ "y": 192
301
+ },
302
+ "stripped_warped_hyphae": {
303
+ "name": "Stripped Warped Hyphae",
304
+ "x": 256,
305
+ "y": 192
306
+ },
307
+ "oak_wood": {
308
+ "name": "Oak Wood",
309
+ "x": 704,
310
+ "y": 3264
311
+ },
312
+ "spruce_wood": {
313
+ "name": "Spruce Wood",
314
+ "x": 736,
315
+ "y": 3296
316
+ },
317
+ "birch_wood": {
318
+ "name": "Birch Wood",
319
+ "x": 0,
320
+ "y": 3232
321
+ },
322
+ "jungle_wood": {
323
+ "name": "Jungle Wood",
324
+ "x": 192,
325
+ "y": 3264
326
+ },
327
+ "acacia_wood": {
328
+ "name": "Acacia Wood",
329
+ "x": 768,
330
+ "y": 3200
331
+ },
332
+ "dark_oak_wood": {
333
+ "name": "Dark Oak Wood",
334
+ "x": 704,
335
+ "y": 3232
336
+ },
337
+ "crimson_hyphae": {
338
+ "name": "Crimson Hyphae",
339
+ "x": 160,
340
+ "y": 192
341
+ },
342
+ "warped_hyphae": {
343
+ "name": "Warped Hyphae",
344
+ "x": 192,
345
+ "y": 192
346
+ },
347
+ "oak_leaves": {
348
+ "name": "Oak Leaves",
349
+ "x": 128,
350
+ "y": 3424
351
+ },
352
+ "spruce_leaves": {
353
+ "name": "Spruce Leaves",
354
+ "x": 544,
355
+ "y": 3424
356
+ },
357
+ "birch_leaves": {
358
+ "name": "Birch Leaves",
359
+ "x": 352,
360
+ "y": 3392
361
+ },
362
+ "jungle_leaves": {
363
+ "name": "Jungle Leaves",
364
+ "x": 896,
365
+ "y": 3392
366
+ },
367
+ "acacia_leaves": {
368
+ "name": "Acacia Leaves",
369
+ "x": 160,
370
+ "y": 3392
371
+ },
372
+ "dark_oak_leaves": {
373
+ "name": "Dark Oak Leaves",
374
+ "x": 704,
375
+ "y": 3392
376
+ },
377
+ "sponge": {
378
+ "name": "Sponge",
379
+ "x": 896,
380
+ "y": 3584
381
+ },
382
+ "wet_sponge": {
383
+ "name": "Wet Sponge",
384
+ "x": 0,
385
+ "y": 3616
386
+ },
387
+ "glass": {
388
+ "name": "Glass",
389
+ "x": 960,
390
+ "y": 3232
391
+ },
392
+ "lapis_ore": {
393
+ "name": "Lapis Lazuli Ore",
394
+ "x": 96,
395
+ "y": 3392
396
+ },
397
+ "lapis_block": {
398
+ "name": "Lapis Lazuli Block",
399
+ "x": 256,
400
+ "y": 3264
401
+ },
402
+ "dispenser": {
403
+ "name": "Dispenser",
404
+ "x": 576,
405
+ "y": 3584
406
+ },
407
+ "sandstone": {
408
+ "name": "Sandstone",
409
+ "x": 512,
410
+ "y": 3360
411
+ },
412
+ "chiseled_sandstone": {
413
+ "name": "Chiseled Sandstone",
414
+ "x": 384,
415
+ "y": 3232
416
+ },
417
+ "cut_sandstone": {
418
+ "name": "Cut Sandstone",
419
+ "x": 544,
420
+ "y": 3232
421
+ },
422
+ "note_block": {
423
+ "name": "Note Block",
424
+ "x": 832,
425
+ "y": 3584
426
+ },
427
+ "powered_rail": {
428
+ "name": "Powered Rail",
429
+ "x": 448,
430
+ "y": 3328
431
+ },
432
+ "detector_rail": {
433
+ "name": "Detector Rail",
434
+ "x": 160,
435
+ "y": 3328
436
+ },
437
+ "sticky_piston": {
438
+ "name": "Sticky Piston",
439
+ "x": 704,
440
+ "y": 3328
441
+ },
442
+ "cobweb": {
443
+ "name": "Cobweb",
444
+ "x": 992,
445
+ "y": 3328
446
+ },
447
+ "grass": {
448
+ "name": "Grass",
449
+ "x": 864,
450
+ "y": 3392
451
+ },
452
+ "fern": {
453
+ "name": "Fern",
454
+ "x": 832,
455
+ "y": 3392
456
+ },
457
+ "dead_bush": {
458
+ "name": "Dead Bush",
459
+ "x": 800,
460
+ "y": 3392
461
+ },
462
+ "seagrass": {
463
+ "name": "Seagrass",
464
+ "x": 384,
465
+ "y": 2016
466
+ },
467
+ "sea_pickle": {
468
+ "name": "Sea Pickle",
469
+ "x": 224,
470
+ "y": 1728
471
+ },
472
+ "piston": {
473
+ "name": "Piston",
474
+ "x": 416,
475
+ "y": 3328
476
+ },
477
+ "white_wool": {
478
+ "name": "White Wool",
479
+ "x": 0,
480
+ "y": 1536
481
+ },
482
+ "orange_wool": {
483
+ "name": "Orange Wool",
484
+ "x": 896,
485
+ "y": 1504
486
+ },
487
+ "magenta_wool": {
488
+ "name": "Magenta Wool",
489
+ "x": 864,
490
+ "y": 1504
491
+ },
492
+ "light_blue_wool": {
493
+ "name": "Light Blue Wool",
494
+ "x": 768,
495
+ "y": 1504
496
+ },
497
+ "yellow_wool": {
498
+ "name": "Yellow Wool",
499
+ "x": 32,
500
+ "y": 1536
501
+ },
502
+ "lime_wool": {
503
+ "name": "Lime Wool",
504
+ "x": 832,
505
+ "y": 1504
506
+ },
507
+ "pink_wool": {
508
+ "name": "Pink Wool",
509
+ "x": 928,
510
+ "y": 1504
511
+ },
512
+ "gray_wool": {
513
+ "name": "Gray Wool",
514
+ "x": 704,
515
+ "y": 1504
516
+ },
517
+ "light_gray_wool": {
518
+ "name": "Light Gray Wool",
519
+ "x": 800,
520
+ "y": 1504
521
+ },
522
+ "cyan_wool": {
523
+ "name": "Cyan Wool",
524
+ "x": 672,
525
+ "y": 1504
526
+ },
527
+ "purple_wool": {
528
+ "name": "Purple Wool",
529
+ "x": 960,
530
+ "y": 1504
531
+ },
532
+ "blue_wool": {
533
+ "name": "Blue Wool",
534
+ "x": 608,
535
+ "y": 1504
536
+ },
537
+ "brown_wool": {
538
+ "name": "Brown Wool",
539
+ "x": 640,
540
+ "y": 1504
541
+ },
542
+ "green_wool": {
543
+ "name": "Green Wool",
544
+ "x": 736,
545
+ "y": 1504
546
+ },
547
+ "red_wool": {
548
+ "name": "Red Wool",
549
+ "x": 992,
550
+ "y": 1504
551
+ },
552
+ "black_wool": {
553
+ "name": "Black Wool",
554
+ "x": 576,
555
+ "y": 1504
556
+ },
557
+ "dandelion": {
558
+ "name": "Dandelion",
559
+ "x": 672,
560
+ "y": 3392
561
+ },
562
+ "poppy": {
563
+ "name": "Poppy",
564
+ "x": 352,
565
+ "y": 3424
566
+ },
567
+ "blue_orchid": {
568
+ "name": "Blue Orchid",
569
+ "x": 448,
570
+ "y": 3392
571
+ },
572
+ "allium": {
573
+ "name": "Allium",
574
+ "x": 256,
575
+ "y": 3392
576
+ },
577
+ "azure_bluet": {
578
+ "name": "Azure Bluet",
579
+ "x": 288,
580
+ "y": 3392
581
+ },
582
+ "red_tulip": {
583
+ "name": "Red Tulip",
584
+ "x": 480,
585
+ "y": 3424
586
+ },
587
+ "orange_tulip": {
588
+ "name": "Orange Tulip",
589
+ "x": 224,
590
+ "y": 3424
591
+ },
592
+ "white_tulip": {
593
+ "name": "White Tulip",
594
+ "x": 768,
595
+ "y": 3424
596
+ },
597
+ "pink_tulip": {
598
+ "name": "Pink Tulip",
599
+ "x": 320,
600
+ "y": 3424
601
+ },
602
+ "oxeye_daisy": {
603
+ "name": "Oxeye Daisy",
604
+ "x": 256,
605
+ "y": 3424
606
+ },
607
+ "cornflower": {
608
+ "name": "Cornflower",
609
+ "x": 640,
610
+ "y": 2368
611
+ },
612
+ "lily_of_the_valley": {
613
+ "name": "Lily of the Valley",
614
+ "x": 672,
615
+ "y": 2368
616
+ },
617
+ "wither_rose": {
618
+ "name": "Wither Rose",
619
+ "x": 608,
620
+ "y": 2368
621
+ },
622
+ "brown_mushroom": {
623
+ "name": "Brown Mushroom",
624
+ "x": 512,
625
+ "y": 3392
626
+ },
627
+ "red_mushroom": {
628
+ "name": "Red Mushroom",
629
+ "x": 448,
630
+ "y": 3424
631
+ },
632
+ "crimson_fungus": {
633
+ "name": "Crimson Fungus",
634
+ "x": 928,
635
+ "y": 128
636
+ },
637
+ "warped_fungus": {
638
+ "name": "Warped Fungus",
639
+ "x": 960,
640
+ "y": 128
641
+ },
642
+ "crimson_roots": {
643
+ "name": "Crimson Roots",
644
+ "x": 928,
645
+ "y": 160
646
+ },
647
+ "warped_roots": {
648
+ "name": "Warped Roots",
649
+ "x": 992,
650
+ "y": 160
651
+ },
652
+ "nether_sprouts": {
653
+ "name": "Nether Sprouts",
654
+ "x": 928,
655
+ "y": 64
656
+ },
657
+ "weeping_vines": {
658
+ "name": "Weeping Vines",
659
+ "x": 992,
660
+ "y": 128
661
+ },
662
+ "twisting_vines": {
663
+ "name": "Twisting Vines",
664
+ "x": 320,
665
+ "y": 192
666
+ },
667
+ "sugar_cane": {
668
+ "name": "Sugar Cane",
669
+ "x": 640,
670
+ "y": 3424
671
+ },
672
+ "kelp": {
673
+ "name": "Kelp",
674
+ "x": 576,
675
+ "y": 1664
676
+ },
677
+ "bamboo": {
678
+ "name": "Bamboo",
679
+ "x": 128,
680
+ "y": 2368
681
+ },
682
+ "gold_block": {
683
+ "name": "Block of Gold",
684
+ "x": 128,
685
+ "y": 3232
686
+ },
687
+ "iron_block": {
688
+ "name": "Block of Iron",
689
+ "x": 160,
690
+ "y": 3232
691
+ },
692
+ "oak_slab": {
693
+ "name": "Oak Slab",
694
+ "x": 640,
695
+ "y": 3264
696
+ },
697
+ "spruce_slab": {
698
+ "name": "Spruce Slab",
699
+ "x": 672,
700
+ "y": 3296
701
+ },
702
+ "birch_slab": {
703
+ "name": "Birch Slab",
704
+ "x": 960,
705
+ "y": 3200
706
+ },
707
+ "jungle_slab": {
708
+ "name": "Jungle Slab",
709
+ "x": 128,
710
+ "y": 3264
711
+ },
712
+ "acacia_slab": {
713
+ "name": "Acacia Slab",
714
+ "x": 704,
715
+ "y": 3200
716
+ },
717
+ "dark_oak_slab": {
718
+ "name": "Dark Oak Slab",
719
+ "x": 640,
720
+ "y": 3232
721
+ },
722
+ "crimson_slab": {
723
+ "name": "Crimson Slab",
724
+ "x": 32,
725
+ "y": 160
726
+ },
727
+ "warped_slab": {
728
+ "name": "Warped Slab",
729
+ "x": 128,
730
+ "y": 160
731
+ },
732
+ "stone_slab": {
733
+ "name": "Stone Slab",
734
+ "x": 864,
735
+ "y": 3296
736
+ },
737
+ "smooth_stone_slab": {
738
+ "name": "Smooth Stone Slab",
739
+ "x": 544,
740
+ "y": 3296
741
+ },
742
+ "sandstone_slab": {
743
+ "name": "Sandstone Slab",
744
+ "x": 192,
745
+ "y": 3296
746
+ },
747
+ "cut_sandstone_slab": {
748
+ "name": "Cut Sandstone Slab",
749
+ "x": 64,
750
+ "y": 2464
751
+ },
752
+ "petrified_oak_slab": {
753
+ "name": "Petrified Oak Slab",
754
+ "x": 224,
755
+ "y": 896
756
+ },
757
+ "cobblestone_slab": {
758
+ "name": "Cobblestone Slab",
759
+ "x": 416,
760
+ "y": 3232
761
+ },
762
+ "brick_slab": {
763
+ "name": "Brick Slab",
764
+ "x": 256,
765
+ "y": 3232
766
+ },
767
+ "stone_brick_slab": {
768
+ "name": "Stone Brick Slab",
769
+ "x": 128,
770
+ "y": 928
771
+ },
772
+ "nether_brick_slab": {
773
+ "name": "Nether Brick Slab",
774
+ "x": 480,
775
+ "y": 3264
776
+ },
777
+ "quartz_slab": {
778
+ "name": "Quartz Slab",
779
+ "x": 960,
780
+ "y": 3264
781
+ },
782
+ "red_sandstone_slab": {
783
+ "name": "Red Sandstone Slab",
784
+ "x": 96,
785
+ "y": 3296
786
+ },
787
+ "cut_red_sandstone_slab": {
788
+ "name": "Cut Red Sandstone Slab",
789
+ "x": 32,
790
+ "y": 2464
791
+ },
792
+ "purpur_slab": {
793
+ "name": "Purpur Slab",
794
+ "x": 896,
795
+ "y": 3264
796
+ },
797
+ "prismarine_slab": {
798
+ "name": "Dark Prismarine Slab",
799
+ "x": 736,
800
+ "y": 3232
801
+ },
802
+ "prismarine_brick_slab": {
803
+ "name": "Prismarine Brick Slab",
804
+ "x": 864,
805
+ "y": 3264
806
+ },
807
+ "dark_prismarine_slab": {
808
+ "name": "Dark Prismarine Slab",
809
+ "x": 736,
810
+ "y": 3232
811
+ },
812
+ "smooth_quartz": {
813
+ "name": "Smooth Quartz Block",
814
+ "x": 64,
815
+ "y": 864
816
+ },
817
+ "smooth_red_sandstone": {
818
+ "name": "Smooth Red Sandstone",
819
+ "x": 416,
820
+ "y": 3296
821
+ },
822
+ "smooth_sandstone": {
823
+ "name": "Smooth Sandstone",
824
+ "x": 512,
825
+ "y": 3296
826
+ },
827
+ "smooth_stone": {
828
+ "name": "Smooth Stone",
829
+ "x": 832,
830
+ "y": 896
831
+ },
832
+ "bricks": {
833
+ "name": "Bricks",
834
+ "x": 416,
835
+ "y": 96
836
+ },
837
+ "tnt": {
838
+ "name": "TNT",
839
+ "x": 960,
840
+ "y": 3584
841
+ },
842
+ "bookshelf": {
843
+ "name": "Bookshelf",
844
+ "x": 224,
845
+ "y": 3232
846
+ },
847
+ "mossy_cobblestone": {
848
+ "name": "Mossy Cobblestone",
849
+ "x": 192,
850
+ "y": 3360
851
+ },
852
+ "obsidian": {
853
+ "name": "Obsidian",
854
+ "x": 288,
855
+ "y": 3360
856
+ },
857
+ "torch": {
858
+ "name": "Torch",
859
+ "x": 928,
860
+ "y": 3360
861
+ },
862
+ "end_rod": {
863
+ "name": "End Rod",
864
+ "x": 672,
865
+ "y": 3168
866
+ },
867
+ "chorus_plant": {
868
+ "name": "Chorus Plant",
869
+ "x": 640,
870
+ "y": 3392
871
+ },
872
+ "chorus_flower": {
873
+ "name": "Chorus Flower",
874
+ "x": 608,
875
+ "y": 3392
876
+ },
877
+ "purpur_block": {
878
+ "name": "Purpur Block",
879
+ "x": 416,
880
+ "y": 896
881
+ },
882
+ "purpur_pillar": {
883
+ "name": "Purpur Pillar",
884
+ "x": 448,
885
+ "y": 896
886
+ },
887
+ "purpur_stairs": {
888
+ "name": "Purpur Stairs",
889
+ "x": 928,
890
+ "y": 3264
891
+ },
892
+ "spawner": {
893
+ "name": "Spawner",
894
+ "x": 576,
895
+ "y": 3360
896
+ },
897
+ "oak_stairs": {
898
+ "name": "Oak Stairs",
899
+ "x": 672,
900
+ "y": 3264
901
+ },
902
+ "chest": {
903
+ "name": "Chest",
904
+ "x": 704,
905
+ "y": 1216
906
+ },
907
+ "diamond_ore": {
908
+ "name": "Diamond Ore",
909
+ "x": 992,
910
+ "y": 3360
911
+ },
912
+ "diamond_block": {
913
+ "name": "Block of Diamond",
914
+ "x": 64,
915
+ "y": 3232
916
+ },
917
+ "crafting_table": {
918
+ "name": "Crafting Table",
919
+ "x": 512,
920
+ "y": 3584
921
+ },
922
+ "farmland": {
923
+ "name": "Farmland",
924
+ "x": 672,
925
+ "y": 864
926
+ },
927
+ "furnace": {
928
+ "name": "Furnace",
929
+ "x": 704,
930
+ "y": 3584
931
+ },
932
+ "ladder": {
933
+ "name": "Ladder",
934
+ "x": 224,
935
+ "y": 3264
936
+ },
937
+ "rail": {
938
+ "name": "Rail",
939
+ "x": 480,
940
+ "y": 3328
941
+ },
942
+ "cobblestone_stairs": {
943
+ "name": "Cobblestone Stairs",
944
+ "x": 448,
945
+ "y": 3232
946
+ },
947
+ "lever": {
948
+ "name": "Lever",
949
+ "x": 288,
950
+ "y": 3328
951
+ },
952
+ "stone_pressure_plate": {
953
+ "name": "Stone Pressure Plate",
954
+ "x": 768,
955
+ "y": 3328
956
+ },
957
+ "oak_pressure_plate": {
958
+ "name": "Oak Pressure Plate",
959
+ "x": 384,
960
+ "y": 3328
961
+ },
962
+ "spruce_pressure_plate": {
963
+ "name": "Spruce Pressure Plate",
964
+ "x": 672,
965
+ "y": 3328
966
+ },
967
+ "birch_pressure_plate": {
968
+ "name": "Birch Pressure Plate",
969
+ "x": 32,
970
+ "y": 3328
971
+ },
972
+ "jungle_pressure_plate": {
973
+ "name": "Jungle Pressure Plate",
974
+ "x": 256,
975
+ "y": 3328
976
+ },
977
+ "acacia_pressure_plate": {
978
+ "name": "Acacia Pressure Plate",
979
+ "x": 960,
980
+ "y": 3296
981
+ },
982
+ "dark_oak_pressure_plate": {
983
+ "name": "Dark Oak Pressure Plate",
984
+ "x": 128,
985
+ "y": 3328
986
+ },
987
+ "crimson_pressure_plate": {
988
+ "name": "Crimson Pressure Plate",
989
+ "x": 256,
990
+ "y": 160
991
+ },
992
+ "warped_pressure_plate": {
993
+ "name": "Warped Pressure Plate",
994
+ "x": 384,
995
+ "y": 160
996
+ },
997
+ "polished_blackstone_pressure_plate": {
998
+ "name": "Polished Blackstone Pressure Plate",
999
+ "x": 928,
1000
+ "y": 256
1001
+ },
1002
+ "redstone_ore": {
1003
+ "name": "Redstone Ore",
1004
+ "x": 128,
1005
+ "y": 3392
1006
+ },
1007
+ "redstone_torch": {
1008
+ "name": "Redstone Torch",
1009
+ "x": 608,
1010
+ "y": 3328
1011
+ },
1012
+ "snow": {
1013
+ "name": "Snow",
1014
+ "x": 544,
1015
+ "y": 3360
1016
+ },
1017
+ "ice": {
1018
+ "name": "Ice",
1019
+ "x": 160,
1020
+ "y": 3360
1021
+ },
1022
+ "snow_block": {
1023
+ "name": "Snow Block",
1024
+ "x": 576,
1025
+ "y": 3296
1026
+ },
1027
+ "cactus": {
1028
+ "name": "Cactus",
1029
+ "x": 544,
1030
+ "y": 3392
1031
+ },
1032
+ "clay": {
1033
+ "name": "Clay",
1034
+ "x": 928,
1035
+ "y": 3328
1036
+ },
1037
+ "jukebox": {
1038
+ "name": "Jukebox",
1039
+ "x": 768,
1040
+ "y": 3584
1041
+ },
1042
+ "oak_fence": {
1043
+ "name": "Oak Fence",
1044
+ "x": 608,
1045
+ "y": 3264
1046
+ },
1047
+ "spruce_fence": {
1048
+ "name": "Spruce Fence",
1049
+ "x": 640,
1050
+ "y": 3296
1051
+ },
1052
+ "birch_fence": {
1053
+ "name": "Birch Fence",
1054
+ "x": 928,
1055
+ "y": 3200
1056
+ },
1057
+ "jungle_fence": {
1058
+ "name": "Jungle Fence",
1059
+ "x": 96,
1060
+ "y": 3264
1061
+ },
1062
+ "acacia_fence": {
1063
+ "name": "Acacia Fence",
1064
+ "x": 672,
1065
+ "y": 3200
1066
+ },
1067
+ "dark_oak_fence": {
1068
+ "name": "Dark Oak Fence",
1069
+ "x": 608,
1070
+ "y": 3232
1071
+ },
1072
+ "crimson_fence": {
1073
+ "name": "Crimson Fence",
1074
+ "x": 0,
1075
+ "y": 160
1076
+ },
1077
+ "warped_fence": {
1078
+ "name": "Warped Fence",
1079
+ "x": 96,
1080
+ "y": 160
1081
+ },
1082
+ "pumpkin": {
1083
+ "name": "Pumpkin",
1084
+ "x": 384,
1085
+ "y": 3424
1086
+ },
1087
+ "carved_pumpkin": {
1088
+ "name": "Carved Pumpkin",
1089
+ "x": 576,
1090
+ "y": 3392
1091
+ },
1092
+ "netherrack": {
1093
+ "name": "Netherrack",
1094
+ "x": 832,
1095
+ "y": 3360
1096
+ },
1097
+ "soul_sand": {
1098
+ "name": "Soul Sand",
1099
+ "x": 864,
1100
+ "y": 3360
1101
+ },
1102
+ "soul_soil": {
1103
+ "name": "Soul Soil",
1104
+ "x": 736,
1105
+ "y": 128
1106
+ },
1107
+ "basalt": {
1108
+ "name": "Basalt",
1109
+ "x": 608,
1110
+ "y": 128
1111
+ },
1112
+ "polished_basalt": {
1113
+ "name": "Polished Basalt",
1114
+ "x": 416,
1115
+ "y": 192
1116
+ },
1117
+ "soul_torch": {
1118
+ "name": "Soul Torch",
1119
+ "x": 864,
1120
+ "y": 128
1121
+ },
1122
+ "glowstone": {
1123
+ "name": "Glowstone",
1124
+ "x": 672,
1125
+ "y": 3360
1126
+ },
1127
+ "jack_o_lantern": {
1128
+ "name": "Jack o'Lantern",
1129
+ "x": 32,
1130
+ "y": 3264
1131
+ },
1132
+ "oak_trapdoor": {
1133
+ "name": "Oak Trapdoor",
1134
+ "x": 928,
1135
+ "y": 928
1136
+ },
1137
+ "spruce_trapdoor": {
1138
+ "name": "Spruce Trapdoor",
1139
+ "x": 448,
1140
+ "y": 1632
1141
+ },
1142
+ "birch_trapdoor": {
1143
+ "name": "Birch Trapdoor",
1144
+ "x": 480,
1145
+ "y": 1632
1146
+ },
1147
+ "jungle_trapdoor": {
1148
+ "name": "Jungle Trapdoor",
1149
+ "x": 512,
1150
+ "y": 1632
1151
+ },
1152
+ "acacia_trapdoor": {
1153
+ "name": "Acacia Trapdoor",
1154
+ "x": 544,
1155
+ "y": 1632
1156
+ },
1157
+ "dark_oak_trapdoor": {
1158
+ "name": "Dark Oak Trapdoor",
1159
+ "x": 576,
1160
+ "y": 1632
1161
+ },
1162
+ "crimson_trapdoor": {
1163
+ "name": "Crimson Trapdoor",
1164
+ "x": 288,
1165
+ "y": 160
1166
+ },
1167
+ "warped_trapdoor": {
1168
+ "name": "Warped Trapdoor",
1169
+ "x": 416,
1170
+ "y": 160
1171
+ },
1172
+ "infested_stone": {
1173
+ "name": "Infested Stone",
1174
+ "x": 224,
1175
+ "y": 992
1176
+ },
1177
+ "infested_cobblestone": {
1178
+ "name": "Infested Cobblestone",
1179
+ "x": 960,
1180
+ "y": 3328
1181
+ },
1182
+ "infested_stone_bricks": {
1183
+ "name": "Infested Stone Bricks",
1184
+ "x": 608,
1185
+ "y": 3360
1186
+ },
1187
+ "infested_mossy_stone_bricks": {
1188
+ "name": "Infested Mossy Stone Bricks",
1189
+ "x": 224,
1190
+ "y": 3360
1191
+ },
1192
+ "infested_cracked_stone_bricks": {
1193
+ "name": "Infested Cracked Stone Bricks",
1194
+ "x": 0,
1195
+ "y": 3360
1196
+ },
1197
+ "infested_chiseled_stone_bricks": {
1198
+ "name": "Infested Chiseled Stone Bricks",
1199
+ "x": 896,
1200
+ "y": 3328
1201
+ },
1202
+ "stone_bricks": {
1203
+ "name": "Stone Bricks",
1204
+ "x": 608,
1205
+ "y": 3360
1206
+ },
1207
+ "mossy_stone_bricks": {
1208
+ "name": "Mossy Stone Bricks",
1209
+ "x": 224,
1210
+ "y": 3360
1211
+ },
1212
+ "cracked_stone_bricks": {
1213
+ "name": "Cracked Stone Bricks",
1214
+ "x": 0,
1215
+ "y": 3360
1216
+ },
1217
+ "chiseled_stone_bricks": {
1218
+ "name": "Chiseled Stone Bricks",
1219
+ "x": 896,
1220
+ "y": 3328
1221
+ },
1222
+ "brown_mushroom_block": {
1223
+ "name": "Brown Mushroom Block",
1224
+ "x": 480,
1225
+ "y": 3392
1226
+ },
1227
+ "red_mushroom_block": {
1228
+ "name": "Red Mushroom Block",
1229
+ "x": 416,
1230
+ "y": 3424
1231
+ },
1232
+ "mushroom_stem": {
1233
+ "name": "Mushroom Stem",
1234
+ "x": 96,
1235
+ "y": 3424
1236
+ },
1237
+ "iron_bars": {
1238
+ "name": "Iron Bars",
1239
+ "x": 0,
1240
+ "y": 3264
1241
+ },
1242
+ "chain": {
1243
+ "name": "Chain",
1244
+ "x": 32,
1245
+ "y": 288
1246
+ },
1247
+ "glass_pane": {
1248
+ "name": "Glass Pane",
1249
+ "x": 928,
1250
+ "y": 3232
1251
+ },
1252
+ "melon": {
1253
+ "name": "Melon",
1254
+ "x": 64,
1255
+ "y": 3424
1256
+ },
1257
+ "vine": {
1258
+ "name": "Vines",
1259
+ "x": 736,
1260
+ "y": 3424
1261
+ },
1262
+ "oak_fence_gate": {
1263
+ "name": "Oak Fence Gate",
1264
+ "x": 576,
1265
+ "y": 3264
1266
+ },
1267
+ "spruce_fence_gate": {
1268
+ "name": "Spruce Fence Gate",
1269
+ "x": 608,
1270
+ "y": 3296
1271
+ },
1272
+ "birch_fence_gate": {
1273
+ "name": "Birch Fence Gate",
1274
+ "x": 896,
1275
+ "y": 3200
1276
+ },
1277
+ "jungle_fence_gate": {
1278
+ "name": "Jungle Fence Gate",
1279
+ "x": 64,
1280
+ "y": 3264
1281
+ },
1282
+ "acacia_fence_gate": {
1283
+ "name": "Acacia Fence Gate",
1284
+ "x": 640,
1285
+ "y": 3200
1286
+ },
1287
+ "dark_oak_fence_gate": {
1288
+ "name": "Dark Oak Fence Gate",
1289
+ "x": 576,
1290
+ "y": 3232
1291
+ },
1292
+ "crimson_fence_gate": {
1293
+ "name": "Crimson Fence Gate",
1294
+ "x": 576,
1295
+ "y": 160
1296
+ },
1297
+ "warped_fence_gate": {
1298
+ "name": "Warped Fence Gate",
1299
+ "x": 608,
1300
+ "y": 160
1301
+ },
1302
+ "brick_stairs": {
1303
+ "name": "Brick Stairs",
1304
+ "x": 288,
1305
+ "y": 3232
1306
+ },
1307
+ "stone_brick_stairs": {
1308
+ "name": "Stone Brick Stairs",
1309
+ "x": 800,
1310
+ "y": 3296
1311
+ },
1312
+ "mycelium": {
1313
+ "name": "Mycelium",
1314
+ "x": 256,
1315
+ "y": 3360
1316
+ },
1317
+ "lily_pad": {
1318
+ "name": "Lily Pad",
1319
+ "x": 32,
1320
+ "y": 3424
1321
+ },
1322
+ "nether_bricks": {
1323
+ "name": "Nether Bricks",
1324
+ "x": 768,
1325
+ "y": 3360
1326
+ },
1327
+ "cracked_nether_bricks": {
1328
+ "name": "Cracked Nether Bricks",
1329
+ "x": 448,
1330
+ "y": 256
1331
+ },
1332
+ "chiseled_nether_bricks": {
1333
+ "name": "Chiseled Nether Bricks",
1334
+ "x": 384,
1335
+ "y": 256
1336
+ },
1337
+ "nether_brick_fence": {
1338
+ "name": "Nether Brick Fence",
1339
+ "x": 704,
1340
+ "y": 3360
1341
+ },
1342
+ "nether_brick_stairs": {
1343
+ "name": "Nether Brick Stairs",
1344
+ "x": 736,
1345
+ "y": 3360
1346
+ },
1347
+ "enchanting_table": {
1348
+ "name": "Enchanting Table",
1349
+ "x": 640,
1350
+ "y": 3584
1351
+ },
1352
+ "end_portal_frame": {
1353
+ "name": "End Portal Frame",
1354
+ "x": 640,
1355
+ "y": 3168
1356
+ },
1357
+ "end_stone": {
1358
+ "name": "End Stone",
1359
+ "x": 704,
1360
+ "y": 3168
1361
+ },
1362
+ "end_stone_bricks": {
1363
+ "name": "End Stone Bricks",
1364
+ "x": 896,
1365
+ "y": 3232
1366
+ },
1367
+ "dragon_egg": {
1368
+ "name": "Dragon Egg",
1369
+ "x": 576,
1370
+ "y": 3168
1371
+ },
1372
+ "redstone_lamp": {
1373
+ "name": "Redstone Lamp",
1374
+ "x": 544,
1375
+ "y": 3328
1376
+ },
1377
+ "sandstone_stairs": {
1378
+ "name": "Sandstone Stairs",
1379
+ "x": 224,
1380
+ "y": 3296
1381
+ },
1382
+ "emerald_ore": {
1383
+ "name": "Emerald Ore",
1384
+ "x": 0,
1385
+ "y": 3392
1386
+ },
1387
+ "ender_chest": {
1388
+ "name": "Ender Chest",
1389
+ "x": 672,
1390
+ "y": 3584
1391
+ },
1392
+ "tripwire_hook": {
1393
+ "name": "Tripwire Hook",
1394
+ "x": 800,
1395
+ "y": 3328
1396
+ },
1397
+ "emerald_block": {
1398
+ "name": "Block of Emerald",
1399
+ "x": 96,
1400
+ "y": 3232
1401
+ },
1402
+ "spruce_stairs": {
1403
+ "name": "Spruce Stairs",
1404
+ "x": 704,
1405
+ "y": 3296
1406
+ },
1407
+ "birch_stairs": {
1408
+ "name": "Birch Stairs",
1409
+ "x": 992,
1410
+ "y": 3200
1411
+ },
1412
+ "jungle_stairs": {
1413
+ "name": "Jungle Stairs",
1414
+ "x": 160,
1415
+ "y": 3264
1416
+ },
1417
+ "crimson_stairs": {
1418
+ "name": "Crimson Stairs",
1419
+ "x": 64,
1420
+ "y": 160
1421
+ },
1422
+ "warped_stairs": {
1423
+ "name": "Warped Stairs",
1424
+ "x": 160,
1425
+ "y": 160
1426
+ },
1427
+ "command_block": {
1428
+ "name": "Impulse Command Block Revision 1",
1429
+ "x": 736,
1430
+ "y": 1216
1431
+ },
1432
+ "beacon": {
1433
+ "name": "Beacon",
1434
+ "x": 352,
1435
+ "y": 3584
1436
+ },
1437
+ "cobblestone_wall": {
1438
+ "name": "Cobblestone Wall",
1439
+ "x": 480,
1440
+ "y": 3232
1441
+ },
1442
+ "mossy_cobblestone_wall": {
1443
+ "name": "Mossy Cobblestone Wall",
1444
+ "x": 352,
1445
+ "y": 3264
1446
+ },
1447
+ "brick_wall": {
1448
+ "name": "Brick Wall",
1449
+ "x": 320,
1450
+ "y": 3232
1451
+ },
1452
+ "prismarine_wall": {
1453
+ "name": "Prismarine Wall",
1454
+ "x": 0,
1455
+ "y": 96
1456
+ },
1457
+ "red_sandstone_wall": {
1458
+ "name": "Red Sandstone Wall",
1459
+ "x": 160,
1460
+ "y": 3296
1461
+ },
1462
+ "mossy_stone_brick_wall": {
1463
+ "name": "Mossy Stone Brick Wall",
1464
+ "x": 448,
1465
+ "y": 3264
1466
+ },
1467
+ "granite_wall": {
1468
+ "name": "Granite Wall",
1469
+ "x": 32,
1470
+ "y": 2400
1471
+ },
1472
+ "stone_brick_wall": {
1473
+ "name": "Stone Brick Wall",
1474
+ "x": 832,
1475
+ "y": 3296
1476
+ },
1477
+ "nether_brick_wall": {
1478
+ "name": "Nether Brick Wall",
1479
+ "x": 512,
1480
+ "y": 3264
1481
+ },
1482
+ "andesite_wall": {
1483
+ "name": "Andesite Wall",
1484
+ "x": 864,
1485
+ "y": 3200
1486
+ },
1487
+ "red_nether_brick_wall": {
1488
+ "name": "Red Nether Brick Wall",
1489
+ "x": 64,
1490
+ "y": 3296
1491
+ },
1492
+ "sandstone_wall": {
1493
+ "name": "Sandstone Wall",
1494
+ "x": 256,
1495
+ "y": 3296
1496
+ },
1497
+ "end_stone_brick_wall": {
1498
+ "name": "End Stone Brick Wall",
1499
+ "x": 0,
1500
+ "y": 2400
1501
+ },
1502
+ "diorite_wall": {
1503
+ "name": "Diorite Wall",
1504
+ "x": 864,
1505
+ "y": 3232
1506
+ },
1507
+ "blackstone_wall": {
1508
+ "name": "Blackstone Wall",
1509
+ "x": 672,
1510
+ "y": 256
1511
+ },
1512
+ "polished_blackstone_wall": {
1513
+ "name": "Polished Blackstone Wall",
1514
+ "x": 864,
1515
+ "y": 256
1516
+ },
1517
+ "polished_blackstone_brick_wall": {
1518
+ "name": "Polished Blackstone Brick Wall",
1519
+ "x": 768,
1520
+ "y": 256
1521
+ },
1522
+ "stone_button": {
1523
+ "name": "Stone Button",
1524
+ "x": 736,
1525
+ "y": 3328
1526
+ },
1527
+ "oak_button": {
1528
+ "name": "Oak Button",
1529
+ "x": 352,
1530
+ "y": 3328
1531
+ },
1532
+ "spruce_button": {
1533
+ "name": "Spruce Button",
1534
+ "x": 640,
1535
+ "y": 3328
1536
+ },
1537
+ "birch_button": {
1538
+ "name": "Birch Button",
1539
+ "x": 0,
1540
+ "y": 3328
1541
+ },
1542
+ "jungle_button": {
1543
+ "name": "Jungle Button",
1544
+ "x": 224,
1545
+ "y": 3328
1546
+ },
1547
+ "acacia_button": {
1548
+ "name": "Acacia Button",
1549
+ "x": 928,
1550
+ "y": 3296
1551
+ },
1552
+ "dark_oak_button": {
1553
+ "name": "Dark Oak Button",
1554
+ "x": 96,
1555
+ "y": 3328
1556
+ },
1557
+ "crimson_button": {
1558
+ "name": "Crimson Button",
1559
+ "x": 192,
1560
+ "y": 160
1561
+ },
1562
+ "warped_button": {
1563
+ "name": "Warped Button",
1564
+ "x": 320,
1565
+ "y": 160
1566
+ },
1567
+ "polished_blackstone_button": {
1568
+ "name": "Polished Blackstone Button",
1569
+ "x": 896,
1570
+ "y": 256
1571
+ },
1572
+ "anvil": {
1573
+ "name": "Anvil",
1574
+ "x": 288,
1575
+ "y": 3584
1576
+ },
1577
+ "chipped_anvil": {
1578
+ "name": "Chipped Anvil",
1579
+ "x": 480,
1580
+ "y": 3584
1581
+ },
1582
+ "damaged_anvil": {
1583
+ "name": "Damaged Anvil",
1584
+ "x": 544,
1585
+ "y": 3584
1586
+ },
1587
+ "trapped_chest": {
1588
+ "name": "Trapped Chest",
1589
+ "x": 992,
1590
+ "y": 3584
1591
+ },
1592
+ "light_weighted_pressure_plate": {
1593
+ "name": "Light Weighted Pressure Plate",
1594
+ "x": 320,
1595
+ "y": 3328
1596
+ },
1597
+ "heavy_weighted_pressure_plate": {
1598
+ "name": "Heavy Weighted Pressure Plate",
1599
+ "x": 192,
1600
+ "y": 3328
1601
+ },
1602
+ "daylight_detector": {
1603
+ "name": "Daylight Detector",
1604
+ "x": 800,
1605
+ "y": 1216
1606
+ },
1607
+ "redstone_block": {
1608
+ "name": "Block of Redstone",
1609
+ "x": 64,
1610
+ "y": 3328
1611
+ },
1612
+ "nether_quartz_ore": {
1613
+ "name": "Nether Quartz Ore",
1614
+ "x": 800,
1615
+ "y": 3360
1616
+ },
1617
+ "hopper": {
1618
+ "name": "Hopper",
1619
+ "x": 736,
1620
+ "y": 3584
1621
+ },
1622
+ "chiseled_quartz_block": {
1623
+ "name": "Chiseled Quartz Block",
1624
+ "x": 224,
1625
+ "y": 864
1626
+ },
1627
+ "quartz_block": {
1628
+ "name": "Block of Quartz",
1629
+ "x": 192,
1630
+ "y": 3232
1631
+ },
1632
+ "quartz_bricks": {
1633
+ "name": "Quartz Bricks",
1634
+ "x": 992,
1635
+ "y": 256
1636
+ },
1637
+ "quartz_pillar": {
1638
+ "name": "Quartz Pillar",
1639
+ "x": 288,
1640
+ "y": 896
1641
+ },
1642
+ "quartz_stairs": {
1643
+ "name": "Quartz Stairs",
1644
+ "x": 992,
1645
+ "y": 3264
1646
+ },
1647
+ "activator_rail": {
1648
+ "name": "Activator Rail",
1649
+ "x": 992,
1650
+ "y": 3296
1651
+ },
1652
+ "dropper": {
1653
+ "name": "Dropper",
1654
+ "x": 608,
1655
+ "y": 3584
1656
+ },
1657
+ "white_terracotta": {
1658
+ "name": "White Terracotta",
1659
+ "x": 672,
1660
+ "y": 768
1661
+ },
1662
+ "orange_terracotta": {
1663
+ "name": "Orange Terracotta",
1664
+ "x": 928,
1665
+ "y": 736
1666
+ },
1667
+ "magenta_terracotta": {
1668
+ "name": "Magenta Terracotta",
1669
+ "x": 736,
1670
+ "y": 736
1671
+ },
1672
+ "light_blue_terracotta": {
1673
+ "name": "Light Blue Terracotta",
1674
+ "x": 160,
1675
+ "y": 736
1676
+ },
1677
+ "yellow_terracotta": {
1678
+ "name": "Yellow Terracotta",
1679
+ "x": 864,
1680
+ "y": 768
1681
+ },
1682
+ "lime_terracotta": {
1683
+ "name": "Lime Terracotta",
1684
+ "x": 544,
1685
+ "y": 736
1686
+ },
1687
+ "pink_terracotta": {
1688
+ "name": "Pink Terracotta",
1689
+ "x": 96,
1690
+ "y": 768
1691
+ },
1692
+ "gray_terracotta": {
1693
+ "name": "Gray Terracotta",
1694
+ "x": 800,
1695
+ "y": 704
1696
+ },
1697
+ "light_gray_terracotta": {
1698
+ "name": "Light Gray Terracotta",
1699
+ "x": 352,
1700
+ "y": 736
1701
+ },
1702
+ "cyan_terracotta": {
1703
+ "name": "Cyan Terracotta",
1704
+ "x": 608,
1705
+ "y": 704
1706
+ },
1707
+ "purple_terracotta": {
1708
+ "name": "Purple Terracotta",
1709
+ "x": 288,
1710
+ "y": 768
1711
+ },
1712
+ "blue_terracotta": {
1713
+ "name": "Blue Terracotta",
1714
+ "x": 224,
1715
+ "y": 704
1716
+ },
1717
+ "brown_terracotta": {
1718
+ "name": "Brown Terracotta",
1719
+ "x": 416,
1720
+ "y": 704
1721
+ },
1722
+ "green_terracotta": {
1723
+ "name": "Green Terracotta",
1724
+ "x": 992,
1725
+ "y": 704
1726
+ },
1727
+ "red_terracotta": {
1728
+ "name": "Red Terracotta",
1729
+ "x": 480,
1730
+ "y": 768
1731
+ },
1732
+ "black_terracotta": {
1733
+ "name": "Black Terracotta",
1734
+ "x": 32,
1735
+ "y": 704
1736
+ },
1737
+ "barrier": {
1738
+ "name": "Barrier",
1739
+ "x": 320,
1740
+ "y": 3584
1741
+ },
1742
+ "iron_trapdoor": {
1743
+ "name": "Iron Trapdoor",
1744
+ "x": 416,
1745
+ "y": 928
1746
+ },
1747
+ "hay_block": {
1748
+ "name": "Hay Bale",
1749
+ "x": 992,
1750
+ "y": 3232
1751
+ },
1752
+ "white_carpet": {
1753
+ "name": "White Carpet",
1754
+ "x": 64,
1755
+ "y": 1632
1756
+ },
1757
+ "orange_carpet": {
1758
+ "name": "Orange Carpet",
1759
+ "x": 960,
1760
+ "y": 1600
1761
+ },
1762
+ "magenta_carpet": {
1763
+ "name": "Magenta Carpet",
1764
+ "x": 928,
1765
+ "y": 1600
1766
+ },
1767
+ "light_blue_carpet": {
1768
+ "name": "Light Blue Carpet",
1769
+ "x": 832,
1770
+ "y": 1600
1771
+ },
1772
+ "yellow_carpet": {
1773
+ "name": "Yellow Carpet",
1774
+ "x": 96,
1775
+ "y": 1632
1776
+ },
1777
+ "lime_carpet": {
1778
+ "name": "Lime Carpet",
1779
+ "x": 896,
1780
+ "y": 1600
1781
+ },
1782
+ "pink_carpet": {
1783
+ "name": "Pink Carpet",
1784
+ "x": 992,
1785
+ "y": 1600
1786
+ },
1787
+ "gray_carpet": {
1788
+ "name": "Gray Carpet",
1789
+ "x": 768,
1790
+ "y": 1600
1791
+ },
1792
+ "light_gray_carpet": {
1793
+ "name": "Light Gray Carpet",
1794
+ "x": 864,
1795
+ "y": 1600
1796
+ },
1797
+ "cyan_carpet": {
1798
+ "name": "Cyan Carpet",
1799
+ "x": 736,
1800
+ "y": 1600
1801
+ },
1802
+ "purple_carpet": {
1803
+ "name": "Purple Carpet",
1804
+ "x": 0,
1805
+ "y": 1632
1806
+ },
1807
+ "blue_carpet": {
1808
+ "name": "Blue Carpet",
1809
+ "x": 672,
1810
+ "y": 1600
1811
+ },
1812
+ "brown_carpet": {
1813
+ "name": "Brown Carpet",
1814
+ "x": 704,
1815
+ "y": 1600
1816
+ },
1817
+ "green_carpet": {
1818
+ "name": "Green Carpet",
1819
+ "x": 800,
1820
+ "y": 1600
1821
+ },
1822
+ "red_carpet": {
1823
+ "name": "Red Carpet",
1824
+ "x": 32,
1825
+ "y": 1632
1826
+ },
1827
+ "black_carpet": {
1828
+ "name": "Black Carpet",
1829
+ "x": 640,
1830
+ "y": 1600
1831
+ },
1832
+ "terracotta": {
1833
+ "name": "Terracotta",
1834
+ "x": 640,
1835
+ "y": 3360
1836
+ },
1837
+ "coal_block": {
1838
+ "name": "Block of Coal",
1839
+ "x": 32,
1840
+ "y": 3232
1841
+ },
1842
+ "packed_ice": {
1843
+ "name": "Packed Ice",
1844
+ "x": 320,
1845
+ "y": 3360
1846
+ },
1847
+ "acacia_stairs": {
1848
+ "name": "Acacia Stairs",
1849
+ "x": 736,
1850
+ "y": 3200
1851
+ },
1852
+ "dark_oak_stairs": {
1853
+ "name": "Dark Oak Stairs",
1854
+ "x": 672,
1855
+ "y": 3232
1856
+ },
1857
+ "slime_block": {
1858
+ "name": "Slime Block",
1859
+ "x": 736,
1860
+ "y": 896
1861
+ },
1862
+ "grass_path": {
1863
+ "name": "Grass Path",
1864
+ "x": 96,
1865
+ "y": 1344
1866
+ },
1867
+ "sunflower": {
1868
+ "name": "Sunflower",
1869
+ "x": 672,
1870
+ "y": 3424
1871
+ },
1872
+ "lilac": {
1873
+ "name": "Lilac",
1874
+ "x": 0,
1875
+ "y": 3424
1876
+ },
1877
+ "rose_bush": {
1878
+ "name": "Rose Bush",
1879
+ "x": 512,
1880
+ "y": 3424
1881
+ },
1882
+ "peony": {
1883
+ "name": "Peony",
1884
+ "x": 288,
1885
+ "y": 3424
1886
+ },
1887
+ "tall_grass": {
1888
+ "name": "Tall Grass",
1889
+ "x": 704,
1890
+ "y": 3424
1891
+ },
1892
+ "large_fern": {
1893
+ "name": "Large Fern",
1894
+ "x": 992,
1895
+ "y": 3392
1896
+ },
1897
+ "white_stained_glass": {
1898
+ "name": "White Stained Glass",
1899
+ "x": 704,
1900
+ "y": 768
1901
+ },
1902
+ "orange_stained_glass": {
1903
+ "name": "Orange Stained Glass",
1904
+ "x": 960,
1905
+ "y": 736
1906
+ },
1907
+ "magenta_stained_glass": {
1908
+ "name": "Magenta Stained Glass",
1909
+ "x": 768,
1910
+ "y": 736
1911
+ },
1912
+ "light_blue_stained_glass": {
1913
+ "name": "Light Blue Stained Glass",
1914
+ "x": 192,
1915
+ "y": 736
1916
+ },
1917
+ "yellow_stained_glass": {
1918
+ "name": "Yellow Stained Glass",
1919
+ "x": 896,
1920
+ "y": 768
1921
+ },
1922
+ "lime_stained_glass": {
1923
+ "name": "Lime Stained Glass",
1924
+ "x": 576,
1925
+ "y": 736
1926
+ },
1927
+ "pink_stained_glass": {
1928
+ "name": "Pink Stained Glass",
1929
+ "x": 128,
1930
+ "y": 768
1931
+ },
1932
+ "gray_stained_glass": {
1933
+ "name": "Gray Stained Glass",
1934
+ "x": 832,
1935
+ "y": 704
1936
+ },
1937
+ "light_gray_stained_glass": {
1938
+ "name": "Light Gray Stained Glass",
1939
+ "x": 384,
1940
+ "y": 736
1941
+ },
1942
+ "cyan_stained_glass": {
1943
+ "name": "Cyan Stained Glass",
1944
+ "x": 640,
1945
+ "y": 704
1946
+ },
1947
+ "purple_stained_glass": {
1948
+ "name": "Purple Stained Glass",
1949
+ "x": 320,
1950
+ "y": 768
1951
+ },
1952
+ "blue_stained_glass": {
1953
+ "name": "Blue Stained Glass",
1954
+ "x": 256,
1955
+ "y": 704
1956
+ },
1957
+ "brown_stained_glass": {
1958
+ "name": "Brown Stained Glass",
1959
+ "x": 448,
1960
+ "y": 704
1961
+ },
1962
+ "green_stained_glass": {
1963
+ "name": "Green Stained Glass",
1964
+ "x": 0,
1965
+ "y": 736
1966
+ },
1967
+ "red_stained_glass": {
1968
+ "name": "Red Stained Glass",
1969
+ "x": 512,
1970
+ "y": 768
1971
+ },
1972
+ "black_stained_glass": {
1973
+ "name": "Black Stained Glass",
1974
+ "x": 64,
1975
+ "y": 704
1976
+ },
1977
+ "white_stained_glass_pane": {
1978
+ "name": "White Stained Glass Pane",
1979
+ "x": 736,
1980
+ "y": 768
1981
+ },
1982
+ "orange_stained_glass_pane": {
1983
+ "name": "Orange Stained Glass Pane",
1984
+ "x": 992,
1985
+ "y": 736
1986
+ },
1987
+ "magenta_stained_glass_pane": {
1988
+ "name": "Magenta Stained Glass Pane",
1989
+ "x": 800,
1990
+ "y": 736
1991
+ },
1992
+ "light_blue_stained_glass_pane": {
1993
+ "name": "Light Blue Stained Glass Pane",
1994
+ "x": 224,
1995
+ "y": 736
1996
+ },
1997
+ "yellow_stained_glass_pane": {
1998
+ "name": "Yellow Stained Glass Pane",
1999
+ "x": 928,
2000
+ "y": 768
2001
+ },
2002
+ "lime_stained_glass_pane": {
2003
+ "name": "Lime Stained Glass Pane",
2004
+ "x": 608,
2005
+ "y": 736
2006
+ },
2007
+ "pink_stained_glass_pane": {
2008
+ "name": "Pink Stained Glass Pane",
2009
+ "x": 160,
2010
+ "y": 768
2011
+ },
2012
+ "gray_stained_glass_pane": {
2013
+ "name": "Gray Stained Glass Pane",
2014
+ "x": 864,
2015
+ "y": 704
2016
+ },
2017
+ "light_gray_stained_glass_pane": {
2018
+ "name": "Light Gray Stained Glass Pane",
2019
+ "x": 416,
2020
+ "y": 736
2021
+ },
2022
+ "cyan_stained_glass_pane": {
2023
+ "name": "Cyan Stained Glass Pane",
2024
+ "x": 672,
2025
+ "y": 704
2026
+ },
2027
+ "purple_stained_glass_pane": {
2028
+ "name": "Purple Stained Glass Pane",
2029
+ "x": 352,
2030
+ "y": 768
2031
+ },
2032
+ "blue_stained_glass_pane": {
2033
+ "name": "Blue Stained Glass Pane",
2034
+ "x": 288,
2035
+ "y": 704
2036
+ },
2037
+ "brown_stained_glass_pane": {
2038
+ "name": "Brown Stained Glass Pane",
2039
+ "x": 480,
2040
+ "y": 704
2041
+ },
2042
+ "green_stained_glass_pane": {
2043
+ "name": "Green Stained Glass Pane",
2044
+ "x": 32,
2045
+ "y": 736
2046
+ },
2047
+ "red_stained_glass_pane": {
2048
+ "name": "Red Stained Glass Pane",
2049
+ "x": 544,
2050
+ "y": 768
2051
+ },
2052
+ "black_stained_glass_pane": {
2053
+ "name": "Black Stained Glass Pane",
2054
+ "x": 96,
2055
+ "y": 704
2056
+ },
2057
+ "prismarine": {
2058
+ "name": "Prismarine Wall",
2059
+ "x": 0,
2060
+ "y": 96
2061
+ },
2062
+ "prismarine_bricks": {
2063
+ "name": "Prismarine Bricks",
2064
+ "x": 384,
2065
+ "y": 3360
2066
+ },
2067
+ "dark_prismarine": {
2068
+ "name": "Dark Prismarine",
2069
+ "x": 32,
2070
+ "y": 3360
2071
+ },
2072
+ "prismarine_stairs": {
2073
+ "name": "Dark Prismarine Stairs",
2074
+ "x": 768,
2075
+ "y": 3232
2076
+ },
2077
+ "prismarine_brick_stairs": {
2078
+ "name": "Prismarine Brick Stairs",
2079
+ "x": 448,
2080
+ "y": 96
2081
+ },
2082
+ "dark_prismarine_stairs": {
2083
+ "name": "Dark Prismarine Stairs",
2084
+ "x": 768,
2085
+ "y": 3232
2086
+ },
2087
+ "sea_lantern": {
2088
+ "name": "Sea Lantern BE",
2089
+ "x": 512,
2090
+ "y": 192
2091
+ },
2092
+ "red_sandstone": {
2093
+ "name": "Red Sandstone",
2094
+ "x": 448,
2095
+ "y": 3360
2096
+ },
2097
+ "chiseled_red_sandstone": {
2098
+ "name": "Chiseled Red Sandstone",
2099
+ "x": 352,
2100
+ "y": 3232
2101
+ },
2102
+ "cut_red_sandstone": {
2103
+ "name": "Cut Red Sandstone",
2104
+ "x": 512,
2105
+ "y": 3232
2106
+ },
2107
+ "red_sandstone_stairs": {
2108
+ "name": "Red Sandstone Stairs",
2109
+ "x": 128,
2110
+ "y": 3296
2111
+ },
2112
+ "magma_block": {
2113
+ "name": "Magma Block BE",
2114
+ "x": 928,
2115
+ "y": 480
2116
+ },
2117
+ "nether_wart_block": {
2118
+ "name": "Nether Wart Block",
2119
+ "x": 544,
2120
+ "y": 3264
2121
+ },
2122
+ "warped_wart_block": {
2123
+ "name": "Warped Wart Block",
2124
+ "x": 832,
2125
+ "y": 128
2126
+ },
2127
+ "red_nether_bricks": {
2128
+ "name": "Red Nether Bricks",
2129
+ "x": 704,
2130
+ "y": 1344
2131
+ },
2132
+ "bone_block": {
2133
+ "name": "Bone Block",
2134
+ "x": 864,
2135
+ "y": 3328
2136
+ },
2137
+ "structure_void": {
2138
+ "name": "Structure Void",
2139
+ "x": 928,
2140
+ "y": 3584
2141
+ },
2142
+ "observer": {
2143
+ "name": "Observer",
2144
+ "x": 864,
2145
+ "y": 3584
2146
+ },
2147
+ "shulker_box": {
2148
+ "name": "Shulker Box",
2149
+ "x": 448,
2150
+ "y": 1600
2151
+ },
2152
+ "white_shulker_box": {
2153
+ "name": "White Shulker Box",
2154
+ "x": 512,
2155
+ "y": 1600
2156
+ },
2157
+ "orange_shulker_box": {
2158
+ "name": "Orange Shulker Box",
2159
+ "x": 384,
2160
+ "y": 1600
2161
+ },
2162
+ "magenta_shulker_box": {
2163
+ "name": "Magenta Shulker Box",
2164
+ "x": 352,
2165
+ "y": 1600
2166
+ },
2167
+ "light_blue_shulker_box": {
2168
+ "name": "Light Blue Shulker Box",
2169
+ "x": 256,
2170
+ "y": 1600
2171
+ },
2172
+ "yellow_shulker_box": {
2173
+ "name": "Yellow Shulker Box",
2174
+ "x": 544,
2175
+ "y": 1600
2176
+ },
2177
+ "lime_shulker_box": {
2178
+ "name": "Lime Shulker Box",
2179
+ "x": 320,
2180
+ "y": 1600
2181
+ },
2182
+ "pink_shulker_box": {
2183
+ "name": "Pink Shulker Box",
2184
+ "x": 416,
2185
+ "y": 1600
2186
+ },
2187
+ "gray_shulker_box": {
2188
+ "name": "Gray Shulker Box",
2189
+ "x": 192,
2190
+ "y": 1600
2191
+ },
2192
+ "light_gray_shulker_box": {
2193
+ "name": "Light Gray Shulker Box",
2194
+ "x": 288,
2195
+ "y": 1600
2196
+ },
2197
+ "cyan_shulker_box": {
2198
+ "name": "Cyan Shulker Box",
2199
+ "x": 160,
2200
+ "y": 1600
2201
+ },
2202
+ "purple_shulker_box": {
2203
+ "name": "Purple Shulker Box",
2204
+ "x": 608,
2205
+ "y": 1408
2206
+ },
2207
+ "blue_shulker_box": {
2208
+ "name": "Blue Shulker Box",
2209
+ "x": 96,
2210
+ "y": 1600
2211
+ },
2212
+ "brown_shulker_box": {
2213
+ "name": "Brown Shulker Box",
2214
+ "x": 128,
2215
+ "y": 1600
2216
+ },
2217
+ "green_shulker_box": {
2218
+ "name": "Green Shulker Box",
2219
+ "x": 224,
2220
+ "y": 1600
2221
+ },
2222
+ "red_shulker_box": {
2223
+ "name": "Red Shulker Box",
2224
+ "x": 480,
2225
+ "y": 1600
2226
+ },
2227
+ "black_shulker_box": {
2228
+ "name": "Black Shulker Box",
2229
+ "x": 64,
2230
+ "y": 1600
2231
+ },
2232
+ "white_glazed_terracotta": {
2233
+ "name": "White Glazed Terracotta",
2234
+ "x": 192,
2235
+ "y": 1536
2236
+ },
2237
+ "orange_glazed_terracotta": {
2238
+ "name": "Orange Glazed Terracotta",
2239
+ "x": 160,
2240
+ "y": 1536
2241
+ },
2242
+ "magenta_glazed_terracotta": {
2243
+ "name": "Magenta Glazed Terracotta",
2244
+ "x": 128,
2245
+ "y": 1536
2246
+ },
2247
+ "light_blue_glazed_terracotta": {
2248
+ "name": "Light Blue Glazed Terracotta",
2249
+ "x": 704,
2250
+ "y": 1472
2251
+ },
2252
+ "yellow_glazed_terracotta": {
2253
+ "name": "Yellow Glazed Terracotta",
2254
+ "x": 544,
2255
+ "y": 1504
2256
+ },
2257
+ "lime_glazed_terracotta": {
2258
+ "name": "Lime Glazed Terracotta",
2259
+ "x": 896,
2260
+ "y": 1472
2261
+ },
2262
+ "pink_glazed_terracotta": {
2263
+ "name": "Pink Glazed Terracotta",
2264
+ "x": 160,
2265
+ "y": 1504
2266
+ },
2267
+ "gray_glazed_terracotta": {
2268
+ "name": "Gray Glazed Terracotta",
2269
+ "x": 512,
2270
+ "y": 1472
2271
+ },
2272
+ "light_gray_glazed_terracotta": {
2273
+ "name": "Light Gray Glazed Terracotta",
2274
+ "x": 800,
2275
+ "y": 1472
2276
+ },
2277
+ "cyan_glazed_terracotta": {
2278
+ "name": "Cyan Glazed Terracotta",
2279
+ "x": 96,
2280
+ "y": 1536
2281
+ },
2282
+ "purple_glazed_terracotta": {
2283
+ "name": "Purple Glazed Terracotta",
2284
+ "x": 256,
2285
+ "y": 1504
2286
+ },
2287
+ "blue_glazed_terracotta": {
2288
+ "name": "Blue Glazed Terracotta",
2289
+ "x": 224,
2290
+ "y": 1472
2291
+ },
2292
+ "brown_glazed_terracotta": {
2293
+ "name": "Brown Glazed Terracotta",
2294
+ "x": 320,
2295
+ "y": 1472
2296
+ },
2297
+ "green_glazed_terracotta": {
2298
+ "name": "Green Glazed Terracotta",
2299
+ "x": 608,
2300
+ "y": 1472
2301
+ },
2302
+ "red_glazed_terracotta": {
2303
+ "name": "Red Glazed Terracotta",
2304
+ "x": 352,
2305
+ "y": 1504
2306
+ },
2307
+ "black_glazed_terracotta": {
2308
+ "name": "Black Glazed Terracotta",
2309
+ "x": 128,
2310
+ "y": 1472
2311
+ },
2312
+ "white_concrete": {
2313
+ "name": "White Concrete",
2314
+ "x": 384,
2315
+ "y": 1504
2316
+ },
2317
+ "orange_concrete": {
2318
+ "name": "Orange Concrete",
2319
+ "x": 0,
2320
+ "y": 1504
2321
+ },
2322
+ "magenta_concrete": {
2323
+ "name": "Magenta Concrete",
2324
+ "x": 928,
2325
+ "y": 1472
2326
+ },
2327
+ "light_blue_concrete": {
2328
+ "name": "Light Blue Concrete",
2329
+ "x": 640,
2330
+ "y": 1472
2331
+ },
2332
+ "yellow_concrete": {
2333
+ "name": "Yellow Concrete",
2334
+ "x": 480,
2335
+ "y": 1504
2336
+ },
2337
+ "lime_concrete": {
2338
+ "name": "Lime Concrete",
2339
+ "x": 832,
2340
+ "y": 1472
2341
+ },
2342
+ "pink_concrete": {
2343
+ "name": "Pink Concrete",
2344
+ "x": 96,
2345
+ "y": 1504
2346
+ },
2347
+ "gray_concrete": {
2348
+ "name": "Gray Concrete",
2349
+ "x": 448,
2350
+ "y": 1472
2351
+ },
2352
+ "light_gray_concrete": {
2353
+ "name": "Light Gray Concrete",
2354
+ "x": 736,
2355
+ "y": 1472
2356
+ },
2357
+ "cyan_concrete": {
2358
+ "name": "Cyan Concrete",
2359
+ "x": 352,
2360
+ "y": 1472
2361
+ },
2362
+ "purple_concrete": {
2363
+ "name": "Purple Concrete",
2364
+ "x": 192,
2365
+ "y": 1504
2366
+ },
2367
+ "blue_concrete": {
2368
+ "name": "Blue Concrete",
2369
+ "x": 160,
2370
+ "y": 1472
2371
+ },
2372
+ "brown_concrete": {
2373
+ "name": "Brown Concrete",
2374
+ "x": 256,
2375
+ "y": 1472
2376
+ },
2377
+ "green_concrete": {
2378
+ "name": "Green Concrete",
2379
+ "x": 544,
2380
+ "y": 1472
2381
+ },
2382
+ "red_concrete": {
2383
+ "name": "Red Concrete",
2384
+ "x": 288,
2385
+ "y": 1504
2386
+ },
2387
+ "black_concrete": {
2388
+ "name": "Black Concrete",
2389
+ "x": 64,
2390
+ "y": 1472
2391
+ },
2392
+ "white_concrete_powder": {
2393
+ "name": "White Concrete Powder",
2394
+ "x": 416,
2395
+ "y": 1504
2396
+ },
2397
+ "orange_concrete_powder": {
2398
+ "name": "Orange Concrete Powder",
2399
+ "x": 32,
2400
+ "y": 1504
2401
+ },
2402
+ "magenta_concrete_powder": {
2403
+ "name": "Magenta Concrete Powder",
2404
+ "x": 960,
2405
+ "y": 1472
2406
+ },
2407
+ "light_blue_concrete_powder": {
2408
+ "name": "Light Blue Concrete Powder",
2409
+ "x": 672,
2410
+ "y": 1472
2411
+ },
2412
+ "yellow_concrete_powder": {
2413
+ "name": "Yellow Concrete Powder",
2414
+ "x": 512,
2415
+ "y": 1504
2416
+ },
2417
+ "lime_concrete_powder": {
2418
+ "name": "Lime Concrete Powder",
2419
+ "x": 864,
2420
+ "y": 1472
2421
+ },
2422
+ "pink_concrete_powder": {
2423
+ "name": "Pink Concrete Powder",
2424
+ "x": 128,
2425
+ "y": 1504
2426
+ },
2427
+ "gray_concrete_powder": {
2428
+ "name": "Gray Concrete Powder",
2429
+ "x": 480,
2430
+ "y": 1472
2431
+ },
2432
+ "light_gray_concrete_powder": {
2433
+ "name": "Light Gray Concrete Powder",
2434
+ "x": 768,
2435
+ "y": 1472
2436
+ },
2437
+ "cyan_concrete_powder": {
2438
+ "name": "Cyan Concrete Powder",
2439
+ "x": 384,
2440
+ "y": 1472
2441
+ },
2442
+ "purple_concrete_powder": {
2443
+ "name": "Purple Concrete Powder",
2444
+ "x": 224,
2445
+ "y": 1504
2446
+ },
2447
+ "blue_concrete_powder": {
2448
+ "name": "Blue Concrete Powder",
2449
+ "x": 192,
2450
+ "y": 1472
2451
+ },
2452
+ "brown_concrete_powder": {
2453
+ "name": "Brown Concrete Powder",
2454
+ "x": 288,
2455
+ "y": 1472
2456
+ },
2457
+ "green_concrete_powder": {
2458
+ "name": "Green Concrete Powder",
2459
+ "x": 576,
2460
+ "y": 1472
2461
+ },
2462
+ "red_concrete_powder": {
2463
+ "name": "Red Concrete Powder",
2464
+ "x": 320,
2465
+ "y": 1504
2466
+ },
2467
+ "black_concrete_powder": {
2468
+ "name": "Black Concrete Powder",
2469
+ "x": 96,
2470
+ "y": 1472
2471
+ },
2472
+ "turtle_egg": {
2473
+ "name": "Turtle Egg",
2474
+ "x": 608,
2475
+ "y": 1952
2476
+ },
2477
+ "dead_tube_coral_block": {
2478
+ "name": "Dead Tube Coral Block",
2479
+ "x": 640,
2480
+ "y": 1696
2481
+ },
2482
+ "dead_brain_coral_block": {
2483
+ "name": "Dead Brain Coral Block",
2484
+ "x": 672,
2485
+ "y": 1696
2486
+ },
2487
+ "dead_bubble_coral_block": {
2488
+ "name": "Dead Bubble Coral Block",
2489
+ "x": 704,
2490
+ "y": 1696
2491
+ },
2492
+ "dead_fire_coral_block": {
2493
+ "name": "Dead Fire Coral Block",
2494
+ "x": 736,
2495
+ "y": 1696
2496
+ },
2497
+ "dead_horn_coral_block": {
2498
+ "name": "Dead Horn Coral Block",
2499
+ "x": 768,
2500
+ "y": 1696
2501
+ },
2502
+ "tube_coral_block": {
2503
+ "name": "Tube Coral Block",
2504
+ "x": 288,
2505
+ "y": 1696
2506
+ },
2507
+ "brain_coral_block": {
2508
+ "name": "Brain Coral Block",
2509
+ "x": 320,
2510
+ "y": 1696
2511
+ },
2512
+ "bubble_coral_block": {
2513
+ "name": "Bubble Coral Block",
2514
+ "x": 352,
2515
+ "y": 1696
2516
+ },
2517
+ "fire_coral_block": {
2518
+ "name": "Fire Coral Block",
2519
+ "x": 384,
2520
+ "y": 1696
2521
+ },
2522
+ "horn_coral_block": {
2523
+ "name": "Horn Coral Block",
2524
+ "x": 416,
2525
+ "y": 1696
2526
+ },
2527
+ "tube_coral": {
2528
+ "name": "Tube Coral",
2529
+ "x": 448,
2530
+ "y": 1696
2531
+ },
2532
+ "brain_coral": {
2533
+ "name": "Brain Coral",
2534
+ "x": 480,
2535
+ "y": 1696
2536
+ },
2537
+ "bubble_coral": {
2538
+ "name": "Bubble Coral",
2539
+ "x": 512,
2540
+ "y": 1696
2541
+ },
2542
+ "fire_coral": {
2543
+ "name": "Fire Coral",
2544
+ "x": 544,
2545
+ "y": 1696
2546
+ },
2547
+ "horn_coral": {
2548
+ "name": "Horn Coral",
2549
+ "x": 576,
2550
+ "y": 1696
2551
+ },
2552
+ "dead_brain_coral": {
2553
+ "name": "Dead Brain Coral",
2554
+ "x": 992,
2555
+ "y": 2336
2556
+ },
2557
+ "dead_bubble_coral": {
2558
+ "name": "Dead Bubble Coral",
2559
+ "x": 0,
2560
+ "y": 2368
2561
+ },
2562
+ "dead_fire_coral": {
2563
+ "name": "Dead Fire Coral",
2564
+ "x": 32,
2565
+ "y": 2368
2566
+ },
2567
+ "dead_horn_coral": {
2568
+ "name": "Dead Horn Coral",
2569
+ "x": 64,
2570
+ "y": 2368
2571
+ },
2572
+ "dead_tube_coral": {
2573
+ "name": "Dead Tube Coral",
2574
+ "x": 960,
2575
+ "y": 2336
2576
+ },
2577
+ "tube_coral_fan": {
2578
+ "name": "Tube Coral Fan",
2579
+ "x": 704,
2580
+ "y": 2112
2581
+ },
2582
+ "brain_coral_fan": {
2583
+ "name": "Brain Coral Fan",
2584
+ "x": 608,
2585
+ "y": 2112
2586
+ },
2587
+ "bubble_coral_fan": {
2588
+ "name": "Bubble Coral Fan",
2589
+ "x": 640,
2590
+ "y": 2112
2591
+ },
2592
+ "fire_coral_fan": {
2593
+ "name": "Fire Coral Fan",
2594
+ "x": 896,
2595
+ "y": 1696
2596
+ },
2597
+ "horn_coral_fan": {
2598
+ "name": "Horn Coral Fan",
2599
+ "x": 672,
2600
+ "y": 2112
2601
+ },
2602
+ "dead_tube_coral_fan": {
2603
+ "name": "Dead Tube Coral Fan",
2604
+ "x": 160,
2605
+ "y": 2144
2606
+ },
2607
+ "dead_brain_coral_fan": {
2608
+ "name": "Dead Brain Coral Fan",
2609
+ "x": 32,
2610
+ "y": 2144
2611
+ },
2612
+ "dead_bubble_coral_fan": {
2613
+ "name": "Dead Bubble Coral Fan",
2614
+ "x": 64,
2615
+ "y": 2144
2616
+ },
2617
+ "dead_fire_coral_fan": {
2618
+ "name": "Dead Fire Coral Fan",
2619
+ "x": 96,
2620
+ "y": 2144
2621
+ },
2622
+ "dead_horn_coral_fan": {
2623
+ "name": "Dead Horn Coral Fan",
2624
+ "x": 128,
2625
+ "y": 2144
2626
+ },
2627
+ "blue_ice": {
2628
+ "name": "Blue Ice",
2629
+ "x": 192,
2630
+ "y": 1728
2631
+ },
2632
+ "conduit": {
2633
+ "name": "Conduit",
2634
+ "x": 512,
2635
+ "y": 2016
2636
+ },
2637
+ "polished_granite_stairs": {
2638
+ "name": "Polished Granite Stairs",
2639
+ "x": 960,
2640
+ "y": 2400
2641
+ },
2642
+ "smooth_red_sandstone_stairs": {
2643
+ "name": "Smooth Red Sandstone Stairs",
2644
+ "x": 384,
2645
+ "y": 3296
2646
+ },
2647
+ "mossy_stone_brick_stairs": {
2648
+ "name": "Mossy Stone Brick Stairs",
2649
+ "x": 416,
2650
+ "y": 3264
2651
+ },
2652
+ "polished_diorite_stairs": {
2653
+ "name": "Polished Diorite Stairs",
2654
+ "x": 832,
2655
+ "y": 3264
2656
+ },
2657
+ "mossy_cobblestone_stairs": {
2658
+ "name": "Mossy Cobblestone Stairs",
2659
+ "x": 320,
2660
+ "y": 3264
2661
+ },
2662
+ "end_stone_brick_stairs": {
2663
+ "name": "End Stone Brick Stairs",
2664
+ "x": 576,
2665
+ "y": 2400
2666
+ },
2667
+ "stone_stairs": {
2668
+ "name": "Stone Stairs",
2669
+ "x": 896,
2670
+ "y": 3296
2671
+ },
2672
+ "smooth_sandstone_stairs": {
2673
+ "name": "Smooth Sandstone Stairs",
2674
+ "x": 480,
2675
+ "y": 3296
2676
+ },
2677
+ "smooth_quartz_stairs": {
2678
+ "name": "Smooth Quartz Stairs",
2679
+ "x": 320,
2680
+ "y": 3296
2681
+ },
2682
+ "granite_stairs": {
2683
+ "name": "Granite Stairs",
2684
+ "x": 640,
2685
+ "y": 2400
2686
+ },
2687
+ "andesite_stairs": {
2688
+ "name": "Andesite Stairs",
2689
+ "x": 832,
2690
+ "y": 3200
2691
+ },
2692
+ "red_nether_brick_stairs": {
2693
+ "name": "Red Nether Brick Stairs",
2694
+ "x": 32,
2695
+ "y": 3296
2696
+ },
2697
+ "polished_andesite_stairs": {
2698
+ "name": "Polished Andesite Stairs",
2699
+ "x": 768,
2700
+ "y": 3264
2701
+ },
2702
+ "diorite_stairs": {
2703
+ "name": "Diorite Stairs",
2704
+ "x": 832,
2705
+ "y": 3232
2706
+ },
2707
+ "polished_granite_slab": {
2708
+ "name": "Polished Granite Slab",
2709
+ "x": 928,
2710
+ "y": 2400
2711
+ },
2712
+ "smooth_red_sandstone_slab": {
2713
+ "name": "Smooth Red Sandstone Slab",
2714
+ "x": 352,
2715
+ "y": 3296
2716
+ },
2717
+ "mossy_stone_brick_slab": {
2718
+ "name": "Mossy Stone Brick Slab",
2719
+ "x": 384,
2720
+ "y": 3264
2721
+ },
2722
+ "polished_diorite_slab": {
2723
+ "name": "Polished Diorite Slab",
2724
+ "x": 800,
2725
+ "y": 3264
2726
+ },
2727
+ "mossy_cobblestone_slab": {
2728
+ "name": "Mossy Cobblestone Slab",
2729
+ "x": 288,
2730
+ "y": 3264
2731
+ },
2732
+ "end_stone_brick_slab": {
2733
+ "name": "End Stone Brick Slab",
2734
+ "x": 544,
2735
+ "y": 2400
2736
+ },
2737
+ "smooth_sandstone_slab": {
2738
+ "name": "Smooth Sandstone Slab",
2739
+ "x": 448,
2740
+ "y": 3296
2741
+ },
2742
+ "smooth_quartz_slab": {
2743
+ "name": "Smooth Quartz Slab",
2744
+ "x": 288,
2745
+ "y": 3296
2746
+ },
2747
+ "granite_slab": {
2748
+ "name": "Granite Slab",
2749
+ "x": 608,
2750
+ "y": 2400
2751
+ },
2752
+ "andesite_slab": {
2753
+ "name": "Andesite Slab",
2754
+ "x": 800,
2755
+ "y": 3200
2756
+ },
2757
+ "red_nether_brick_slab": {
2758
+ "name": "Red Nether Brick Slab",
2759
+ "x": 0,
2760
+ "y": 3296
2761
+ },
2762
+ "polished_andesite_slab": {
2763
+ "name": "Polished Andesite Slab",
2764
+ "x": 736,
2765
+ "y": 3264
2766
+ },
2767
+ "diorite_slab": {
2768
+ "name": "Diorite Slab",
2769
+ "x": 800,
2770
+ "y": 3232
2771
+ },
2772
+ "scaffolding": {
2773
+ "name": "Scaffolding",
2774
+ "x": 416,
2775
+ "y": 2400
2776
+ },
2777
+ "iron_door": {
2778
+ "name": "Iron Door",
2779
+ "x": 384,
2780
+ "y": 928
2781
+ },
2782
+ "oak_door": {
2783
+ "name": "Oak Door",
2784
+ "x": 512,
2785
+ "y": 928
2786
+ },
2787
+ "spruce_door": {
2788
+ "name": "Spruce Door",
2789
+ "x": 800,
2790
+ "y": 928
2791
+ },
2792
+ "birch_door": {
2793
+ "name": "Birch Door",
2794
+ "x": 256,
2795
+ "y": 928
2796
+ },
2797
+ "jungle_door": {
2798
+ "name": "Jungle Door",
2799
+ "x": 448,
2800
+ "y": 928
2801
+ },
2802
+ "acacia_door": {
2803
+ "name": "Acacia Door",
2804
+ "x": 192,
2805
+ "y": 928
2806
+ },
2807
+ "dark_oak_door": {
2808
+ "name": "Dark Oak Door",
2809
+ "x": 320,
2810
+ "y": 928
2811
+ },
2812
+ "crimson_door": {
2813
+ "name": "Crimson Door",
2814
+ "x": 224,
2815
+ "y": 160
2816
+ },
2817
+ "warped_door": {
2818
+ "name": "Warped Door",
2819
+ "x": 352,
2820
+ "y": 160
2821
+ },
2822
+ "repeater": {
2823
+ "name": "Redstone Repeater",
2824
+ "x": 576,
2825
+ "y": 3328
2826
+ },
2827
+ "comparator": {
2828
+ "name": "Redstone Comparator",
2829
+ "x": 512,
2830
+ "y": 3328
2831
+ },
2832
+ "structure_block": {
2833
+ "name": "Structure Block",
2834
+ "x": 96,
2835
+ "y": 1376
2836
+ },
2837
+ "jigsaw": {
2838
+ "name": "Jigsaw Block",
2839
+ "x": 64,
2840
+ "y": 288
2841
+ },
2842
+ "turtle_helmet": {
2843
+ "name": "Turtle Shell",
2844
+ "x": 512,
2845
+ "y": 1664
2846
+ },
2847
+ "scute": {
2848
+ "name": "Scute",
2849
+ "x": 608,
2850
+ "y": 1664
2851
+ },
2852
+ "flint_and_steel": {
2853
+ "name": "Flint and Steel",
2854
+ "x": 480,
2855
+ "y": 3552
2856
+ },
2857
+ "apple": {
2858
+ "name": "Apple",
2859
+ "x": 768,
2860
+ "y": 3168
2861
+ },
2862
+ "bow": {
2863
+ "name": "Bow",
2864
+ "x": 992,
2865
+ "y": 1248
2866
+ },
2867
+ "arrow": {
2868
+ "name": "Arrow",
2869
+ "x": 576,
2870
+ "y": 1248
2871
+ },
2872
+ "coal": {
2873
+ "name": "Coal",
2874
+ "x": 576,
2875
+ "y": 3488
2876
+ },
2877
+ "charcoal": {
2878
+ "name": "Charcoal",
2879
+ "x": 512,
2880
+ "y": 3488
2881
+ },
2882
+ "diamond": {
2883
+ "name": "Diamond",
2884
+ "x": 608,
2885
+ "y": 3488
2886
+ },
2887
+ "iron_ingot": {
2888
+ "name": "Iron Ingot",
2889
+ "x": 896,
2890
+ "y": 3488
2891
+ },
2892
+ "gold_ingot": {
2893
+ "name": "Gold Ingot",
2894
+ "x": 800,
2895
+ "y": 3488
2896
+ },
2897
+ "netherite_ingot": {
2898
+ "name": "Netherite Ingot",
2899
+ "x": 192,
2900
+ "y": 128
2901
+ },
2902
+ "netherite_scrap": {
2903
+ "name": "Netherite Scrap",
2904
+ "x": 224,
2905
+ "y": 128
2906
+ },
2907
+ "wooden_sword": {
2908
+ "name": "Wooden Sword",
2909
+ "x": 800,
2910
+ "y": 3616
2911
+ },
2912
+ "wooden_shovel": {
2913
+ "name": "Wooden Shovel",
2914
+ "x": 192,
2915
+ "y": 3584
2916
+ },
2917
+ "wooden_pickaxe": {
2918
+ "name": "Wooden Pickaxe",
2919
+ "x": 160,
2920
+ "y": 3584
2921
+ },
2922
+ "wooden_axe": {
2923
+ "name": "Wooden Axe",
2924
+ "x": 96,
2925
+ "y": 3584
2926
+ },
2927
+ "wooden_hoe": {
2928
+ "name": "Wooden Hoe",
2929
+ "x": 128,
2930
+ "y": 3584
2931
+ },
2932
+ "stone_sword": {
2933
+ "name": "Stone Sword",
2934
+ "x": 736,
2935
+ "y": 3616
2936
+ },
2937
+ "stone_shovel": {
2938
+ "name": "Stone Shovel",
2939
+ "x": 64,
2940
+ "y": 3584
2941
+ },
2942
+ "stone_pickaxe": {
2943
+ "name": "Stone Pickaxe",
2944
+ "x": 32,
2945
+ "y": 3584
2946
+ },
2947
+ "stone_axe": {
2948
+ "name": "Stone Axe",
2949
+ "x": 992,
2950
+ "y": 3552
2951
+ },
2952
+ "stone_hoe": {
2953
+ "name": "Stone Hoe",
2954
+ "x": 0,
2955
+ "y": 3584
2956
+ },
2957
+ "golden_sword": {
2958
+ "name": "Golden Sword",
2959
+ "x": 608,
2960
+ "y": 3616
2961
+ },
2962
+ "golden_shovel": {
2963
+ "name": "Golden Shovel",
2964
+ "x": 640,
2965
+ "y": 3552
2966
+ },
2967
+ "golden_pickaxe": {
2968
+ "name": "Golden Pickaxe",
2969
+ "x": 608,
2970
+ "y": 3552
2971
+ },
2972
+ "golden_axe": {
2973
+ "name": "Golden Axe",
2974
+ "x": 544,
2975
+ "y": 3552
2976
+ },
2977
+ "golden_hoe": {
2978
+ "name": "Golden Hoe",
2979
+ "x": 576,
2980
+ "y": 3552
2981
+ },
2982
+ "iron_sword": {
2983
+ "name": "Iron Sword",
2984
+ "x": 640,
2985
+ "y": 3616
2986
+ },
2987
+ "iron_shovel": {
2988
+ "name": "Iron Shovel",
2989
+ "x": 768,
2990
+ "y": 3552
2991
+ },
2992
+ "iron_pickaxe": {
2993
+ "name": "Iron Pickaxe",
2994
+ "x": 736,
2995
+ "y": 3552
2996
+ },
2997
+ "iron_axe": {
2998
+ "name": "Iron Axe",
2999
+ "x": 672,
3000
+ "y": 3552
3001
+ },
3002
+ "iron_hoe": {
3003
+ "name": "Iron Hoe",
3004
+ "x": 704,
3005
+ "y": 3552
3006
+ },
3007
+ "diamond_sword": {
3008
+ "name": "Diamond Sword",
3009
+ "x": 576,
3010
+ "y": 3616
3011
+ },
3012
+ "diamond_shovel": {
3013
+ "name": "Diamond Shovel",
3014
+ "x": 288,
3015
+ "y": 3552
3016
+ },
3017
+ "diamond_pickaxe": {
3018
+ "name": "Diamond Pickaxe",
3019
+ "x": 256,
3020
+ "y": 3552
3021
+ },
3022
+ "diamond_axe": {
3023
+ "name": "Diamond Axe",
3024
+ "x": 192,
3025
+ "y": 3552
3026
+ },
3027
+ "diamond_hoe": {
3028
+ "name": "Diamond Hoe",
3029
+ "x": 224,
3030
+ "y": 3552
3031
+ },
3032
+ "netherite_sword": {
3033
+ "name": "Netherite Sword",
3034
+ "x": 384,
3035
+ "y": 128
3036
+ },
3037
+ "netherite_shovel": {
3038
+ "name": "Netherite Shovel",
3039
+ "x": 352,
3040
+ "y": 128
3041
+ },
3042
+ "netherite_pickaxe": {
3043
+ "name": "Netherite Pickaxe",
3044
+ "x": 320,
3045
+ "y": 128
3046
+ },
3047
+ "netherite_axe": {
3048
+ "name": "Netherite Axe",
3049
+ "x": 256,
3050
+ "y": 128
3051
+ },
3052
+ "netherite_hoe": {
3053
+ "name": "Netherite Hoe",
3054
+ "x": 288,
3055
+ "y": 128
3056
+ },
3057
+ "stick": {
3058
+ "name": "Stick",
3059
+ "x": 608,
3060
+ "y": 1120
3061
+ },
3062
+ "bowl": {
3063
+ "name": "Bowl",
3064
+ "x": 384,
3065
+ "y": 3520
3066
+ },
3067
+ "mushroom_stew": {
3068
+ "name": "Mushroom Stew",
3069
+ "x": 224,
3070
+ "y": 3200
3071
+ },
3072
+ "string": {
3073
+ "name": "String",
3074
+ "x": 320,
3075
+ "y": 3520
3076
+ },
3077
+ "feather": {
3078
+ "name": "Feather",
3079
+ "x": 704,
3080
+ "y": 3488
3081
+ },
3082
+ "gunpowder": {
3083
+ "name": "Gunpowder",
3084
+ "x": 864,
3085
+ "y": 3488
3086
+ },
3087
+ "wheat_seeds": {
3088
+ "name": "Wheat Seeds",
3089
+ "x": 320,
3090
+ "y": 1056
3091
+ },
3092
+ "wheat": {
3093
+ "name": "Wheat",
3094
+ "x": 608,
3095
+ "y": 3200
3096
+ },
3097
+ "bread": {
3098
+ "name": "Bread",
3099
+ "x": 896,
3100
+ "y": 3168
3101
+ },
3102
+ "leather_helmet": {
3103
+ "name": "Leather Cap",
3104
+ "x": 608,
3105
+ "y": 2496
3106
+ },
3107
+ "leather_chestplate": {
3108
+ "name": "Leather Tunic",
3109
+ "x": 672,
3110
+ "y": 2496
3111
+ },
3112
+ "leather_leggings": {
3113
+ "name": "Leather Pants",
3114
+ "x": 640,
3115
+ "y": 2496
3116
+ },
3117
+ "leather_boots": {
3118
+ "name": "Leather Boots",
3119
+ "x": 576,
3120
+ "y": 2496
3121
+ },
3122
+ "chainmail_helmet": {
3123
+ "name": "Chainmail Helmet",
3124
+ "x": 320,
3125
+ "y": 2464
3126
+ },
3127
+ "chainmail_chestplate": {
3128
+ "name": "Chainmail Chestplate",
3129
+ "x": 288,
3130
+ "y": 2464
3131
+ },
3132
+ "chainmail_leggings": {
3133
+ "name": "Chainmail Leggings",
3134
+ "x": 352,
3135
+ "y": 2464
3136
+ },
3137
+ "chainmail_boots": {
3138
+ "name": "Chainmail Boots",
3139
+ "x": 256,
3140
+ "y": 2464
3141
+ },
3142
+ "iron_helmet": {
3143
+ "name": "Iron Helmet",
3144
+ "x": 512,
3145
+ "y": 2496
3146
+ },
3147
+ "iron_chestplate": {
3148
+ "name": "Iron Chestplate",
3149
+ "x": 480,
3150
+ "y": 2496
3151
+ },
3152
+ "iron_leggings": {
3153
+ "name": "Iron Leggings",
3154
+ "x": 544,
3155
+ "y": 2496
3156
+ },
3157
+ "iron_boots": {
3158
+ "name": "Iron Boots",
3159
+ "x": 448,
3160
+ "y": 2496
3161
+ },
3162
+ "diamond_helmet": {
3163
+ "name": "Diamond Helmet",
3164
+ "x": 160,
3165
+ "y": 2496
3166
+ },
3167
+ "diamond_chestplate": {
3168
+ "name": "Diamond Chestplate",
3169
+ "x": 128,
3170
+ "y": 2496
3171
+ },
3172
+ "diamond_leggings": {
3173
+ "name": "Diamond Leggings",
3174
+ "x": 192,
3175
+ "y": 2496
3176
+ },
3177
+ "diamond_boots": {
3178
+ "name": "Diamond Boots",
3179
+ "x": 96,
3180
+ "y": 2496
3181
+ },
3182
+ "golden_helmet": {
3183
+ "name": "Golden Helmet",
3184
+ "x": 320,
3185
+ "y": 2496
3186
+ },
3187
+ "golden_chestplate": {
3188
+ "name": "Golden Chestplate",
3189
+ "x": 288,
3190
+ "y": 2496
3191
+ },
3192
+ "golden_leggings": {
3193
+ "name": "Golden Leggings",
3194
+ "x": 352,
3195
+ "y": 2496
3196
+ },
3197
+ "golden_boots": {
3198
+ "name": "Golden Boots",
3199
+ "x": 256,
3200
+ "y": 2496
3201
+ },
3202
+ "netherite_helmet": {
3203
+ "name": "Netherite Helmet",
3204
+ "x": 480,
3205
+ "y": 128
3206
+ },
3207
+ "netherite_chestplate": {
3208
+ "name": "Netherite Chestplate",
3209
+ "x": 448,
3210
+ "y": 128
3211
+ },
3212
+ "netherite_leggings": {
3213
+ "name": "Netherite Leggings",
3214
+ "x": 512,
3215
+ "y": 128
3216
+ },
3217
+ "netherite_boots": {
3218
+ "name": "Netherite Boots",
3219
+ "x": 416,
3220
+ "y": 128
3221
+ },
3222
+ "flint": {
3223
+ "name": "Flint",
3224
+ "x": 736,
3225
+ "y": 3488
3226
+ },
3227
+ "porkchop": {
3228
+ "name": "Raw Porkchop",
3229
+ "x": 480,
3230
+ "y": 3200
3231
+ },
3232
+ "cooked_porkchop": {
3233
+ "name": "Cooked Porkchop",
3234
+ "x": 32,
3235
+ "y": 3200
3236
+ },
3237
+ "painting": {
3238
+ "name": "Painting",
3239
+ "x": 544,
3240
+ "y": 3136
3241
+ },
3242
+ "golden_apple": {
3243
+ "name": "Golden Apple",
3244
+ "x": 160,
3245
+ "y": 3200
3246
+ },
3247
+ "enchanted_golden_apple": {
3248
+ "name": "Enchanted Golden Apple",
3249
+ "x": 128,
3250
+ "y": 256
3251
+ },
3252
+ "oak_sign": {
3253
+ "name": "Oak Sign",
3254
+ "x": 896,
3255
+ "y": 3360
3256
+ },
3257
+ "spruce_sign": {
3258
+ "name": "Spruce Sign",
3259
+ "x": 800,
3260
+ "y": 2368
3261
+ },
3262
+ "birch_sign": {
3263
+ "name": "Birch Sign",
3264
+ "x": 768,
3265
+ "y": 2368
3266
+ },
3267
+ "jungle_sign": {
3268
+ "name": "Jungle Sign",
3269
+ "x": 832,
3270
+ "y": 2368
3271
+ },
3272
+ "acacia_sign": {
3273
+ "name": "Acacia Sign",
3274
+ "x": 864,
3275
+ "y": 2368
3276
+ },
3277
+ "dark_oak_sign": {
3278
+ "name": "Dark Oak Sign",
3279
+ "x": 896,
3280
+ "y": 2368
3281
+ },
3282
+ "crimson_sign": {
3283
+ "name": "Crimson Sign",
3284
+ "x": 512,
3285
+ "y": 160
3286
+ },
3287
+ "warped_sign": {
3288
+ "name": "Warped Sign",
3289
+ "x": 544,
3290
+ "y": 160
3291
+ },
3292
+ "bucket": {
3293
+ "name": "Bucket",
3294
+ "x": 288,
3295
+ "y": 3136
3296
+ },
3297
+ "water_bucket": {
3298
+ "name": "Water Bucket",
3299
+ "x": 384,
3300
+ "y": 3136
3301
+ },
3302
+ "lava_bucket": {
3303
+ "name": "Lava Bucket",
3304
+ "x": 320,
3305
+ "y": 3136
3306
+ },
3307
+ "minecart": {
3308
+ "name": "Minecart",
3309
+ "x": 160,
3310
+ "y": 3616
3311
+ },
3312
+ "saddle": {
3313
+ "name": "Saddle",
3314
+ "x": 928,
3315
+ "y": 3552
3316
+ },
3317
+ "redstone": {
3318
+ "name": "Redstone Dust",
3319
+ "x": 224,
3320
+ "y": 3520
3321
+ },
3322
+ "snowball": {
3323
+ "name": "Snowball",
3324
+ "x": 672,
3325
+ "y": 3616
3326
+ },
3327
+ "oak_boat": {
3328
+ "name": "Oak Boat",
3329
+ "x": 352,
3330
+ "y": 3616
3331
+ },
3332
+ "leather": {
3333
+ "name": "Leather",
3334
+ "x": 960,
3335
+ "y": 3488
3336
+ },
3337
+ "milk_bucket": {
3338
+ "name": "Milk Bucket",
3339
+ "x": 352,
3340
+ "y": 3136
3341
+ },
3342
+ "pufferfish_bucket": {
3343
+ "name": "Bucket of Pufferfish",
3344
+ "x": 704,
3345
+ "y": 1664
3346
+ },
3347
+ "salmon_bucket": {
3348
+ "name": "Bucket of Salmon",
3349
+ "x": 736,
3350
+ "y": 1664
3351
+ },
3352
+ "cod_bucket": {
3353
+ "name": "Bucket of Cod",
3354
+ "x": 672,
3355
+ "y": 1664
3356
+ },
3357
+ "tropical_fish_bucket": {
3358
+ "name": "Bucket of Tropical Fish",
3359
+ "x": 352,
3360
+ "y": 2016
3361
+ },
3362
+ "brick": {
3363
+ "name": "Brick",
3364
+ "x": 480,
3365
+ "y": 3488
3366
+ },
3367
+ "clay_ball": {
3368
+ "name": "Clay Ball",
3369
+ "x": 544,
3370
+ "y": 3488
3371
+ },
3372
+ "dried_kelp_block": {
3373
+ "name": "Dried Kelp Block",
3374
+ "x": 128,
3375
+ "y": 1664
3376
+ },
3377
+ "paper": {
3378
+ "name": "Paper",
3379
+ "x": 64,
3380
+ "y": 3520
3381
+ },
3382
+ "book": {
3383
+ "name": "Book",
3384
+ "x": 448,
3385
+ "y": 3488
3386
+ },
3387
+ "slime_ball": {
3388
+ "name": "Slimeball",
3389
+ "x": 288,
3390
+ "y": 3520
3391
+ },
3392
+ "chest_minecart": {
3393
+ "name": "Minecart with Chest",
3394
+ "x": 192,
3395
+ "y": 3616
3396
+ },
3397
+ "furnace_minecart": {
3398
+ "name": "Minecart with Furnace",
3399
+ "x": 256,
3400
+ "y": 3616
3401
+ },
3402
+ "egg": {
3403
+ "name": "Egg",
3404
+ "x": 128,
3405
+ "y": 3200
3406
+ },
3407
+ "compass": {
3408
+ "name": "Compass",
3409
+ "x": 992,
3410
+ "y": 480
3411
+ },
3412
+ "fishing_rod": {
3413
+ "name": "Fishing Rod",
3414
+ "x": 448,
3415
+ "y": 3552
3416
+ },
3417
+ "clock": {
3418
+ "name": "Clock",
3419
+ "x": 960,
3420
+ "y": 480
3421
+ },
3422
+ "glowstone_dust": {
3423
+ "name": "Glowstone Dust",
3424
+ "x": 768,
3425
+ "y": 3488
3426
+ },
3427
+ "cod": {
3428
+ "name": "Raw Cod",
3429
+ "x": 896,
3430
+ "y": 1664
3431
+ },
3432
+ "salmon": {
3433
+ "name": "Raw Salmon",
3434
+ "x": 928,
3435
+ "y": 1664
3436
+ },
3437
+ "tropical_fish": {
3438
+ "name": "Tropical Fish",
3439
+ "x": 768,
3440
+ "y": 1664
3441
+ },
3442
+ "pufferfish": {
3443
+ "name": "Pufferfish",
3444
+ "x": 864,
3445
+ "y": 1664
3446
+ },
3447
+ "cooked_cod": {
3448
+ "name": "Cooked Cod",
3449
+ "x": 800,
3450
+ "y": 1664
3451
+ },
3452
+ "cooked_salmon": {
3453
+ "name": "Cooked Salmon",
3454
+ "x": 832,
3455
+ "y": 1664
3456
+ },
3457
+ "ink_sac": {
3458
+ "name": "Ink Sac",
3459
+ "x": 736,
3460
+ "y": 3136
3461
+ },
3462
+ "cocoa_beans": {
3463
+ "name": "Cocoa Beans",
3464
+ "x": 608,
3465
+ "y": 3136
3466
+ },
3467
+ "lapis_lazuli": {
3468
+ "name": "Lapis Lazuli",
3469
+ "x": 768,
3470
+ "y": 3136
3471
+ },
3472
+ "white_dye": {
3473
+ "name": "White Dye",
3474
+ "x": 288,
3475
+ "y": 2368
3476
+ },
3477
+ "orange_dye": {
3478
+ "name": "Orange Dye",
3479
+ "x": 928,
3480
+ "y": 3136
3481
+ },
3482
+ "magenta_dye": {
3483
+ "name": "Magenta Dye",
3484
+ "x": 896,
3485
+ "y": 3136
3486
+ },
3487
+ "light_blue_dye": {
3488
+ "name": "Light Blue Dye",
3489
+ "x": 800,
3490
+ "y": 3136
3491
+ },
3492
+ "yellow_dye": {
3493
+ "name": "Yellow Dye",
3494
+ "x": 32,
3495
+ "y": 3168
3496
+ },
3497
+ "lime_dye": {
3498
+ "name": "Lime Dye",
3499
+ "x": 864,
3500
+ "y": 3136
3501
+ },
3502
+ "pink_dye": {
3503
+ "name": "Pink Dye",
3504
+ "x": 960,
3505
+ "y": 3136
3506
+ },
3507
+ "gray_dye": {
3508
+ "name": "Gray Dye",
3509
+ "x": 672,
3510
+ "y": 3136
3511
+ },
3512
+ "light_gray_dye": {
3513
+ "name": "Light Gray Dye",
3514
+ "x": 832,
3515
+ "y": 3136
3516
+ },
3517
+ "cyan_dye": {
3518
+ "name": "Cyan Dye",
3519
+ "x": 640,
3520
+ "y": 3136
3521
+ },
3522
+ "purple_dye": {
3523
+ "name": "Purple Dye",
3524
+ "x": 992,
3525
+ "y": 3136
3526
+ },
3527
+ "blue_dye": {
3528
+ "name": "Blue Dye",
3529
+ "x": 224,
3530
+ "y": 2368
3531
+ },
3532
+ "brown_dye": {
3533
+ "name": "Brown Dye",
3534
+ "x": 256,
3535
+ "y": 2368
3536
+ },
3537
+ "green_dye": {
3538
+ "name": "Green Dye",
3539
+ "x": 704,
3540
+ "y": 3136
3541
+ },
3542
+ "red_dye": {
3543
+ "name": "Red Dye",
3544
+ "x": 0,
3545
+ "y": 3168
3546
+ },
3547
+ "black_dye": {
3548
+ "name": "Black Dye",
3549
+ "x": 192,
3550
+ "y": 2368
3551
+ },
3552
+ "bone_meal": {
3553
+ "name": "Bone Meal",
3554
+ "x": 576,
3555
+ "y": 3136
3556
+ },
3557
+ "bone": {
3558
+ "name": "Bone",
3559
+ "x": 416,
3560
+ "y": 3488
3561
+ },
3562
+ "sugar": {
3563
+ "name": "Sugar",
3564
+ "x": 576,
3565
+ "y": 3200
3566
+ },
3567
+ "cake": {
3568
+ "name": "Cake",
3569
+ "x": 416,
3570
+ "y": 3584
3571
+ },
3572
+ "white_bed": {
3573
+ "name": "White Bed",
3574
+ "x": 512,
3575
+ "y": 3168
3576
+ },
3577
+ "orange_bed": {
3578
+ "name": "Orange Bed",
3579
+ "x": 384,
3580
+ "y": 3168
3581
+ },
3582
+ "magenta_bed": {
3583
+ "name": "Magenta Bed",
3584
+ "x": 352,
3585
+ "y": 3168
3586
+ },
3587
+ "light_blue_bed": {
3588
+ "name": "Light Blue Bed",
3589
+ "x": 256,
3590
+ "y": 3168
3591
+ },
3592
+ "yellow_bed": {
3593
+ "name": "Yellow Bed",
3594
+ "x": 544,
3595
+ "y": 3168
3596
+ },
3597
+ "lime_bed": {
3598
+ "name": "Lime Bed",
3599
+ "x": 320,
3600
+ "y": 3168
3601
+ },
3602
+ "pink_bed": {
3603
+ "name": "Pink Bed",
3604
+ "x": 416,
3605
+ "y": 3168
3606
+ },
3607
+ "gray_bed": {
3608
+ "name": "Gray Bed",
3609
+ "x": 192,
3610
+ "y": 3168
3611
+ },
3612
+ "light_gray_bed": {
3613
+ "name": "Light Gray Bed",
3614
+ "x": 288,
3615
+ "y": 3168
3616
+ },
3617
+ "cyan_bed": {
3618
+ "name": "Cyan Bed",
3619
+ "x": 160,
3620
+ "y": 3168
3621
+ },
3622
+ "purple_bed": {
3623
+ "name": "Purple Bed",
3624
+ "x": 448,
3625
+ "y": 3168
3626
+ },
3627
+ "blue_bed": {
3628
+ "name": "Blue Bed",
3629
+ "x": 96,
3630
+ "y": 3168
3631
+ },
3632
+ "brown_bed": {
3633
+ "name": "Brown Bed",
3634
+ "x": 128,
3635
+ "y": 3168
3636
+ },
3637
+ "green_bed": {
3638
+ "name": "Green Bed",
3639
+ "x": 224,
3640
+ "y": 3168
3641
+ },
3642
+ "red_bed": {
3643
+ "name": "Red Bed",
3644
+ "x": 480,
3645
+ "y": 3168
3646
+ },
3647
+ "black_bed": {
3648
+ "name": "Black Bed",
3649
+ "x": 64,
3650
+ "y": 3168
3651
+ },
3652
+ "cookie": {
3653
+ "name": "Cookie",
3654
+ "x": 96,
3655
+ "y": 3200
3656
+ },
3657
+ "filled_map": {
3658
+ "name": "Map",
3659
+ "x": 832,
3660
+ "y": 3552
3661
+ },
3662
+ "shears": {
3663
+ "name": "Shears",
3664
+ "x": 960,
3665
+ "y": 3552
3666
+ },
3667
+ "melon_slice": {
3668
+ "name": "Melon Slice",
3669
+ "x": 192,
3670
+ "y": 3200
3671
+ },
3672
+ "dried_kelp": {
3673
+ "name": "Dried Kelp",
3674
+ "x": 544,
3675
+ "y": 1664
3676
+ },
3677
+ "pumpkin_seeds": {
3678
+ "name": "Pumpkin Seeds",
3679
+ "x": 128,
3680
+ "y": 1056
3681
+ },
3682
+ "melon_seeds": {
3683
+ "name": "Melon Seeds",
3684
+ "x": 800,
3685
+ "y": 1024
3686
+ },
3687
+ "beef": {
3688
+ "name": "Raw Beef",
3689
+ "x": 384,
3690
+ "y": 3200
3691
+ },
3692
+ "cooked_beef": {
3693
+ "name": "Steak",
3694
+ "x": 480,
3695
+ "y": 832
3696
+ },
3697
+ "chicken": {
3698
+ "name": "Raw Chicken",
3699
+ "x": 416,
3700
+ "y": 3200
3701
+ },
3702
+ "cooked_chicken": {
3703
+ "name": "Cooked Chicken",
3704
+ "x": 992,
3705
+ "y": 3168
3706
+ },
3707
+ "rotten_flesh": {
3708
+ "name": "Rotten Flesh",
3709
+ "x": 544,
3710
+ "y": 3200
3711
+ },
3712
+ "ender_pearl": {
3713
+ "name": "Ender Pearl",
3714
+ "x": 672,
3715
+ "y": 3488
3716
+ },
3717
+ "blaze_rod": {
3718
+ "name": "Blaze Rod",
3719
+ "x": 448,
3720
+ "y": 640
3721
+ },
3722
+ "ghast_tear": {
3723
+ "name": "Ghast Tear",
3724
+ "x": 96,
3725
+ "y": 3136
3726
+ },
3727
+ "gold_nugget": {
3728
+ "name": "Gold Nugget",
3729
+ "x": 832,
3730
+ "y": 3488
3731
+ },
3732
+ "nether_wart": {
3733
+ "name": "Nether Wart",
3734
+ "x": 704,
3735
+ "y": 640
3736
+ },
3737
+ "potion": {
3738
+ "name": "Potion of Luck",
3739
+ "x": 960,
3740
+ "y": 3424
3741
+ },
3742
+ "glass_bottle": {
3743
+ "name": "Glass Bottle",
3744
+ "x": 512,
3745
+ "y": 3552
3746
+ },
3747
+ "spider_eye": {
3748
+ "name": "Spider Eye",
3749
+ "x": 256,
3750
+ "y": 3136
3751
+ },
3752
+ "fermented_spider_eye": {
3753
+ "name": "Fermented Spider Eye",
3754
+ "x": 64,
3755
+ "y": 3136
3756
+ },
3757
+ "blaze_powder": {
3758
+ "name": "Blaze Powder",
3759
+ "x": 416,
3760
+ "y": 640
3761
+ },
3762
+ "magma_cream": {
3763
+ "name": "Magma Cream",
3764
+ "x": 192,
3765
+ "y": 3136
3766
+ },
3767
+ "brewing_stand": {
3768
+ "name": "Brewing Stand",
3769
+ "x": 384,
3770
+ "y": 3584
3771
+ },
3772
+ "cauldron": {
3773
+ "name": "Cauldron",
3774
+ "x": 448,
3775
+ "y": 3584
3776
+ },
3777
+ "ender_eye": {
3778
+ "name": "Eye of Ender",
3779
+ "x": 384,
3780
+ "y": 3552
3781
+ },
3782
+ "glistering_melon_slice": {
3783
+ "name": "Glistering Melon Slice",
3784
+ "x": 128,
3785
+ "y": 3136
3786
+ },
3787
+ "bat_spawn_egg": {
3788
+ "name": "Bat Spawn Egg",
3789
+ "x": 672,
3790
+ "y": 1120
3791
+ },
3792
+ "bee_spawn_egg": {
3793
+ "name": "Bee Spawn Egg",
3794
+ "x": 224,
3795
+ "y": 96
3796
+ },
3797
+ "blaze_spawn_egg": {
3798
+ "name": "Blaze Spawn Egg",
3799
+ "x": 704,
3800
+ "y": 1120
3801
+ },
3802
+ "cat_spawn_egg": {
3803
+ "name": "Cat Spawn Egg",
3804
+ "x": 288,
3805
+ "y": 2400
3806
+ },
3807
+ "cave_spider_spawn_egg": {
3808
+ "name": "Cave Spider Spawn Egg",
3809
+ "x": 736,
3810
+ "y": 1120
3811
+ },
3812
+ "chicken_spawn_egg": {
3813
+ "name": "Chicken Spawn Egg",
3814
+ "x": 768,
3815
+ "y": 1120
3816
+ },
3817
+ "cod_spawn_egg": {
3818
+ "name": "Cod Spawn Egg",
3819
+ "x": 0,
3820
+ "y": 1696
3821
+ },
3822
+ "cow_spawn_egg": {
3823
+ "name": "Cow Spawn Egg",
3824
+ "x": 800,
3825
+ "y": 1120
3826
+ },
3827
+ "creeper_spawn_egg": {
3828
+ "name": "Creeper Spawn Egg",
3829
+ "x": 832,
3830
+ "y": 1120
3831
+ },
3832
+ "dolphin_spawn_egg": {
3833
+ "name": "Dolphin Spawn Egg",
3834
+ "x": 448,
3835
+ "y": 1952
3836
+ },
3837
+ "donkey_spawn_egg": {
3838
+ "name": "Donkey Spawn Egg",
3839
+ "x": 832,
3840
+ "y": 1344
3841
+ },
3842
+ "drowned_spawn_egg": {
3843
+ "name": "Drowned Spawn Egg",
3844
+ "x": 960,
3845
+ "y": 1696
3846
+ },
3847
+ "elder_guardian_spawn_egg": {
3848
+ "name": "Elder Guardian Spawn Egg",
3849
+ "x": 864,
3850
+ "y": 1344
3851
+ },
3852
+ "enderman_spawn_egg": {
3853
+ "name": "Enderman Spawn Egg",
3854
+ "x": 864,
3855
+ "y": 1120
3856
+ },
3857
+ "endermite_spawn_egg": {
3858
+ "name": "Endermite Spawn Egg",
3859
+ "x": 896,
3860
+ "y": 1120
3861
+ },
3862
+ "evoker_spawn_egg": {
3863
+ "name": "Evoker Spawn Egg",
3864
+ "x": 64,
3865
+ "y": 1408
3866
+ },
3867
+ "fox_spawn_egg": {
3868
+ "name": "Fox Spawn Egg",
3869
+ "x": 992,
3870
+ "y": 2432
3871
+ },
3872
+ "ghast_spawn_egg": {
3873
+ "name": "Ghast Spawn Egg",
3874
+ "x": 928,
3875
+ "y": 1120
3876
+ },
3877
+ "guardian_spawn_egg": {
3878
+ "name": "Guardian Spawn Egg",
3879
+ "x": 960,
3880
+ "y": 1120
3881
+ },
3882
+ "hoglin_spawn_egg": {
3883
+ "name": "Hoglin Spawn Egg",
3884
+ "x": 32,
3885
+ "y": 192
3886
+ },
3887
+ "horse_spawn_egg": {
3888
+ "name": "Horse Spawn Egg",
3889
+ "x": 992,
3890
+ "y": 1120
3891
+ },
3892
+ "husk_spawn_egg": {
3893
+ "name": "Husk Spawn Egg",
3894
+ "x": 896,
3895
+ "y": 1344
3896
+ },
3897
+ "llama_spawn_egg": {
3898
+ "name": "Llama Spawn Egg",
3899
+ "x": 96,
3900
+ "y": 1408
3901
+ },
3902
+ "magma_cube_spawn_egg": {
3903
+ "name": "Magma Cube Spawn Egg",
3904
+ "x": 0,
3905
+ "y": 1152
3906
+ },
3907
+ "mooshroom_spawn_egg": {
3908
+ "name": "Mooshroom Spawn Egg",
3909
+ "x": 32,
3910
+ "y": 1152
3911
+ },
3912
+ "mule_spawn_egg": {
3913
+ "name": "Mule Spawn Egg",
3914
+ "x": 928,
3915
+ "y": 1344
3916
+ },
3917
+ "ocelot_spawn_egg": {
3918
+ "name": "Ocelot Spawn Egg",
3919
+ "x": 64,
3920
+ "y": 1152
3921
+ },
3922
+ "panda_spawn_egg": {
3923
+ "name": "Panda Spawn Egg",
3924
+ "x": 352,
3925
+ "y": 2400
3926
+ },
3927
+ "parrot_spawn_egg": {
3928
+ "name": "Parrot Spawn Egg",
3929
+ "x": 224,
3930
+ "y": 1536
3931
+ },
3932
+ "phantom_spawn_egg": {
3933
+ "name": "Phantom Spawn Egg",
3934
+ "x": 672,
3935
+ "y": 1952
3936
+ },
3937
+ "pig_spawn_egg": {
3938
+ "name": "Pig Spawn Egg",
3939
+ "x": 96,
3940
+ "y": 1152
3941
+ },
3942
+ "piglin_spawn_egg": {
3943
+ "name": "Piglin Spawn Egg",
3944
+ "x": 0,
3945
+ "y": 192
3946
+ },
3947
+ "piglin_brute_spawn_egg": {
3948
+ "name": "Piglin Brute Spawn Egg",
3949
+ "x": 160,
3950
+ "y": 256
3951
+ },
3952
+ "pillager_spawn_egg": {
3953
+ "name": "Pillager Spawn Egg",
3954
+ "x": 384,
3955
+ "y": 2400
3956
+ },
3957
+ "polar_bear_spawn_egg": {
3958
+ "name": "Polar Bear Spawn Egg",
3959
+ "x": 960,
3960
+ "y": 1344
3961
+ },
3962
+ "pufferfish_spawn_egg": {
3963
+ "name": "Pufferfish Spawn Egg",
3964
+ "x": 32,
3965
+ "y": 1696
3966
+ },
3967
+ "rabbit_spawn_egg": {
3968
+ "name": "Rabbit Spawn Egg",
3969
+ "x": 128,
3970
+ "y": 1152
3971
+ },
3972
+ "ravager_spawn_egg": {
3973
+ "name": "Ravager Spawn Egg",
3974
+ "x": 320,
3975
+ "y": 2400
3976
+ },
3977
+ "salmon_spawn_egg": {
3978
+ "name": "Salmon Spawn Egg",
3979
+ "x": 64,
3980
+ "y": 1696
3981
+ },
3982
+ "sheep_spawn_egg": {
3983
+ "name": "Sheep Spawn Egg",
3984
+ "x": 160,
3985
+ "y": 1152
3986
+ },
3987
+ "shulker_spawn_egg": {
3988
+ "name": "Shulker Spawn Egg",
3989
+ "x": 192,
3990
+ "y": 1152
3991
+ },
3992
+ "silverfish_spawn_egg": {
3993
+ "name": "Silverfish Spawn Egg",
3994
+ "x": 224,
3995
+ "y": 1152
3996
+ },
3997
+ "skeleton_spawn_egg": {
3998
+ "name": "Skeleton Spawn Egg",
3999
+ "x": 256,
4000
+ "y": 1152
4001
+ },
4002
+ "skeleton_horse_spawn_egg": {
4003
+ "name": "Skeleton Horse Spawn Egg",
4004
+ "x": 992,
4005
+ "y": 1344
4006
+ },
4007
+ "slime_spawn_egg": {
4008
+ "name": "Slime Spawn Egg",
4009
+ "x": 288,
4010
+ "y": 1152
4011
+ },
4012
+ "spider_spawn_egg": {
4013
+ "name": "Spider Spawn Egg",
4014
+ "x": 320,
4015
+ "y": 1152
4016
+ },
4017
+ "squid_spawn_egg": {
4018
+ "name": "Squid Spawn Egg",
4019
+ "x": 352,
4020
+ "y": 1152
4021
+ },
4022
+ "stray_spawn_egg": {
4023
+ "name": "Stray Spawn Egg",
4024
+ "x": 0,
4025
+ "y": 1376
4026
+ },
4027
+ "strider_spawn_egg": {
4028
+ "name": "Strider Spawn Egg",
4029
+ "x": 960,
4030
+ "y": 192
4031
+ },
4032
+ "trader_llama_spawn_egg": {
4033
+ "name": "Trader Llama Spawn Egg",
4034
+ "x": 928,
4035
+ "y": 2432
4036
+ },
4037
+ "tropical_fish_spawn_egg": {
4038
+ "name": "Tropical Fish Spawn Egg",
4039
+ "x": 800,
4040
+ "y": 1696
4041
+ },
4042
+ "turtle_spawn_egg": {
4043
+ "name": "Turtle Spawn Egg",
4044
+ "x": 0,
4045
+ "y": 1728
4046
+ },
4047
+ "vex_spawn_egg": {
4048
+ "name": "Vex Spawn Egg",
4049
+ "x": 128,
4050
+ "y": 1408
4051
+ },
4052
+ "villager_spawn_egg": {
4053
+ "name": "Villager Spawn Egg",
4054
+ "x": 384,
4055
+ "y": 1152
4056
+ },
4057
+ "vindicator_spawn_egg": {
4058
+ "name": "Vindicator Spawn Egg",
4059
+ "x": 160,
4060
+ "y": 1408
4061
+ },
4062
+ "wandering_trader_spawn_egg": {
4063
+ "name": "Wandering Trader Spawn Egg",
4064
+ "x": 960,
4065
+ "y": 2432
4066
+ },
4067
+ "witch_spawn_egg": {
4068
+ "name": "Witch Spawn Egg",
4069
+ "x": 416,
4070
+ "y": 1152
4071
+ },
4072
+ "wither_skeleton_spawn_egg": {
4073
+ "name": "Wither Skeleton Spawn Egg",
4074
+ "x": 32,
4075
+ "y": 1376
4076
+ },
4077
+ "wolf_spawn_egg": {
4078
+ "name": "Wolf Spawn Egg",
4079
+ "x": 448,
4080
+ "y": 1152
4081
+ },
4082
+ "zoglin_spawn_egg": {
4083
+ "name": "Zoglin Spawn Egg",
4084
+ "x": 352,
4085
+ "y": 256
4086
+ },
4087
+ "zombie_spawn_egg": {
4088
+ "name": "Zombie Spawn Egg",
4089
+ "x": 480,
4090
+ "y": 1152
4091
+ },
4092
+ "zombie_horse_spawn_egg": {
4093
+ "name": "Zombie Horse Spawn Egg",
4094
+ "x": 64,
4095
+ "y": 1376
4096
+ },
4097
+ "zombie_villager_spawn_egg": {
4098
+ "name": "Zombie Villager Spawn Egg",
4099
+ "x": 128,
4100
+ "y": 1344
4101
+ },
4102
+ "zombified_piglin_spawn_egg": {
4103
+ "name": "Zombified Piglin Spawn Egg",
4104
+ "x": 512,
4105
+ "y": 1152
4106
+ },
4107
+ "experience_bottle": {
4108
+ "name": "Bottle o' Enchanting",
4109
+ "x": 288,
4110
+ "y": 3456
4111
+ },
4112
+ "fire_charge": {
4113
+ "name": "Fire Charge",
4114
+ "x": 416,
4115
+ "y": 3552
4116
+ },
4117
+ "writable_book": {
4118
+ "name": "Book and Quill",
4119
+ "x": 352,
4120
+ "y": 3520
4121
+ },
4122
+ "written_book": {
4123
+ "name": "Written Book",
4124
+ "x": 256,
4125
+ "y": 3584
4126
+ },
4127
+ "emerald": {
4128
+ "name": "Emerald",
4129
+ "x": 640,
4130
+ "y": 3488
4131
+ },
4132
+ "item_frame": {
4133
+ "name": "Item Frame",
4134
+ "x": 480,
4135
+ "y": 3136
4136
+ },
4137
+ "flower_pot": {
4138
+ "name": "Flower Pot",
4139
+ "x": 448,
4140
+ "y": 3136
4141
+ },
4142
+ "carrot": {
4143
+ "name": "Carrot",
4144
+ "x": 928,
4145
+ "y": 3168
4146
+ },
4147
+ "potato": {
4148
+ "name": "Potato",
4149
+ "x": 288,
4150
+ "y": 3200
4151
+ },
4152
+ "baked_potato": {
4153
+ "name": "Baked Potato",
4154
+ "x": 800,
4155
+ "y": 3168
4156
+ },
4157
+ "poisonous_potato": {
4158
+ "name": "Poisonous Potato",
4159
+ "x": 256,
4160
+ "y": 3200
4161
+ },
4162
+ "map": {
4163
+ "name": "Empty Map",
4164
+ "x": 320,
4165
+ "y": 3552
4166
+ },
4167
+ "golden_carrot": {
4168
+ "name": "Golden Carrot",
4169
+ "x": 160,
4170
+ "y": 3136
4171
+ },
4172
+ "skeleton_skull": {
4173
+ "name": "Skeleton Skull",
4174
+ "x": 192,
4175
+ "y": 960
4176
+ },
4177
+ "wither_skeleton_skull": {
4178
+ "name": "Wither Skeleton Skull",
4179
+ "x": 224,
4180
+ "y": 960
4181
+ },
4182
+ "player_head": {
4183
+ "name": "Player Head",
4184
+ "x": 160,
4185
+ "y": 960
4186
+ },
4187
+ "zombie_head": {
4188
+ "name": "Zombie Head",
4189
+ "x": 256,
4190
+ "y": 960
4191
+ },
4192
+ "creeper_head": {
4193
+ "name": "Creeper Head",
4194
+ "x": 96,
4195
+ "y": 960
4196
+ },
4197
+ "dragon_head": {
4198
+ "name": "Dragon Head",
4199
+ "x": 128,
4200
+ "y": 960
4201
+ },
4202
+ "carrot_on_a_stick": {
4203
+ "name": "Carrot on a Stick",
4204
+ "x": 416,
4205
+ "y": 3520
4206
+ },
4207
+ "warped_fungus_on_a_stick": {
4208
+ "name": "Warped Fungus on a Stick",
4209
+ "x": 992,
4210
+ "y": 192
4211
+ },
4212
+ "nether_star": {
4213
+ "name": "Nether Star",
4214
+ "x": 64,
4215
+ "y": 352
4216
+ },
4217
+ "pumpkin_pie": {
4218
+ "name": "Pumpkin Pie",
4219
+ "x": 320,
4220
+ "y": 3200
4221
+ },
4222
+ "firework_rocket": {
4223
+ "name": "Firework Rocket",
4224
+ "x": 736,
4225
+ "y": 3168
4226
+ },
4227
+ "firework_star": {
4228
+ "name": "Firework Star",
4229
+ "x": 256,
4230
+ "y": 800
4231
+ },
4232
+ "enchanted_book": {
4233
+ "name": "Enchanted Book",
4234
+ "x": 352,
4235
+ "y": 3552
4236
+ },
4237
+ "nether_brick": {
4238
+ "name": "Nether Brick",
4239
+ "x": 992,
4240
+ "y": 3488
4241
+ },
4242
+ "quartz": {
4243
+ "name": "Nether Quartz",
4244
+ "x": 0,
4245
+ "y": 3520
4246
+ },
4247
+ "tnt_minecart": {
4248
+ "name": "Minecart with TNT",
4249
+ "x": 320,
4250
+ "y": 3616
4251
+ },
4252
+ "hopper_minecart": {
4253
+ "name": "Minecart with Hopper",
4254
+ "x": 288,
4255
+ "y": 3616
4256
+ },
4257
+ "prismarine_shard": {
4258
+ "name": "Prismarine Shard",
4259
+ "x": 160,
4260
+ "y": 3520
4261
+ },
4262
+ "prismarine_crystals": {
4263
+ "name": "Prismarine Crystals",
4264
+ "x": 128,
4265
+ "y": 3520
4266
+ },
4267
+ "rabbit": {
4268
+ "name": "Raw Rabbit",
4269
+ "x": 512,
4270
+ "y": 3200
4271
+ },
4272
+ "cooked_rabbit": {
4273
+ "name": "Cooked Rabbit",
4274
+ "x": 64,
4275
+ "y": 3200
4276
+ },
4277
+ "rabbit_stew": {
4278
+ "name": "Rabbit Stew",
4279
+ "x": 352,
4280
+ "y": 3200
4281
+ },
4282
+ "rabbit_foot": {
4283
+ "name": "Rabbit's Foot",
4284
+ "x": 224,
4285
+ "y": 3136
4286
+ },
4287
+ "rabbit_hide": {
4288
+ "name": "Rabbit Hide",
4289
+ "x": 192,
4290
+ "y": 3520
4291
+ },
4292
+ "armor_stand": {
4293
+ "name": "Armor Stand",
4294
+ "x": 416,
4295
+ "y": 3136
4296
+ },
4297
+ "iron_horse_armor": {
4298
+ "name": "Iron Horse Armor",
4299
+ "x": 192,
4300
+ "y": 32
4301
+ },
4302
+ "golden_horse_armor": {
4303
+ "name": "Golden Horse Armor",
4304
+ "x": 32,
4305
+ "y": 32
4306
+ },
4307
+ "diamond_horse_armor": {
4308
+ "name": "Diamond Horse Armor",
4309
+ "x": 896,
4310
+ "y": 0
4311
+ },
4312
+ "leather_horse_armor": {
4313
+ "name": "Leather Horse Armor",
4314
+ "x": 160,
4315
+ "y": 1376
4316
+ },
4317
+ "lead": {
4318
+ "name": "Lead",
4319
+ "x": 800,
4320
+ "y": 3552
4321
+ },
4322
+ "name_tag": {
4323
+ "name": "Name Tag",
4324
+ "x": 864,
4325
+ "y": 3552
4326
+ },
4327
+ "command_block_minecart": {
4328
+ "name": "Minecart with Command Block",
4329
+ "x": 224,
4330
+ "y": 3616
4331
+ },
4332
+ "mutton": {
4333
+ "name": "Raw Mutton",
4334
+ "x": 448,
4335
+ "y": 3200
4336
+ },
4337
+ "cooked_mutton": {
4338
+ "name": "Cooked Mutton",
4339
+ "x": 0,
4340
+ "y": 3200
4341
+ },
4342
+ "white_banner": {
4343
+ "name": "White Banner",
4344
+ "x": 608,
4345
+ "y": 768
4346
+ },
4347
+ "orange_banner": {
4348
+ "name": "Orange Banner",
4349
+ "x": 864,
4350
+ "y": 736
4351
+ },
4352
+ "magenta_banner": {
4353
+ "name": "Magenta Banner",
4354
+ "x": 672,
4355
+ "y": 736
4356
+ },
4357
+ "light_blue_banner": {
4358
+ "name": "Light Blue Banner",
4359
+ "x": 96,
4360
+ "y": 736
4361
+ },
4362
+ "yellow_banner": {
4363
+ "name": "Yellow Banner",
4364
+ "x": 800,
4365
+ "y": 768
4366
+ },
4367
+ "lime_banner": {
4368
+ "name": "Lime Banner",
4369
+ "x": 480,
4370
+ "y": 736
4371
+ },
4372
+ "pink_banner": {
4373
+ "name": "Pink Banner",
4374
+ "x": 32,
4375
+ "y": 768
4376
+ },
4377
+ "gray_banner": {
4378
+ "name": "Gray Banner",
4379
+ "x": 736,
4380
+ "y": 704
4381
+ },
4382
+ "light_gray_banner": {
4383
+ "name": "Light Gray Banner",
4384
+ "x": 288,
4385
+ "y": 736
4386
+ },
4387
+ "cyan_banner": {
4388
+ "name": "Cyan Banner",
4389
+ "x": 544,
4390
+ "y": 704
4391
+ },
4392
+ "purple_banner": {
4393
+ "name": "Purple Banner",
4394
+ "x": 224,
4395
+ "y": 768
4396
+ },
4397
+ "blue_banner": {
4398
+ "name": "Blue Banner",
4399
+ "x": 160,
4400
+ "y": 704
4401
+ },
4402
+ "brown_banner": {
4403
+ "name": "Brown Banner",
4404
+ "x": 352,
4405
+ "y": 704
4406
+ },
4407
+ "green_banner": {
4408
+ "name": "Green Banner",
4409
+ "x": 928,
4410
+ "y": 704
4411
+ },
4412
+ "red_banner": {
4413
+ "name": "Red Banner",
4414
+ "x": 416,
4415
+ "y": 768
4416
+ },
4417
+ "black_banner": {
4418
+ "name": "Black Banner",
4419
+ "x": 992,
4420
+ "y": 672
4421
+ },
4422
+ "end_crystal": {
4423
+ "name": "End Crystal",
4424
+ "x": 608,
4425
+ "y": 3168
4426
+ },
4427
+ "chorus_fruit": {
4428
+ "name": "Chorus Fruit",
4429
+ "x": 960,
4430
+ "y": 3168
4431
+ },
4432
+ "popped_chorus_fruit": {
4433
+ "name": "Popped Chorus Fruit",
4434
+ "x": 96,
4435
+ "y": 3520
4436
+ },
4437
+ "beetroot": {
4438
+ "name": "Beetroot",
4439
+ "x": 864,
4440
+ "y": 3168
4441
+ },
4442
+ "beetroot_seeds": {
4443
+ "name": "Beetroot Seeds",
4444
+ "x": 320,
4445
+ "y": 3392
4446
+ },
4447
+ "beetroot_soup": {
4448
+ "name": "Beetroot Soup",
4449
+ "x": 832,
4450
+ "y": 3168
4451
+ },
4452
+ "dragon_breath": {
4453
+ "name": "Dragon's Breath",
4454
+ "x": 32,
4455
+ "y": 3136
4456
+ },
4457
+ "splash_potion": {
4458
+ "name": "Splash Potion of Luck",
4459
+ "x": 512,
4460
+ "y": 3456
4461
+ },
4462
+ "spectral_arrow": {
4463
+ "name": "Spectral Arrow",
4464
+ "x": 704,
4465
+ "y": 3616
4466
+ },
4467
+ "tipped_arrow": {
4468
+ "name": "Tipped Arrow",
4469
+ "x": 544,
4470
+ "y": 1248
4471
+ },
4472
+ "lingering_potion": {
4473
+ "name": "Lingering Potion of Luck",
4474
+ "x": 0,
4475
+ "y": 3488
4476
+ },
4477
+ "shield": {
4478
+ "name": "Shield",
4479
+ "x": 960,
4480
+ "y": 2496
4481
+ },
4482
+ "elytra": {
4483
+ "name": "Elytra",
4484
+ "x": 224,
4485
+ "y": 2496
4486
+ },
4487
+ "spruce_boat": {
4488
+ "name": "Spruce Boat",
4489
+ "x": 384,
4490
+ "y": 3616
4491
+ },
4492
+ "birch_boat": {
4493
+ "name": "Birch Boat",
4494
+ "x": 64,
4495
+ "y": 3616
4496
+ },
4497
+ "jungle_boat": {
4498
+ "name": "Jungle Boat",
4499
+ "x": 128,
4500
+ "y": 3616
4501
+ },
4502
+ "acacia_boat": {
4503
+ "name": "Acacia Boat",
4504
+ "x": 32,
4505
+ "y": 3616
4506
+ },
4507
+ "dark_oak_boat": {
4508
+ "name": "Dark Oak Boat",
4509
+ "x": 96,
4510
+ "y": 3616
4511
+ },
4512
+ "totem_of_undying": {
4513
+ "name": "Totem of Undying",
4514
+ "x": 768,
4515
+ "y": 3616
4516
+ },
4517
+ "shulker_shell": {
4518
+ "name": "Shulker Shell",
4519
+ "x": 256,
4520
+ "y": 3520
4521
+ },
4522
+ "iron_nugget": {
4523
+ "name": "Iron Nugget",
4524
+ "x": 928,
4525
+ "y": 3488
4526
+ },
4527
+ "knowledge_book": {
4528
+ "name": "Knowledge Book",
4529
+ "x": 800,
4530
+ "y": 3584
4531
+ },
4532
+ "debug_stick": {
4533
+ "name": "Debug Stick",
4534
+ "x": 608,
4535
+ "y": 1120
4536
+ },
4537
+ "music_disc_pigstep": {
4538
+ "name": "Music Disc 13",
4539
+ "x": 0,
4540
+ "y": 672
4541
+ },
4542
+ "trident": {
4543
+ "name": "Trident",
4544
+ "x": 608,
4545
+ "y": 1696
4546
+ },
4547
+ "phantom_membrane": {
4548
+ "name": "Phantom Membrane",
4549
+ "x": 32,
4550
+ "y": 1728
4551
+ },
4552
+ "nautilus_shell": {
4553
+ "name": "Nautilus Shell",
4554
+ "x": 448,
4555
+ "y": 1728
4556
+ },
4557
+ "heart_of_the_sea": {
4558
+ "name": "Heart of the Sea",
4559
+ "x": 416,
4560
+ "y": 1728
4561
+ },
4562
+ "crossbow": {
4563
+ "name": "Crossbow",
4564
+ "x": 416,
4565
+ "y": 2368
4566
+ },
4567
+ "suspicious_stew": {
4568
+ "name": "Suspicious Stew",
4569
+ "x": 928,
4570
+ "y": 2368
4571
+ },
4572
+ "loom": {
4573
+ "name": "Loom",
4574
+ "x": 416,
4575
+ "y": 2432
4576
+ },
4577
+ "flower_banner_pattern": {
4578
+ "name": "Banner Pattern",
4579
+ "x": 704,
4580
+ "y": 2368
4581
+ },
4582
+ "creeper_banner_pattern": {
4583
+ "name": "Banner Pattern",
4584
+ "x": 704,
4585
+ "y": 2368
4586
+ },
4587
+ "skull_banner_pattern": {
4588
+ "name": "Banner Pattern",
4589
+ "x": 704,
4590
+ "y": 2368
4591
+ },
4592
+ "mojang_banner_pattern": {
4593
+ "name": "Banner Pattern",
4594
+ "x": 704,
4595
+ "y": 2368
4596
+ },
4597
+ "globe_banner_pattern": {
4598
+ "name": "Banner Pattern",
4599
+ "x": 704,
4600
+ "y": 2368
4601
+ },
4602
+ "piglin_banner_pattern": {
4603
+ "name": "Banner Pattern",
4604
+ "x": 704,
4605
+ "y": 2368
4606
+ },
4607
+ "composter": {
4608
+ "name": "Composter",
4609
+ "x": 864,
4610
+ "y": 2432
4611
+ },
4612
+ "barrel": {
4613
+ "name": "Barrel",
4614
+ "x": 64,
4615
+ "y": 2432
4616
+ },
4617
+ "smoker": {
4618
+ "name": "Smoker",
4619
+ "x": 480,
4620
+ "y": 2432
4621
+ },
4622
+ "blast_furnace": {
4623
+ "name": "Blast Furnace",
4624
+ "x": 288,
4625
+ "y": 2432
4626
+ },
4627
+ "cartography_table": {
4628
+ "name": "Cartography Table",
4629
+ "x": 608,
4630
+ "y": 2432
4631
+ },
4632
+ "fletching_table": {
4633
+ "name": "Fletching Table",
4634
+ "x": 640,
4635
+ "y": 2432
4636
+ },
4637
+ "grindstone": {
4638
+ "name": "Grindstone",
4639
+ "x": 896,
4640
+ "y": 2432
4641
+ },
4642
+ "lectern": {
4643
+ "name": "Lectern",
4644
+ "x": 576,
4645
+ "y": 0
4646
+ },
4647
+ "smithing_table": {
4648
+ "name": "Smithing Table",
4649
+ "x": 672,
4650
+ "y": 2432
4651
+ },
4652
+ "stonecutter": {
4653
+ "name": "Stonecutter BE",
4654
+ "x": 800,
4655
+ "y": 1056
4656
+ },
4657
+ "bell": {
4658
+ "name": "Bell",
4659
+ "x": 256,
4660
+ "y": 2400
4661
+ },
4662
+ "lantern": {
4663
+ "name": "Lantern",
4664
+ "x": 576,
4665
+ "y": 2432
4666
+ },
4667
+ "soul_lantern": {
4668
+ "name": "Soul Lantern",
4669
+ "x": 896,
4670
+ "y": 128
4671
+ },
4672
+ "sweet_berries": {
4673
+ "name": "Sweet Berries",
4674
+ "x": 768,
4675
+ "y": 2432
4676
+ },
4677
+ "campfire": {
4678
+ "name": "Campfire",
4679
+ "x": 832,
4680
+ "y": 2432
4681
+ },
4682
+ "soul_campfire": {
4683
+ "name": "Soul Campfire",
4684
+ "x": 960,
4685
+ "y": 256
4686
+ },
4687
+ "shroomlight": {
4688
+ "name": "Shroomlight",
4689
+ "x": 704,
4690
+ "y": 128
4691
+ },
4692
+ "honeycomb": {
4693
+ "name": "Honeycomb",
4694
+ "x": 928,
4695
+ "y": 32
4696
+ },
4697
+ "bee_nest": {
4698
+ "name": "Bee Nest",
4699
+ "x": 992,
4700
+ "y": 32
4701
+ },
4702
+ "beehive": {
4703
+ "name": "Beehive",
4704
+ "x": 960,
4705
+ "y": 32
4706
+ },
4707
+ "honey_bottle": {
4708
+ "name": "Honey Bottle",
4709
+ "x": 896,
4710
+ "y": 32
4711
+ },
4712
+ "honey_block": {
4713
+ "name": "Honey Block",
4714
+ "x": 320,
4715
+ "y": 96
4716
+ },
4717
+ "honeycomb_block": {
4718
+ "name": "Honeycomb Block",
4719
+ "x": 64,
4720
+ "y": 96
4721
+ },
4722
+ "lodestone": {
4723
+ "name": "Lodestone",
4724
+ "x": 928,
4725
+ "y": 192
4726
+ },
4727
+ "netherite_block": {
4728
+ "name": "Block of Netherite",
4729
+ "x": 96,
4730
+ "y": 128
4731
+ },
4732
+ "ancient_debris": {
4733
+ "name": "Ancient Debris",
4734
+ "x": 160,
4735
+ "y": 128
4736
+ },
4737
+ "target": {
4738
+ "name": "Target",
4739
+ "x": 96,
4740
+ "y": 192
4741
+ },
4742
+ "crying_obsidian": {
4743
+ "name": "Crying Obsidian",
4744
+ "x": 128,
4745
+ "y": 192
4746
+ },
4747
+ "blackstone": {
4748
+ "name": "Blackstone",
4749
+ "x": 96,
4750
+ "y": 256
4751
+ },
4752
+ "blackstone_slab": {
4753
+ "name": "Blackstone Slab",
4754
+ "x": 608,
4755
+ "y": 256
4756
+ },
4757
+ "blackstone_stairs": {
4758
+ "name": "Blackstone Stairs",
4759
+ "x": 640,
4760
+ "y": 256
4761
+ },
4762
+ "gilded_blackstone": {
4763
+ "name": "Gilded Blackstone",
4764
+ "x": 512,
4765
+ "y": 256
4766
+ },
4767
+ "polished_blackstone": {
4768
+ "name": "Polished Blackstone",
4769
+ "x": 544,
4770
+ "y": 256
4771
+ },
4772
+ "polished_blackstone_slab": {
4773
+ "name": "Polished Blackstone Slab",
4774
+ "x": 800,
4775
+ "y": 256
4776
+ },
4777
+ "polished_blackstone_stairs": {
4778
+ "name": "Polished Blackstone Stairs",
4779
+ "x": 832,
4780
+ "y": 256
4781
+ },
4782
+ "chiseled_polished_blackstone": {
4783
+ "name": "Chiseled Polished Blackstone",
4784
+ "x": 416,
4785
+ "y": 256
4786
+ },
4787
+ "polished_blackstone_bricks": {
4788
+ "name": "Polished Blackstone Bricks",
4789
+ "x": 576,
4790
+ "y": 256
4791
+ },
4792
+ "polished_blackstone_brick_slab": {
4793
+ "name": "Polished Blackstone Brick Slab",
4794
+ "x": 704,
4795
+ "y": 256
4796
+ },
4797
+ "polished_blackstone_brick_stairs": {
4798
+ "name": "Polished Blackstone Brick Stairs",
4799
+ "x": 736,
4800
+ "y": 256
4801
+ },
4802
+ "cracked_polished_blackstone_bricks": {
4803
+ "name": "Cracked Polished Blackstone Bricks",
4804
+ "x": 480,
4805
+ "y": 256
4806
+ },
4807
+ "respawn_anchor": {
4808
+ "name": "Respawn Anchor",
4809
+ "x": 448,
4810
+ "y": 192
4811
+ }
4812
+ }
lib/menus/components/bossbars_overlay.js ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { LitElement, html, css } = require('lit')
2
+ const { styleMap } = require('lit/directives/style-map.js')
3
+
4
+ const colors = ['pink', 'blue', 'red', 'green', 'yellow', 'purple', 'white']
5
+ const divs = [0, 6, 10, 12, 20]
6
+ const translations = {
7
+ 'entity.minecraft.ender_dragon': 'Ender Dragon',
8
+ 'entity.minecraft.wither': 'Wither'
9
+ }
10
+ class BossBar extends LitElement {
11
+ constructor (bar) {
12
+ super()
13
+ this.bar = bar
14
+ this.title = ''
15
+ this.progress = 0
16
+ this.bossBarStyles = {}
17
+ this.fillStyles = {}
18
+ this.div1Styles = {}
19
+ this.div2Styles = {}
20
+ }
21
+
22
+ static get styles () {
23
+ return css`
24
+ .container {
25
+ display: flex;
26
+ flex-direction: column;
27
+ align-items: center;
28
+ }
29
+ .title {
30
+ font-size: 7px;
31
+ color: #fff;
32
+ }
33
+ .bossbar {
34
+ background-image: url("textures/1.18.1/gui/bars.png");
35
+ width: 182px;
36
+ height: 5px;
37
+ position: relative;
38
+ }
39
+ .bossbar .fill {
40
+ content: "";
41
+ position: absolute;
42
+ top: 0;
43
+ left: 0;
44
+ height: 5px;
45
+ width: 0;
46
+ background-image: url("textures/1.18.1/gui/bars.png");
47
+ }`
48
+ }
49
+
50
+ static get properties () {
51
+ return {
52
+ bar: { type: Object }
53
+ }
54
+ }
55
+
56
+ render () {
57
+ this.updateBar(this.bar)
58
+
59
+ return html`
60
+ <div class="container">
61
+ <div class="title">${this.title}</div>
62
+ <div class="bossbar" style=${styleMap(this.bossBarStyles)}>
63
+ <div class="fill" style=${styleMap(this.fillStyles)}></div>
64
+ <div class="fill" style=${styleMap(this.div1Styles)}></div>
65
+ <div class="fill" style=${styleMap(this.div2Styles)}></div>
66
+ </div>
67
+ </div>`
68
+ }
69
+
70
+ setTitle (bar) {
71
+ if (bar._title.text) this.title = bar._title.text
72
+ else this.title = translations[this._title.translate] || 'Unkown Entity'
73
+ }
74
+
75
+ setColor (bar) {
76
+ this.bossBarStyles.backgroundPositionY = `-${colors.indexOf(bar._color) * 10}px`
77
+ this.fillStyles.backgroundPositionY = `-${colors.indexOf(bar._color) * 10 + 5}px`
78
+ }
79
+
80
+ setProgress (bar) {
81
+ this.fillStyles.width = `${bar._health * 100}%`
82
+ this.div2Styles.width = `${bar._health * 100}%`
83
+ }
84
+
85
+ setDiv (bar) {
86
+ this.div1Styles.backgroundPositionY = `-${divs.indexOf(bar._dividers) * 10 + 70}px`
87
+ this.div2Styles.backgroundPositionY = `-${divs.indexOf(bar._dividers) * 10 + 75}px`
88
+ }
89
+
90
+ updateBar (bar) {
91
+ this.setTitle(bar)
92
+ this.setColor(bar)
93
+ this.setDiv(bar)
94
+ this.setProgress(bar)
95
+ }
96
+ }
97
+
98
+ class BossBars extends LitElement {
99
+ constructor () {
100
+ super()
101
+ this.bossBars = new Map()
102
+ }
103
+
104
+ static get styles () {
105
+ return css`
106
+ .bossBars {
107
+ display: flex;
108
+ flex-direction: column;
109
+ gap: 5px;
110
+ position: absolute;
111
+ top: 9px;
112
+ left: 50%;
113
+ transform: translate(-50%);
114
+ }`
115
+ }
116
+
117
+ static get properties () {
118
+ return {
119
+ bossBars: { type: Map }
120
+ }
121
+ }
122
+
123
+ render () {
124
+ return html`<div class="bossBars" id="bossBars">
125
+ ${[...this.bossBars.values()]}
126
+ </div>`
127
+ }
128
+
129
+ init () {
130
+ this.bot.on('bossBarCreated', async (bossBar) => {
131
+ this.bossBars.set(bossBar.entityUUID, new BossBar(bossBar))
132
+ this.requestUpdate()
133
+ })
134
+ this.bot.on('bossBarUpdated', (bossBar) => {
135
+ const bar = this.bossBars.get(bossBar.entityUUID)
136
+ bar.bar = bossBar
137
+ bar.requestUpdate()
138
+ })
139
+ this.bot.on('bossBarDeleted', (bossBar) => {
140
+ this.bossBars.delete(bossBar.entityUUID)
141
+ this.requestUpdate()
142
+ })
143
+ }
144
+ }
145
+
146
+ window.customElements.define('pmui-bossbars-overlay', BossBars)
147
+ window.customElements.define('pmui-bossbar', BossBar)
lib/menus/components/breath_bar.js ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { LitElement, html, css } = require('lit')
2
+
3
+ class BreathBar extends LitElement {
4
+ static get styles () {
5
+ return css`
6
+ .breathbar {
7
+ position: absolute;
8
+ display: flex;
9
+ flex-direction: row-reverse;
10
+ left: calc(50% + 91px);
11
+ transform: translate(-100%);
12
+ bottom: 40px;
13
+ --offset: calc(-1 * 16px);
14
+ --bg-x: calc(-1 * 16px);
15
+ --bg-y: calc(-1 * 18px);
16
+ }
17
+
18
+ .breath {
19
+ width: 9px;
20
+ height: 9px;
21
+ margin-left: -1px;
22
+ }
23
+
24
+ .breath.full {
25
+ background-image: url('textures/1.17.1/gui/icons.png');
26
+ background-size: 256px;
27
+ background-position: var(--offset) var(--bg-y);
28
+ }
29
+
30
+ .breath.half {
31
+ background-image: url('textures/1.17.1/gui/icons.png');
32
+ background-size: 256px;
33
+ background-position: calc(var(--offset) - 9) var(--bg-y);
34
+ }
35
+ `
36
+ }
37
+
38
+ gameModeChanged (gamemode) {
39
+ this.shadowRoot.querySelector('#breathbar').classList.toggle('creative', gamemode === 1)
40
+ }
41
+
42
+ updateOxygen (hValue) {
43
+ const breathbar = this.shadowRoot.querySelector('#breathbar')
44
+ breathbar.style.display = 'block'
45
+
46
+ const breaths = breathbar.children
47
+
48
+ for (let i = 0; i < breaths.length; i++) {
49
+ breaths[i].classList.remove('full')
50
+ breaths[i].classList.remove('half')
51
+ }
52
+
53
+ for (let i = 0; i < Math.ceil(hValue / 2); i++) {
54
+ if (i >= breaths.length) break
55
+
56
+ if (hValue % 2 !== 0 && Math.ceil(hValue / 2) === i + 1) {
57
+ breaths[i].classList.add('half')
58
+ } else {
59
+ breaths[i].classList.add('full')
60
+ }
61
+ }
62
+
63
+ // if (hValue === 20) {
64
+ // setTimeout(() => {
65
+ // breathbar.style.display = 'none'
66
+ // }, 1000)
67
+ // }
68
+ }
69
+
70
+ render () {
71
+ return html`
72
+ <div id="breathbar" class="breathbar">
73
+ <div class="breath"></div>
74
+ <div class="breath"></div>
75
+ <div class="breath"></div>
76
+ <div class="breath"></div>
77
+ <div class="breath"></div>
78
+ <div class="breath"></div>
79
+ <div class="breath"></div>
80
+ <div class="breath"></div>
81
+ <div class="breath"></div>
82
+ <div class="breath"></div>
83
+ </div>
84
+ `
85
+ }
86
+ }
87
+
88
+ window.customElements.define('pmui-breathbar', BreathBar)
lib/menus/components/button.js ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { LitElement, html, css } = require('lit')
2
+
3
+ const audioContext = new window.AudioContext()
4
+ const sounds = {}
5
+
6
+ async function playSound (path) {
7
+ let volume = 1
8
+ const options = document.getElementById('options-screen')
9
+ if (options) {
10
+ volume = options.sound / 100
11
+ }
12
+
13
+ let soundBuffer = sounds[path]
14
+
15
+ if (!soundBuffer) {
16
+ const res = await window.fetch(path)
17
+ const data = await res.arrayBuffer()
18
+
19
+ soundBuffer = await audioContext.decodeAudioData(data)
20
+ sounds[path] = soundBuffer
21
+ }
22
+
23
+ const gainNode = audioContext.createGain()
24
+ const source = audioContext.createBufferSource()
25
+ source.buffer = soundBuffer
26
+ source.connect(gainNode)
27
+ gainNode.connect(audioContext.destination)
28
+ gainNode.gain.value = volume
29
+ source.start(0)
30
+ }
31
+
32
+ class Button extends LitElement {
33
+ static get styles () {
34
+ return css`
35
+ .button {
36
+ --txrV: 66px;
37
+ position: relative;
38
+ width: 200px;
39
+ height: 20px;
40
+ font-family: minecraft, mojangles, monospace;
41
+ font-size: 10px;
42
+ color: white;
43
+ text-shadow: 1px 1px #222;
44
+ border: none;
45
+ z-index: 1;
46
+ outline: none;
47
+ }
48
+
49
+ .button:hover,
50
+ .button:focus-visible {
51
+ --txrV: 86px;
52
+ }
53
+
54
+ .button:disabled {
55
+ --txrV: 46px;
56
+ color: #A0A0A0;
57
+ text-shadow: 1px 1px #111;
58
+ }
59
+
60
+ .button::after {
61
+ content: '';
62
+ display: block;
63
+ position: absolute;
64
+ top: 0;
65
+ left: 0;
66
+ width: 50%;
67
+ height: 20px;
68
+ background: url('textures/1.17.1/gui/widgets.png');
69
+ background-size: 256px;
70
+ background-position-y: calc(var(--txrV) * -1);
71
+ z-index: -1;
72
+ }
73
+
74
+ .button::before {
75
+ content: '';
76
+ display: block;
77
+ position: absolute;
78
+ top: 0;
79
+ left: 50%;
80
+ width: 50%;
81
+ height: 20px;
82
+ background: url('textures/1.17.1/gui/widgets.png');
83
+ background-size: 256px;
84
+ background-position-x: calc(-200px + 100%);
85
+ background-position-y: calc(var(--txrV) * -1);
86
+ z-index: -1;
87
+ }
88
+ `
89
+ }
90
+
91
+ static get properties () {
92
+ return {
93
+ label: {
94
+ type: String,
95
+ attribute: 'pmui-label'
96
+ },
97
+ width: {
98
+ type: String,
99
+ attribute: 'pmui-width'
100
+ },
101
+ disabled: {
102
+ type: Boolean,
103
+ attribute: 'pmui-disabled'
104
+ },
105
+ onPress: {
106
+ type: Function,
107
+ attribute: 'pmui-click'
108
+ }
109
+ }
110
+ }
111
+
112
+ constructor () {
113
+ super()
114
+ this.label = ''
115
+ this.disabled = false
116
+ this.width = '200px'
117
+ this.onPress = () => {}
118
+ }
119
+
120
+ render () {
121
+ return html`
122
+ <button
123
+ class="button"
124
+ ?disabled=${this.disabled}
125
+ @click=${this.onBtnClick}
126
+ style="width: ${this.width};"
127
+ >
128
+ ${this.label}
129
+ </button>`
130
+ }
131
+
132
+ onBtnClick () {
133
+ playSound('click_stereo.ogg')
134
+ this.dispatchEvent(new window.CustomEvent('pmui-click'))
135
+ }
136
+ }
137
+
138
+ window.customElements.define('pmui-button', Button)
139
+ const _playSound = playSound
140
+ export { _playSound as playSound }
lib/menus/components/common.js ADDED
@@ -0,0 +1,72 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { css } from 'lit'
2
+
3
+ const commonCss = css`
4
+ .dirt-bg {
5
+ position: absolute;
6
+ top: 0;
7
+ left: 0;
8
+ background: url('textures/1.17.1/gui/options_background.png'), rgba(0, 0, 0, 0.75);
9
+ background-size: 16px;
10
+ background-repeat: repeat;
11
+ width: 100%;
12
+ height: 100%;
13
+ transform-origin: top left;
14
+ transform: scale(2);
15
+ background-blend-mode: overlay;
16
+ }
17
+
18
+ .bg {
19
+ position: absolute;
20
+ top: 0;
21
+ left: 0;
22
+ background: rgba(0, 0, 0, 0.75);
23
+ width: 100%;
24
+ height: 100%;
25
+ }
26
+
27
+ .title {
28
+ position: absolute;
29
+ top: 0;
30
+ left: 50%;
31
+ transform: translate(-50%);
32
+ font-size: 10px;
33
+ color: white;
34
+ text-align: center;
35
+ text-shadow: 1px 1px #222;
36
+ }
37
+
38
+ .text {
39
+ color: white;
40
+ font-size: 10px;
41
+ text-shadow: 1px 1px #222;
42
+ }
43
+ `
44
+
45
+ /** @returns {boolean} */
46
+ function isMobile () {
47
+ const m = require('ismobilejs').default()
48
+ return m.any
49
+ }
50
+
51
+ /**
52
+ * @param {string} url
53
+ */
54
+ function openURL (url) {
55
+ window.open(url, '_blank', 'noopener,noreferrer')
56
+ }
57
+
58
+ /**
59
+ * @param {HTMLElement} prev
60
+ * @param {HTMLElement} next
61
+ */
62
+ function displayScreen (prev, next) {
63
+ prev.style.display = 'none'
64
+ next.style.display = 'block'
65
+ }
66
+
67
+ export {
68
+ commonCss,
69
+ isMobile,
70
+ openURL,
71
+ displayScreen
72
+ }
lib/menus/components/debug_overlay.js ADDED
@@ -0,0 +1,146 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { LitElement, html, css } = require('lit')
2
+
3
+ class DebugOverlay extends LitElement {
4
+ static get styles () {
5
+ return css`
6
+ .debug-left-side,
7
+ .debug-right-side {
8
+ position: absolute;
9
+ display: flex;
10
+ flex-direction: column;
11
+ z-index: 40;
12
+ }
13
+
14
+ .debug-left-side {
15
+ top: 1px;
16
+ left: 1px;
17
+ }
18
+
19
+ .debug-right-side {
20
+ top: 1px;
21
+ right: 1px;
22
+ }
23
+
24
+ p {
25
+ display: block;
26
+ color: white;
27
+ font-size: 10px;
28
+ width: fit-content;
29
+ height: 9px;
30
+ margin: 0;
31
+ padding: 0;
32
+ padding-bottom: 1px;
33
+ background: rgba(110, 110, 110, 0.5);
34
+ }
35
+
36
+ .debug-right-side p {
37
+ margin-left: auto;
38
+ }
39
+
40
+ .empty {
41
+ display: block;
42
+ height: 9px;
43
+ }
44
+ `
45
+ }
46
+
47
+ static get properties () {
48
+ return {
49
+ showOverlay: { type: Boolean },
50
+ cursorBlock: { type: Object },
51
+ bot: { type: Object },
52
+ customEntries: { type: Object }
53
+ }
54
+ }
55
+
56
+ constructor () {
57
+ super()
58
+ this.showOverlay = false
59
+ this.customEntries = {}
60
+ }
61
+
62
+ firstUpdated () {
63
+ document.addEventListener('keydown', e => {
64
+ e ??= window.event
65
+ if (e.key === 'F3') {
66
+ this.showOverlay = !this.showOverlay
67
+ e.preventDefault()
68
+ }
69
+ })
70
+ }
71
+
72
+ updated (changedProperties) {
73
+ if (changedProperties.has('bot')) {
74
+ this.bot.on('move', () => {
75
+ this.requestUpdate()
76
+ })
77
+ this.bot.on('time', () => {
78
+ this.requestUpdate()
79
+ })
80
+ this.bot.on('entitySpawn', () => {
81
+ this.requestUpdate()
82
+ })
83
+ this.bot.on('entityGone', () => {
84
+ this.requestUpdate()
85
+ })
86
+ }
87
+ }
88
+
89
+ render () {
90
+ if (!this.showOverlay) {
91
+ return html``
92
+ }
93
+
94
+ const target = this.cursorBlock
95
+ const targetDiggable = (target && this.bot.canDigBlock(target))
96
+
97
+ const pos = this.bot.entity.position
98
+ const rot = [this.bot.entity.yaw, this.bot.entity.pitch]
99
+
100
+ const viewDegToMinecraft = (yaw) => yaw % 360 - 180 * (yaw < 0 ? -1 : 1)
101
+
102
+ const quadsDescription = [
103
+ 'north (towards negative Z)',
104
+ 'east (towards positive X)',
105
+ 'south (towards positive Z)',
106
+ 'west (towards negative X)'
107
+ ]
108
+
109
+ const minecraftYaw = viewDegToMinecraft(rot[0] * -180 / Math.PI)
110
+ const minecraftQuad = Math.floor(((minecraftYaw + 180) / 90 + 0.5) % 4)
111
+
112
+ const renderProp = (name, value) => {
113
+ return html`<p>${name}: ${typeof value === 'boolean' ? html`<span style="color: ${value ? 'lightgreen' : 'red'}">${value}</span>` : value}</p>`
114
+ }
115
+
116
+ const skyL = this.bot.world.getSkyLight(this.bot.entity.position)
117
+ const biomeId = this.bot.world.getBiome(this.bot.entity.position)
118
+
119
+ return html`
120
+ <div class="debug-left-side">
121
+ <p>Prismarine Web Client (${this.bot.version})</p>
122
+ <p>E: ${Object.values(this.bot.entities).length}</p>
123
+ <p>${this.bot.game.dimension}</p>
124
+ <div class="empty"></div>
125
+ <p>XYZ: ${pos.x.toFixed(3)} / ${pos.y.toFixed(3)} / ${pos.z.toFixed(3)}</p>
126
+ <p>Chunk: ${Math.floor(pos.x % 16)} ~ ${Math.floor(pos.z % 16)} in ${Math.floor(pos.x / 16)} ~ ${Math.floor(pos.z / 16)}</p>
127
+ <p>Facing (viewer): ${rot[0].toFixed(3)} ${rot[1].toFixed(3)}</p>
128
+ <p>Facing (minecraft): ${quadsDescription[minecraftQuad]} (${minecraftYaw.toFixed(1)} ${(rot[1] * -180 / Math.PI).toFixed(1)})</p>
129
+ <p>Light: ${skyL} (${skyL} sky)</p>
130
+ <p>Biome: minecraft:${window.mcData.biomesArray[biomeId].name}</p>
131
+ <p>Day: ${this.bot.time.day}</p>
132
+ <div class="empty"></div>
133
+ ${Object.entries(this.customEntries).map(([name, value]) => html`<p>${name}: ${value}</p>`)}
134
+ </div>
135
+
136
+ <div class="debug-right-side">
137
+ <p>Renderer: three.js r${global.THREE.REVISION}</p>
138
+ <div class="empty"></div>
139
+ ${targetDiggable ? html`<p>${target.name}</p>${Object.entries(target.getProperties()).map(([n, p], idx, arr) => renderProp(n, p, arr[idx + 1]))}` : ''}
140
+ ${targetDiggable ? html`<p>Looking at: ${target.position.x} ${target.position.y} ${target.position.z}</p>` : ''}
141
+ </div>
142
+ `
143
+ }
144
+ }
145
+
146
+ window.customElements.define('pmui-debug-overlay', DebugOverlay)
lib/menus/components/edit_box.js ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { LitElement, html, css } = require('lit')
2
+
3
+ class EditBox extends LitElement {
4
+ static get styles () {
5
+ return css`
6
+ .edit-container {
7
+ position: relative;
8
+ width: 200px;
9
+ height: 20px;
10
+ background: black;
11
+ border: 1px solid grey;
12
+ }
13
+
14
+ .edit-container:hover,
15
+ .edit-container:focus-within {
16
+ border-color: white;
17
+ }
18
+
19
+ .edit-container label {
20
+ position: absolute;
21
+ z-index: 2;
22
+ pointer-events: none;
23
+ bottom: 21px;
24
+ left: 0;
25
+ font-size: 10px;
26
+ color: rgb(206, 206, 206);
27
+ text-shadow: 1px 1px black;
28
+ }
29
+
30
+ .edit-box {
31
+ position: relative;
32
+ outline: none;
33
+ border: none;
34
+ background: none;
35
+ left: 1px;
36
+ width: calc(100% - 2px);
37
+ height: 100%;
38
+ font-family: minecraft, mojangles, monospace;
39
+ font-size: 10px;
40
+ color: white;
41
+ text-shadow: 1px 1px #222;
42
+ }
43
+ `
44
+ }
45
+
46
+ constructor () {
47
+ super()
48
+ this.width = '200px'
49
+ this.id = ''
50
+ this.value = ''
51
+ this.label = ''
52
+ }
53
+
54
+ static get properties () {
55
+ return {
56
+ width: {
57
+ type: String,
58
+ attribute: 'pmui-width'
59
+ },
60
+ id: {
61
+ type: String,
62
+ attribute: 'pmui-id'
63
+ },
64
+ label: {
65
+ type: String,
66
+ attribute: 'pmui-label'
67
+ },
68
+ value: {
69
+ type: String,
70
+ attribute: 'pmui-value'
71
+ }
72
+ }
73
+ }
74
+
75
+ render () {
76
+ return html`
77
+ <div
78
+ class="edit-container"
79
+ style="width: ${this.width};"
80
+ >
81
+ <label for="${this.id}">${this.label}</label>
82
+ <input
83
+ id="${this.id}"
84
+ type="text"
85
+ name=""
86
+ spellcheck="false"
87
+ required=""
88
+ autocomplete="off"
89
+ value="${this.value}"
90
+ @input=${(e) => { this.value = e.target.value }}
91
+ class="edit-box">
92
+ </div>
93
+ `
94
+ }
95
+ }
96
+
97
+ window.customElements.define('pmui-editbox', EditBox)
lib/menus/components/food_bar.js ADDED
@@ -0,0 +1,117 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { LitElement, html, css } = require('lit')
2
+
3
+ class FoodBar extends LitElement {
4
+ static get styles () {
5
+ return css`
6
+ .foodbar {
7
+ position: absolute;
8
+ display: flex;
9
+ flex-direction: row-reverse;
10
+ left: calc(50% + 91px);
11
+ transform: translate(-100%);
12
+ bottom: 30px;
13
+ --lightened: 0;
14
+ --offset: calc(-1 * (52px));
15
+ --bg-x: calc(-1 * (16px + 9px * var(--lightened)));
16
+ --bg-y: calc(-1 * 27px);
17
+ }
18
+
19
+ .food {
20
+ width: 9px;
21
+ height: 9px;
22
+ background-image: url('textures/1.17.1/gui/icons.png'), url('textures/1.17.1/gui/icons.png');
23
+ background-size: 256px, 256px;
24
+ background-position: var(--bg-x) var(--bg-y), var(--bg-x) var(--bg-y);
25
+ margin-left: -1px;
26
+ }
27
+
28
+ .food.full {
29
+ background-position: var(--offset) var(--bg-y), var(--bg-x) var(--bg-y);
30
+ }
31
+
32
+ .food.half {
33
+ background-position: calc(var(--offset) - 9px) var(--bg-y), var(--bg-x) var(--bg-y);
34
+ }
35
+
36
+ .foodbar.low .food {
37
+ animation: lowHungerAnim 0.2s steps(2, end) infinite;
38
+ }
39
+
40
+ .foodbar.low .food:nth-of-type(2n) {
41
+ animation-direction: reverse;
42
+ }
43
+
44
+ .foodbar.low .food:nth-of-type(3n) {
45
+ animation-duration: 0.1s;
46
+ }
47
+
48
+ .foodbar.updated {
49
+ animation: updatedAnim 0.3s steps(2, end) 2;
50
+ }
51
+
52
+ @keyframes lowHungerAnim {
53
+ to { transform: translateY(1px); }
54
+ }
55
+
56
+ @keyframes updatedAnim {
57
+ to { --lightened: 1; }
58
+ }
59
+ `
60
+ }
61
+
62
+ gameModeChanged (gamemode) {
63
+ this.shadowRoot.querySelector('#foodbar').classList.toggle('creative', gamemode === 1)
64
+ }
65
+
66
+ onHungerUpdate () {
67
+ this.shadowRoot.querySelector('#foodbar').classList.toggle('updated', true)
68
+ if (this.hungerTimeout) clearTimeout(this.hungerTimeout)
69
+ this.hungerTimeout = setTimeout(() => {
70
+ this.shadowRoot.querySelector('#foodbar').classList.toggle('updated', false)
71
+ this.hungerTimeout = null
72
+ }, 1000)
73
+ }
74
+
75
+ updateHunger (hValue, d) {
76
+ const foodbar = this.shadowRoot.querySelector('#foodbar')
77
+ foodbar.classList.toggle('low', hValue <= 5)
78
+
79
+ const foods = foodbar.children
80
+
81
+ for (let i = 0; i < foods.length; i++) {
82
+ foods[i].classList.remove('full')
83
+ foods[i].classList.remove('half')
84
+ }
85
+
86
+ // if (d) this.onHungerUpdate()
87
+
88
+ for (let i = 0; i < Math.ceil(hValue / 2); i++) {
89
+ if (i >= foods.length) break
90
+
91
+ if (hValue % 2 !== 0 && Math.ceil(hValue / 2) === i + 1) {
92
+ foods[i].classList.add('half')
93
+ } else {
94
+ foods[i].classList.add('full')
95
+ }
96
+ }
97
+ }
98
+
99
+ render () {
100
+ return html`
101
+ <div id="foodbar" class="foodbar" data-value="4">
102
+ <div class="food"></div>
103
+ <div class="food"></div>
104
+ <div class="food"></div>
105
+ <div class="food"></div>
106
+ <div class="food"></div>
107
+ <div class="food"></div>
108
+ <div class="food"></div>
109
+ <div class="food"></div>
110
+ <div class="food"></div>
111
+ <div class="food"></div>
112
+ </div>
113
+ `
114
+ }
115
+ }
116
+
117
+ window.customElements.define('pmui-foodbar', FoodBar)
lib/menus/components/health_bar.js ADDED
@@ -0,0 +1,158 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { LitElement, html, css } = require('lit')
2
+
3
+ function getEffectClass (effect) {
4
+ switch (effect.id) {
5
+ case 19: return 'poisoned'
6
+ case 20: return 'withered'
7
+ case 22: return 'absorption'
8
+ default: return ''
9
+ }
10
+ }
11
+
12
+ class HealthBar extends LitElement {
13
+ static get styles () {
14
+ return css`
15
+ .health {
16
+ position: absolute;
17
+ display: flex;
18
+ flex-direction: row;
19
+ left: calc(50% - 91px);
20
+ bottom: 30px;
21
+ --hardcore: 0;
22
+ --kind: 0;
23
+ --lightened: 0;
24
+ --offset: calc(-1 * (52px + (9px * (4 * var(--kind) + var(--lightened) * 2)) ));
25
+ --bg-x: calc(-1 * (16px + 9px * var(--lightened)));
26
+ --bg-y: calc(-1 * var(--hardcore) * 45px);
27
+ }
28
+
29
+ .health.creative {
30
+ display: none;
31
+ }
32
+
33
+ .health.hardcore {
34
+ --hardcore: 1;
35
+ }
36
+
37
+ .health.poisoned {
38
+ --kind: 1;
39
+ }
40
+
41
+ .health.withered {
42
+ --kind: 2;
43
+ }
44
+
45
+ .health.absorption {
46
+ --kind: 3;
47
+ }
48
+
49
+ .heart {
50
+ width: 9px;
51
+ height: 9px;
52
+ background-image: url('textures/1.17.1/gui/icons.png'), url('textures/1.17.1/gui/icons.png');
53
+ background-size: 256px, 256px;
54
+ background-position: var(--bg-x) var(--bg-y), var(--bg-x) var(--bg-y);
55
+ margin-left: -1px;
56
+ }
57
+
58
+ .heart.full {
59
+ background-position: var(--offset) var(--bg-y), var(--bg-x) var(--bg-y);
60
+ }
61
+
62
+ .heart.half {
63
+ background-position: calc(var(--offset) - 9px) var(--bg-y), var(--bg-x) var(--bg-y);
64
+ }
65
+
66
+ .health.low .heart {
67
+ animation: lowHealthAnim 0.2s steps(2, end) infinite;
68
+ }
69
+
70
+ .health.low .heart:nth-of-type(2n) {
71
+ animation-direction: reverse;
72
+ }
73
+
74
+ .health.low .heart:nth-of-type(3n) {
75
+ animation-duration: 0.1s;
76
+ }
77
+
78
+ .health.damaged {
79
+ animation: damagedAnim 0.3s steps(2, end) 2;
80
+ }
81
+
82
+ @keyframes lowHealthAnim {
83
+ to {
84
+ transform: translateY(1px);
85
+ }
86
+ }
87
+
88
+ @keyframes damagedAnim {
89
+ to { --lightened: 1; }
90
+ }
91
+ `
92
+ }
93
+
94
+ effectAdded (effect) {
95
+ this.shadowRoot.querySelector('#health').classList.add(getEffectClass(effect))
96
+ }
97
+
98
+ effectEnded (effect) {
99
+ this.shadowRoot.querySelector('#health').classList.remove(getEffectClass(effect))
100
+ }
101
+
102
+ onDamage () {
103
+ this.shadowRoot.querySelector('#health').classList.toggle('damaged', true)
104
+ if (this.hurtTimeout) clearTimeout(this.hurtTimeout)
105
+ this.hurtTimeout = setTimeout(() => {
106
+ this.shadowRoot.querySelector('#health').classList.toggle('damaged', false)
107
+ this.hurtTimeout = null
108
+ }, 1000)
109
+ }
110
+
111
+ gameModeChanged (gamemode, hardcore) {
112
+ this.shadowRoot.querySelector('#health').classList.toggle('creative', gamemode === 1)
113
+ this.shadowRoot.querySelector('#health').classList.toggle('hardcore', hardcore)
114
+ }
115
+
116
+ updateHealth (hValue, d) {
117
+ const health = this.shadowRoot.querySelector('#health')
118
+ health.classList.toggle('low', hValue <= 4)
119
+
120
+ const hearts = health.children
121
+
122
+ for (let i = 0; i < hearts.length; i++) {
123
+ hearts[i].classList.remove('full')
124
+ hearts[i].classList.remove('half')
125
+ }
126
+
127
+ if (d) this.onDamage()
128
+
129
+ for (let i = 0; i < Math.ceil(hValue / 2); i++) {
130
+ if (i >= hearts.length) break
131
+
132
+ if (hValue % 2 !== 0 && Math.ceil(hValue / 2) === i + 1) {
133
+ hearts[i].classList.add('half')
134
+ } else {
135
+ hearts[i].classList.add('full')
136
+ }
137
+ }
138
+ }
139
+
140
+ render () {
141
+ return html`
142
+ <div id="health" class="health">
143
+ <div class="heart"></div>
144
+ <div class="heart"></div>
145
+ <div class="heart"></div>
146
+ <div class="heart"></div>
147
+ <div class="heart"></div>
148
+ <div class="heart"></div>
149
+ <div class="heart"></div>
150
+ <div class="heart"></div>
151
+ <div class="heart"></div>
152
+ <div class="heart"></div>
153
+ </div>
154
+ `
155
+ }
156
+ }
157
+
158
+ window.customElements.define('pmui-healthbar', HealthBar)
lib/menus/components/hotbar.js ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { LitElement, html, css } = require('lit')
2
+ const invsprite = require('../../invsprite.json')
3
+
4
+ class Hotbar extends LitElement {
5
+ static get styles () {
6
+ return css`
7
+ .hotbar {
8
+ position: absolute;
9
+ bottom: 0;
10
+ left: 50%;
11
+ transform: translate(-50%);
12
+ width: 182px;
13
+ height: 22px;
14
+ background: url("textures/1.16.4/gui/widgets.png");
15
+ background-size: 256px;
16
+ }
17
+
18
+ #hotbar-selected {
19
+ position: absolute;
20
+ left: -1px;
21
+ top: -1px;
22
+ width: 24px;
23
+ height: 24px;
24
+ background: url("textures/1.16.4/gui/widgets.png");
25
+ background-size: 256px;
26
+ background-position-y: -22px;
27
+ }
28
+
29
+ #hotbar-items-wrapper {
30
+ position: absolute;
31
+ top: 0;
32
+ left: 1px;
33
+ display: flex;
34
+ flex-direction: row;
35
+ height: 22px;
36
+ margin: 0;
37
+ padding: 0;
38
+ }
39
+
40
+ .hotbar-item {
41
+ position: relative;
42
+ width: 20px;
43
+ height: 22px;
44
+ }
45
+
46
+ .item-icon {
47
+ top: 3px;
48
+ left: 2px;
49
+ position: absolute;
50
+ width: 32px;
51
+ height: 32px;
52
+ transform-origin: top left;
53
+ transform: scale(0.5);
54
+ background-image: url('invsprite.png');
55
+ background-size: 1024px auto;
56
+ }
57
+
58
+ .item-stack {
59
+ position: absolute;
60
+ color: white;
61
+ font-size: 10px;
62
+ text-shadow: 1px 1px 0 rgb(63, 63, 63);
63
+ right: 1px;
64
+ bottom: 1px;
65
+ }
66
+
67
+ #hotbar-item-name {
68
+ color: white;
69
+ position: absolute;
70
+ bottom: 51px;
71
+ left: 50%;
72
+ transform: translate(-50%);
73
+ text-shadow: rgb(63, 63, 63) 1px 1px 0px;
74
+ font-family: mojangles, minecraft, monospace;
75
+ font-size: 10px;
76
+ text-align: center;
77
+ }
78
+
79
+ .hotbar-item-name-fader {
80
+ opacity: 0;
81
+ transition: visibility 0s, opacity 1s linear;
82
+ transition-delay: 2s;
83
+ }
84
+ `
85
+ }
86
+
87
+ static get properties () {
88
+ return {
89
+ activeItemName: { type: String },
90
+ bot: { type: Object },
91
+ viewerVersion: { type: String }
92
+ }
93
+ }
94
+
95
+ constructor () {
96
+ super()
97
+ this.activeItemName = ''
98
+ }
99
+
100
+ updated (changedProperties) {
101
+ if (changedProperties.has('bot')) {
102
+ // inventory listener
103
+ this.bot.once('spawn', () => {
104
+ this.init()
105
+ })
106
+ }
107
+ }
108
+
109
+ init () {
110
+ this.reloadHotbar()
111
+ this.reloadHotbarSelected(0)
112
+
113
+ document.addEventListener('wheel', (e) => {
114
+ const newSlot = ((this.bot.quickBarSlot + Math.sign(e.deltaY)) % 9 + 9) % 9
115
+ this.reloadHotbarSelected(newSlot)
116
+ })
117
+
118
+ document.addEventListener('keydown', (e) => {
119
+ const numPressed = e.code.substr(5)
120
+ if (numPressed < 1 || numPressed > 9) return
121
+ this.reloadHotbarSelected(numPressed - 1)
122
+ })
123
+
124
+ this.bot.inventory.on('updateSlot', (slot, oldItem, newItem) => {
125
+ if (slot >= this.bot.inventory.hotbarStart + 9) return
126
+ if (slot < this.bot.inventory.hotbarStart) return
127
+
128
+ const sprite = newItem ? invsprite[newItem.name] : invsprite.air
129
+ const slotEl = this.shadowRoot.getElementById('hotbar-' + (slot - this.bot.inventory.hotbarStart))
130
+ const slotIcon = slotEl.children[0]
131
+ const slotStack = slotEl.children[1]
132
+ slotIcon.style['background-position-x'] = `-${sprite.x}px`
133
+ slotIcon.style['background-position-y'] = `-${sprite.y}px`
134
+ slotStack.innerHTML = newItem?.count > 1 ? newItem.count : ''
135
+ })
136
+ }
137
+
138
+ async reloadHotbar () {
139
+ for (let i = 0; i < 9; i++) {
140
+ const item = this.bot.inventory.slots[this.bot.inventory.hotbarStart + i]
141
+ const sprite = item ? invsprite[item.name] : invsprite.air
142
+ const slotEl = this.shadowRoot.getElementById('hotbar-' + i)
143
+ const slotIcon = slotEl.children[0]
144
+ const slotStack = slotEl.children[1]
145
+ slotIcon.style['background-position-x'] = `-${sprite.x}px`
146
+ slotIcon.style['background-position-y'] = `-${sprite.y}px`
147
+ slotStack.innerHTML = item?.count > 1 ? item.count : ''
148
+ }
149
+ }
150
+
151
+ async reloadHotbarSelected (slot) {
152
+ const item = this.bot.inventory.slots[this.bot.inventory.hotbarStart + slot]
153
+ const newLeftPos = (-1 + 20 * slot) + 'px'
154
+ this.shadowRoot.getElementById('hotbar-selected').style.left = newLeftPos
155
+ this.bot.setQuickBarSlot(slot)
156
+ this.activeItemName = item?.displayName ?? ''
157
+ const name = this.shadowRoot.getElementById('hotbar-item-name')
158
+ name.classList.remove('hotbar-item-name-fader')
159
+ setTimeout(() => name.classList.add('hotbar-item-name-fader'), 10)
160
+ }
161
+
162
+ render () {
163
+ return html`
164
+ <div class="hotbar">
165
+ <p id="hotbar-item-name">${this.activeItemName}</p>
166
+ <div id="hotbar-selected"></div>
167
+ <div id="hotbar-items-wrapper">
168
+ <div class="hotbar-item" id="hotbar-0">
169
+ <div class="item-icon"></div>
170
+ <span class="item-stack"></span>
171
+ </div>
172
+ <div class="hotbar-item" id="hotbar-1">
173
+ <div class="item-icon"></div>
174
+ <span class="item-stack"></span>
175
+ </div>
176
+ <div class="hotbar-item" id="hotbar-2">
177
+ <div class="item-icon"></div>
178
+ <span class="item-stack"></span>
179
+ </div>
180
+ <div class="hotbar-item" id="hotbar-3">
181
+ <div class="item-icon"></div>
182
+ <span class="item-stack"></span>
183
+ </div>
184
+ <div class="hotbar-item" id="hotbar-4">
185
+ <div class="item-icon"></div>
186
+ <span class="item-stack"></span>
187
+ </div>
188
+ <div class="hotbar-item" id="hotbar-5">
189
+ <div class="item-icon"></div>
190
+ <span class="item-stack"></span>
191
+ </div>
192
+ <div class="hotbar-item" id="hotbar-6">
193
+ <div class="item-icon"></div>
194
+ <span class="item-stack"></span>
195
+ </div>
196
+ <div class="hotbar-item" id="hotbar-7">
197
+ <div class="item-icon"></div>
198
+ <span class="item-stack"></span>
199
+ </div>
200
+ <div class="hotbar-item" id="hotbar-8">
201
+ <div class="item-icon"></div>
202
+ <span class="item-stack"></span>
203
+ </div>
204
+ </div>
205
+ </div>
206
+ `
207
+ }
208
+ }
209
+
210
+ window.customElements.define('pmui-hotbar', Hotbar)
lib/menus/components/playerlist_overlay.js ADDED
@@ -0,0 +1,179 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { LitElement, html, css } = require('lit')
2
+
3
+ const MAX_ROWS_PER_COL = 10
4
+
5
+ class PlayerListOverlay extends LitElement {
6
+ static get styles () {
7
+ return css`
8
+ .playerlist-container {
9
+ position: absolute;
10
+ background-color: rgba(0, 0, 0, 0.3);
11
+ top: 9px;
12
+ left: 50%;
13
+ transform: translate(-50%);
14
+ width: fit-content;
15
+ padding: 1px;
16
+ display: flex;
17
+ flex-direction: column;
18
+ gap: 1px 0;
19
+ place-items: center;
20
+ z-index: 30;
21
+ }
22
+
23
+ .title {
24
+ color: white;
25
+ text-shadow: 1px 1px 0px #3f3f3f;
26
+ font-size: 10px;
27
+ margin: 0;
28
+ padding: 0;
29
+ }
30
+
31
+ .playerlist-entry {
32
+ overflow: hidden;
33
+ color: white;
34
+ font-size: 10px;
35
+ margin: 0px;
36
+ line-height: calc(100% - 1px);
37
+ text-shadow: 1px 1px 0px #3f3f3f;
38
+ font-family: mojangles, minecraft, monospace;
39
+ background: rgba(255, 255, 255, 0.1);
40
+ width: 100%;
41
+ }
42
+
43
+ .active-player {
44
+ color: rgb(42, 204, 237);
45
+ text-shadow: 1px 1px 0px rgb(4, 44, 67);
46
+ }
47
+
48
+ .playerlist-ping {
49
+ text-align: right;
50
+ float: right;
51
+ padding-left: 10px;
52
+ }
53
+
54
+ .playerlist-ping-value {
55
+ color: rgb(114, 255, 114);
56
+ text-shadow: 1px 1px 0px rgb(28, 105, 28);
57
+ float: left;
58
+ margin: 0;
59
+ margin-right: 1px;
60
+ }
61
+
62
+ .playerlist-ping-label {
63
+ text-shadow: 1px 1px 0px #3f3f3f;
64
+ color: white;
65
+ float: right;
66
+ margin: 0px;
67
+ }
68
+
69
+ .player-lists {
70
+ display: flex;
71
+ flex-direction: row;
72
+ place-items: center;
73
+ place-content: center;
74
+ gap: 0 4px;
75
+ }
76
+
77
+ .player-list {
78
+ display: flex;
79
+ flex-direction: column;
80
+ gap: 1px 0;
81
+ min-width: 80px;
82
+ }
83
+ `
84
+ }
85
+
86
+ static get properties () {
87
+ return {
88
+ serverIP: { type: String },
89
+ clientId: { type: String },
90
+ players: { type: Object }
91
+ }
92
+ }
93
+
94
+ constructor () {
95
+ super()
96
+ this.serverIP = ''
97
+ this.clientId = ''
98
+ this.players = {}
99
+ }
100
+
101
+ init (bot, ip) {
102
+ const playerList = this.shadowRoot.querySelector('#playerlist-container')
103
+
104
+ this.isOpen = false
105
+ this.players = bot.players
106
+ this.clientId = bot.player.uuid
107
+ this.serverIP = ip
108
+
109
+ this.requestUpdate()
110
+
111
+ const showList = (shouldShow = true) => {
112
+ playerList.style.display = shouldShow ? 'block' : 'none'
113
+ this.isOpen = shouldShow
114
+ }
115
+
116
+ document.addEventListener('keydown', e => {
117
+ e ??= window.event
118
+ if (e.key === 'Tab') {
119
+ showList(true)
120
+ e.preventDefault()
121
+ }
122
+ })
123
+
124
+ document.addEventListener('keyup', e => {
125
+ if (!this.isOpen) return
126
+ e ??= window.event
127
+ if (e.key === 'Tab') {
128
+ showList(false)
129
+ e.preventDefault()
130
+ }
131
+ })
132
+
133
+ bot.on('playerUpdated', () => this.requestUpdate()) // LitElement seems to be batching requests, so it should be fine?
134
+ bot.on('playerJoined', () => this.requestUpdate())
135
+ bot.on('playerLeft', () => this.requestUpdate())
136
+ }
137
+
138
+ render () {
139
+ const lists = []
140
+ const players = Object.values(this.players).sort((a, b) => {
141
+ if (a.username > b.username) return 1
142
+ if (a.username < b.username) return -1
143
+ return 0
144
+ })
145
+
146
+ let tempList = []
147
+ for (let i = 0; i < players.length; i++) {
148
+ tempList.push(players[i])
149
+
150
+ if ((i + 1) / MAX_ROWS_PER_COL === 1 || i + 1 === players.length) {
151
+ lists.push([...tempList])
152
+ tempList = []
153
+ }
154
+ }
155
+
156
+ return html`
157
+ <div class="playerlist-container" id="playerlist-container" style="display: none;">
158
+ <span class="title">Server IP: ${this.serverIP}</span>
159
+ <div class="player-lists">
160
+ ${lists.map(list => html`
161
+ <div class="player-list">
162
+ ${list.map(player => html`
163
+ <div class="playerlist-entry${this.clientId === player.uuid ? ' active-player' : ''}" id="plist-player-${player.uuid}">
164
+ ${player.username}
165
+ <div class="playerlist-ping">
166
+ <p class="playerlist-ping-value">${player.ping}</p>
167
+ <p class="playerlist-ping-label">ms</p>
168
+ </div>
169
+ </div>
170
+ `)}
171
+ </div>
172
+ `)}
173
+ </div>
174
+ </div>
175
+ `
176
+ }
177
+ }
178
+
179
+ window.customElements.define('pmui-playerlist-overlay', PlayerListOverlay)
lib/menus/components/slider.js ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { LitElement, html, css } = require('lit')
2
+
3
+ class Slider extends LitElement {
4
+ static get styles () {
5
+ return css`
6
+ .slider-container {
7
+ --txrV: -46px;
8
+ position: relative;
9
+ width: 150px;
10
+ height: 20px;
11
+ font-family: minecraft, mojangles, monospace;
12
+ font-size: 10px;
13
+ color: white;
14
+ text-shadow: 1px 1px #220;
15
+ z-index: 1;
16
+ }
17
+
18
+ .slider-thumb {
19
+ --txrV: -66px;
20
+ pointer-events: none;
21
+ width: 8px;
22
+ height: 20px;
23
+ position: absolute;
24
+ top: 0;
25
+ left: 0;
26
+ z-index: 3;
27
+ }
28
+
29
+ .slider-container:hover .slider-thumb {
30
+ --txrV: -86px;
31
+ }
32
+
33
+ .slider-container::after,
34
+ .slider-thumb::after {
35
+ content: '';
36
+ display: block;
37
+ position: absolute;
38
+ top: 0;
39
+ left: 0;
40
+ width: 50%;
41
+ height: 20px;
42
+ background: url('textures/1.17.1/gui/widgets.png');
43
+ background-size: 256px;
44
+ background-position-y: var(--txrV);
45
+ z-index: -1;
46
+ }
47
+
48
+ .slider-container::before,
49
+ .slider-thumb::before {
50
+ content: '';
51
+ display: block;
52
+ position: absolute;
53
+ top: 0;
54
+ left: 50%;
55
+ width: 50%;
56
+ height: 20px;
57
+ background: url('textures/1.17.1/gui/widgets.png');
58
+ background-size: 256px;
59
+ background-position-x: calc(-200px + 100%);
60
+ background-position-y: var(--txrV);
61
+ z-index: -1;
62
+ }
63
+
64
+ .slider {
65
+ display: block;
66
+ position: absolute;
67
+ top: 0;
68
+ left: 0;
69
+ -webkit-appearance: none;
70
+ appearance: none;
71
+ background: none;
72
+ width: 100%;
73
+ height: 20px;
74
+ margin: 0;
75
+ }
76
+
77
+ .slider::-webkit-slider-thumb {
78
+ -webkit-appearance: none;
79
+ position: relative;
80
+ appearance: none;
81
+ width: 8px;
82
+ height: 20px;
83
+ background: transparent;
84
+ }
85
+
86
+ .slider::-moz-range-thumb {
87
+ width: 8px;
88
+ height: 20px;
89
+ background: transparent;
90
+ }
91
+
92
+ label {
93
+ pointer-events: none;
94
+ position: absolute;
95
+ top: 50%;
96
+ left: 50%;
97
+ transform: translate(-50%, -50%);
98
+ z-index: 6;
99
+ width: max-content;
100
+ }
101
+ `
102
+ }
103
+
104
+ constructor () {
105
+ super()
106
+ this.label = ''
107
+ this.type = '%'
108
+ this.width = '150px'
109
+ this.value = '50'
110
+ this.min = '0'
111
+ this.max = '100'
112
+ this.ratio = (Number(this.value) - Number(this.min)) / (Number(this.max) - Number(this.min))
113
+ }
114
+
115
+ updated () {
116
+ this.ratio = (Number(this.value) - Number(this.min)) / (Number(this.max) - Number(this.min))
117
+ }
118
+
119
+ static get properties () {
120
+ return {
121
+ label: {
122
+ type: String,
123
+ attribute: 'pmui-label'
124
+ },
125
+ type: {
126
+ type: String,
127
+ attribute: 'pmui-type'
128
+ },
129
+ width: {
130
+ type: String,
131
+ attribute: 'pmui-width'
132
+ },
133
+ value: {
134
+ type: String,
135
+ attribute: 'pmui-value'
136
+ },
137
+ min: {
138
+ type: String,
139
+ attribute: 'pmui-min'
140
+ },
141
+ max: {
142
+ type: String,
143
+ attribute: 'pmui-max'
144
+ },
145
+ ratio: { type: Number }
146
+ }
147
+ }
148
+
149
+ render () {
150
+ return html`
151
+ <div
152
+ class="slider-container"
153
+ style="width: ${this.width};"
154
+ >
155
+ <input
156
+ type="range"
157
+ class="slider"
158
+ min="${this.min}"
159
+ max="${this.max}"
160
+ value="${this.value}"
161
+ @input=${(e) => {
162
+ const range = e.target
163
+ this.ratio = (range.value - range.min) / (range.max - range.min)
164
+ this.value = range.value
165
+ }}>
166
+ <div
167
+ class="slider-thumb"
168
+ style="left: calc((100% * ${this.ratio}) - (8px * ${this.ratio}));"
169
+ ></div>
170
+ <label>${this.label}: ${this.value}${this.type}</label>
171
+ </div>
172
+ `
173
+ }
174
+ }
175
+
176
+ window.customElements.define('pmui-slider', Slider)
lib/menus/hud.js ADDED
@@ -0,0 +1,370 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { LitElement, html, css } = require('lit')
2
+ const { isMobile } = require('./components/common')
3
+
4
+ class Hud extends LitElement {
5
+ static get styles () {
6
+ return css`
7
+ :host {
8
+ position: absolute;
9
+ top: 0;
10
+ left: 0;
11
+ z-index: -2;
12
+ width: 100%;
13
+ height: 100%;
14
+ }
15
+
16
+ .crosshair {
17
+ width: 16px;
18
+ height: 16px;
19
+ background: url('textures/1.17.1/gui/icons.png');
20
+ background-size: 256px;
21
+ position: absolute;
22
+ top: 50%;
23
+ left: 50%;
24
+ transform: translate(-50%, -50%);
25
+ z-index: 2;
26
+ }
27
+
28
+ #xp-label {
29
+ position: absolute;
30
+ top: -8px;
31
+ left: 50%;
32
+ transform: translate(-50%);
33
+ font-size: 10px;
34
+ font-family: minecraft, mojangles, monospace;
35
+ color: rgb(30, 250, 30);
36
+ text-shadow: 0px -1px #000, 0px 1px #000, 1px 0px #000, -1px 0px #000;
37
+ z-index: 10;
38
+ }
39
+
40
+ #xp-bar-bg {
41
+ position: absolute;
42
+ left: 50%;
43
+ bottom: 24px;
44
+ transform: translate(-50%);
45
+ width: 182px;
46
+ height: 5px;
47
+ background-image: url('textures/1.16.4/gui/icons.png');
48
+ background-size: 256px;
49
+ background-position-y: -64px;
50
+ }
51
+
52
+ .xp-bar {
53
+ width: 182px;
54
+ height: 5px;
55
+ background-image: url('textures/1.17.1/gui/icons.png');
56
+ background-size: 256px;
57
+ background-position-y: -69px;
58
+ }
59
+
60
+ .mobile-top-btns {
61
+ display: none;
62
+ flex-direction: row;
63
+ position: absolute;
64
+ top: 0;
65
+ left: 50%;
66
+ transform: translate(-50%);
67
+ gap: 0 1px;
68
+ z-index: 20;
69
+ }
70
+
71
+ .pause-btn,
72
+ .chat-btn {
73
+ border: none;
74
+ outline: none;
75
+ width: 18px;
76
+ height: 18px;
77
+ background-image: url('extra-textures/gui.png');
78
+ background-size: 256px;
79
+ background-position-x: -200px;
80
+ background-position-y: -64px;
81
+ }
82
+
83
+ .chat-btn {
84
+ background-position-y: -82px;
85
+ }
86
+
87
+ .mobile-control-forward,
88
+ .mobile-control-back,
89
+ .mobile-control-left,
90
+ .mobile-control-sneak,
91
+ .mobile-control-jump,
92
+ .mobile-control-right {
93
+ position: absolute;
94
+ width: 22px;
95
+ height: 22px;
96
+ background-image: url('extra-textures/gui.png');
97
+ background-size: 256px;
98
+ border: none;
99
+ outline: none;
100
+ }
101
+
102
+ .mobile-control-forward:active,
103
+ .mobile-control-back:active,
104
+ .mobile-control-sneak:active,
105
+ .mobile-control-left:active,
106
+ .mobile-control-jump:active,
107
+ .mobile-control-right:active {
108
+ filter: brightness(85%);
109
+ }
110
+
111
+ .mobile-control-forward {
112
+ top: 0;
113
+ left: 50%;
114
+ transform: translate(-50%);
115
+ background-position: -2px -109px;
116
+ }
117
+
118
+ .mobile-control-back {
119
+ bottom: 0;
120
+ left: 50%;
121
+ transform: translate(-50%);
122
+ background-position: -54px -109px;
123
+ }
124
+
125
+ .mobile-control-left {
126
+ top: 50%;
127
+ left: 0;
128
+ transform: translate(0, -50%);
129
+ background-position: -28px -109px;
130
+ }
131
+
132
+ .mobile-control-right {
133
+ top: 50%;
134
+ right: 0;
135
+ transform: translate(0, -50%);
136
+ background-position: -80px -109px;
137
+ }
138
+
139
+ .mobile-control-jump {
140
+ position: relative;
141
+ width: 18px;
142
+ height: 18px;
143
+ background-position: -108px -111px;
144
+ }
145
+
146
+ .mobile-control-sneak {
147
+ width: 18px;
148
+ height: 18px;
149
+ top: 50%;
150
+ left: 50%;
151
+ transform: translate(-50%, -50%);
152
+ background-position: -218px -82px;
153
+ }
154
+ .mobile-control-sneak.is-down {
155
+ background-position: -218px -64px;
156
+ }
157
+
158
+ .mobile-controls-left {
159
+ display: none;
160
+ position: absolute;
161
+ left: 8px;
162
+ bottom: 0;
163
+ width: 70px;
164
+ height: 70px;
165
+ z-index: 30;
166
+ opacity: 0.65;
167
+ transform-origin: bottom left;
168
+ transform: scale(1.5);
169
+ }
170
+
171
+ .mobile-controls-right {
172
+ display: none;
173
+ flex-direction: column;
174
+ place-items: center;
175
+ place-content: center;
176
+ position: absolute;
177
+ right: 20px;
178
+ bottom: 0;
179
+ width: 22px;
180
+ height: 70px;
181
+ z-index: 30;
182
+ opacity: 0.65;
183
+ transform-origin: bottom right;
184
+ transform: scale(1.5);
185
+ }
186
+ `
187
+ }
188
+
189
+ static get properties () {
190
+ return {
191
+ bot: { type: Object }
192
+ }
193
+ }
194
+
195
+ /**
196
+ * @param {import('mineflayer').Bot} bot
197
+ */
198
+ preload (bot) {
199
+ const bossBars = this.shadowRoot.querySelector('#bossbars-overlay')
200
+ bossBars.bot = bot
201
+
202
+ bossBars.init()
203
+ }
204
+
205
+ /**
206
+ * @param {globalThis.THREE.Renderer} renderer
207
+ * @param {import('mineflayer').Bot} bot
208
+ * @param {string} host
209
+ */
210
+ init (renderer, bot, host) {
211
+ const debugMenu = this.shadowRoot.querySelector('#debug-overlay')
212
+ const playerList = this.shadowRoot.querySelector('#playerlist-overlay')
213
+ const healthbar = this.shadowRoot.querySelector('#health-bar')
214
+ const foodbar = this.shadowRoot.querySelector('#food-bar')
215
+ // const breathbar = this.shadowRoot.querySelector('#breath-bar')
216
+ const chat = this.shadowRoot.querySelector('#chat')
217
+ const hotbar = this.shadowRoot.querySelector('#hotbar')
218
+ const xpLabel = this.shadowRoot.querySelector('#xp-label')
219
+
220
+ this.bot = bot
221
+ hotbar.bot = bot
222
+ debugMenu.bot = bot
223
+
224
+ hotbar.init()
225
+ chat.init(bot._client, renderer)
226
+ bot.on('spawn', () => playerList.init(bot, host))
227
+
228
+ bot.on('entityHurt', (entity) => {
229
+ if (entity !== bot.entity) return
230
+ healthbar.onDamage()
231
+ })
232
+
233
+ bot.on('entityEffect', (entity, effect) => {
234
+ if (entity !== bot.entity) return
235
+ healthbar.effectAdded(effect)
236
+ })
237
+
238
+ bot.on('entityEffectEnd', (entity, effect) => {
239
+ if (entity !== bot.entity) return
240
+ healthbar.effectEnded(effect)
241
+ })
242
+
243
+ bot.on('game', () => {
244
+ healthbar.gameModeChanged(bot.player.gamemode, bot.game.hardcore)
245
+ foodbar.gameModeChanged(bot.player.gamemode)
246
+ // breathbar.gameModeChanged(bot.player.gamemode)
247
+ this.shadowRoot.querySelector('#xp-bar-bg').style.display = bot.player.gamemode === 1 ? 'none' : 'block'
248
+ })
249
+
250
+ bot.on('health', () => {
251
+ healthbar.updateHealth(bot.health, true)
252
+ foodbar.updateHunger(bot.food, true)
253
+ })
254
+
255
+ bot.on('experience', () => {
256
+ this.shadowRoot.querySelector('#xp-bar-bg').firstElementChild.style.width = `${182 * bot.experience.progress}px`
257
+ xpLabel.innerHTML = bot.experience.level
258
+ xpLabel.style.display = bot.experience.level > 0 ? 'block' : 'none'
259
+ })
260
+
261
+ // bot.on('breath', () => {
262
+ // breathbar.updateOxygen(bot.oxygenLevel)
263
+ // })
264
+
265
+ bot.on('spawn', () => {
266
+ this.shadowRoot.querySelector('#xp-bar-bg').style.display = bot.player.gamemode === 1 ? 'none' : 'block'
267
+ this.shadowRoot.querySelector('#xp-bar-bg').firstElementChild.style.width = `${182 * bot.experience.progress}px`
268
+ xpLabel.innerHTML = bot.experience.level
269
+ xpLabel.style.display = bot.experience.level > 0 ? 'block' : 'none'
270
+ healthbar.gameModeChanged(bot.player.gamemode, bot.game.hardcore)
271
+ healthbar.updateHealth(bot.health)
272
+ foodbar.updateHunger(bot.food)
273
+ // breathbar.updateOxygen(bot.oxygenLevel ?? 20)
274
+ })
275
+
276
+ if (document.getElementById('options-screen').forceMobileControls || isMobile()) {
277
+ this.showMobileControls(true)
278
+ } else {
279
+ this.showMobileControls(false)
280
+ }
281
+ }
282
+
283
+ /** @param {boolean} bl */
284
+ showMobileControls (bl) {
285
+ this.shadowRoot.querySelector('#mobile-top').style.display = bl ? 'flex' : 'none'
286
+ this.shadowRoot.querySelector('#mobile-left').style.display = bl ? 'block' : 'none'
287
+ this.shadowRoot.querySelector('#mobile-right').style.display = bl ? 'flex' : 'none'
288
+ }
289
+
290
+ /**
291
+ * @param {string} id
292
+ * @param {boolean} action
293
+ */
294
+ mobileControl (e, id, action) {
295
+ e.stopPropagation()
296
+ this.bot.setControlState(id, action)
297
+ }
298
+
299
+ render () {
300
+ return html`
301
+ <div class="mobile-top-btns" id="mobile-top">
302
+ <button class="chat-btn" @click=${(e) => {
303
+ e.stopPropagation()
304
+ this.shadowRoot.querySelector('#chat').enableChat(false)
305
+ }}></button>
306
+ <button class="pause-btn" @click=${(e) => {
307
+ e.stopPropagation()
308
+ document.getElementById('pause-screen').enableGameMenu()
309
+ }}></button>
310
+ </div>
311
+ <div class="mobile-controls-left" id="mobile-left">
312
+ <button
313
+ class="mobile-control-forward"
314
+ @touchstart=${(e) => this.mobileControl(e, 'forward', true)}
315
+ @touchend=${(e) => this.mobileControl(e, 'forward', false)}
316
+ @mousedown=${(e) => this.mobileControl(e, 'forward', true)}
317
+ @mouseup=${(e) => this.mobileControl(e, 'forward', false)}
318
+ ></button>
319
+ <button
320
+ class="mobile-control-back"
321
+ @touchstart=${(e) => this.mobileControl(e, 'back', true)}
322
+ @touchend=${(e) => this.mobileControl(e, 'back', false)}
323
+ @mousedown=${(e) => this.mobileControl(e, 'back', true)}
324
+ @mouseup=${(e) => this.mobileControl(e, 'back', false)}
325
+ ></button>
326
+ <button class="mobile-control-left"
327
+ @touchstart=${(e) => this.mobileControl(e, 'right', true)}
328
+ @touchend=${(e) => this.mobileControl(e, 'right', false)}
329
+ @mousedown=${(e) => this.mobileControl(e, 'right', true)}
330
+ @mouseup=${(e) => this.mobileControl(e, 'right', false)}
331
+ ></button>
332
+ <button class="mobile-control-right"
333
+ @touchstart=${(e) => this.mobileControl(e, 'left', true)}
334
+ @touchend=${(e) => this.mobileControl(e, 'left', false)}
335
+ @mousedown=${(e) => this.mobileControl(e, 'left', true)}
336
+ @mouseup=${(e) => this.mobileControl(e, 'left', false)}
337
+ ></button>
338
+ <button class="mobile-control-sneak" @dblclick=${(e) => {
339
+ e.stopPropagation()
340
+ const b = e.target.classList.toggle('is-down')
341
+ this.bot.setControlState('sneak', b)
342
+ }}></button>
343
+ </div>
344
+ <div class="mobile-controls-right" id="mobile-right">
345
+ <button class="mobile-control-jump"
346
+ @touchstart=${(e) => this.mobileControl(e, 'jump', true)}
347
+ @touchend=${(e) => this.mobileControl(e, 'jump', false)}
348
+ @mousedown=${(e) => this.mobileControl(e, 'jump', true)}
349
+ @mouseup=${(e) => this.mobileControl(e, 'jump', false)}
350
+ ></button>
351
+ </div>
352
+
353
+ <pmui-debug-overlay id="debug-overlay"></pmui-debug-overlay>
354
+ <pmui-playerlist-overlay id="playerlist-overlay"></pmui-playerlist-overlay>
355
+ <pmui-bossbars-overlay id="bossbars-overlay"></pmui-bossbars-overlay>
356
+ <div class="crosshair"></div>
357
+ <chat-box id="chat"></chat-box>
358
+ <!--<pmui-breathbar id="breath-bar"></pmui-breathbar>-->
359
+ <pmui-healthbar id="health-bar"></pmui-healthbar>
360
+ <pmui-foodbar id="food-bar"></pmui-foodbar>
361
+ <div id="xp-bar-bg">
362
+ <div class="xp-bar"></div>
363
+ <span id="xp-label"></span>
364
+ </div>
365
+ <pmui-hotbar id="hotbar"></pmui-hotbar>
366
+ `
367
+ }
368
+ }
369
+
370
+ window.customElements.define('pmui-hud', Hud)
lib/menus/keybinds_screen.js ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { LitElement, html, css } = require('lit')
2
+ const { commonCss, displayScreen } = require('./components/common')
3
+
4
+ class KeyBindsScreen extends LitElement {
5
+ static get styles () {
6
+ return css`
7
+ ${commonCss}
8
+ .title {
9
+ top: 4px;
10
+ }
11
+
12
+ main {
13
+ display: flex;
14
+ flex-direction: column;
15
+ position: absolute;
16
+ top: 30px;
17
+ left: 50%;
18
+ transform: translate(-50%);
19
+ width: 100%;
20
+ height: calc(100% - 64px);
21
+ place-items: center;
22
+ background: rgba(0, 0, 0, 0.5);
23
+ box-shadow: inset 0 3px 6px rgba(0, 0, 0, 0.7), inset 0 -3px 6px rgba(0, 0, 0, 0.7);
24
+ }
25
+
26
+ .keymap-list {
27
+ width: 288px;
28
+ display: flex;
29
+ flex-direction: column;
30
+ padding: 4px 0;
31
+ overflow-y: auto;
32
+ }
33
+
34
+ .keymap-list::-webkit-scrollbar {
35
+ width: 6px;
36
+ }
37
+
38
+ .keymap-list::-webkit-scrollbar-track {
39
+ background: #000;
40
+ }
41
+
42
+ .keymap-list::-webkit-scrollbar-thumb {
43
+ background: #ccc;
44
+ box-shadow: inset -1px -1px 0 #4f4f4f;
45
+ }
46
+
47
+ .keymap-entry {
48
+ display: flex;
49
+ flex-direction: row;
50
+ width: 100%;
51
+ height: 20px;
52
+ place-content: center;
53
+ place-items: center;
54
+ justify-content: space-between;
55
+ }
56
+
57
+ span {
58
+ color: white;
59
+ text-shadow: 1px 1px 0 rgb(63, 63, 63);
60
+ font-size: 10px;
61
+ }
62
+
63
+ .keymap-entry-btns {
64
+ display: flex;
65
+ flex-direction: row;
66
+ gap: 4px;
67
+ }
68
+
69
+ .bottom-btns {
70
+ display: flex;
71
+ flex-direction: row;
72
+ width: 310px;
73
+ height: 20px;
74
+ justify-content: space-between;
75
+ position: absolute;
76
+ bottom: 9px;
77
+ left: 50%;
78
+ transform: translate(-50%);
79
+ }
80
+
81
+ `
82
+ }
83
+
84
+ static get properties () {
85
+ return {
86
+ keymaps: { type: Object },
87
+ selected: { type: Number }
88
+ }
89
+ }
90
+
91
+ constructor () {
92
+ super()
93
+ this.selected = -1
94
+ this.keymaps = [
95
+ { defaultKey: 'KeyW', key: 'KeyW', name: 'Walk Forwards' },
96
+ { defaultKey: 'KeyS', key: 'KeyS', name: 'Walk Backwards' },
97
+ { defaultKey: 'KeyA', key: 'KeyA', name: 'Strafe Left' },
98
+ { defaultKey: 'KeyD', key: 'KeyD', name: 'Strafe Right' },
99
+ { defaultKey: 'Space', key: 'Space', name: 'Jump' },
100
+ { defaultKey: 'ShiftLeft', key: 'ShiftLeft', name: 'Sneak' },
101
+ { defaultKey: 'ControlLeft', key: 'ControlLeft', name: 'Sprint' },
102
+ { defaultKey: 'KeyT', key: 'KeyT', name: 'Open Chat' },
103
+ { defaultKey: 'Slash', key: 'Slash', name: 'Open Command' },
104
+ // { defaultKey: '0', key: '0', name: 'Attack/Destroy' },
105
+ // { defaultKey: '1', key: '1', name: 'Place Block' },
106
+ { defaultKey: 'KeyQ', key: 'KeyQ', name: 'Drop Item' }
107
+ // { defaultKey: 'Digit1', key: 'Digit1', name: 'Hotbar Slot 1' },
108
+ // { defaultKey: 'Digit2', key: 'Digit2', name: 'Hotbar Slot 2' },
109
+ // { defaultKey: 'Digit3', key: 'Digit3', name: 'Hotbar Slot 3' },
110
+ // { defaultKey: 'Digit4', key: 'Digit4', name: 'Hotbar Slot 4' },
111
+ // { defaultKey: 'Digit5', key: 'Digit5', name: 'Hotbar Slot 5' },
112
+ // { defaultKey: 'Digit6', key: 'Digit6', name: 'Hotbar Slot 6' },
113
+ // { defaultKey: 'Digit7', key: 'Digit7', name: 'Hotbar Slot 7' },
114
+ // { defaultKey: 'Digit8', key: 'Digit8', name: 'Hotbar Slot 8' },
115
+ // { defaultKey: 'Digit9', key: 'Digit9', name: 'Hotbar Slot 9' },
116
+ // { defaultKey: 'KeyE', key: 'KeyE', name: 'Open Inventory' }
117
+ ]
118
+
119
+ document.addEventListener('keydown', (e) => {
120
+ if (this.selected !== -1) {
121
+ this.keymaps[this.selected].key = e.code
122
+ this.selected = -1
123
+ this.requestUpdate()
124
+ }
125
+ })
126
+ }
127
+
128
+ render () {
129
+ return html`
130
+ <div class="dirt-bg"></div>
131
+
132
+ <p class="title">Key Binds</p>
133
+
134
+ <main>
135
+ <div class="keymap-list">
136
+ ${this.keymaps.map((m, i) => html`
137
+ <div class="keymap-entry">
138
+ <span>${m.name}</span>
139
+
140
+ <div class="keymap-entry-btns">
141
+ <pmui-button pmui-width="72px" pmui-label="${this.selected === i ? `> ${m.key} <` : m.key}" @pmui-click=${e => {
142
+ e.target.setAttribute('pmui-label', `> ${m.key} <`)
143
+ this.selected = i
144
+ this.requestUpdate()
145
+ }}></pmui-button>
146
+ <pmui-button pmui-width="50px" ?pmui-disabled=${m.key === m.defaultKey} pmui-label="Reset" @pmui-click=${() => {
147
+ this.keymaps[i].key = this.keymaps[i].defaultKey
148
+ this.requestUpdate()
149
+ this.selected = -1
150
+ }}></pmui-button>
151
+ </div>
152
+ </div>
153
+ `)}
154
+ </div>
155
+ </main>
156
+
157
+ <div class="bottom-btns">
158
+ <pmui-button pmui-width="150px" pmui-label="Reset All Keys" ?pmui-disabled=${!this.keymaps.some(v => v.key !== v.defaultKey)} @pmui-click=${this.onResetAllPress}></pmui-button>
159
+ <pmui-button pmui-width="150px" pmui-label="Done" @pmui-click=${() => displayScreen(this, document.getElementById('options-screen'))}></pmui-button>
160
+ </div>
161
+ `
162
+ }
163
+
164
+ onResetAllPress () {
165
+ for (let i = 0; i < this.keymaps.length; i++) {
166
+ this.keymaps[i].key = this.keymaps[i].defaultKey
167
+ }
168
+ this.requestUpdate()
169
+ }
170
+ }
171
+
172
+ window.customElements.define('pmui-keybindsscreen', KeyBindsScreen)
lib/menus/loading_screen.js ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ const { LitElement, html, css } = require('lit')
2
+ const { commonCss } = require('./components/common')
3
+
4
+ class LoadingScreen extends LitElement {
5
+ static get styles () {
6
+ return css`
7
+ ${commonCss}
8
+ .title {
9
+ top: 30px;
10
+ }
11
+
12
+ #cancel-btn {
13
+ position: absolute;
14
+ top: calc(20% + 50px);
15
+ left: 50%;
16
+ transform: translate(-50%);
17
+ }
18
+ `
19
+ }
20
+
21
+ static get properties () {
22
+ return {
23
+ status: { type: String },
24
+ loadingText: { type: String },
25
+ hasError: { type: Number }
26
+ }
27
+ }
28
+
29
+ constructor () {
30
+ super()
31
+ this.hasError = false
32
+ this.status = 'Waiting for JS load'
33
+ }
34
+
35
+ firstUpdated () {
36
+ this.statusRunner()
37
+ }
38
+
39
+ async statusRunner () {
40
+ const array = ['.', '..', '...', '']
41
+ const timer = ms => new Promise((resolve) => setTimeout(resolve, ms))
42
+
43
+ const load = async () => {
44
+ for (let i = 0; true; i = ((i + 1) % array.length)) {
45
+ this.loadingText = this.status + array[i]
46
+ await timer(500)
47
+ }
48
+ }
49
+
50
+ load()
51
+ }
52
+
53
+ render () {
54
+ return html`
55
+ <div class="dirt-bg"></div>
56
+
57
+ <p class="title">${this.hasError ? this.status : this.loadingText}</p>
58
+
59
+ ${this.hasError
60
+ ? html`<pmui-button id="cancel-btn" pmui-width="200px" pmui-label="Cancel" @pmui-click=${() => window.location.reload()}></pmui-button>`
61
+ : ''
62
+ }
63
+ `
64
+ }
65
+ }
66
+
67
+ window.customElements.define('pmui-loadingscreen', LoadingScreen)