From ccdcf9e7e34a3ea2a25492f62717cf486b5bef2d Mon Sep 17 00:00:00 2001 From: Misode Date: Tue, 15 Oct 2024 05:14:02 +0200 Subject: [PATCH 001/119] =?UTF-8?q?=F0=9F=94=A5=20Nuke=20all=20mcschema=20?= =?UTF-8?q?related=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package-lock.json | 263 ------- package.json | 16 - src/app/Utils.ts | 17 - src/app/components/ItemDisplay.tsx | 12 +- src/app/components/ItemDisplay1204.tsx | 11 +- .../customized/CustomizedSlider.tsx | 2 - src/app/components/generator/FileCreation.tsx | 6 +- src/app/components/generator/PreviewPanel.tsx | 42 +- src/app/components/generator/ProjectPanel.tsx | 5 - .../components/generator/SchemaGenerator.tsx | 138 ++-- src/app/components/generator/SourcePanel.tsx | 38 +- src/app/components/generator/Tree.tsx | 22 +- .../previews/BiomeSourcePreview.tsx | 12 +- .../components/previews/BlockStatePreview.tsx | 7 +- src/app/components/previews/Decorator.ts | 9 +- .../components/previews/DecoratorPreview.tsx | 9 +- .../previews/DensityFunctionPreview.tsx | 7 +- .../components/previews/LootTablePreview.tsx | 5 +- src/app/components/previews/ModelPreview.tsx | 11 +- src/app/components/previews/NoisePreview.tsx | 7 +- .../previews/NoiseSettingsPreview.tsx | 23 +- src/app/components/previews/RecipePreview.tsx | 8 +- .../previews/StructureSetPreview.tsx | 14 +- src/app/components/previews/index.ts | 11 +- src/app/contexts/Locale.tsx | 8 +- src/app/hooks/index.ts | 1 - src/app/hooks/useModel.ts | 20 - src/app/partners/ImmersiveWeathering.ts | 210 ----- src/app/partners/Lithostitched.ts | 239 ------ src/app/partners/NeoForge.ts | 492 ------------ src/app/partners/Obsidian.ts | 442 ----------- src/app/partners/OhTheTreesYoullGrow.ts | 114 --- src/app/partners/index.ts | 18 - src/app/partners/locales/en.json | 176 ----- src/app/schema/ModelWrapper.ts | 25 - src/app/schema/renderHtml.tsx | 719 ------------------ src/app/schema/transformOutput.ts | 67 -- src/app/services/DataFetcher.ts | 62 +- src/app/services/Schemas.ts | 131 +--- 39 files changed, 199 insertions(+), 3220 deletions(-) delete mode 100644 src/app/hooks/useModel.ts delete mode 100644 src/app/partners/ImmersiveWeathering.ts delete mode 100644 src/app/partners/Lithostitched.ts delete mode 100644 src/app/partners/NeoForge.ts delete mode 100644 src/app/partners/Obsidian.ts delete mode 100644 src/app/partners/OhTheTreesYoullGrow.ts delete mode 100644 src/app/partners/index.ts delete mode 100644 src/app/partners/locales/en.json delete mode 100644 src/app/schema/ModelWrapper.ts delete mode 100644 src/app/schema/renderHtml.tsx delete mode 100644 src/app/schema/transformOutput.ts diff --git a/package-lock.json b/package-lock.json index 0641b63d..1ef731fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,22 +10,6 @@ "license": "MIT", "dependencies": { "@giscus/react": "^2.2.3", - "@mcschema/core": "^0.13.0", - "@mcschema/java-1.15": "^0.2.13", - "@mcschema/java-1.16": "^0.6.20", - "@mcschema/java-1.17": "^0.2.40", - "@mcschema/java-1.18": "^0.3.16", - "@mcschema/java-1.18.2": "^0.1.26", - "@mcschema/java-1.19": "^0.1.54", - "@mcschema/java-1.19.3": "^0.0.17", - "@mcschema/java-1.19.4": "^0.1.21", - "@mcschema/java-1.20": "^0.0.24", - "@mcschema/java-1.20.2": "^0.0.15", - "@mcschema/java-1.20.3": "^0.0.16", - "@mcschema/java-1.20.5": "^0.0.42", - "@mcschema/java-1.21": "^0.0.27", - "@mcschema/java-1.21.2": "^0.0.13", - "@mcschema/locales": "^0.1.104", "@zip.js/zip.js": "^2.4.5", "brace": "^0.11.1", "buffer": "^6.0.3", @@ -68,9 +52,6 @@ "vite-plugin-static-copy": "^0.12.0" } }, - "@mcschema/java-1.18@0.3.0-beta": { - "extraneous": true - }, "node_modules/@alloc/quick-lru": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", @@ -629,128 +610,6 @@ "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.4.2.tgz", "integrity": "sha512-VMOxsWh/QDwrxPsgkSQnuZ+8mfNy1OTjzzUdLBvvZtpahwPTHTeVZ51RZRqO4xfKVrR+btIPA8D01IL3xeG66w==" }, - "node_modules/@mcschema/core": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@mcschema/core/-/core-0.13.0.tgz", - "integrity": "sha512-nJRDvdEI2Z7Yw7eWKcbkuLFKtPIyeCc1d04E7EeUOpwxfHffgL5a0VBD2PX692z3igfTHGNXgPkzrleV91Q/ww==" - }, - "node_modules/@mcschema/java-1.15": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.15/-/java-1.15-0.2.13.tgz", - "integrity": "sha512-f3NanEsd48svxZfqquSylXrHZDd5vjvi8D6r15blrCi2J2C42032Ir0dMPD38hLxu9ey0eIrgucDApn/GXO1uA==", - "dependencies": { - "@mcschema/core": "^0.13.0" - } - }, - "node_modules/@mcschema/java-1.16": { - "version": "0.6.20", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.16/-/java-1.16-0.6.20.tgz", - "integrity": "sha512-pJihtCYPloVAk6Tq2JVvfk666rPLaNmXkHhD6/a1kk/AUaP2wk/3YuYdXyRqz7/lmxkBpJK/BvhAO4ZtsQfNtg==", - "dependencies": { - "@mcschema/core": "^0.13.0" - } - }, - "node_modules/@mcschema/java-1.17": { - "version": "0.2.40", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.17/-/java-1.17-0.2.40.tgz", - "integrity": "sha512-aFlH9APa4JEMsz0y3BKjYGILXn6QQcQDOCHA+qgdXDjc0xsrHffO1l/TVVDi5GQCCqEgGA15guqfLVV+7Vtb2A==", - "dependencies": { - "@mcschema/core": "^0.13.0" - } - }, - "node_modules/@mcschema/java-1.18": { - "version": "0.3.16", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.18/-/java-1.18-0.3.16.tgz", - "integrity": "sha512-crxXl0OW6BYlD+Cjaa8cJEsoehnBa6whrE6JBG37nZ1nQBl0e9vun4fbaZi0buzFjeJGZ0st7Lm0LsFJRe7FEw==", - "dependencies": { - "@mcschema/core": "^0.13.0" - } - }, - "node_modules/@mcschema/java-1.18.2": { - "version": "0.1.26", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.18.2/-/java-1.18.2-0.1.26.tgz", - "integrity": "sha512-GN6gCyEyTTJTiv0vn4cTVMYVgG2BJpDXJh2KPrg5cT/7gCpHUrt4PJAyzEaYLkDZoW17p2gWuY12gIM/yfuiDA==", - "dependencies": { - "@mcschema/core": "^0.13.0" - } - }, - "node_modules/@mcschema/java-1.19": { - "version": "0.1.54", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.19/-/java-1.19-0.1.54.tgz", - "integrity": "sha512-eh8kTBs3EAGlWzTbmGzoIRtePd2dUkttooGsmXmjadvwf/yT19Ew+P+U4Y6LLFLnNoWJxruCVhznS1KxzoT0wA==", - "dependencies": { - "@mcschema/core": "^0.13.0" - } - }, - "node_modules/@mcschema/java-1.19.3": { - "version": "0.0.17", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.19.3/-/java-1.19.3-0.0.17.tgz", - "integrity": "sha512-8V3UpdmVPb2JZJ5A3Mi6J5Lf5dicmY9w11dq8VQm9jSEPwY7IXSnE4l9J3AmFkIgAhiaNTQ+/lbmliR7LNUAlQ==", - "dependencies": { - "@mcschema/core": "^0.13.0" - } - }, - "node_modules/@mcschema/java-1.19.4": { - "version": "0.1.21", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.19.4/-/java-1.19.4-0.1.21.tgz", - "integrity": "sha512-QZhe7L6t7/Uf6vK0pXWSJYoGA0D+VAv10wrMrwG6jTHoCI1iPkFhet9JqUnOwOv0Ql+jwh7zDNQjTHJIkHwfMQ==", - "dependencies": { - "@mcschema/core": "^0.13.0" - } - }, - "node_modules/@mcschema/java-1.20": { - "version": "0.0.24", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.20/-/java-1.20-0.0.24.tgz", - "integrity": "sha512-Bcm4n7YTXQ/6mGmj7l9KcRXl8ta9nokNZDyrgEeexsrE9jzj1ef6TsNra2bI9kCka9l4s4XzZ1VDuM/Ag/Ud0g==", - "dependencies": { - "@mcschema/core": "^0.13.0" - } - }, - "node_modules/@mcschema/java-1.20.2": { - "version": "0.0.15", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.20.2/-/java-1.20.2-0.0.15.tgz", - "integrity": "sha512-crGOWodFnWT5XGjp2b8kZeXKsHpdQHDaES09NYf/VNWUIdGNYD7hXlIVvQEsqbZt1ABuisIKWvNYZJwH7Fhdew==", - "dependencies": { - "@mcschema/core": "^0.13.0" - } - }, - "node_modules/@mcschema/java-1.20.3": { - "version": "0.0.16", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.20.3/-/java-1.20.3-0.0.16.tgz", - "integrity": "sha512-XNX02G7RHB8u/ibwU0GSo+lsz/5rcduHnWKk/BJcGH6Q2NswLKJDiyt8Ow5KrcmtCBxprCLjg5pJaj/Ql6aKoQ==", - "dependencies": { - "@mcschema/core": "^0.13.0" - } - }, - "node_modules/@mcschema/java-1.20.5": { - "version": "0.0.42", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.20.5/-/java-1.20.5-0.0.42.tgz", - "integrity": "sha512-LgVeCvHQPMQUMPPiJ5tkm8RG7EKowvw6eHxu8RPakeX/Del5OYkQI252hkP2RC3AA46NHE+iKqtsk8A+lvCuow==", - "dependencies": { - "@mcschema/core": "^0.13.0" - } - }, - "node_modules/@mcschema/java-1.21": { - "version": "0.0.27", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.21/-/java-1.21-0.0.27.tgz", - "integrity": "sha512-X2o8VJouEv5ZixLrpngyq0srwYB8Bp0lmIBKRJvJ+7/5RB6Mrf9I/Z4y7BkPjpKjw8TME1r5Tw/g7sjrYXvEUQ==", - "dependencies": { - "@mcschema/core": "^0.13.0" - } - }, - "node_modules/@mcschema/java-1.21.2": { - "version": "0.0.13", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.21.2/-/java-1.21.2-0.0.13.tgz", - "integrity": "sha512-qGDOczhRd/KY+75oXxoKwZSuJS8k038mkiSqCbe+TFapXCZSv87TOnXCUD+LFK0v51ejwFM6mErv8ZJinuKq9g==", - "dependencies": { - "@mcschema/core": "^0.13.0" - } - }, - "node_modules/@mcschema/locales": { - "version": "0.1.104", - "resolved": "https://registry.npmjs.org/@mcschema/locales/-/locales-0.1.104.tgz", - "integrity": "sha512-fZ9zzb4OvMnxRFtVYpPuFDugd2LGYMfGRsYzl+RG6wFZAUuB6pe+igNmK5o8VfX1ldO2W5FWkddgh/MjtemFOA==" - }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -4775,128 +4634,6 @@ "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-1.4.2.tgz", "integrity": "sha512-VMOxsWh/QDwrxPsgkSQnuZ+8mfNy1OTjzzUdLBvvZtpahwPTHTeVZ51RZRqO4xfKVrR+btIPA8D01IL3xeG66w==" }, - "@mcschema/core": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@mcschema/core/-/core-0.13.0.tgz", - "integrity": "sha512-nJRDvdEI2Z7Yw7eWKcbkuLFKtPIyeCc1d04E7EeUOpwxfHffgL5a0VBD2PX692z3igfTHGNXgPkzrleV91Q/ww==" - }, - "@mcschema/java-1.15": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.15/-/java-1.15-0.2.13.tgz", - "integrity": "sha512-f3NanEsd48svxZfqquSylXrHZDd5vjvi8D6r15blrCi2J2C42032Ir0dMPD38hLxu9ey0eIrgucDApn/GXO1uA==", - "requires": { - "@mcschema/core": "^0.13.0" - } - }, - "@mcschema/java-1.16": { - "version": "0.6.20", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.16/-/java-1.16-0.6.20.tgz", - "integrity": "sha512-pJihtCYPloVAk6Tq2JVvfk666rPLaNmXkHhD6/a1kk/AUaP2wk/3YuYdXyRqz7/lmxkBpJK/BvhAO4ZtsQfNtg==", - "requires": { - "@mcschema/core": "^0.13.0" - } - }, - "@mcschema/java-1.17": { - "version": "0.2.40", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.17/-/java-1.17-0.2.40.tgz", - "integrity": "sha512-aFlH9APa4JEMsz0y3BKjYGILXn6QQcQDOCHA+qgdXDjc0xsrHffO1l/TVVDi5GQCCqEgGA15guqfLVV+7Vtb2A==", - "requires": { - "@mcschema/core": "^0.13.0" - } - }, - "@mcschema/java-1.18": { - "version": "0.3.16", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.18/-/java-1.18-0.3.16.tgz", - "integrity": "sha512-crxXl0OW6BYlD+Cjaa8cJEsoehnBa6whrE6JBG37nZ1nQBl0e9vun4fbaZi0buzFjeJGZ0st7Lm0LsFJRe7FEw==", - "requires": { - "@mcschema/core": "^0.13.0" - } - }, - "@mcschema/java-1.18.2": { - "version": "0.1.26", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.18.2/-/java-1.18.2-0.1.26.tgz", - "integrity": "sha512-GN6gCyEyTTJTiv0vn4cTVMYVgG2BJpDXJh2KPrg5cT/7gCpHUrt4PJAyzEaYLkDZoW17p2gWuY12gIM/yfuiDA==", - "requires": { - "@mcschema/core": "^0.13.0" - } - }, - "@mcschema/java-1.19": { - "version": "0.1.54", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.19/-/java-1.19-0.1.54.tgz", - "integrity": "sha512-eh8kTBs3EAGlWzTbmGzoIRtePd2dUkttooGsmXmjadvwf/yT19Ew+P+U4Y6LLFLnNoWJxruCVhznS1KxzoT0wA==", - "requires": { - "@mcschema/core": "^0.13.0" - } - }, - "@mcschema/java-1.19.3": { - "version": "0.0.17", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.19.3/-/java-1.19.3-0.0.17.tgz", - "integrity": "sha512-8V3UpdmVPb2JZJ5A3Mi6J5Lf5dicmY9w11dq8VQm9jSEPwY7IXSnE4l9J3AmFkIgAhiaNTQ+/lbmliR7LNUAlQ==", - "requires": { - "@mcschema/core": "^0.13.0" - } - }, - "@mcschema/java-1.19.4": { - "version": "0.1.21", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.19.4/-/java-1.19.4-0.1.21.tgz", - "integrity": "sha512-QZhe7L6t7/Uf6vK0pXWSJYoGA0D+VAv10wrMrwG6jTHoCI1iPkFhet9JqUnOwOv0Ql+jwh7zDNQjTHJIkHwfMQ==", - "requires": { - "@mcschema/core": "^0.13.0" - } - }, - "@mcschema/java-1.20": { - "version": "0.0.24", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.20/-/java-1.20-0.0.24.tgz", - "integrity": "sha512-Bcm4n7YTXQ/6mGmj7l9KcRXl8ta9nokNZDyrgEeexsrE9jzj1ef6TsNra2bI9kCka9l4s4XzZ1VDuM/Ag/Ud0g==", - "requires": { - "@mcschema/core": "^0.13.0" - } - }, - "@mcschema/java-1.20.2": { - "version": "0.0.15", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.20.2/-/java-1.20.2-0.0.15.tgz", - "integrity": "sha512-crGOWodFnWT5XGjp2b8kZeXKsHpdQHDaES09NYf/VNWUIdGNYD7hXlIVvQEsqbZt1ABuisIKWvNYZJwH7Fhdew==", - "requires": { - "@mcschema/core": "^0.13.0" - } - }, - "@mcschema/java-1.20.3": { - "version": "0.0.16", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.20.3/-/java-1.20.3-0.0.16.tgz", - "integrity": "sha512-XNX02G7RHB8u/ibwU0GSo+lsz/5rcduHnWKk/BJcGH6Q2NswLKJDiyt8Ow5KrcmtCBxprCLjg5pJaj/Ql6aKoQ==", - "requires": { - "@mcschema/core": "^0.13.0" - } - }, - "@mcschema/java-1.20.5": { - "version": "0.0.42", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.20.5/-/java-1.20.5-0.0.42.tgz", - "integrity": "sha512-LgVeCvHQPMQUMPPiJ5tkm8RG7EKowvw6eHxu8RPakeX/Del5OYkQI252hkP2RC3AA46NHE+iKqtsk8A+lvCuow==", - "requires": { - "@mcschema/core": "^0.13.0" - } - }, - "@mcschema/java-1.21": { - "version": "0.0.27", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.21/-/java-1.21-0.0.27.tgz", - "integrity": "sha512-X2o8VJouEv5ZixLrpngyq0srwYB8Bp0lmIBKRJvJ+7/5RB6Mrf9I/Z4y7BkPjpKjw8TME1r5Tw/g7sjrYXvEUQ==", - "requires": { - "@mcschema/core": "^0.13.0" - } - }, - "@mcschema/java-1.21.2": { - "version": "0.0.13", - "resolved": "https://registry.npmjs.org/@mcschema/java-1.21.2/-/java-1.21.2-0.0.13.tgz", - "integrity": "sha512-qGDOczhRd/KY+75oXxoKwZSuJS8k038mkiSqCbe+TFapXCZSv87TOnXCUD+LFK0v51ejwFM6mErv8ZJinuKq9g==", - "requires": { - "@mcschema/core": "^0.13.0" - } - }, - "@mcschema/locales": { - "version": "0.1.104", - "resolved": "https://registry.npmjs.org/@mcschema/locales/-/locales-0.1.104.tgz", - "integrity": "sha512-fZ9zzb4OvMnxRFtVYpPuFDugd2LGYMfGRsYzl+RG6wFZAUuB6pe+igNmK5o8VfX1ldO2W5FWkddgh/MjtemFOA==" - }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", diff --git a/package.json b/package.json index e6d291c6..e1485b94 100644 --- a/package.json +++ b/package.json @@ -16,22 +16,6 @@ "license": "MIT", "dependencies": { "@giscus/react": "^2.2.3", - "@mcschema/core": "^0.13.0", - "@mcschema/java-1.15": "^0.2.13", - "@mcschema/java-1.16": "^0.6.20", - "@mcschema/java-1.17": "^0.2.40", - "@mcschema/java-1.18": "^0.3.16", - "@mcschema/java-1.18.2": "^0.1.26", - "@mcschema/java-1.19": "^0.1.54", - "@mcschema/java-1.19.3": "^0.0.17", - "@mcschema/java-1.19.4": "^0.1.21", - "@mcschema/java-1.20": "^0.0.24", - "@mcschema/java-1.20.2": "^0.0.15", - "@mcschema/java-1.20.3": "^0.0.16", - "@mcschema/java-1.20.5": "^0.0.42", - "@mcschema/java-1.21": "^0.0.27", - "@mcschema/java-1.21.2": "^0.0.13", - "@mcschema/locales": "^0.1.104", "@zip.js/zip.js": "^2.4.5", "brace": "^0.11.1", "buffer": "^6.0.3", diff --git a/src/app/Utils.ts b/src/app/Utils.ts index 578d6b33..29757e85 100644 --- a/src/app/Utils.ts +++ b/src/app/Utils.ts @@ -1,5 +1,3 @@ -import type { DataModel } from '@mcschema/core' -import { Path } from '@mcschema/core' import * as zip from '@zip.js/zip.js' import type { Identifier, NbtTag, Random } from 'deepslate' import { Matrix3, Matrix4, NbtByte, NbtCompound, NbtDouble, NbtInt, NbtList, NbtString, Vector } from 'deepslate' @@ -47,21 +45,6 @@ export function generateColor() { return Math.floor(Math.random() * 16777215) } -export function newSeed(model: DataModel) { - const seed = Math.floor(Math.random() * (4294967296)) - 2147483648 - const dimensions = model.get(new Path(['dimensions'])) - model.set(new Path(['seed']), seed, true) - if (isObject(dimensions)) { - Object.keys(dimensions).forEach(id => { - model.set(new Path(['dimensions', id, 'generator', 'seed']), seed, true) - model.set(new Path(['dimensions', id, 'generator', 'biome_source', 'seed']), seed, true) - }) - } - model.set(new Path(['placement', 'salt']), Math.abs(seed), true) - model.set(new Path(['generator', 'seed']), seed, true) - model.set(new Path(['generator', 'biome_source', 'seed']), seed) -} - export function htmlEncode(str: string) { return str.replace(/&/g, '&').replace(//g, '>') .replace(/"/g, '"').replace(/'/g, ''').replace(/\//g, '/') diff --git a/src/app/components/ItemDisplay.tsx b/src/app/components/ItemDisplay.tsx index 17f8e1ae..0b46068e 100644 --- a/src/app/components/ItemDisplay.tsx +++ b/src/app/components/ItemDisplay.tsx @@ -3,10 +3,9 @@ import { Identifier } from 'deepslate/core' import { useCallback, useEffect, useMemo, useRef, useState } from 'preact/hooks' import { useVersion } from '../contexts/Version.jsx' import { useAsync } from '../hooks/useAsync.js' -import { fetchItemComponents } from '../services/index.js' +import { fetchItemComponents, fetchRegistries } from '../services/index.js' import { ResolvedItem } from '../services/ResolvedItem.js' import { renderItem } from '../services/Resources.js' -import { getCollections } from '../services/Schemas.js' import { jsonToNbt } from '../Utils.js' import { ItemTooltip } from './ItemTooltip.jsx' import { Octicon } from './Octicon.jsx' @@ -83,14 +82,17 @@ function ItemItself({ item }: ResolvedProps) { return Octicon.package } - const { value: collections } = useAsync(() => getCollections(version), []) + const { value: allModels, loading: loadingModels } = useAsync(async () => { + const registries = await fetchRegistries(version) + return registries.get('model') + }, [version]) - if (collections === undefined) { + if (loadingModels || allModels === undefined) { return null } const modelPath = `item/${item.id.path}` - if (collections.get('model').includes('minecraft:' + modelPath)) { + if (allModels && allModels.includes('minecraft:' + modelPath)) { return } diff --git a/src/app/components/ItemDisplay1204.tsx b/src/app/components/ItemDisplay1204.tsx index 05b5d959..f8bf9ce7 100644 --- a/src/app/components/ItemDisplay1204.tsx +++ b/src/app/components/ItemDisplay1204.tsx @@ -3,8 +3,8 @@ import { Identifier } from 'deepslate-1.20.4/core' import { useEffect, useRef, useState } from 'preact/hooks' import { useVersion } from '../contexts/Version.jsx' import { useAsync } from '../hooks/useAsync.js' +import { fetchRegistries } from '../services/index.js' import { renderItem } from '../services/Resources1204.js' -import { getCollections } from '../services/Schemas.js' import { ItemTooltip1204 } from './ItemTooltip1204.jsx' import { Octicon } from './Octicon.jsx' import { itemHasGlint } from './previews/LootTable1204.js' @@ -69,14 +69,17 @@ function ItemItself({ item }: Props) { return Octicon.package } - const { value: collections } = useAsync(() => getCollections(version), []) + const { value: allModels, loading: loadingModels } = useAsync(async () => { + const registries = await fetchRegistries(version) + return registries.get('model') + }, [version]) - if (collections === undefined) { + if (loadingModels || allModels === undefined) { return null } const modelPath = `item/${item.id.path}` - if (collections.get('model').includes('minecraft:' + modelPath)) { + if (allModels && allModels.includes('minecraft:' + modelPath)) { return } diff --git a/src/app/components/customized/CustomizedSlider.tsx b/src/app/components/customized/CustomizedSlider.tsx index 3a15c447..4ecdd33b 100644 --- a/src/app/components/customized/CustomizedSlider.tsx +++ b/src/app/components/customized/CustomizedSlider.tsx @@ -1,4 +1,3 @@ -import type { NodeChildren } from '@mcschema/core' import { NumberInput, RangeInput } from '../index.js' import { CustomizedInput } from './CustomizedInput.jsx' @@ -12,7 +11,6 @@ interface Props { initial?: number, error?: string, onChange: (value: number) => void, - children?: NodeChildren, } export function CustomizedSlider(props: Props) { const isInteger = (props.step ?? 1) >= 1 diff --git a/src/app/components/generator/FileCreation.tsx b/src/app/components/generator/FileCreation.tsx index 83252fd2..740bbab8 100644 --- a/src/app/components/generator/FileCreation.tsx +++ b/src/app/components/generator/FileCreation.tsx @@ -1,13 +1,13 @@ -import { DataModel } from '@mcschema/core' import { useState } from 'preact/hooks' import { Analytics } from '../../Analytics.js' import { useLocale, useProject } from '../../contexts/index.js' +import type { FileModel } from '../../services/index.js' import { Btn } from '../Btn.js' import { TextInput } from '../forms/index.js' import { Modal } from '../Modal.js' interface Props { - model: DataModel, + model: FileModel, id: string, method: string, onClose: () => void, @@ -29,7 +29,7 @@ export function FileCreation({ model, id, method, onClose }: Props) { return } Analytics.saveProjectFile(id, projects.length, project.files.length, method as any) - updateFile(id, undefined, { type: id, id: fileId, data: DataModel.unwrapLists(model.data) }) + updateFile(id, undefined, { type: id, id: fileId, data: model.data }) onClose() } diff --git a/src/app/components/generator/PreviewPanel.tsx b/src/app/components/generator/PreviewPanel.tsx index 5cc5f8e7..c2576361 100644 --- a/src/app/components/generator/PreviewPanel.tsx +++ b/src/app/components/generator/PreviewPanel.tsx @@ -1,69 +1,59 @@ -import type { DataModel } from '@mcschema/core' -import { Path } from '@mcschema/core' -import { useState } from 'preact/hooks' -import { useModel } from '../../hooks/index.js' -import type { VersionId } from '../../services/index.js' +import { useVersion } from '../../contexts/Version.jsx' +import type { FileModel } from '../../services/index.js' import { checkVersion } from '../../services/index.js' import { BiomeSourcePreview, BlockStatePreview, DecoratorPreview, DensityFunctionPreview, LootTablePreview, ModelPreview, NoisePreview, NoiseSettingsPreview, RecipePreview, StructureSetPreview } from '../previews/index.js' export const HasPreview = ['loot_table', 'recipe', 'dimension', 'worldgen/density_function', 'worldgen/noise', 'worldgen/noise_settings', 'worldgen/configured_feature', 'worldgen/placed_feature', 'worldgen/structure_set', 'block_definition', 'model'] type PreviewPanelProps = { - model: DataModel | undefined, - version: VersionId, + model: FileModel | undefined, id: string, shown: boolean, onError: (message: string) => unknown, } -export function PreviewPanel({ model, version, id, shown }: PreviewPanelProps) { - const [, setCount] = useState(0) - - useModel(model, () => { - setCount(count => count + 1) - }) +export function PreviewPanel({ model, id, shown }: PreviewPanelProps) { + const { version } = useVersion() if (!model) return <> - const data = model.get(new Path([])) - if (!data) return <> if (id === 'loot_table') { - return + return } if (id === 'recipe') { - return + return } - if (id === 'dimension' && model.get(new Path(['generator', 'type']))?.endsWith('noise')) { - return + if (id === 'dimension' && model.data.generator?.type?.endsWith('noise')) { + return } if (id === 'worldgen/density_function') { - return + return } if (id === 'worldgen/noise') { - return + return } if (id === 'worldgen/noise_settings' && checkVersion(version, '1.18')) { - return + return } if ((id === 'worldgen/placed_feature' || (id === 'worldgen/configured_feature' && checkVersion(version, '1.16', '1.17')))) { - return + return } if (id === 'worldgen/structure_set' && checkVersion(version, '1.19')) { - return + return } if (id === 'block_definition') { - return + return } if (id === 'model') { - return + return } return <> diff --git a/src/app/components/generator/ProjectPanel.tsx b/src/app/components/generator/ProjectPanel.tsx index a602809d..b468db59 100644 --- a/src/app/components/generator/ProjectPanel.tsx +++ b/src/app/components/generator/ProjectPanel.tsx @@ -1,10 +1,8 @@ -import type { DataModel } from '@mcschema/core' import { useCallback, useMemo, useRef, useState } from 'preact/hooks' import { Analytics } from '../../Analytics.js' import config from '../../Config.js' import { disectFilePath, DRAFT_PROJECT, getFilePath, useLocale, useProject, useVersion } from '../../contexts/index.js' import { useFocus } from '../../hooks/useFocus.js' -import type { VersionId } from '../../services/index.js' import { stringifySource } from '../../services/index.js' import { Store } from '../../Store.js' import { writeZip } from '../../Utils.js' @@ -15,9 +13,6 @@ import type { TreeViewGroupRenderer, TreeViewLeafRenderer } from '../TreeView.js import { TreeView } from '../TreeView.js' interface Props { - model: DataModel | undefined, - version: VersionId, - id: string, onError: (message: string) => unknown, onRename: (file: { type: string, id: string }) => unknown, onCreate: () => unknown, diff --git a/src/app/components/generator/SchemaGenerator.tsx b/src/app/components/generator/SchemaGenerator.tsx index 540af753..a1014a8f 100644 --- a/src/app/components/generator/SchemaGenerator.tsx +++ b/src/app/components/generator/SchemaGenerator.tsx @@ -1,14 +1,12 @@ -import { DataModel, Path } from '@mcschema/core' import { route } from 'preact-router' -import { useCallback, useEffect, useErrorBoundary, useMemo, useRef, useState } from 'preact/hooks' +import { useCallback, useEffect, useErrorBoundary, useMemo, useState } from 'preact/hooks' import { Analytics } from '../../Analytics.js' import type { ConfigGenerator } from '../../Config.js' import config from '../../Config.js' import { DRAFT_PROJECT, useLocale, useProject, useVersion } from '../../contexts/index.js' -import { AsyncCancel, useActiveTimeout, useAsync, useModel, useSearchParam } from '../../hooks/index.js' -import { getOutput } from '../../schema/transformOutput.js' -import type { VersionId } from '../../services/index.js' -import { checkVersion, fetchPreset, getBlockStates, getCollections, getModel, getSnippet, shareSnippet } from '../../services/index.js' +import { AsyncCancel, useActiveTimeout, useAsync, useSearchParam } from '../../hooks/index.js' +import type { FileModel, VersionId } from '../../services/index.js' +import { checkVersion, createMockFileModel, fetchPreset, fetchRegistries, getSnippet, shareSnippet } from '../../services/index.js' import { Store } from '../../Store.js' import { cleanUrl, deepEqual, genPath } from '../../Utils.js' import { Ad, Btn, BtnMenu, ErrorPanel, FileCreation, FileRenaming, Footer, HasPreview, Octicon, PreviewPanel, ProjectCreation, ProjectDeletion, ProjectPanel, SearchList, SourcePanel, TextInput, Tree, VersionSwitcher } from '../index.js' @@ -22,7 +20,7 @@ interface Props { export function SchemaGenerator({ gen, allowedVersions }: Props) { const { locale } = useLocale() const { version, changeVersion, changeTargetVersion } = useVersion() - const { projects, project, file, updateProject, updateFile, closeFile } = useProject() + const { projects, project, file, updateProject, closeFile } = useProject() const [error, setError] = useState(null) const [errorBoundary, errorRetry] = useErrorBoundary() if (errorBoundary) { @@ -34,16 +32,15 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) { const [currentPreset, setCurrentPreset] = useSearchParam('preset') const [sharedSnippetId, setSharedSnippetId] = useSearchParam(SHARE_KEY) - const ignoreChange = useRef(false) const backup = useMemo(() => Store.getBackup(gen.id), [gen.id]) const loadBackup = () => { if (backup !== undefined) { - model?.reset(DataModel.wrapLists(backup), false) + // TODO: implement } } - const { value } = useAsync(async () => { + const {} = useAsync(async () => { let data: unknown = undefined if (currentPreset && sharedSnippetId) { setSharedSnippetId(undefined) @@ -81,81 +78,65 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) { } data = file.data } - const [model, blockStates] = await Promise.all([ - getModel(version, gen.id), - getBlockStates(version), - ]) if (data) { - ignoreChange.current = true - model.reset(DataModel.wrapLists(data), false) + // TODO: set file contents to data } Analytics.setGenerator(gen.id) - return { model, blockStates } + return {} }, [gen.id, version, sharedSnippetId, currentPreset, project.name, file?.id]) - const model = value?.model - const blockStates = value?.blockStates + const model: FileModel = createMockFileModel() - useModel(model, model => { - if (!ignoreChange.current) { - setCurrentPreset(undefined, true) - setSharedSnippetId(undefined, true) - } - if (file && model && blockStates) { - const data = getOutput(model, blockStates) - updateFile(gen.id, file.id, { id: file.id, data }) - } - ignoreChange.current = false - Store.setBackup(gen.id, DataModel.unwrapLists(model.data)) - setError(null) - }, [gen.id, setCurrentPreset, setSharedSnippetId, blockStates, file?.id]) + // TODO: when contents of file change: + // - remove preset and share id from url + // - update project + // - store backup const reset = () => { - Analytics.resetGenerator(gen.id, model?.historyIndex ?? 1, 'menu') - model?.reset(DataModel.wrapLists(model.schema.default()), true) + Analytics.resetGenerator(gen.id, 1, 'menu') + // TODO } const undo = (e: MouseEvent) => { e.stopPropagation() - Analytics.undoGenerator(gen.id, model?.historyIndex ?? 1, 'menu') - model?.undo() + Analytics.undoGenerator(gen.id, 1, 'menu') + // TODO } const redo = (e: MouseEvent) => { e.stopPropagation() - Analytics.redoGenerator(gen.id, model?.historyIndex ?? 1, 'menu') - model?.redo() + Analytics.redoGenerator(gen.id, 1, 'menu') + // TODO } - const onKeyUp = (e: KeyboardEvent) => { - if (e.ctrlKey && e.key === 'z') { - Analytics.undoGenerator(gen.id, model?.historyIndex ?? 1, 'hotkey') - model?.undo() - } else if (e.ctrlKey && e.key === 'y') { - Analytics.redoGenerator(gen.id, model?.historyIndex ?? 1, 'hotkey') - model?.redo() - } - } - const onKeyDown = (e: KeyboardEvent) => { - if (e.ctrlKey && e.key === 's') { - setFileSaving('hotkey') - e.preventDefault() - e.stopPropagation() - } - } useEffect(() => { + const onKeyUp = (e: KeyboardEvent) => { + if (e.ctrlKey && e.key === 'z') { + Analytics.undoGenerator(gen.id, 1, 'hotkey') + // TODO + } else if (e.ctrlKey && e.key === 'y') { + Analytics.redoGenerator(gen.id, 1, 'hotkey') + // TODO + } + } + const onKeyDown = (e: KeyboardEvent) => { + if (e.ctrlKey && e.key === 's') { + setFileSaving('hotkey') + e.preventDefault() + e.stopPropagation() + } + } + document.addEventListener('keyup', onKeyUp) document.addEventListener('keydown', onKeyDown) return () => { document.removeEventListener('keyup', onKeyUp) document.removeEventListener('keydown', onKeyDown) } - }, [model, blockStates, file]) + }, [gen.id]) - const [presets, setPresets] = useState([]) - useEffect(() => { - getCollections(version).then(collections => { - setPresets(collections.get(gen.id).map(p => p.startsWith('minecraft:') ? p.slice(10) : p)) - }) - .catch(e => { console.error(e); setError(e) }) + const { value: presets } = useAsync(async () => { + const registries = await fetchRegistries(version) + const entries = registries.get(gen.id) ?? [] + return entries.map(e => e.startsWith('minecraft:') ? e.slice(10) : e) }, [version, gen.id]) const selectPreset = (id: string) => { @@ -168,13 +149,7 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) { const loadPreset = async (id: string) => { try { const preset = await fetchPreset(version, genPath(gen, version), id) - const seed = model?.get(new Path(['generator', 'seed'])) - if (preset?.generator?.seed !== undefined && seed !== undefined) { - preset.generator.seed = seed - if (preset.generator.biome_source?.seed !== undefined) { - preset.generator.biome_source.seed = seed - } - } + // TODO: sync random seed return preset } catch (e) { setError(`Cannot load preset ${id} in ${version}`) @@ -203,14 +178,14 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) { setShareUrl(`${location.origin}/${gen.url}/?version=${version}&preset=${currentPreset}`) setShareShown(true) copySharedId() - } else if (model && blockStates) { - const output = getOutput(model, blockStates) - if (deepEqual(output, model.schema.default())) { + } else { + // TODO: get contents from file, and compare to default of type + if (deepEqual(model.data, {})) { setShareUrl(`${location.origin}/${gen.url}/?version=${version}`) setShareShown(true) } else { setShareLoading(true) - shareSnippet(gen.id, version, output, previewShown) + shareSnippet(gen.id, version, model.data, previewShown) .then(({ id, length, compressed, rate }) => { Analytics.createSnippet(gen.id, id, version, length, compressed, rate) const url = `${location.origin}/${gen.url}/?${SHARE_KEY}=${id}` @@ -298,21 +273,12 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) { const [projectDeleting, setprojectDeleting] = useState(false) const [fileSaving, setFileSaving] = useState(undefined) const [fileRenaming, setFileRenaming] = useState<{ type: string, id: string } | undefined>(undefined) - const [newFileQueued, setNewFileQueued] = useState(false) const onNewFile = useCallback(() => { closeFile() - // Need to queue reset because otherwise the useModel hook will update the old file - setNewFileQueued(true) + // TODO: create new file with default contents }, [closeFile]) - useEffect(() => { - if (file === undefined && newFileQueued) { - model?.reset(DataModel.wrapLists(model.schema.default()), true) - setNewFileQueued(false) - } - }, [model, newFileQueued, file]) - return <>
{!gen.tags?.includes('partners') && } @@ -335,7 +301,7 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) { {error && setError(null)} />} - +
- +
- +
@@ -371,7 +337,7 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) {
- setprojectDeleting(true)} onRename={setFileRenaming} onCreate={() => setProjectCreating(true)} /> + setprojectDeleting(true)} onRename={setFileRenaming} onCreate={() => setProjectCreating(true)} />
{projectCreating && setProjectCreating(false)} />} {projectDeleting && setprojectDeleting(false)} />} diff --git a/src/app/components/generator/SourcePanel.tsx b/src/app/components/generator/SourcePanel.tsx index 643618b1..809866ff 100644 --- a/src/app/components/generator/SourcePanel.tsx +++ b/src/app/components/generator/SourcePanel.tsx @@ -1,9 +1,7 @@ -import { DataModel } from '@mcschema/core' import { useCallback, useEffect, useRef, useState } from 'preact/hooks' import { useLocale } from '../../contexts/index.js' -import { useLocalStorage, useModel } from '../../hooks/index.js' -import { getOutput } from '../../schema/transformOutput.js' -import type { BlockStateRegistry } from '../../services/index.js' +import { useLocalStorage } from '../../hooks/index.js' +import type { FileModel } from '../../services/index.js' import { getSourceFormats, getSourceIndent, getSourceIndents, parseSource, sortData, stringifySource } from '../../services/index.js' import { Store } from '../../Store.js' import { message } from '../../Utils.js' @@ -18,15 +16,14 @@ interface Editor { type SourcePanelProps = { name: string, - model: DataModel | undefined, - blockStates: BlockStateRegistry | undefined, + model: FileModel | undefined, doCopy?: number, doDownload?: number, doImport?: number, copySuccess: () => unknown, onError: (message: string | Error) => unknown, } -export function SourcePanel({ name, model, blockStates, doCopy, doDownload, doImport, copySuccess, onError }: SourcePanelProps) { +export function SourcePanel({ name, model, doCopy, doDownload, doImport, copySuccess, onError }: SourcePanelProps) { const { locale } = useLocale() const [indent, setIndent] = useState(Store.getIndent()) const [format, setFormat] = useState(Store.getFormat()) @@ -40,8 +37,8 @@ export function SourcePanel({ name, model, blockStates, doCopy, doDownload, doIm const textarea = useRef(null) const editor = useRef() - const getSerializedOutput = useCallback((model: DataModel, blockStates: BlockStateRegistry) => { - let data = getOutput(model, blockStates) + const getSerializedOutput = useCallback((model: FileModel) => { + let data = model.data if (sort === 'alphabetically') { data = sortData(data) } @@ -51,9 +48,9 @@ export function SourcePanel({ name, model, blockStates, doCopy, doDownload, doIm useEffect(() => { retransform.current = () => { if (!editor.current) return - if (!model || !blockStates) return + if (!model) return try { - const output = getSerializedOutput(model, blockStates) + const output = getSerializedOutput(model) editor.current.setValue(output) } catch (e) { if (e instanceof Error) { @@ -72,8 +69,8 @@ export function SourcePanel({ name, model, blockStates, doCopy, doDownload, doIm const value = editor.current.getValue() if (value.length === 0) return try { - const data = await parseSource(value, format) - model?.reset(DataModel.wrapLists(data), false) + await parseSource(value, format) + // TODO: import } catch (e) { if (e instanceof Error) { e.message = `Error importing: ${e.message}` @@ -84,7 +81,7 @@ export function SourcePanel({ name, model, blockStates, doCopy, doDownload, doIm console.error(e) } } - }, [model, blockStates, indent, format, sort, highlighting]) + }, [model, indent, format, sort, highlighting]) useEffect(() => { if (highlighting) { @@ -145,10 +142,7 @@ export function SourcePanel({ name, model, blockStates, doCopy, doDownload, doIm } }, [highlighting]) - useModel(model, () => { - if (!retransform.current) return - retransform.current() - }) + // TODO: when file contents change, retransform useEffect(() => { if (!retransform.current) return if (model) retransform.current() @@ -163,16 +157,16 @@ export function SourcePanel({ name, model, blockStates, doCopy, doDownload, doIm }, [indent, format, sort, highlighting, braceLoaded]) useEffect(() => { - if (doCopy && model && blockStates) { - navigator.clipboard.writeText(getSerializedOutput(model, blockStates)).then(() => { + if (doCopy && model) { + navigator.clipboard.writeText(getSerializedOutput(model)).then(() => { copySuccess() }) } }, [doCopy]) useEffect(() => { - if (doDownload && model && blockStates && download.current) { - const content = encodeURIComponent(getSerializedOutput(model, blockStates)) + if (doDownload && model && download.current) { + const content = encodeURIComponent(getSerializedOutput(model)) download.current.setAttribute('href', `data:text/json;charset=utf-8,${content}`) const fileName = name === 'pack_mcmeta' ? 'pack.mcmeta' : `${name}.${format}` download.current.setAttribute('download', fileName) diff --git a/src/app/components/generator/Tree.tsx b/src/app/components/generator/Tree.tsx index 3f955c98..3b9c662f 100644 --- a/src/app/components/generator/Tree.tsx +++ b/src/app/components/generator/Tree.tsx @@ -1,19 +1,14 @@ -import type { DataModel } from '@mcschema/core' -import { useErrorBoundary, useState } from 'preact/hooks' +import { useErrorBoundary } from 'preact/hooks' import { useLocale } from '../../contexts/index.js' -import { useModel } from '../../hooks/index.js' -import { FullNode } from '../../schema/renderHtml.js' -import type { BlockStateRegistry, VersionId } from '../../services/index.js' +import type { FileModel } from '../../services/index.js' type TreePanelProps = { - version: VersionId, - model: DataModel | undefined, - blockStates: BlockStateRegistry | undefined, + model: FileModel | undefined, onError: (message: string) => unknown, } -export function Tree({ version, model, blockStates, onError }: TreePanelProps) { +export function Tree({ model, onError }: TreePanelProps) { const { lang } = useLocale() - if (!model || !blockStates || lang === 'none') return <> + if (!model || lang === 'none') return <> const [error] = useErrorBoundary(e => { onError(`Error rendering the tree: ${e.message}`) @@ -21,12 +16,7 @@ export function Tree({ version, model, blockStates, onError }: TreePanelProps) { }) if (error) return <> - const [, setState] = useState(0) - useModel(model, () => { - setState(state => state + 1) - }) - return
- + {/* TODO: render tree */}
} diff --git a/src/app/components/previews/BiomeSourcePreview.tsx b/src/app/components/previews/BiomeSourcePreview.tsx index 63275888..4fe0bed8 100644 --- a/src/app/components/previews/BiomeSourcePreview.tsx +++ b/src/app/components/previews/BiomeSourcePreview.tsx @@ -1,8 +1,7 @@ -import { DataModel } from '@mcschema/core' import { clampedMap } from 'deepslate' import { mat3 } from 'gl-matrix' import { useCallback, useRef, useState } from 'preact/hooks' -import { getProjectData, useLocale, useProject, useStore } from '../../contexts/index.js' +import { getProjectData, useLocale, useProject, useStore, useVersion } from '../../contexts/index.js' import { useAsync } from '../../hooks/index.js' import { checkVersion } from '../../services/Schemas.js' import { Store } from '../../Store.js' @@ -21,8 +20,9 @@ type Layer = typeof LAYERS[number] const DETAIL_DELAY = 300 const DETAIL_SCALE = 2 -export const BiomeSourcePreview = ({ data, shown, version }: PreviewProps) => { +export const BiomeSourcePreview = ({ model, shown }: PreviewProps) => { const { locale } = useLocale() + const { version } = useVersion() const { project } = useProject() const { biomeColors } = useStore() const [seed, setSeed] = useState(randomSeed()) @@ -31,13 +31,13 @@ export const BiomeSourcePreview = ({ data, shown, version }: PreviewProps) => { const [focused, setFocused] = useState([]) const [focused2, setFocused2] = useState([]) - const state = JSON.stringify(data) - const type: string = data?.generator?.biome_source?.type?.replace(/^minecraft:/, '') ?? '' + const state = JSON.stringify(model.data) + const type: string = model.data?.generator?.biome_source?.type?.replace(/^minecraft:/, '') ?? '' const hasRandomness = type === 'multi_noise' || type === 'the_end' const { value } = useAsync(async function loadBiomeSource() { await DEEPSLATE.loadVersion(version, getProjectData(project)) - await DEEPSLATE.loadChunkGenerator(DataModel.unwrapLists(data?.generator?.settings), DataModel.unwrapLists(data?.generator?.biome_source), seed) + await DEEPSLATE.loadChunkGenerator(model.data?.generator?.settings, model.data?.generator?.biome_source, seed) return { biomeSource: { loaded: true }, noiseRouter: checkVersion(version, '1.19') ? DEEPSLATE.getNoiseRouter() : undefined, diff --git a/src/app/components/previews/BlockStatePreview.tsx b/src/app/components/previews/BlockStatePreview.tsx index 89575fb5..adb99d4b 100644 --- a/src/app/components/previews/BlockStatePreview.tsx +++ b/src/app/components/previews/BlockStatePreview.tsx @@ -1,4 +1,3 @@ -import { DataModel } from '@mcschema/core' import { BlockDefinition, Identifier, Structure, StructureRenderer } from 'deepslate/render' import type { mat4 } from 'gl-matrix' import { useCallback, useRef } from 'preact/hooks' @@ -11,14 +10,14 @@ import { InteractiveCanvas3D } from './InteractiveCanvas3D.jsx' const PREVIEW_ID = Identifier.parse('misode:preview') -export const BlockStatePreview = ({ data, shown }: PreviewProps) => { +export const BlockStatePreview = ({ model, shown }: PreviewProps) => { const { version } = useVersion() - const serializedData = JSON.stringify(data) + const serializedData = JSON.stringify(model.data) const { value: resources } = useAsync(async () => { if (!shown) return AsyncCancel const resources = await getResources(version) - const definition = BlockDefinition.fromJson(DataModel.unwrapLists(data)) + const definition = BlockDefinition.fromJson(model.data) const wrapper = new ResourceWrapper(resources, { getBlockDefinition(id) { if (id.equals(PREVIEW_ID)) return definition diff --git a/src/app/components/previews/Decorator.ts b/src/app/components/previews/Decorator.ts index 23a26de4..f65b4c78 100644 --- a/src/app/components/previews/Decorator.ts +++ b/src/app/components/previews/Decorator.ts @@ -1,9 +1,8 @@ -import { DataModel } from '@mcschema/core' import type { BlockPos, ChunkPos, PerlinNoise, Random } from 'deepslate/worldgen' -import type { Color } from '../../Utils.js' -import { clamp, isObject, stringToColor } from '../../Utils.js' import type { VersionId } from '../../services/index.js' import { checkVersion } from '../../services/index.js' +import type { Color } from '../../Utils.js' +import { clamp, isObject, stringToColor } from '../../Utils.js' export type Placement = [BlockPos, number] @@ -38,9 +37,9 @@ export const featureColors: Color[] = [ export function decorateChunk(pos: ChunkPos, state: any, ctx: PlacementContext): PlacedFeature[] { if (checkVersion(ctx.version, undefined, '1.17')) { - getPlacements([pos[0] * 16, 0, pos[1] * 16], DataModel.unwrapLists(state), ctx) + getPlacements([pos[0] * 16, 0, pos[1] * 16], state, ctx) } else { - modifyPlacement([pos[0] * 16, 0, pos[1] * 16], DataModel.unwrapLists(state.placement), ctx) + modifyPlacement([pos[0] * 16, 0, pos[1] * 16], state.placement, ctx) } return ctx.placements.map(([pos, i]) => { diff --git a/src/app/components/previews/DecoratorPreview.tsx b/src/app/components/previews/DecoratorPreview.tsx index 9b038e0d..86031dff 100644 --- a/src/app/components/previews/DecoratorPreview.tsx +++ b/src/app/components/previews/DecoratorPreview.tsx @@ -1,7 +1,7 @@ import { BlockPos, ChunkPos, LegacyRandom, PerlinNoise } from 'deepslate' import type { mat3 } from 'gl-matrix' import { useCallback, useMemo, useRef, useState } from 'preact/hooks' -import { useLocale } from '../../contexts/index.js' +import { useLocale, useVersion } from '../../contexts/index.js' import { computeIfAbsent, iterateWorld2D, randomSeed } from '../../Utils.js' import { Btn } from '../index.js' import type { PlacedFeature, PlacementContext } from './Decorator.js' @@ -9,10 +9,11 @@ import { decorateChunk } from './Decorator.js' import type { PreviewProps } from './index.js' import { InteractiveCanvas2D } from './InteractiveCanvas2D.jsx' -export const DecoratorPreview = ({ data, version, shown }: PreviewProps) => { +export const DecoratorPreview = ({ model, shown }: PreviewProps) => { const { locale } = useLocale() + const { version } = useVersion() const [seed, setSeed] = useState(randomSeed()) - const state = JSON.stringify(data) + const state = JSON.stringify(model.data) const { context, chunkFeatures } = useMemo(() => { const random = new LegacyRandom(seed) @@ -51,7 +52,7 @@ export const DecoratorPreview = ({ data, version, shown }: PreviewProps) => { iterateWorld2D(imageData.current, transform, (x, y) => { const pos = ChunkPos.create(Math.floor(x / 16), Math.floor(-y / 16)) - const features = computeIfAbsent(chunkFeatures, `${pos[0]} ${pos[1]}`, () => decorateChunk(pos, data, context)) + const features = computeIfAbsent(chunkFeatures, `${pos[0]} ${pos[1]}`, () => decorateChunk(pos, model.data, context)) return features.find(f => f.pos[0] === x && f.pos[2] == -y) ?? { pos: BlockPos.create(x, 0, -y) } }, (feature) => { if ('color' in feature) { diff --git a/src/app/components/previews/DensityFunctionPreview.tsx b/src/app/components/previews/DensityFunctionPreview.tsx index 4742e0dc..886a8541 100644 --- a/src/app/components/previews/DensityFunctionPreview.tsx +++ b/src/app/components/previews/DensityFunctionPreview.tsx @@ -1,4 +1,3 @@ -import { DataModel } from '@mcschema/core' import type { Voxel } from 'deepslate/render' import { clampedMap, VoxelRenderer } from 'deepslate/render' import type { mat3, mat4 } from 'gl-matrix' @@ -19,7 +18,7 @@ import { InteractiveCanvas3D } from './InteractiveCanvas3D.jsx' const MODES = ['side', 'top', '3d'] as const -export const DensityFunctionPreview = ({ data, shown }: PreviewProps) => { +export const DensityFunctionPreview = ({ model, shown }: PreviewProps) => { const { locale } = useLocale() const { project } = useProject() const { version } = useVersion() @@ -29,11 +28,11 @@ export const DensityFunctionPreview = ({ data, shown }: PreviewProps) => { const [seed, setSeed] = useState(randomSeed()) const [minY] = useState(0) const [height] = useState(256) - const serializedData = JSON.stringify(data) + const serializedData = JSON.stringify(model.data) const { value: df } = useAsync(async () => { await DEEPSLATE.loadVersion(version, getProjectData(project)) - const df = DEEPSLATE.loadDensityFunction(DataModel.unwrapLists(data), minY, height, seed) + const df = DEEPSLATE.loadDensityFunction(model.data, minY, height, seed) return df }, [version, project, minY, height, seed, serializedData]) diff --git a/src/app/components/previews/LootTablePreview.tsx b/src/app/components/previews/LootTablePreview.tsx index 60c68fe5..1205ba96 100644 --- a/src/app/components/previews/LootTablePreview.tsx +++ b/src/app/components/previews/LootTablePreview.tsx @@ -1,4 +1,3 @@ -import { DataModel } from '@mcschema/core' import { Identifier } from 'deepslate' import { useMemo, useRef, useState } from 'preact/hooks' import { useLocale, useVersion } from '../../contexts/index.js' @@ -12,7 +11,7 @@ import type { PreviewProps } from './index.js' import { generateLootTable } from './LootTable.js' import { generateLootTable as generateLootTable1204 } from './LootTable1204.js' -export const LootTablePreview = ({ data }: PreviewProps) => { +export const LootTablePreview = ({ model }: PreviewProps) => { const { locale } = useLocale() const { version } = useVersion() const use1204 = !checkVersion(version, '1.20.5') @@ -35,7 +34,7 @@ export const LootTablePreview = ({ data }: PreviewProps) => { ]) }, [version]) - const table = DataModel.unwrapLists(data) + const table = model.data const state = JSON.stringify(table) const items = useMemo(() => { if (dependencies === undefined || loading) { diff --git a/src/app/components/previews/ModelPreview.tsx b/src/app/components/previews/ModelPreview.tsx index 9c440f32..0b7b31c4 100644 --- a/src/app/components/previews/ModelPreview.tsx +++ b/src/app/components/previews/ModelPreview.tsx @@ -1,4 +1,3 @@ -import { DataModel } from '@mcschema/core' import { BlockDefinition, BlockModel, Identifier, Structure, StructureRenderer } from 'deepslate/render' import type { mat4 } from 'gl-matrix' import { useCallback, useRef } from 'preact/hooks' @@ -12,22 +11,22 @@ import { InteractiveCanvas3D } from './InteractiveCanvas3D.jsx' const PREVIEW_ID = Identifier.parse('misode:preview') const PREVIEW_DEFINITION = new BlockDefinition({ '': { model: PREVIEW_ID.toString() }}, undefined) -export const ModelPreview = ({ data, shown }: PreviewProps) => { +export const ModelPreview = ({ model, shown }: PreviewProps) => { const { version } = useVersion() - const serializedData = JSON.stringify(data) + const serializedData = JSON.stringify(model.data) const { value: resources } = useAsync(async () => { if (!shown) return AsyncCancel const resources = await getResources(version) - const model = BlockModel.fromJson(DataModel.unwrapLists(data)) - model.flatten(resources) + const blockModel = BlockModel.fromJson(model.data) + blockModel.flatten(resources) const wrapper = new ResourceWrapper(resources, { getBlockDefinition(id) { if (id.equals(PREVIEW_ID)) return PREVIEW_DEFINITION return null }, getBlockModel(id) { - if (id.equals(PREVIEW_ID)) return model + if (id.equals(PREVIEW_ID)) return blockModel return null }, }) diff --git a/src/app/components/previews/NoisePreview.tsx b/src/app/components/previews/NoisePreview.tsx index 097d83f2..7d12be0b 100644 --- a/src/app/components/previews/NoisePreview.tsx +++ b/src/app/components/previews/NoisePreview.tsx @@ -1,4 +1,3 @@ -import { DataModel } from '@mcschema/core' import { clampedMap, NoiseParameters, NormalNoise, XoroshiroRandom } from 'deepslate' import type { mat3 } from 'gl-matrix' import { useCallback, useMemo, useRef, useState } from 'preact/hooks' @@ -12,14 +11,14 @@ import { ColormapSelector } from './ColormapSelector.jsx' import type { PreviewProps } from './index.js' import { InteractiveCanvas2D } from './InteractiveCanvas2D.jsx' -export const NoisePreview = ({ data, shown }: PreviewProps) => { +export const NoisePreview = ({ model, shown }: PreviewProps) => { const { locale } = useLocale() const [seed, setSeed] = useState(randomSeed()) - const state = JSON.stringify(data) + const state = JSON.stringify(model.data) const noise = useMemo(() => { const random = XoroshiroRandom.create(seed) - const params = NoiseParameters.fromJson(DataModel.unwrapLists(data)) + const params = NoiseParameters.fromJson(model.data) return new NormalNoise(random, params) }, [state, seed]) diff --git a/src/app/components/previews/NoiseSettingsPreview.tsx b/src/app/components/previews/NoiseSettingsPreview.tsx index a75a25e3..e8752b69 100644 --- a/src/app/components/previews/NoiseSettingsPreview.tsx +++ b/src/app/components/previews/NoiseSettingsPreview.tsx @@ -1,31 +1,31 @@ -import { DataModel } from '@mcschema/core' import { clampedMap } from 'deepslate' import type { mat3 } from 'gl-matrix' import { vec2 } from 'gl-matrix' -import { useCallback, useMemo, useRef, useState } from 'preact/hooks' +import { useCallback, useRef, useState } from 'preact/hooks' +import { getProjectData, useLocale, useProject, useVersion } from '../../contexts/index.js' +import { useAsync } from '../../hooks/index.js' +import { fetchRegistries } from '../../services/index.js' import { Store } from '../../Store.js' import { iterateWorld2D, randomSeed } from '../../Utils.js' -import { getProjectData, useLocale, useProject } from '../../contexts/index.js' -import { useAsync } from '../../hooks/index.js' -import { CachedCollections } from '../../services/index.js' import { Btn, BtnInput, BtnMenu, ErrorPanel } from '../index.js' import type { ColormapType } from './Colormap.js' import { getColormap } from './Colormap.js' import { ColormapSelector } from './ColormapSelector.jsx' import { DEEPSLATE } from './Deepslate.js' -import { InteractiveCanvas2D } from './InteractiveCanvas2D.jsx' import type { PreviewProps } from './index.js' +import { InteractiveCanvas2D } from './InteractiveCanvas2D.jsx' -export const NoiseSettingsPreview = ({ data, shown, version }: PreviewProps) => { +export const NoiseSettingsPreview = ({ model, shown }: PreviewProps) => { const { locale } = useLocale() + const { version } = useVersion() const { project } = useProject() const [seed, setSeed] = useState(randomSeed()) const [biome, setBiome] = useState('minecraft:plains') const [layer, setLayer] = useState('terrain') - const state = JSON.stringify(data) + const state = JSON.stringify(model.data) const { value, error } = useAsync(async () => { - const unwrapped = DataModel.unwrapLists(data) + const unwrapped = model.data await DEEPSLATE.loadVersion(version, getProjectData(project)) const biomeSource = { type: 'fixed', biome } await DEEPSLATE.loadChunkGenerator(unwrapped, biomeSource, seed) @@ -86,7 +86,10 @@ export const NoiseSettingsPreview = ({ data, shown, version }: PreviewProps) => } }, [noiseSettings, finalDensity]) - const allBiomes = useMemo(() => CachedCollections?.get('worldgen/biome') ?? [], [version]) + const { value: allBiomes } = useAsync(async () => { + const registries = await fetchRegistries(version) + return registries.get('worldgen/biome') + }, [version]) if (error) { return diff --git a/src/app/components/previews/RecipePreview.tsx b/src/app/components/previews/RecipePreview.tsx index 9eaccba8..2451ca1b 100644 --- a/src/app/components/previews/RecipePreview.tsx +++ b/src/app/components/previews/RecipePreview.tsx @@ -1,7 +1,6 @@ -import { DataModel } from '@mcschema/core' import { Identifier, ItemStack } from 'deepslate' import { useEffect, useMemo, useRef, useState } from 'preact/hooks' -import { useLocale } from '../../contexts/index.js' +import { useLocale, useVersion } from '../../contexts/index.js' import { useAsync } from '../../hooks/useAsync.js' import type { VersionId } from '../../services/index.js' import { checkVersion, fetchAllPresets } from '../../services/index.js' @@ -12,8 +11,9 @@ import type { PreviewProps } from './index.js' const ANIMATION_TIME = 1000 -export const RecipePreview = ({ data, version }: PreviewProps) => { +export const RecipePreview = ({ model }: PreviewProps) => { const { locale } = useLocale() + const { version } = useVersion() const [advancedTooltips, setAdvancedTooltips] = useState(true) const [animation, setAnimation] = useState(0) const overlay = useRef(null) @@ -29,7 +29,7 @@ export const RecipePreview = ({ data, version }: PreviewProps) => { return () => clearInterval(interval) }, []) - const recipe = DataModel.unwrapLists(data) + const recipe = model.data const state = JSON.stringify(recipe) const items = useMemo>(() => { return placeItems(version, recipe, animation, itemTags ?? new Map()) diff --git a/src/app/components/previews/StructureSetPreview.tsx b/src/app/components/previews/StructureSetPreview.tsx index 451d563c..80f10b56 100644 --- a/src/app/components/previews/StructureSetPreview.tsx +++ b/src/app/components/previews/StructureSetPreview.tsx @@ -1,26 +1,26 @@ -import { DataModel } from '@mcschema/core' import type { Identifier } from 'deepslate' import { ChunkPos } from 'deepslate' import type { mat3 } from 'gl-matrix' import { useCallback, useMemo, useRef, useState } from 'preact/hooks' +import { useLocale, useVersion } from '../../contexts/index.js' +import { useAsync } from '../../hooks/useAsync.js' import type { Color } from '../../Utils.js' import { computeIfAbsent, iterateWorld2D, randomSeed, stringToColor } from '../../Utils.js' -import { useLocale } from '../../contexts/index.js' -import { useAsync } from '../../hooks/useAsync.js' import { Btn } from '../index.js' import { featureColors } from './Decorator.js' import { DEEPSLATE } from './Deepslate.js' -import { InteractiveCanvas2D } from './InteractiveCanvas2D.jsx' import type { PreviewProps } from './index.js' +import { InteractiveCanvas2D } from './InteractiveCanvas2D.jsx' -export const StructureSetPreview = ({ data, version, shown }: PreviewProps) => { +export const StructureSetPreview = ({ model, shown }: PreviewProps) => { const { locale } = useLocale() + const { version } = useVersion() const [seed, setSeed] = useState(randomSeed()) - const state = JSON.stringify(data) + const state = JSON.stringify(model.data) const { value: structureSet } = useAsync(async () => { await DEEPSLATE.loadVersion(version) - const structureSet = DEEPSLATE.loadStructureSet(DataModel.unwrapLists(data), seed) + const structureSet = DEEPSLATE.loadStructureSet(model.data, seed) return structureSet }, [state, version, seed]) diff --git a/src/app/components/previews/index.ts b/src/app/components/previews/index.ts index abadf129..b139e825 100644 --- a/src/app/components/previews/index.ts +++ b/src/app/components/previews/index.ts @@ -1,5 +1,4 @@ -import type { DataModel } from '@mcschema/core' -import type { VersionId } from '../../services/index.js' +import type { FileModel } from '../../services/index.js' export * from './BiomeSourcePreview.js' export * from './BlockStatePreview.jsx' @@ -12,9 +11,7 @@ export * from './NoiseSettingsPreview.js' export * from './RecipePreview.jsx' export * from './StructureSetPreview.jsx' -export type PreviewProps = { - model: DataModel, - data: any, - shown: boolean, - version: VersionId, +export interface PreviewProps { + model: FileModel + shown: boolean } diff --git a/src/app/contexts/Locale.tsx b/src/app/contexts/Locale.tsx index 1b40eb5f..596253a5 100644 --- a/src/app/contexts/Locale.tsx +++ b/src/app/contexts/Locale.tsx @@ -46,13 +46,7 @@ async function loadLocale(language: string) { const langConfig = config.languages.find(lang => lang.code === language) if (!langConfig) return const data = await import(`../../locales/${language}.json`) - const schema = langConfig.schemas !== false - && await import(`../../../node_modules/@mcschema/locales/src/${language}.json`) - let partners = { default: {} } - if (language === 'en') { - partners = await import('../partners/locales/en.json') - } - Locales[language] = { ...data.default, ...schema.default, ...partners.default } + Locales[language] = data.default } export function useLocale() { diff --git a/src/app/hooks/index.ts b/src/app/hooks/index.ts index ce5d2c4b..449eb0dd 100644 --- a/src/app/hooks/index.ts +++ b/src/app/hooks/index.ts @@ -5,6 +5,5 @@ export * from './useFocus.js' export * from './useHash.js' export * from './useLocalStorage.js' export * from './useMediaQuery.js' -export * from './useModel.js' export * from './useSearchParam.js' export * from './useTags.js' diff --git a/src/app/hooks/useModel.ts b/src/app/hooks/useModel.ts deleted file mode 100644 index 4567deb8..00000000 --- a/src/app/hooks/useModel.ts +++ /dev/null @@ -1,20 +0,0 @@ -import type { DataModel } from '@mcschema/core' -import type { Inputs } from 'preact/hooks' -import { useEffect } from 'preact/hooks' - -export function useModel(model: DataModel | undefined | null, invalidated: (model: DataModel) => unknown, inputs?: Inputs) { - const listener = { - invalidated() { - if (model) { - invalidated(model) - } - }, - } - - useEffect(() => { - model?.addListener(listener) - return () => { - model?.removeListener(listener) - } - }, [model, ...inputs ?? []]) -} diff --git a/src/app/partners/ImmersiveWeathering.ts b/src/app/partners/ImmersiveWeathering.ts deleted file mode 100644 index ac3da960..00000000 --- a/src/app/partners/ImmersiveWeathering.ts +++ /dev/null @@ -1,210 +0,0 @@ -import type { CollectionRegistry, ResourceType, SchemaRegistry } from '@mcschema/core' -import { BooleanNode, Case, ChoiceNode, ListNode, MapNode, NumberNode, ObjectNode, Opt, Reference as RawReference, StringNode as RawStringNode, Switch } from '@mcschema/core' - -const ID = 'immersive_weathering' - -export function initImmersiveWeathering(schemas: SchemaRegistry, collections: CollectionRegistry) { - const Reference = RawReference.bind(undefined, schemas) - const StringNode = RawStringNode.bind(undefined, collections) - - const Tag = (id: Exclude) => ChoiceNode([ - { - type: 'string', - node: StringNode({ validator: 'resource', params: { pool: id, allowTag: true } }), - change: (v: unknown) => { - if (Array.isArray(v) && typeof v[0] === 'string' && !v[0].startsWith('#')) { - return v[0] - } - return undefined - }, - }, - { - type: 'list', - node: ListNode( - StringNode({ validator: 'resource', params: { pool: id } }) - ), - change: (v: unknown) => { - if (typeof v === 'string' && !v.startsWith('#')) { - return [v] - } - return [] - }, - }, - ], { choiceContext: 'tag' }) - - schemas.register(`${ID}:block_growth`, ObjectNode({ - area_condition: Reference(`${ID}:area_condition`), - position_predicates: Opt(ListNode( - Reference(`${ID}:position_test`) - )), - growth_chance: NumberNode({ min: 0, max: 1 }), - growth_for_face: ListNode( - ObjectNode({ - direction: Opt(StringNode({ enum: 'direction' })), - weight: Opt(NumberNode({ integer: true })), - growth: ListNode( - ObjectNode({ - data: Reference(`${ID}:block_pair`), - weight: NumberNode({ integer: true }), - }) - ), - }, { category: 'pool' }) - ), - owners: ListNode( - StringNode({ validator: 'resource', params: { pool: 'block' } }) - ), - replacing_target: Reference(`${ID}:rule_test`), - target_self: Opt(BooleanNode()), - destroy_target: Opt(BooleanNode()), - }, { context: `${ID}.block_growth` })) - - schemas.register(`${ID}:area_condition`, ObjectNode({ - type: StringNode({ enum: ['generate_if_not_too_many', 'neighbor_based_generation'] }), - [Switch]: [{ push: 'type' }], - [Case]: { - generate_if_not_too_many: { - radiusX: NumberNode({ integer: true }), - radiusY: NumberNode({ integer: true }), - radiusZ: NumberNode({ integer: true }), - requiredAmount: NumberNode({ integer: true }), - yOffset: Opt(NumberNode({ integer: true })), - must_have: Opt(Reference(`${ID}:rule_test`)), - must_not_have: Opt(Reference(`${ID}:rule_test`)), - includes: Opt(Tag('block')), - }, - neighbor_based_generation: { - must_have: Reference(`${ID}:rule_test`), - must_not_have: Opt(Reference(`${ID}:rule_test`)), - required_amount: Opt(NumberNode({ integer: true })), - directions: ListNode( - StringNode({ enum: 'direction' }) - ), - }, - }, - }, { context: `${ID}.area_condition` })) - - schemas.register(`${ID}:block_pair`, ObjectNode({ - block: Reference(`${ID}:block_state`), - above_block: Opt(Reference(`${ID}:block_state`)), - }, { context: `${ID}.block_pair` })) - - schemas.register(`${ID}:block_state`, ObjectNode({ - Name: StringNode({ validator: 'resource', params: { pool: 'block' } }), - Properties: Opt(MapNode( - StringNode(), - StringNode(), - )), - }, { context: 'block_state' })) - - schemas.register(`${ID}:position_test`, ObjectNode({ - predicate_type: StringNode({ enum: ['biome_match', 'day_test', 'nand', 'precipitation_test', 'temperature_range'] }), - [Switch]: [{ push: 'predicate_type' }], - [Case]: { - biome_match: { - biomes: Tag('$worldgen/biome'), - }, - day_test: { - day: BooleanNode(), - }, - nand: { - predicates: ListNode( - Reference(`${ID}:position_test`) - ), - }, - precipitation_test: { - precipitation: StringNode({ enum: ['none', 'rain', 'snow']}), - }, - temperature_range: { - min: NumberNode(), - max: NumberNode(), - use_local_pos: Opt(BooleanNode()), - }, - }, - }, { context: `${ID}.position_test`, category: 'predicate' })) - - collections.register(`${ID}:rule_test`, [ - ...collections.get('rule_test'), - 'immersive_weathering:block_set_match', - 'immersive_weathering:fluid_match', - 'immersive_weathering:tree_log', - ]) - - schemas.register(`${ID}:rule_test`, ObjectNode({ - predicate_type: StringNode({ validator: 'resource', params: { pool: `${ID}:rule_test` as any } }), - [Switch]: [{ push: 'predicate_type' }], - [Case]: { - 'minecraft:block_match': { - block: StringNode({ validator: 'resource', params: { pool: 'block' } }), - }, - 'minecraft:blockstate_match': { - block_state: Reference('block_state'), - }, - 'minecraft:random_block_match': { - block: StringNode({ validator: 'resource', params: { pool: 'block' } }), - probability: NumberNode({ min: 0, max: 1 }), - }, - 'minecraft:random_blockstate_match': { - block_state: Reference('block_state'), - probability: NumberNode({ min: 0, max: 1 }), - }, - 'minecraft:tag_match': { - tag: StringNode({ validator: 'resource', params: { pool: '$tag/block' }}), - }, - 'immersive_weathering:block_set_match': { - blocks: Tag('block'), - probability: Opt(NumberNode({ min: 0, max: 1 })), - }, - 'immersive_weathering:fluid_match': { - fluid: StringNode({ validator: 'resource', params: { pool: 'fluid' } }), - }, - }, - }, { context: 'rule_test', disableSwitchContext: true })) - - collections.register('block_growth', [ - 'immersive_weathering:brain_coral', - 'immersive_weathering:bubble_coral', - 'immersive_weathering:cracked_mud_rivers', - 'immersive_weathering:crimson_nylium', - 'immersive_weathering:cryosol', - 'immersive_weathering:farmland_rare_weeds', - 'immersive_weathering:farmland_weeds', - 'immersive_weathering:fire_coral', - 'immersive_weathering:fire_soot', - 'immersive_weathering:fluvisol', - 'immersive_weathering:grass_base', - 'immersive_weathering:grass_block_badlands', - 'immersive_weathering:grass_block_bamboo_jungle', - 'immersive_weathering:grass_block_birch_forest', - 'immersive_weathering:grass_block_dark_forest', - 'immersive_weathering:grass_block_flower_forest', - 'immersive_weathering:grass_block_forest', - 'immersive_weathering:grass_block_jungle', - 'immersive_weathering:grass_block_lush_caves', - 'immersive_weathering:grass_block_old_growth_spruce', - 'immersive_weathering:grass_block_plains', - 'immersive_weathering:grass_block_sunflower_plains', - 'immersive_weathering:grass_block_swamp', - 'immersive_weathering:grass_block_taiga', - 'immersive_weathering:grass_block_wooded_badlands', - 'immersive_weathering:hanging_roots', - 'immersive_weathering:horn_coral', - 'immersive_weathering:humus', - 'immersive_weathering:icicle_growth', - 'immersive_weathering:large_fern', - 'immersive_weathering:magma', - 'immersive_weathering:mycelium', - 'immersive_weathering:podzol', - 'immersive_weathering:red_sand_weathering', - 'immersive_weathering:rooted_dirt', - 'immersive_weathering:rooted_grass', - 'immersive_weathering:sand_weathering', - 'immersive_weathering:sapling', - 'immersive_weathering:sapling_nether', - 'immersive_weathering:silt', - 'immersive_weathering:tall_grass', - 'immersive_weathering:tall_seagrass', - 'immersive_weathering:tube_coral', - 'immersive_weathering:vertisol', - 'immersive_weathering:warped_nylium', - ]) -} diff --git a/src/app/partners/Lithostitched.ts b/src/app/partners/Lithostitched.ts deleted file mode 100644 index 675ee272..00000000 --- a/src/app/partners/Lithostitched.ts +++ /dev/null @@ -1,239 +0,0 @@ -import type { CollectionRegistry, ResourceType, SchemaRegistry } from '@mcschema/core' -import { BooleanNode, Case, ChoiceNode, ListNode, Mod, NumberNode, ObjectNode, Opt, Reference as RawReference, StringNode as RawStringNode, Switch } from '@mcschema/core' -import type { VersionId } from '../services/Schemas.js' - - -const ID = 'lithostitched' - -export function initLithostitched(schemas: SchemaRegistry, collections: CollectionRegistry, version: VersionId) { - const Reference = RawReference.bind(undefined, schemas) - const StringNode = RawStringNode.bind(undefined, collections) - - const Tag = (id: Exclude) => - ChoiceNode( - [ - { - type: 'string', - node: StringNode({ - validator: 'resource', - params: { pool: id, allowTag: true }, - }), - change: (v: unknown) => { - if ( - Array.isArray(v) && - typeof v[0] === 'string' && - !v[0].startsWith('#') - ) { - return v[0] - } - return undefined - }, - }, - { - type: 'list', - node: ListNode( - StringNode({ validator: 'resource', params: { pool: id } }) - ), - change: (v: unknown) => { - if (typeof v === 'string' && !v.startsWith('#')) { - return [v] - } - return [] - }, - }, - ], - { choiceContext: 'tag' } - ) - - // Worldgen Modifiers - const MobCategorySpawnSettings = Mod( - ObjectNode({ - type: StringNode({ - validator: 'resource', - params: { pool: 'entity_type' }, - }), - weight: NumberNode({ integer: true }), - minCount: NumberNode({ integer: true }), - maxCount: NumberNode({ integer: true }), - }), - { - category: () => 'pool', - default: () => [ - { - type: 'minecraft:bat', - weight: 1, - }, - ], - } - ) - - collections.register(`${ID}:modifier_type`, [ - 'lithostitched:add_biome_spawns', - 'lithostitched:add_features', - ...(version === '1.20.5' || version === '1.21') - ? ['lithostitched:add_pool_aliases'] - : [], - 'lithostitched:add_structure_set_entries', - 'lithostitched:add_surface_rule', - 'lithostitched:add_template_pool_elements', - 'lithostitched:no_op', - 'lithostitched:redirect_feature', - 'lithostitched:remove_biome_spawns', - 'lithostitched:remove_features', - 'lithostitched:remove_structures_from_structure_set', - 'lithostitched:replace_climate', - 'lithostitched:replace_effects', - ]) - - collections.register(`${ID}:modifier_predicate_type`, [ - 'lithostitched:all_of', - 'lithostitched:any_of', - 'lithostitched:mod_loaded', - 'lithostitched:not', - 'lithostitched:true', - ]) - - schemas.register(`${ID}:worldgen_modifier`, Mod(ObjectNode({ - type: StringNode({ validator: 'resource', params: { pool: `${ID}:modifier_type` as any } }), - predicate: Mod(Opt(Reference(`${ID}:modifier_predicate`)), { - enabled: () => version !== '1.21', - }), - [Switch]: [{ push: 'type' }], - [Case]: { - 'lithostitched:add_biome_spawns': { - biomes: Tag('$worldgen/biome'), - spawners: ChoiceNode([ - { - type: 'object', - node: MobCategorySpawnSettings, - change: (v: any) => v[0], - }, - { - type: 'list', - node: ListNode(MobCategorySpawnSettings), - change: (v: any) => Array(v), - }, - ]), - }, - 'lithostitched:add_features': { - biomes: Tag('$worldgen/biome'), - features: Tag('$worldgen/configured_feature'), - step: StringNode({ enum: 'decoration_step' }), - }, - 'lithostitched:add_pool_aliases': { - structure: StringNode({ validator: 'resource', params: { pool: '$worldgen/structure' } }), - pool_aliases: Reference('pool_alias_binding'), - }, - 'lithostitched:add_structure_set_entries': { - structure_set: StringNode({ validator: 'resource', params: { pool: '$worldgen/structure_set' } }), - entries: ListNode( - ObjectNode({ - structure: StringNode({ validator: 'resource', params: { pool: '$worldgen/structure' } }), - weight: NumberNode({ integer: true, min: 1 }), - }) - ), - }, - 'lithostitched:add_surface_rule': { - levels: ListNode(StringNode({ validator: 'resource', params: { pool: '$dimension' } })), - surface_rule: Reference('material_rule'), - }, - 'lithostitched:add_template_pool_elements': { - template_pool: StringNode({ validator: 'resource', params: { pool: '$worldgen/template_pool' } }), - elements: ListNode( - Reference('template_weighted_element') - ), - }, - 'lithostitched:redirect_feature': { - placed_feature: StringNode({ validator: 'resource', params: { pool: '$worldgen/placed_feature' } }), - redirect_to: StringNode({ validator: 'resource', params: { pool: '$worldgen/configured_feature' } }), - }, - 'lithostitched:remove_biome_spawns': { - biomes: Tag('$worldgen/biome'), - mobs: Tag('entity_type'), - }, - 'lithostitched:remove_features': { - biomes: Tag('$worldgen/biome'), - features: Tag('$worldgen/configured_feature'), - step: StringNode({ enum: 'decoration_step' }), - }, - 'lithostitched:remove_structures_from_structure_set': { - structure_set: StringNode({ validator: 'resource', params: { pool: '$worldgen/structure_set' } }), - structures: ListNode( - StringNode({ validator: 'resource', params: { pool: '$worldgen/structure' } }) - ), - }, - 'lithostitched:replace_climate': { - biomes: Tag('$worldgen/biome'), - climate: ObjectNode({ - temperature: NumberNode(), - downfall: NumberNode(), - has_precipitation: BooleanNode(), - temperature_modifier: Opt(StringNode({ enum: ['none', 'frozen'] })), - }), - }, - 'lithostitched:replace_effects': { - biomes: Tag('$worldgen/biome'), - effects: ObjectNode({ - sky_color: Opt(NumberNode({ color: true })), - fog_color: Opt(NumberNode({ color: true })), - water_color: Opt(NumberNode({ color: true })), - water_fog_color: Opt(NumberNode({ color: true })), - grass_color: Opt(NumberNode({ color: true })), - foliage_color: Opt(NumberNode({ color: true })), - grass_color_modifier: Opt(StringNode({ enum: ['none', 'dark_forest', 'swamp'] })), - ambient_sound: Opt(StringNode()), - mood_sound: Opt(ObjectNode({ - sound: StringNode(), - tick_delay: NumberNode({ integer: true }), - block_search_extent: NumberNode({ integer: true }), - offset: NumberNode(), - })), - additions_sound: Opt(ObjectNode({ - sound: StringNode(), - tick_chance: NumberNode({ min: 0, max: 1 }), - })), - music: Opt(ObjectNode({ - sound: StringNode(), - min_delay: NumberNode({ integer: true, min: 0 }), - max_delay: NumberNode({ integer: true, min: 0 }), - replace_current_music: BooleanNode(), - })), - particle: Opt(ObjectNode({ - options: ObjectNode({ - type: StringNode(), - }), - probability: NumberNode({ min: 0, max: 1 }), - })), - }), - }, - }, - }, { context: `${ID}.worldgen_modifier`, disableSwitchContext: true }), { - default: () => ({ - type: `${ID}:add_features`, - biomes: '#minecraft:is_overworld', - features: 'example:ore_ruby', - step: 'underground_ores', - }), - })) - - schemas.register(`${ID}:modifier_predicate`, ObjectNode({ - type: StringNode({ validator: 'resource', params: { pool: `${ID}:modifier_predicate_type` as any } }), - [Switch]: [{ push: 'type' }], - [Case]: { - 'lithostitched:all_of': { - predicates: ListNode(Reference(`${ID}:modifier_predicate`)), - }, - 'lithostitched:any_of': { - predicates: ListNode(Reference(`${ID}:modifier_predicate`)), - }, - 'lithostitched:mod_loaded': { - mod_id: StringNode(), - }, - 'lithostitched:not': { - predicate: Reference(`${ID}:modifier_predicate`), - }, - }, - }, { - context: `${ID}.modifier_predicate`, disableSwitchContext: true, - })) -} diff --git a/src/app/partners/NeoForge.ts b/src/app/partners/NeoForge.ts deleted file mode 100644 index 5048df7c..00000000 --- a/src/app/partners/NeoForge.ts +++ /dev/null @@ -1,492 +0,0 @@ -import type { CollectionRegistry, INode, ResourceType, SchemaRegistry } from '@mcschema/core' -import { BooleanNode, Case, ChoiceNode, ListNode, MapNode, Mod, NumberNode, ObjectNode, Opt, StringNode as RawStringNode, Switch } from '@mcschema/core' -import type { VersionId } from '../services/Schemas.js' - -const ID = 'neoforge' - -export function initNeoForge(schemas: SchemaRegistry, collections: CollectionRegistry, _version: VersionId) { - const StringNode = RawStringNode.bind(undefined, collections) - - // Homogenous list (ref, list of refs, tag) - const Tag = (id: Exclude) => - ChoiceNode( - [ - { - type: 'string', - node: StringNode({ - validator: 'resource', - params: { pool: id, allowTag: true }, - }), - change: (v: unknown) => { - if ( - Array.isArray(v) && - typeof v[0] === 'string' && - !v[0].startsWith('#') - ) { - return v[0] - } - return undefined - }, - }, - { - type: 'list', - node: ListNode( - StringNode({ validator: 'resource', params: { pool: id } }) - ), - change: (v: unknown) => { - if (typeof v === 'string' && !v.startsWith('#')) { - return [v] - } - return [] - }, - }, - ], - { choiceContext: 'tag' } - ) - - // Spawner data - const MobCategorySpawnSettings = Mod( - ObjectNode({ - type: StringNode({ validator: 'resource', params: { pool: 'entity_type' }}), - weight: NumberNode({ integer: true, min: 0 }), - minCount: NumberNode({ integer: true, min: 1 }), - maxCount: NumberNode({ integer: true, min: 1 }), - }), - { - category: () => 'pool', - default: () => [ - { - type: 'minecraft:bat', - weight: 1, - }, - ], - } - ) - - // Generation step carving - const CarvingStep = StringNode({ enum: [ 'air', 'liquid' ] }) - - // Mob category - const MobCategory = StringNode({ enum: [ 'monster', 'creature', 'ambient', 'axolotls', 'underground_water_creature', 'water_creature', 'water_ambient', 'misc' ], additional: true }) - - // Biome modifier types - collections.register(`${ID}:biome_modifier_type`, [ - 'neoforge:none', - 'neoforge:add_features', - 'neoforge:remove_features', - 'neoforge:add_spawns', - 'neoforge:remove_spawns', - 'neoforge:add_carvers', - 'neoforge:remove_carvers', - 'neoforge:add_spawn_costs', - 'neoforge:remove_spawn_costs', - ]) - - // Biome modifiers - schemas.register(`${ID}:biome_modifier`, Mod( - ObjectNode({ - type: StringNode({ validator: 'resource', params: { pool: `${ID}:biome_modifier_type` as any }}), - [Switch]: [{ push: 'type' }], - [Case]: { - 'neoforge:none': {}, - 'neoforge:add_features': { - biomes: Tag('$worldgen/biome'), - features: Tag('$worldgen/placed_feature'), - step: StringNode({ enum: 'decoration_step' }), - }, - 'neoforge:remove_features': { - biomes: Tag('$worldgen/biome'), - features: Tag('$worldgen/placed_feature'), - steps: Opt(ChoiceNode([ - { - type: 'string', - node: StringNode({ enum: 'decoration_step' }), - change: (v: any) => v[0], - }, - { - type: 'list', - node: ListNode(StringNode({ enum: 'decoration_step' })), - change: (v: any) => Array(v), - }, - ])), - }, - 'neoforge:add_spawns': { - biomes: Tag('$worldgen/biome'), - spawners: ChoiceNode([ - { - type: 'object', - node: MobCategorySpawnSettings, - change: (v: any) => v[0], - }, - { - type: 'list', - node: MobCategorySpawnSettings, - change: (v: any) => Array(v), - }, - ]), - }, - 'neoforge:remove_spawns': { - biomes: Tag('$worldgen/biome'), - entity_types: Tag('entity_type'), - }, - 'neoforge:add_carvers': { - biomes: Tag('$worldgen/biome'), - carvers: Tag('$worldgen/configured_carver'), - step: CarvingStep, - }, - 'neoforge:remove_carvers': { - biomes: Tag('$worldgen/biome'), - carvers: Tag('$worldgen/configured_carver'), - steps: Opt(ChoiceNode([ - { - type: 'string', - node: CarvingStep, - change: (v: any) => v[0], - }, - { - type: 'list', - node: ListNode(CarvingStep), - change: (v: any) => Array(v), - }, - ])), - }, - 'neoforge:add_spawn_costs': { - biomes: Tag('$worldgen/biome'), - entity_types: Tag('entity_type'), - spawn_cost: ObjectNode({ - energy_budget: NumberNode(), - charge: NumberNode(), - }), - }, - 'neoforge:remove_spawn_costs': { - biomes: Tag('$worldgen/biome'), - entity_types: Tag('entity_type'), - }, - }, - }, { context: `${ID}.biome_modifier`, disableSwitchContext: true }), - { - default: () => ({ - type: `${ID}:add_features`, - biomes: '#minecraft:is_overworld', - features: 'minecraft:ore_iron_small', - step: 'underground_ores', - }), - } - )) - - // Structure modifier types - collections.register(`${ID}:structure_modifier_type`, [ - 'neoforge:none', - 'neoforge:add_spawns', - 'neoforge:remove_spawns', - 'neoforge:clear_spawns', - ]) - - // Structure modifiers - schemas.register(`${ID}:structure_modifier`, Mod( - ObjectNode({ - type: StringNode({ validator: 'resource', params: { pool: `${ID}:structure_modifier_type` as any }}), - [Switch]: [{ push: 'type' }], - [Case]: { - 'neoforge:none': {}, - 'neoforge:add_spawns': { - structures: Tag('$worldgen/structure'), - spawners: ChoiceNode([ - { - type: 'object', - node: MobCategorySpawnSettings, - change: (v: any) => v[0], - }, - { - type: 'list', - node: MobCategorySpawnSettings, - change: (v: any) => Array(v), - }, - ]), - }, - 'neoforge:remove_spawns': { - structures: Tag('$worldgen/structure'), - entity_types: Tag('entity_type'), - }, - 'neoforge:clear_spawns': { - structures: Tag('$worldgen/structure'), - categories: ChoiceNode([ - { - type: 'string', - node: MobCategory, - change: (v: any) => v[0], - }, - { - type: 'list', - node: MobCategory, - change: (v: any) => Array(v), - }, - ]), - }, - }, - }, { context: `${ID}.structure_modifier`, disableSwitchContext: true }), - { - default: () => ({ - type: `${ID}:add_spawns`, - structures: '#minecraft:village', - spawners: { - type: 'minecraft:bat', - weight: 1, - }, - }), - } - )) - - // Data maps - createDataMap(schemas, collections, 'compostables', 'item', ChoiceNode([ - { - type: 'number', - node: NumberNode({ - min: 0, - max: 1, - }), - change: (v: any) => v?.chance, - }, - { - type: 'object', - node: ObjectNode({ - chance: NumberNode({ - min: 0, - max: 1, - }), - can_villager_compost: Opt(BooleanNode()), - }), - change: (v: any) => ({ - chance: v, - can_villager_compost: false, - }), - }, - ]), (values) => values['minecraft:apple'] = { - chance: 1, - can_villager_compost: true, - } - ) - createDataMap(schemas, collections, 'furnace_fuels', 'item', ChoiceNode([ - { - type: 'number', - node: NumberNode({ - min: 1, - integer: true, - }), - change: (v: any) => v?.burn_time, - }, - { - type: 'object', - node: ObjectNode({ - burn_time: NumberNode({ - min: 1, - integer: true, - }), - }), - change: (v: any) => ({ - burn_time: v, - }), - }, - ]), (values) => values['minecraft:chest'] = { - burn_time: 300, - } - ) - createDataMap(schemas, collections, 'monster_room_mobs', 'entity_type', ChoiceNode([ - { - type: 'number', - node: NumberNode({ - min: 0, - integer: true, - }), - change: (v: any) => v?.weight, - }, - { - type: 'object', - node: ObjectNode({ - weight: NumberNode({ - min: 0, - integer: true, - }), - }), - change: (v: any) => ({ - weight: v, - }), - }, - ]), (values) => values['minecraft:bat'] = { - weight: 5, - }) - createDataMap(schemas, collections, 'oxidizables', 'block', ChoiceNode([ - { - type: 'string', - node: StringNode({ - validator: 'resource', - params: { pool: 'block' }, - }), - change: (v: any) => v?.next_oxidation_stage, - }, - { - type: 'object', - node: ObjectNode({ - next_oxidation_stage: StringNode({ - validator: 'resource', - params: { pool: 'block' }, - }), - }), - change: (v: any) => ({ - next_oxidation_stage: v, - }), - }, - ]), (values) => values['minecraft:grass_block'] = { - next_oxidation_stage: 'minecraft:dirt', - }) - createDataMap(schemas, collections, 'parrot_imitations', 'entity_type', ChoiceNode([ - { - type: 'string', - node: StringNode({ - validator: 'resource', - params: { pool: 'sound_event' as any }, - }), - change: (v: any) => v?.sound, - }, - { - type: 'object', - node: ObjectNode({ - sound: StringNode({ - validator: 'resource', - params: { pool: 'sound_event' as any }, - }), - }), - change: (v: any) => ({ - sound: v, - }), - }, - ]), (values) => values['minecraft:allay'] = { - sound: 'minecraft:entity.allay.ambient_without_item', - }) - createDataMap(schemas, collections, 'raid_hero_gifts', 'villager_profession', ChoiceNode([ - { - type: 'string', - node: StringNode({ - validator: 'resource', - params: { pool: '$loot_table' }, - }), - change: (v: any) => v?.loot_table, - }, - { - type: 'object', - node: ObjectNode({ - loot_table: StringNode({ - validator: 'resource', - params: { pool: '$loot_table' }, - }), - }), - change: (v: any) => ({ - loot_table: v, - }), - }, - ]), (values) => values['minecraft:cleric'] = { - loot_table: 'minecraft:empty', - }) - createDataMap(schemas, collections, 'vibration_frequencies', 'game_event', ChoiceNode([ - { - type: 'number', - node: NumberNode({ - min: 1, - max: 15, - integer: true, - }), - change: (v: any) => v?.frequency, - }, - { - type: 'object', - node: ObjectNode({ - frequency: NumberNode({ - min: 1, - max: 15, - integer: true, - }), - }), - change: (v: any) => ({ - frequency: v, - }), - }, - ]), (values) => values['minecraft:block_change'] = { - frequency: 5, - }) - createDataMap(schemas, collections, 'waxables', 'block', ChoiceNode([ - { - type: 'string', - node: StringNode({ - validator: 'resource', - params: { pool: 'block' }, - }), - change: (v: any) => v?.waxed, - }, - { - type: 'object', - node: ObjectNode({ - waxed: StringNode({ - validator: 'resource', - params: { pool: 'block' }, - }), - }), - change: (v: any) => ({ - waxed: v, - }), - }, - ]), (values) => values['minecraft:dirt'] = { - waxed: 'minecraft:coarse_dirt', - }) -} - -function createDataMap(schemas: SchemaRegistry, collections: CollectionRegistry, dataMap: string, registry: ResourceType, valueNode: INode, def: (values: any) => void) { - const StringNode = RawStringNode.bind(undefined, collections) - - // Ref or tag - const Tag = StringNode({ - validator: 'resource', - params: { pool: registry, allowTag: true }, - }) - - // Create data map - schemas.register(`${ID}:data_map_${dataMap}`, Mod( - ObjectNode({ - replace: Opt(BooleanNode()), - values: MapNode( - Tag, - ChoiceNode([ - { - type: 'direct', - match: () => true, - node: valueNode, - change: (v: any) => v?.value, - }, - { - type: 'replaceable', - match: (v: any) => typeof v === 'object' && v?.value !== undefined, - priority: 1, - node: ObjectNode({ - replace: Opt(BooleanNode()), - value: valueNode, - }), - change: (v: any) => ({ - replace: true, - value: v, - }), - }, - ]), - ), - remove: Opt(ListNode(Tag)), - }, {context: `${ID}.data_map_${dataMap}`, disableSwitchContext: true}), - { - default: () => { - const result = { - values: {}, - } - def(result.values) - - return result - }, - } - )) -} diff --git a/src/app/partners/Obsidian.ts b/src/app/partners/Obsidian.ts deleted file mode 100644 index ca6f59e3..00000000 --- a/src/app/partners/Obsidian.ts +++ /dev/null @@ -1,442 +0,0 @@ -import type { CollectionRegistry, SchemaRegistry } from '@mcschema/core' -import { BooleanNode, Case, ListNode, MapNode, Mod, NumberNode, ObjectNode, Opt, Reference as RawReference, StringNode as RawStringNode, Switch } from '@mcschema/core' - -const ID = 'obsidian' - -export function initObsidian(schemas: SchemaRegistry, collections: CollectionRegistry) { - const Reference = RawReference.bind(undefined, schemas) - const StringNode = RawStringNode.bind(undefined, collections) - - // ITEMS - schemas.register(`${ID}:item`, Mod(ObjectNode({ - information: Opt(Reference(`${ID}:item_information`)), - display: Opt(ObjectNode({ - model: Opt(Reference(`${ID}:model`)), - item_model: Opt(Reference(`${ID}:model`)), - lore: Opt(ListNode( - ObjectNode({ - text: Reference(`${ID}:name_information`), - }), - )), - })), - use_action: Opt(ObjectNode({ - action: Opt(StringNode({ enum: ['none', 'eat', 'drink', 'block', 'bow', 'spear', 'crossbow', 'spyglass'] })), - right_click_action: Opt(StringNode({ enum: ['open_gui', 'run_command', 'open_url']})) , - command: Opt(StringNode()), - url: Opt(StringNode()), - gui_size: Opt(NumberNode({ integer: true, min: 1, max: 6 })), - gui_title: Opt(Reference(`${ID}:name_information`)), - })), - }, { context: `${ID}:item` }), { - default: () => ({}), - })) - - schemas.register(`${ID}:item_information`, ObjectNode({ - rarity: Opt(StringNode({ enum: ['common', 'uncommon', 'rare', 'epic']})), - creative_tab: Opt(StringNode()), - max_stack_size: Opt(NumberNode({ integer: true, min: 1 })), - name: Opt(Reference(`${ID}:name_information`)), - has_enchantment_glint: Opt(BooleanNode()), - is_enchantable: Opt(BooleanNode()), - enchantability: Opt(NumberNode({ integer: true })), - use_duration: Opt(NumberNode({ integer: true })), - can_place_block: Opt(BooleanNode()), - placable_block: Opt(StringNode({ validator: 'resource', params: { pool: 'block' } })), - wearable: Opt(BooleanNode()), - default_color: Opt(NumberNode({ color: true })), - wearable_slot: Opt(StringNode()), - custom_render_mode: Opt(BooleanNode()), - render_mode_models: Opt(ListNode( - ObjectNode({ - model: Reference('model_identifier'), - modes: ListNode(StringNode()), - }) - )), - }, { context: `${ID}:item_information` })) - - schemas.register(`${ID}:item_model`, ObjectNode({ - textures: Opt(MapNode( - StringNode(), - StringNode({ validator: 'resource', params: { pool: '$texture' } }), - )), - parent: StringNode({ validator: 'resource', params: { pool: '$model'} }), - }, { context: `${ID}:item_model` })) - - schemas.register(`${ID}:block`, Mod(ObjectNode({ - block_type: Opt(StringNode({ enum: `${ID}:block_type`})), - information: Opt(Reference(`${ID}:block_information`)), - display: Opt(ObjectNode({ - model: Opt(Reference(`${ID}:model`)), - item_model: Opt(Reference(`${ID}:model`)), - block_model: Opt(Reference(`${ID}:model`)), - lore: ListNode( - ObjectNode({ - text: Reference(`${ID}:item_name_information`), - }), - ), - })), - additional_information: Opt(ObjectNode({ - extraBlocksName: Opt(StringNode()), - slab: Opt(BooleanNode()), - stairs: Opt(BooleanNode()), - walls: Opt(BooleanNode()), - fence: Opt(BooleanNode()), - fenceGate: Opt(BooleanNode()), - button: Opt(BooleanNode()), - pressurePlate: Opt(BooleanNode()), - door: Opt(BooleanNode()), - trapdoor: Opt(BooleanNode()), - path: Opt(BooleanNode()), - lantern: Opt(BooleanNode()), - barrel: Opt(BooleanNode()), - leaves: Opt(BooleanNode()), - plant: Opt(BooleanNode()), - chains: Opt(BooleanNode()), - cake_like: Opt(BooleanNode()), - waterloggable: Opt(BooleanNode()), - dyable: Opt(BooleanNode()), - defaultColor: Opt(NumberNode({ color: true })), - sittable: Opt(BooleanNode()), - isConvertible: Opt(BooleanNode()), - convertible: Opt(ObjectNode({ - drops_item: Opt(BooleanNode()), - reversible: Opt(BooleanNode()), - parent_block: Opt(StringNode({ validator: 'resource', params: { pool: 'block' } })), - transformed_block: Opt(StringNode({ validator: 'resource', params: { pool: 'block' } })), - dropped_item: Opt(StringNode({ validator: 'resource', params: { pool: 'item' } })), - sound: Opt(StringNode()), - conversionItem: Opt(ObjectNode({ - item: StringNode({ validator: 'resource', params: { pool: 'item' } }), - tag: StringNode({ validator: 'resource', params: { pool: '$tag/item' } }), - })), - reversalItem: Opt(ObjectNode({ - item: StringNode({ validator: 'resource', params: { pool: 'item' } }), - tag: StringNode({ validator: 'resource', params: { pool: '$tag/item' } }), - })), - })), - })), - functions: Opt(ObjectNode({ - random_tick: Opt(Reference(`${ID}:function`)), - scheduled_tick: Opt(Reference(`${ID}:function`)), - random_display_tick: Opt(Reference(`${ID}:function`)), - place: Opt(Reference(`${ID}:function`)), - break: Opt(Reference(`${ID}:function`)), - use: Opt(Reference(`${ID}:function`)), - walk_on: Opt(Reference(`${ID}:function`)), - })), - ore_information: Opt(ObjectNode({ - test_type: Opt(StringNode({ enum: ['tag', 'always', 'block_match', 'block_state_match', 'random_block_match', 'random_block_state_match']})), - target_state: Opt(ObjectNode({ - block: Opt(StringNode({ validator: 'resource', params: { pool: 'block' }})), - tag: Opt(StringNode({ validator: 'resource', params: { pool: '$tag/block' } })), - properties: Opt(MapNode( - StringNode(), - StringNode(), - )), - probability: Opt(NumberNode({ min: 0, max: 1 })), - })), - triangleRange: Opt(BooleanNode()), - plateau: Opt(NumberNode({ integer: true, min: 0 })), - spawnPredicate: Opt(StringNode({ enum: ['built_in', 'vanilla', 'overworld', 'the_nether', 'the_end', 'categories', 'biomes'] })), - biomeCategories: ListNode(StringNode()), - biomes: ListNode( - StringNode({ validator: 'resource', params: { pool: '$worldgen/biome' }}) - ), - size: Opt(NumberNode({ integer: true })), - chance: Opt(NumberNode({ integer: true, min: 1 })), - discardOnAirChance: Opt(NumberNode({ min: 0, max: 1 })), - topOffset: Reference(`${ID}:block_y_offset`), - bottomOffset: Reference(`${ID}:block_y_offset`), - })), - food_information: Opt(ObjectNode({ - hunger: Opt(NumberNode({ integer: true, min: 0 })), - saturation: Opt(NumberNode({ integer: true, min: 0 })), - effects: ListNode( - ObjectNode({ - effect: StringNode({ validator: 'resource', params: { pool: 'mob_effect' } }), - duration: Opt(NumberNode({ integer: true, min: 0 })), - amplifier: Opt(NumberNode({ integer: true, min: 0 })), - chance: Opt(NumberNode({ integer: true, min: 0, max: 1 })), - }) - ), - })), - cake_slices: Opt(NumberNode({integer: true, min: 1})), - campfire_properties: Opt(ObjectNode({ - emits_particles: Opt(BooleanNode()), - fire_damage: Opt(NumberNode({ integer: true })), - luminance: Opt(NumberNode({ integer: true })), - })), - particle_type: Opt(StringNode()), - can_plant_on: Opt(ListNode( - StringNode({ validator: 'resource', params: { pool: 'block' } }) - )), - growable: Opt(ObjectNode({ - min_age: Opt(NumberNode({ integer: true, min: 1 })), - max_age: Opt(NumberNode({ integer: true })), - })), - oxidizable_properties: Opt(ObjectNode({ - stages: Opt(ListNode( - ObjectNode({ - can_be_waxed: Opt(BooleanNode()), - stairs: Opt(BooleanNode()), - slab: Opt(BooleanNode()), - blocks: Opt(ListNode( - ObjectNode({ - name: Opt(Reference(`${ID}:name_information`)), - display: Opt(Reference(`${ID}:model`)), - }) - )), - }) - )), - })), - events: Opt(ListNode(Reference(`${ID}:event`))), - drop_information: Opt(ObjectNode({ - drops: Opt(ListNode( - ObjectNode({ - name: StringNode({ validator: 'resource', params: { pool: 'item' } }), - drops_if_silk_touch: Opt(BooleanNode()), - }) - )), - survives_explosion: Opt(BooleanNode()), - xp_drop_amount: Opt(NumberNode({ integer: true })), - })), - is_multi_block: Opt(BooleanNode()), - multiblock_information: Opt(ObjectNode({ - width: Opt(NumberNode({ integer: true })), - height: Opt(NumberNode({ integer: true })), - })), - placable_feature: Opt(StringNode({ validator: 'resource', params: { pool: '$worldgen/configured_feature' } })), - }, { context: `${ID}:block` }), { - default: () => ({}), - })) - - schemas.register(`${ID}:block_information`, ObjectNode({ - rarity: Opt(StringNode({ enum: ['common', 'uncommon', 'rare', 'epic']})), - creative_tab: Opt(StringNode()), - collidable: Opt(BooleanNode()), - max_stack_size: Opt(NumberNode({ integer: true, min: 1 })), - name: Opt(Reference(`${ID}:name_information`)), - vanilla_sound_group: Opt(StringNode()), - custom_sound_group: Opt(Reference(`${ID}:sound_group`)), - vanilla_material: Opt(StringNode()), - custom_material: Opt(Reference(`${ID}:material`)), - has_glint: Opt(BooleanNode()), - is_enchantable: Opt(BooleanNode()), - enchantability: Opt(NumberNode({ integer: true })), - fireproof: Opt(BooleanNode()), - translucent: Opt(BooleanNode()), - dynamic_boundaries: Opt(BooleanNode()), - has_item: Opt(BooleanNode()), - dyeable: Opt(BooleanNode()), - defaultColor: Opt(NumberNode({ color: true })), - wearable: Opt(BooleanNode()), - wearble_slot: Opt(StringNode()), - custom_render_mode: Opt(BooleanNode()), - render_mode_models: Opt(ListNode( - ObjectNode({ - model: Reference('model_identifier'), - modes: ListNode(StringNode()), - }) - )), - }, { context: `${ID}:block_information` })) - - schemas.register(`${ID}:block_y_offset`, ObjectNode({ - type: Opt(StringNode({enum: ['fixed', 'above_bottom', 'below_top', 'bottom', 'top']})), - offset: Opt(NumberNode({ integer: true })), - })) - - schemas.register(`${ID}:function`, ObjectNode({ - predicate: Opt(Reference(`${ID}:predicate`)), - function_type: StringNode({ enum: ['NONE', 'REQUIRES_SHIFTING', 'REQUIRES_ITEM', 'REQUIRES_SHIFTING_AND_ITEM'] }), - [Switch]: [{ push: 'function_type' }], - [Case]: { - NONE: {}, - REQUIRES_SHIFTING: {}, - REQUIRES_ITEM: { item: StringNode({ validator: 'resource', params: { pool: 'item' } }) }, - REQUIRES_SHIFTING_AND_ITEM: { item: StringNode({ validator: 'resource', params: { pool: 'item' } }) }, - }, - function_file: StringNode(), - }, { context: `${ID}:function` })) - - schemas.register(`${ID}:predicate`, ObjectNode({ - predicate_type: Opt(StringNode({ enum: ['ALWAYS', 'EQUALS', 'NOT_EQUALS', 'CONTAINS', 'NOT_CONTAINS', 'BEGINS_WITH', 'ENDS_WITH', 'REGEX'] })), - [Switch]: [{ push: 'predicate_type' }], - [Case]: { - ALWAYS: {}, - EQUALS: { left: StringNode(), right: StringNode() }, - NOT_EQUALS: { left: StringNode(), right: StringNode() }, - CONTAINS: { left: StringNode(), right: StringNode() }, - NOT_CONTAINS: { left: StringNode(), right: StringNode() }, - BEGINS_WITH: { left: StringNode(), right: StringNode() }, - ENDS_WITH: { left: StringNode(), right: StringNode() }, - REGEX: { left: StringNode(), right: StringNode() }, - }, - }, { context: `${ID}:predicate` })) - - schemas.register(`${ID}:model`, ObjectNode({ - textures: Opt(MapNode( - StringNode(), - StringNode({ validator: 'resource', params: { pool: '$texture' } }), - )), - parent: StringNode({ validator: 'resource', params: { pool: '$model'} }), - }, { context: `${ID}:model` })) - - schemas.register(`${ID}:sound_group`, ObjectNode({ - id: Opt(StringNode()), - break_sound: Opt(StringNode()), - step_sound: Opt(StringNode()), - place_sound: Opt(StringNode()), - hit_sound: Opt(StringNode()), - }, { context: `${ID}:sound_group` })) - - schemas.register(`${ID}:material`, ObjectNode({ - id: Opt(StringNode()), - map_color: Opt(StringNode()), - allows_movement: Opt(BooleanNode()), - burnable: Opt(BooleanNode()), - liquid: Opt(BooleanNode()), - allows_light: Opt(BooleanNode()), - replacable: Opt(BooleanNode()), - solid: Opt(BooleanNode()), - piston_behaviour: Opt(StringNode({ enum: ['NORMAL', 'DESTROY', 'BLOCK', 'IGNORE', 'PUSH_ONLY'] })), - }, { context: `${ID}:material` })) - - // COMMON - schemas.register(`${ID}:name_information`, ObjectNode({ - id: StringNode(), - text: Opt(StringNode()), - type: Opt(StringNode({ enum: ['literal', 'translatable'] })), - translated: Opt(MapNode( - StringNode(), - StringNode(), - )), - color: Opt(StringNode()), - formatting: Opt(ListNode(StringNode())), - })) - - schemas.register(`${ID}:display_information`, ObjectNode({ - // TODO - })) - - schemas.register(`${ID}:event`, ObjectNode({ - activations: StringNode({enum: ['use', 'shift_use', 'collide', 'walk_on']}), - predicate: Opt(StringNode({ validator: 'resource', params: { pool: '$predicate' } })), - type: StringNode({ enum: ['give_effect', 'damage', 'decrement_stack', 'kill', 'play_sound', 'remove_effect', 'run_command', 'set_block', 'set_block_at_pos', 'set_block_property', 'spawn_loot', 'spawn_entity'] }), - [Switch]: [{ push: 'type' }], - [Case]: { - give_effect: { - amplifier: NumberNode({ integer: true }), - duration: NumberNode(), - effect: StringNode({ validator: 'resource', params: { pool: 'mob_effect' } }), - target: StringNode(), - }, - damage: { - amount: NumberNode({ integer: true }), - target: StringNode(), - damage_type: StringNode(), - }, - decrement_stack: { - amount: NumberNode({ integer: true }), - }, - kill: { - target: StringNode(), - }, - remove_effect: { - effect: StringNode({ validator: 'resource', params: { pool: 'mob_effect' } }), - target: StringNode(), - }, - run_command: { - command: StringNode(), - target: StringNode(), - }, - set_block: { - block: StringNode({ validator: 'resource', params: { pool: 'block' } }), - x_pos: NumberNode(), - y_pos: NumberNode(), - z_pos: NumberNode(), - }, - set_block_at_pos: { - block: StringNode({ validator: 'resource', params: { pool: 'block' } }), - x_pos: NumberNode(), - y_pos: NumberNode(), - z_pos: NumberNode(), - }, - set_block_property: { - block: StringNode({ validator: 'resource', params: { pool: 'block' } }), - property: StringNode(), - value: StringNode(), - }, - spawn_loot: { - loot_table: StringNode({ validator: 'resource', params: { pool: '$loot_table' } }), - x_pos: NumberNode(), - y_pos: NumberNode(), - z_pos: NumberNode(), - }, - spawn_entity: { - entity_type: StringNode({ validator: 'resource', params: { pool: 'entity_type' } }), - x_pos: NumberNode(), - y_pos: NumberNode(), - z_pos: NumberNode(), - amount: NumberNode({ integer: true }), - }, - }, - })) - - - // COLLECTIONS - collections.register(`${ID}:block_type`, [ - 'BLOCK', - 'HORIZONTAL_FACING_BLOCK', - 'ROTATABLE_BLOCK', - 'CAMPFIRE', - 'STAIRS', - 'SLAB', - 'WALL', - 'FENCE', - 'FENCE_GATE', - 'CAKE', - 'BED', - 'TRAPDOOR', - 'METAL_DOOR', - 'WOODEN_DOOR', - 'LOG', - 'STEM', - 'WOOD', - 'OXIDIZING_BLOCK', - 'PLANT', - 'PILLAR', - 'HORIZONTAL_FACING_PLANT', - 'SAPLING', - 'TORCH', - 'BEEHIVE', - 'LEAVES', - 'LADDER', - 'PATH', - 'WOODEN_BUTTON', - 'STONE_BUTTON', - 'DOUBLE_PLANT', - 'HORIZONTAL_FACING_DOUBLE_PLANT', - 'HANGING_DOUBLE_LEAVES', - 'EIGHT_DIRECTIONAL_BLOCK', - 'LANTERN', - 'CHAIN', - 'PANE', - 'DYEABLE', - 'LOOM', - 'GRINDSTONE', - 'CRAFTING_TABLE', - 'PISTON', - 'NOTEBLOCK', - 'JUKEBOX', - 'SMOKER', - 'FURNACE', - 'BLAST_FURNACE', - 'LECTERN', - 'FLETCHING_TABLE', - 'BARREL', - 'COMPOSTER', - 'RAILS', - 'CARTOGRAPHY_TABLE', - 'CARPET', - ]) -} diff --git a/src/app/partners/OhTheTreesYoullGrow.ts b/src/app/partners/OhTheTreesYoullGrow.ts deleted file mode 100644 index e33ba726..00000000 --- a/src/app/partners/OhTheTreesYoullGrow.ts +++ /dev/null @@ -1,114 +0,0 @@ -import type { CollectionRegistry, SchemaRegistry } from '@mcschema/core' -import { Case, ListNode, Mod, NumberNode, ObjectNode, Opt, Reference as RawReference, StringNode as RawStringNode, Switch } from '@mcschema/core' - -export function initOhTheTreesYoullGrow(schemas: SchemaRegistry, collections: CollectionRegistry) { - const Reference = RawReference.bind(undefined, schemas) - const StringNode = RawStringNode.bind(undefined, collections) - - collections.register('ohthetreesyoullgrow:feature', [ - 'ohthetreesyoullgrow:tree_from_nbt_v1', - ]) - - const BlockSet = ListNode( - StringNode({ validator: 'resource', params: { pool: 'block' } }) - ) - - schemas.register('ohthetreesyoullgrow:configured_feature', Mod(ObjectNode({ - type: StringNode({ validator: 'resource', params: { pool: 'ohthetreesyoullgrow:feature' as any } }), - config: ObjectNode({ - [Switch]: ['pop', { push: 'type' }], - [Case]: { - 'ohthetreesyoullgrow:tree_from_nbt_v1': { - base_location: StringNode({ validator: 'resource', params: { pool: '$structure' } }), - canopy_location: StringNode({ validator: 'resource', params: { pool: '$structure' } }), - can_grow_on_filter: Reference('block_predicate_worldgen'), - can_leaves_place_filter: Reference('block_predicate_worldgen'), - decorators: Opt(ListNode( - ObjectNode({ - type: StringNode({ validator: 'resource', params: { pool: 'worldgen/tree_decorator_type' } }), - [Switch]: [{ push: 'type' }], - [Case]: { - 'minecraft:alter_ground': { - provider: Reference('block_state_provider'), - }, - 'minecraft:attached_to_leaves': { - probability: NumberNode({ min: 0, max: 1 }), - exclusion_radius_xz: NumberNode({ integer: true, min: 0, max: 16 }), - exclusion_radius_y: NumberNode({ integer: true, min: 0, max: 16 }), - required_empty_blocks: NumberNode({ integer: true, min: 1, max: 16 }), - block_provider: Reference('block_state_provider'), - directions: ListNode( - StringNode({ enum: 'direction' }) - ), - }, - 'minecraft:beehive': { - probability: NumberNode({ min: 0, max: 1 }), - }, - 'minecraft:cocoa': { - probability: NumberNode({ min: 0, max: 1 }), - }, - 'minecraft:leave_vine': { - probability: NumberNode({ min: 0, max: 1 }), - }, - }, - }, { context: 'tree_decorator' }) - )), - height: Reference('int_provider'), - leaves_provider: Reference('block_state_provider'), - leaves_target: BlockSet, - log_provider: Reference('block_state_provider'), - log_target: BlockSet, - max_log_depth: Opt(NumberNode({ integer: true })), - place_from_nbt: BlockSet, - }, - }, - }, { disableSwitchContext: true }), - }, { context: 'ohthetreesyoullgrow.configured_feature' }), { - default: () => ({ - type: 'ohthetreesyoullgrow:tree_from_nbt_v1', - config: { - can_grow_on_filter: { - type: 'minecraft:matching_block_tag', - tag: 'minecraft:dirt', - }, - can_leaves_place_filter: { - type: 'minecraft:replaceable', - }, - height: { - type: 'minecraft:uniform', - value: { - min_inclusive: 5, - max_inclusive: 10, - }, - }, - leaves_provider: { - type: 'minecraft:simple_state_provider', - state: { - Name: 'minecraft:acacia_leaves', - Properties: { - distance: '7', - persistent: 'false', - waterlogged: 'false', - }, - }, - }, - leaves_target: [ - 'minecraft:oak_leaves', - ], - log_provider: { - type: 'minecraft:simple_state_provider', - state: { - Name: 'minecraft:acacia_log', - Properties: { - axis: 'y', - }, - }, - }, - log_target: [ - 'minecraft:oak_log', - ], - place_from_nbt: [], - }, - }), - })) -} diff --git a/src/app/partners/index.ts b/src/app/partners/index.ts deleted file mode 100644 index 40686fa9..00000000 --- a/src/app/partners/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -import type { CollectionRegistry, SchemaRegistry } from '@mcschema/core' -import type { VersionId } from '../services/Schemas.js' -import { initImmersiveWeathering } from './ImmersiveWeathering.js' -import { initLithostitched } from './Lithostitched.js' -import { initNeoForge } from './NeoForge.js' -import { initObsidian } from './Obsidian.js' -import { initOhTheTreesYoullGrow } from './OhTheTreesYoullGrow.js' - -export * from './ImmersiveWeathering.js' -export * from './Lithostitched.js' - -export function initPartners(schemas: SchemaRegistry, collections: CollectionRegistry, version: VersionId) { - initImmersiveWeathering(schemas, collections) - initLithostitched(schemas, collections, version) - initNeoForge(schemas, collections, version) - initObsidian(schemas, collections) - initOhTheTreesYoullGrow(schemas, collections) -} diff --git a/src/app/partners/locales/en.json b/src/app/partners/locales/en.json deleted file mode 100644 index c5cb767e..00000000 --- a/src/app/partners/locales/en.json +++ /dev/null @@ -1,176 +0,0 @@ -{ - "immersive_weathering.area_condition.type": "Type", - "immersive_weathering.area_condition.type.generate_if_not_too_many": "Generate if not too many", - "immersive_weathering.area_condition.type.neighbor_based_generation": "Neighbor based generation", - "immersive_weathering.area_condition.generate_if_not_too_many.radiusX": "Radius X", - "immersive_weathering.area_condition.generate_if_not_too_many.radiusY": "Radius Y", - "immersive_weathering.area_condition.generate_if_not_too_many.radiusZ": "Radius Z", - "immersive_weathering.area_condition.generate_if_not_too_many.requiredAmount": "Required amount", - "immersive_weathering.area_condition.generate_if_not_too_many.yOffset": "Y offset", - "immersive_weathering.area_condition.generate_if_not_too_many.must_have": "Must have", - "immersive_weathering.area_condition.generate_if_not_too_many.must_not_have": "Must not have", - "immersive_weathering.area_condition.generate_if_not_too_many.includes": "Includes", - "immersive_weathering.area_condition.neighbor_based_generation.must_have": "Must have", - "immersive_weathering.area_condition.neighbor_based_generation.must_not_have": "Must not have", - "immersive_weathering.area_condition.neighbor_based_generation.required_amount": "Required amount", - "immersive_weathering.area_condition.neighbor_based_generation.directions": "Directions", - "immersive_weathering.area_condition.neighbor_based_generation.directions.entry": "Direction", - "immersive_weathering.block_growth.area_condition": "Area conditions", - "immersive_weathering.block_growth.position_predicates": "Position predicates", - "immersive_weathering.block_growth.position_predicates.entry": "Position test", - "immersive_weathering.block_growth.growth_chance": "Growth chance", - "immersive_weathering.block_growth.growth_for_face": "Growth for face", - "immersive_weathering.block_growth.growth_for_face.entry": "Face", - "immersive_weathering.block_growth.growth_for_face.entry.direction": "Direction", - "immersive_weathering.block_growth.growth_for_face.entry.weight": "Weight", - "immersive_weathering.block_growth.growth_for_face.entry.growth": "Growth", - "immersive_weathering.block_growth.growth_for_face.entry.growth.entry.data": "Block pair", - "immersive_weathering.block_growth.growth_for_face.entry.growth.entry.weight": "Weight", - "immersive_weathering.block_growth.owners": "Owners", - "immersive_weathering.block_growth.owners.entry": "Block", - "immersive_weathering.block_growth.replacing_target": "Replacing target", - "immersive_weathering.block_growth.target_self": "Target self", - "immersive_weathering.block_growth.destroy_target": "Destroy target", - "immersive_weathering.block_pair.block": "Block", - "immersive_weathering.block_pair.above_block": "Above block", - "immersive_weathering.position_test.predicate_type": "Predicate type", - "immersive_weathering.position_test.predicate_type.biome_match": "Biome match", - "immersive_weathering.position_test.predicate_type.day_test": "Day test", - "immersive_weathering.position_test.predicate_type.nand": "NAND", - "immersive_weathering.position_test.predicate_type.precipitation_test": "Precipitation test", - "immersive_weathering.position_test.predicate_type.temperature_range": "Temperature range", - "immersive_weathering.position_test.biome_match.biomes": "Biomes", - "immersive_weathering.position_test.day_test.day": "Day", - "immersive_weathering.position_test.nand.predicates": "Predicates", - "immersive_weathering.position_test.precipitation_test.precipitation": "Precipitation", - "immersive_weathering.position_test.temperature_range.min": "Min", - "immersive_weathering.position_test.temperature_range.max": "Max", - "immersive_weathering.position_test.temperature_range.use_local_pos": "Use local pos", - "immersive_weathering:rule_test.always_true": "Always true", - "immersive_weathering:rule_test.block_match": "Block match", - "immersive_weathering:rule_test.blockstate_match": "Block state match", - "immersive_weathering:rule_test.random_block_match": "Random block match", - "immersive_weathering:rule_test.random_blockstate_match": "Random block state match", - "immersive_weathering:rule_test.tag_match": "Tag match", - "immersive_weathering:rule_test.immersive_weathering:block_set_match": "Block set match", - "immersive_weathering:rule_test.immersive_weathering:fluid_match": "Fluid match", - "immersive_weathering:rule_test.immersive_weathering:tree_log": "Tree log", - - "lithostitched:modifier_type.lithostitched:add_biome_spawns": "Add biome spawns", - "lithostitched:modifier_type.lithostitched:add_features": "Add features", - "lithostitched:modifier_type.lithostitched:add_pool_aliases": "Add pool aliases", - "lithostitched:modifier_type.lithostitched:add_structure_set_entries": "Add structure set entries", - "lithostitched:modifier_type.lithostitched:add_surface_rule": "Add surface rule", - "lithostitched:modifier_type.lithostitched:add_template_pool_elements": "Add template pool elements", - "lithostitched:modifier_type.lithostitched:no_op": "Nothing", - "lithostitched:modifier_type.lithostitched:redirect_feature": "Redirect feature", - "lithostitched:modifier_type.lithostitched:remove_biome_spawns": "Remove biome spawns", - "lithostitched:modifier_type.lithostitched:remove_features": "Remove features", - "lithostitched:modifier_type.lithostitched:remove_structures_from_structure_set": "Remove structures from set", - "lithostitched:modifier_type.lithostitched:replace_climate": "Replace climate", - "lithostitched:modifier_type.lithostitched:replace_effects": "Replace effects", - "lithostitched:modifier_predicate_type.lithostitched:all_of": "All of", - "lithostitched:modifier_predicate_type.lithostitched:any_of": "Any of", - "lithostitched:modifier_predicate_type.lithostitched:mod_loaded": "Mod loaded", - "lithostitched:modifier_predicate_type.lithostitched:not": "Not", - "lithostitched:modifier_predicate_type.lithostitched:true": "True", - - "neoforge:biome_modifier_type.neoforge:none": "Disable Biome Modifier", - "neoforge:biome_modifier_type.neoforge:add_features": "Add Features", - "neoforge:biome_modifier_type.neoforge:remove_features": "Remove Features", - "neoforge:biome_modifier_type.neoforge:add_spawns": "Add Mob Spawns", - "neoforge:biome_modifier_type.neoforge:remove_spawns": "Remove Mob Spawns", - "neoforge:biome_modifier_type.neoforge:add_carvers": "Add World Carvers", - "neoforge:biome_modifier_type.neoforge:remove_carvers": "Remove World Carvers", - "neoforge:biome_modifier_type.neoforge:add_spawn_costs": "Add Mob Spawn Costs", - "neoforge:biome_modifier_type.neoforge:remove_spawn_costs": "Remove Mob Spawn Costs", - "neoforge:structure_modifier_type.neoforge:none": "Disable Structure Modifier", - "neoforge:structure_modifier_type.neoforge:add_spawns": "Add Mob Spawns", - "neoforge:structure_modifier_type.neoforge:remove_spawns": "Remove Mob Spawns", - "neoforge:structure_modifier_type.neoforge:clear_spawns": "Clear Mob Spawns", - - "obsidian:item.information": "Item Information", - "obsidian:item_information.rarity": "Rarity", - "obsidian:item_information.creative_tab": "Creative Tab", - "obsidian:item_information.max_stack_size": "Max Stack Size", - "obsidian:item_information.name": "Item Name", - "obsidian:item_information.has_enchantment_glint": "Has Enchantment Glint", - "obsidian:item_information.is_enchantable": "Is Enchantable", - "obsidian:item_information.enchantability": "Enchantability", - "obsidian:item_information.use_duration": "Item Duration", - "obsidian:item_information.can_place_block": "Can Place Block", - "obsidian:item_information.placable_block": "Placable Block", - "obsidian:item_information.wearable": "Wearable", - "obsidian:item_information.default_color": "Default Color", - "obsidian:item_information.wearable_slot": "Wearable Slot", - "obsidian:item_information.custom_render_mode": "Has display-based models", - "obsidian:item_information.render_mode_models": "Display-based Models", - "obsidian:item.display": "Display", - "obsidian:item.display.model": "Model", - "obsidian:item.display.item_model": "Item Model", - "obsidian:item.display.lore": "Lore", - "obsidian:item.use_action": "Use Action", - "obsidian:item.use_action.action": "Action", - "obsidian:item.use_action.right_click_action": "Right Click Action", - "obsidian:item.use_action.command": "Command", - "obsidian:item.use_action.url": "URL", - "obsidian:item.use_action.gui_size": "GUI Size", - "obsidian:item.use_action.gui_title": "GUI Title", - - "obsidian:block.block_type": "Block Type", - "obsidian:block.information": "Block Information", - "obsidian:block_information.rarity": "Rarity", - "obsidian:block_information.creative_tab": "Creative Tab", - "obsidian:block_information.max_stack_size": "Max Stack Size", - "obsidian:block_information.name": "Item Name", - "obsidian:block_information.sound_group_type": "Sound Group Type", - "obsidian:block_information.vanilla_sound_group": "Vanilla Sound Group", - "obsidian:block_information.custom_sound_group": "Custom Sound Group", - "obsidian:block_information.material_type": "Material Type", - "obsidian:block_information.vanilla_material": "Vanilla Material", - "obsidian:block_information.custom_material": "Custom Material", - "obsidian:block.display": "Display", - "obsidian:block.additional_information": "Additional Information", - "obsidian:block.ore_information": "Ore Information", - "obsidian:block.food_information": "Food Information", - "obsidian:block.block_type.CAMPFIRE.campfire_properties": "Campfire Properties", - "obsidian:block.can_plant_on": "Can Plant On", - "obsidian:block.particle_type": "Particle Type", - "obsidian:block.growable": "Growable", - "obsidian:block.oxidizable_properties": "Oxidizable Properties", - "obsidian:block.events": "Events", - "obsidian:block.drop_information": "Drop Information", - "obsidian:block.is_multi_block": "Is Multi-Block", - "obsidian:block.multiblock_information": "Multiblock Information", - "obsidian:block.placable_feature": "Placable Feature", - "obsidian:block.display.model": "Model", - "obsidian:block.display.item_model": "Item Model", - "obsidian:block.display.block_model": "Block Model", - "obsidian:block.display.lore": "Lore", - - "ohthetreesyoullgrow:feature.ohthetreesyoullgrow:tree_from_nbt_v1": "Tree from NBT v1", - "ohthetreesyoullgrow.configured_feature.type": "Type", - "ohthetreesyoullgrow.configured_feature.config": "Config", - "ohthetreesyoullgrow.configured_feature.config.base_location": "Base location", - "ohthetreesyoullgrow.configured_feature.config.base_location.help": "The path to the trunk structure piece.", - "ohthetreesyoullgrow.configured_feature.config.canopy_location": "Canopy location", - "ohthetreesyoullgrow.configured_feature.config.canopy_location.help": "The path to the canopy structure piece.", - "ohthetreesyoullgrow.configured_feature.config.can_grow_on_filter": "Can grow on filter", - "ohthetreesyoullgrow.configured_feature.config.can_grow_on_filter.help": "Block filter for which this tree is allowed to grow on. Checks all of the red wool positions defined by the trunk.", - "ohthetreesyoullgrow.configured_feature.config.can_leaves_place_filter": "Can leaves place filter", - "ohthetreesyoullgrow.configured_feature.config.can_leaves_place_filter.help": "Block filter for which this tree's leaves are allowed to place.", - "ohthetreesyoullgrow.configured_feature.config.decorators": "Decorators", - "ohthetreesyoullgrow.configured_feature.config.decorators.entry": "Decorator", - "ohthetreesyoullgrow.configured_feature.config.height": "Height", - "ohthetreesyoullgrow.configured_feature.config.height.help": "Int provider defining the height of the tree.", - "ohthetreesyoullgrow.configured_feature.config.leaves_provider": "Leaves provider", - "ohthetreesyoullgrow.configured_feature.config.leaves_target": "Leaves target", - "ohthetreesyoullgrow.configured_feature.config.leaves_target.entry": "Block", - "ohthetreesyoullgrow.configured_feature.config.log_provider": "Log provider", - "ohthetreesyoullgrow.configured_feature.config.log_target": "Log target", - "ohthetreesyoullgrow.configured_feature.config.log_target.entry": "Block", - "ohthetreesyoullgrow.configured_feature.config.max_log_depth": "Max log depth", - "ohthetreesyoullgrow.configured_feature.config.place_from_nbt": "Place from NBT", - "ohthetreesyoullgrow.configured_feature.config.place_from_nbt.help": "Additional blocks from the structure pieces that should be placed in the world.", - "ohthetreesyoullgrow.configured_feature.config.place_from_nbt.entry": "Block" -} diff --git a/src/app/schema/ModelWrapper.ts b/src/app/schema/ModelWrapper.ts deleted file mode 100644 index ffe811d6..00000000 --- a/src/app/schema/ModelWrapper.ts +++ /dev/null @@ -1,25 +0,0 @@ -import type { INode, Path } from '@mcschema/core' -import { DataModel } from '@mcschema/core' - -export class ModelWrapper extends DataModel { - constructor( - schema: INode, - private readonly mapper: (path: Path) => Path, - private readonly getter: (path: Path) => any, - private readonly setter: (path: Path, value: any, silent?: boolean) => any, - ) { - super(schema) - } - - map(path: Path) { - return this.mapper(path) - } - - get(path: Path) { - return this.getter(path) - } - - set(path: Path, value: any, silent?: boolean) { - return this.setter(path, value, silent) - } -} diff --git a/src/app/schema/renderHtml.tsx b/src/app/schema/renderHtml.tsx deleted file mode 100644 index 67b068c1..00000000 --- a/src/app/schema/renderHtml.tsx +++ /dev/null @@ -1,719 +0,0 @@ -import type { BooleanHookParams, EnumOption, Hook, INode, ListHookParams, NodeChildren, NumberHookParams, StringHookParams, ValidationOption } from '@mcschema/core' -import { DataModel, ListNode, MapNode, ModelPath, ObjectNode, Path, relativePath, StringNode } from '@mcschema/core' -import { Identifier, ItemStack } from 'deepslate/core' -import type { ComponentChildren, JSX } from 'preact' -import { memo } from 'preact/compat' -import { useState } from 'preact/hooks' -import { Btn, Octicon } from '../components/index.js' -import { ItemDisplay } from '../components/ItemDisplay.jsx' -import { VanillaColors } from '../components/previews/BiomeSourcePreview.jsx' -import config from '../Config.js' -import { localize, useLocale, useStore } from '../contexts/index.js' -import { useFocus } from '../hooks/index.js' -import type { BlockStateRegistry, VersionId } from '../services/index.js' -import { CachedDecorator, CachedFeature, checkVersion } from '../services/index.js' -import { deepClone, deepEqual, generateColor, generateUUID, hexId, hexToRgb, isObject, newSeed, rgbToHex, stringToColor } from '../Utils.js' -import { ModelWrapper } from './ModelWrapper.js' - -const selectRegistries = ['loot_table.type', 'loot_entry.type', 'function.function', 'condition.condition', 'criterion.trigger', 'recipe.type', 'dimension.generator.type', 'dimension.generator.biome_source.type', 'dimension.generator.biome_source.preset', 'carver.type', 'feature.type', 'decorator.type', 'feature.tree.minimum_size.type', 'block_state_provider.type', 'trunk_placer.type', 'foliage_placer.type', 'tree_decorator.type', 'int_provider.type', 'float_provider.type', 'height_provider.type', 'structure_feature.type', 'surface_builder.type', 'processor.processor_type', 'rule_test.predicate_type', 'pos_rule_test.predicate_type', 'template_element.element_type', 'block_placer.type', 'block_predicate.type', 'material_rule.type', 'material_condition.type', 'structure_placement.type', 'density_function.type', 'root_placer.type', 'entity.type_specific.cat.variant', 'entity.type_specific.frog.variant', 'rule_block_entity_modifier.type', 'pool_alias_binding.type', 'lithostitched.worldgen_modifier.type', 'lithostitched.modifier_predicate.type', 'ohthetreesyoullgrow.configured_feature.type', 'enchantment_provider.type', 'enchantment_value_effect.type', 'level_based_value.type', 'neoforge.biome_modifier.type', 'neoforge.structure_modifier.type'] -const datalistEnums = ['item_stack.components', 'function.set_components.components'] -const hiddenFields = ['number_provider.type', 'score_provider.type', 'nbt_provider.type', 'int_provider.type', 'float_provider.type', 'height_provider.type', 'level_based_value.type'] -const flattenedFields = ['feature.config', 'decorator.config', 'int_provider.value', 'float_provider.value', 'block_state_provider.simple_state_provider.state', 'block_state_provider.rotated_block_provider.state', 'block_state_provider.weighted_state_provider.entries.entry.data', 'rule_test.block_state', 'structure_feature.config', 'surface_builder.config', 'template_pool.elements.entry.element', 'decorator.block_survives_filter.state', 'material_rule.block.result_state', 'enchantment.effects.entry.effect'] -const inlineFields = ['loot_entry.type', 'function.function', 'condition.condition', 'criterion.trigger', 'dimension.generator.type', 'dimension.generator.biome_source.type', 'feature.type', 'decorator.type', 'block_state_provider.type', 'feature.tree.minimum_size.type', 'trunk_placer.type', 'foliage_placer.type', 'tree_decorator.type', 'block_placer.type', 'rule_test.predicate_type', 'processor.processor_type', 'template_element.element_type', 'nbt_operation.op', 'number_provider.value', 'score_provider.name', 'score_provider.target', 'nbt_provider.source', 'nbt_provider.target', 'generator_biome.biome', 'block_predicate.type', 'material_rule.type', 'material_condition.type', 'density_function.type', 'root_placer.type', 'entity.type_specific.type', 'glyph_provider.type', 'sprite_source.type', 'rule_block_entity_modifier.type', 'immersive_weathering.area_condition.type', 'immersive_weathering.block_growth.growth_for_face.entry.direction', 'immersive_weathering.position_test.predicate_type', 'pool_alias_binding.type', 'item_stack.id', 'data_component.container.entry.slot', 'map_decoration.type', 'suspicious_stew_effect_instance.id', 'enchantment_value_effect.type', 'enchantment_effect.type', 'particle.type'] -const nbtFields = ['function.set_nbt.tag', 'advancement.display.icon.nbt', 'text_component_object.nbt', 'entity.nbt', 'block.nbt', 'item.nbt'] -const fixedLists = ['generator_biome.parameters.temperature', 'generator_biome.parameters.humidity', 'generator_biome.parameters.continentalness', 'generator_biome.parameters.erosion', 'generator_biome.parameters.depth', 'generator_biome.parameters.weirdness', 'feature.end_spike.crystal_beam_target', 'feature.end_gateway.exit', 'decorator.block_filter.offset', 'block_predicate.has_sturdy_face.offset', 'block_predicate.inside_world_bounds.offset', 'block_predicate.matching_block_tag.offset', 'block_predicate.matching_blocks.offset', 'block_predicate.matching_fluids.offset', 'block_predicate.would_survive.offset', 'model_element.from', 'model_element.to', 'model_element.rotation.origin', 'model_element.faces.uv', 'item_transform.rotation', 'item_transform.translation', 'item_transform.scale', 'generator_structure.random_spread.locate_offset', 'pack_overlay.formats', 'data_component.profile.id', 'data_component.lodestone_tracker.tracker.pos', 'attribute_modifier.uuid'] -const collapsedFields = ['noise_settings.surface_rule', 'noise_settings.noise.terrain_shaper'] -const collapsableFields = ['density_function.argument', 'density_function.argument1', 'density_function.argument2', 'density_function.input', 'density_function.when_in_range', 'density_function.when_out_of_range'] -const itemPreviewFields = ['loot_pool.entries.entry', 'loot_entry.alternatives.children.entry', 'loot_entry.group.children.entry', 'loot_entry.sequence.children.entry', 'function.set_contents.entries.entry'] -const forceEnumContexts: Record = { 'loot_table.type': 'loot_table.type', 'condition.condition': 'loot_condition_type', 'function.function': 'loot_function_type' } - -const findGenerator = (id: string) => { - return config.generators.find(g => g.id === id.replace(/^\$/, '')) -} - -/** - * Secondary model used to remember the keys of a map - */ -const keysModel = new DataModel(MapNode( - StringNode(), - StringNode() -), { historyMax: 0 }) - -type JSXTriple = [JSX.Element | null, JSX.Element | null, JSX.Element | null] -type RenderHook = Hook<[any, string, VersionId, BlockStateRegistry, Record], JSXTriple> - -type NodeProps = T & { - node: INode, - path: ModelPath, - value: any, - lang: string, - version: VersionId, - states: BlockStateRegistry, - ctx: Record, -} - -export function FullNode({ model, lang, version, blockStates }: { model: DataModel, lang: string, version: VersionId, blockStates: BlockStateRegistry }) { - const path = new ModelPath(model) - const [prefix, suffix, body] = model.schema.hook(renderHtml, path, deepClone(model.data), lang, version, blockStates, {}) - return suffix?.props?.children.some((c: any) => c) ?
-
{prefix}{suffix}
-
{body}
-
: body -} - -const renderHtml: RenderHook = { - base() { - return [null, null, null] - }, - - boolean(params, path, value, lang, version, states, ctx) { - return [null, , null] - }, - - choice({ choices, config, switchNode }, path, value, lang, version, states, ctx) { - const choice = switchNode.activeCase(path, true) as typeof choices[number] - const contextPath = (config?.context) ? new ModelPath(path.getModel(), new Path(path.getArray(), [config.context])) : path - const [prefix, suffix, body] = choice.node.hook(this, contextPath, value, lang, version, states, ctx) - if (choices.length === 1) { - return [prefix, suffix, body] - } - const choiceContextPath = config?.choiceContext ? new Path([], [config.choiceContext]) : config?.context ? new Path([], [config.context]) : path - const set = (type: string) => { - const c = choices.find(c => c.type === type) ?? choice - const def = c.node.default() - const newValue = c.change - ? c.change(DataModel.unwrapLists(value)) - : config.choiceContext === 'feature' && def?.type === 'minecraft:decorated' ? def.config.feature : def - path.model.set(path, DataModel.wrapLists(newValue)) - } - const inject = - return [prefix, <>{inject}{suffix}, body] - }, - - list({ children, config, node }, path, value, lang, version, states, ctx) { - const context = path.getContext().join('.') - if (fixedLists.includes(context)) { - const prefix = <> - {[...Array(config.maxLength!)].map((_, i) => - )} -
- - const suffix = <>{[...Array(config.maxLength)].map((_, i) => { - const child = children.hook(this, path.modelPush(i), value?.[i]?.node, lang, version, states, ctx) - return child[1] - })} - return [prefix, suffix, null] - } - - const onAdd = () => { - if (!Array.isArray(value)) value = [] - const node = DataModel.wrapLists(children.default()) - path.model.set(path, [{ node, id: hexId() }, ...value]) - } - const suffix = - return [null, suffix, ] - }, - - map({ children, keys, config }, path, value, lang, version, states, ctx) { - const { expand, collapse, isToggled } = useToggles() - - const keyPath = new ModelPath(keysModel, new Path([hashString(path.toString())], path.contextArr)) - const onAdd = () => { - const key = keyPath.get() - if (path.model.get(path.push(key)) === undefined) { - path.model.set(path.push(key), DataModel.wrapLists(children.default())) - } - keyPath.set('') - } - const blockState = config.validation?.validator === 'block_state_map' ? states?.[relativePath(path, config.validation.params.id).get()] : null - const keysSchema = blockState?.properties - ? StringNode(null!, { enum: Object.keys(blockState.properties ?? {}) }) - : keys - if (blockState && path.last() === 'Properties') { - if (typeof value !== 'object') value = {} - const properties = Object.entries(blockState.properties ?? {}) - .map(([key, values]) => [key, StringNode(null!, { enum: values })]) - Object.entries(blockState.properties ?? {}).forEach(([key, values]) => { - if (typeof value[key] !== 'string') { - path.model.errors.add(path.push(key), 'error.expected_string') - } else if (!values.includes(value[key])) { - path.model.errors.add(path.push(key), 'error.invalid_enum_option', value[key]) - } - }) - return ObjectNode(Object.fromEntries(properties)).hook(this, path, value, lang, version, states, ctx) - } - const suffix = <> - {keysSchema.hook(this, keyPath, keyPath.get() ?? '', lang, version, states, ctx)[1]} - - - const body = <> - {typeof value === 'object' && Object.entries(value).map(([key, cValue]) => { - const pathWithContext = (config?.context) ? new ModelPath(path.getModel(), new Path(path.getArray(), [config.context])) : path - const cPath = pathWithContext.modelPush(key) - const canToggle = children.type(cPath) === 'object' - const toggle = isToggled(key) - if (canToggle && (toggle === false || (toggle === undefined && value.length > 20))) { - return
- - - - -
- } - const cSchema = blockState - ? StringNode(null!, { enum: blockState.properties?.[key] ?? [] }) - : children - if (blockState?.properties?.[key] && typeof cValue === 'string' - && !blockState.properties?.[key].includes(cValue)) { - path.model.errors.add(cPath, 'error.invalid_enum_option', cValue) - } - const onRemove = () => cPath.set(undefined) - return - {canToggle && } - - - })} - - return [null, suffix, body] - }, - - number(params, path, value, lang, version, states, ctx) { - return [null, , null] - }, - - object({ node, config, getActiveFields, getChildModelPath }, path, value, lang, version, states, ctx) { - const { expand, collapse, isToggled } = useToggles() - - if (path.getArray().length == 0 && isDecorated(config.context, value)) { - const { wrapper, fields } = createDecoratorsWrapper(getActiveFields(path), path, value) - value = wrapper.data - getActiveFields = () => fields - getChildModelPath = (path, key) => new ModelPath(wrapper, new Path(path.getArray(), ['feature'])).push(key) - } - - let prefix: JSX.Element | null = null - let suffix: JSX.Element | null = null - let body: JSX.Element | null = null - if (node.optional()) { - if (value === undefined) { - const onExpand = () => path.set(DataModel.wrapLists(node.default())) - suffix = - } else if (typeof value === 'object' && value !== null){ - const onCollapse = () => path.set(undefined) - suffix = - } - } - const context = path.getContext().join('.') - if (collapsableFields.includes(context) || collapsedFields.includes(context)) { - const toggled = isToggled('') - const expanded = collapsedFields.includes(context) ? toggled : !toggled - prefix = <> - - - if (!expanded) { - return [prefix, suffix, null] - } - } - if (!(node.optional() && value === undefined)) { - if (typeof value === 'object' && value !== null) { - const newCtx = (typeof value === 'object' && value !== null && node.default()?.pools) - ? { ...ctx, loot: value?.type } : ctx - body = <>{Object.entries(getActiveFields(path)) - .filter(([_, child]) => child.enabled(path)) - .map(([key, child]) => { - const cPath = getChildModelPath(path, key) - const context = cPath.getContext().join('.') - if (hiddenFields.includes(context)) return null - const [cPrefix, cSuffix, cBody] = child.hook(this, cPath, value[key], lang, version, states, newCtx) - const isFlattened = child.type(cPath) === 'object' && flattenedFields.includes(context) - const isInlined = inlineFields.includes(context) - if (isFlattened || isInlined) { - prefix = <>{prefix}{cPrefix} - suffix = <>{suffix}{cSuffix} - return isFlattened ? cBody : null - } - return - })} - } else { - const onReset = () => path.set(DataModel.wrapLists(node.default())) - suffix = <>{suffix} - } - } - return [prefix, suffix, body] - }, - - string(params, path, value, lang, version, states, ctx) { - return [null, , null] - }, -} - -function Collapsed({ path, value }: { path: ModelPath, value: any, schema: INode }) { - const { locale } = useLocale() - const context = path.getContext().join('.') - switch (context) { - case 'loot_table.pools.entry': - const count = value?.entries?.length ?? 0 - return - case 'function.set_contents.entries.entry': - case 'loot_pool.entries.entry': - const name = value?.name?.replace(/^minecraft:/, '') ?? value?.type?.replace(/^minecraft:/, '') - const weight = value?.weight || undefined - return <> - - {weight !== undefined && } - - } - for (const child of Object.values(value ?? {})) { - if (typeof child === 'string') { - return - } - } - return null -} - -function useToggles() { - const [toggleState, setToggleState] = useState(new Map()) - const [toggleAll, setToggleAll] = useState(undefined) - - const expand = (key: string) => (evt: MouseEvent) => { - if (evt.ctrlKey) { - setToggleState(new Map()) - setToggleAll(true) - } else { - setToggleState(state => new Map(state.set(key, true))) - } - } - const collapse = (key: string) => (evt: MouseEvent) => { - if (evt.ctrlKey) { - setToggleState(new Map()) - setToggleAll(false) - } else { - setToggleState(state => new Map(state.set(key, false))) - } - } - - const isToggled = (key: string) => { - if (!(toggleState instanceof Map)) return false - return toggleState.get(key) ?? toggleAll - } - - return { expand, collapse, isToggled } -} - -function ListBody({ path, value, lang, config, children, version, states, ctx }: NodeProps) { - const { expand, collapse, isToggled } = useToggles() - const [maxShown, setMaxShown] = useState(50) - const onAddBottom = () => { - if (!Array.isArray(value)) value = [] - const node = DataModel.wrapLists(children.default()) - path.model.set(path, [...value, { node, id: hexId() }]) - } - return <> - {(value && Array.isArray(value)) && value.map(({ node: cValue, id: cId }, index) => { - if (index === maxShown) { - return
- - - -
- } - if (index > maxShown) { - return null - } - const pathWithContext = (config?.context) ? new ModelPath(path.getModel(), new Path(path.getArray(), [config.context])) : path - const cPath = pathWithContext.push(index).contextPush('entry') - const canToggle = children.type(cPath) === 'object' - const toggle = isToggled(cId) - - let label: undefined | string | JSX.Element - if (itemPreviewFields.includes(cPath.getContext().join('.'))) { - if (isObject(cValue) && typeof cValue.type === 'string' && cValue.type.replace(/^minecraft:/, '') === 'item' && typeof cValue.name === 'string') { - let itemStack: ItemStack | undefined - try { - itemStack = new ItemStack(Identifier.parse(cValue.name), 1) - } catch (e) {} - if (itemStack !== undefined) { - label = - } - } - } - - if (canToggle && (toggle === false || (toggle === undefined && value.length > 20))) { - return
- - - - -
- } - - const onRemove = () => cPath.set(undefined) - const onMoveUp = () => { - const v = [...path.get()]; - [v[index - 1], v[index]] = [v[index], v[index - 1]] - path.model.set(path, v) - } - const onMoveDown = () => { - const v = [...path.get()]; - [v[index + 1], v[index]] = [v[index], v[index + 1]] - path.model.set(path, v) - } - const actions: MenuAction[] = [ - { - icon: 'duplicate', - label: 'duplicate', - onSelect: () => { - const v = [...path.get()] - v.splice(index, 0, { id: hexId(), node: deepClone(cValue) }) - path.model.set(path, v) - }, - }, - ] - return - {canToggle && } - - {value.length > 1 &&
- - -
} -
- })} - {(value && value.length > 0 && value.length <= maxShown) &&
- -
} - -} - -function BooleanSuffix({ path, node, value, lang }: NodeProps) { - const set = (target: boolean) => { - path.model.set(path, node.optional() && value === target ? undefined : target) - } - return <> - - - -} - -function NumberSuffix({ path, config, integer, value, lang }: NodeProps) { - const onChange = (evt: Event) => { - const value = (evt.target as HTMLInputElement).value - const parsed = integer ? parseInt(value) : parseFloat(value) - path.model.set(path, parsed) - } - const onColor = (evt: Event) => { - const value = (evt.target as HTMLInputElement).value - const parsed = parseInt(value.slice(1), 16) - path.model.set(path, parsed) - } - return <> - {if (evt.key === 'Enter') onChange(evt)}} /> - {config?.color && } - {config?.color && } - {['dimension.generator.seed', 'dimension.generator.biome_source.seed', 'world_settings.seed', 'structure_placement.salt'].includes(path.getContext().join('.')) && } - -} - -function StringSuffix({ path, getValues, config, node, value, lang, version, states }: NodeProps) { - const context = path.getContext().join('.') - const onChange = (evt: Event) => { - evt.stopPropagation() - const newValue = (evt.target as HTMLSelectElement).value - if (newValue === value) return - // Hackfix to support switching between checkerboard and multi_noise biome sources - if (context === 'dimension.generator.biome_source.type') { - const biomeSourceType = newValue.replace(/^minecraft:/, '') - const biomePath = path.pop().push('biomes') - const biomes = biomePath.get() - if (biomeSourceType === 'multi_noise') { - const newBiomes = Array.isArray(biomes) - ? biomes.flatMap((b: any) => { - if (typeof b.node !== 'string') return [] - return [{ node: { biome: b.node }}] - }) - : [{ node: { biome: 'minecraft:plains' } }] - path.model.set(biomePath, newBiomes, true) - } else if (biomeSourceType === 'checkerboard') { - const newBiomes = typeof biomes === 'string' - ? biomes - : Array.isArray(biomes) - ? biomes.flatMap((b: any) => { - if (typeof b.node !== 'object' || b.node === null || typeof b.node.biome !== 'string') return [] - return [{ node: b.node.biome }] - }) - : [{ node: 'minecraft:plains' }] - path.model.set(biomePath, newBiomes, true) - } - } - path.model.set(path, newValue.length === 0 ? undefined : newValue) - } - const values = getValues() - const id = !isEnum(config) && config?.validator === 'resource' && typeof config.params.pool === 'string' ? config.params.pool : undefined - - if (nbtFields.includes(context)) { - return - } else if ((isEnum(config) && !config.additional && !datalistEnums.includes(context)) || selectRegistries.includes(context)) { - let childPath = new Path([]) - if (isEnum(config) && typeof config.enum === 'string') { - childPath = childPath.contextPush(config.enum) - } else if (id) { - childPath = childPath.contextPush(id) - } else if (isEnum(config)) { - childPath = path - } else if (Object.hasOwn(forceEnumContexts, context)) { - childPath = childPath.contextPush(forceEnumContexts[context]) - } - return - } else if (!isEnum(config) && config?.validator === 'block_state_key') { - const blockState = states?.[relativePath(path, config.params.id).get()] - const values = Object.keys(blockState?.properties ?? {}) - return - } else { - const { biomeColors, setBiomeColor } = useStore() - const fullId = typeof value === 'string' ? value.includes(':') ? value : 'minecraft:' + value : 'unknown' - const datalistId = hexId() - const gen = id ? findGenerator(id) : undefined - return <> - {if (evt.key === 'Enter') onChange(evt)}} - list={values.length > 0 ? datalistId : ''} /> - {values.length > 0 && - {values.map(v => } - {['generator_biome.biome'].includes(context) && setBiomeColor(fullId, hexToRgb(v.currentTarget.value))}>} - {(['text_component_object.hoverEvent.show_entity.contents.id', 'enchantment.effects.entry.uuid'].includes(context) || ('attribute_modifier.id' === context && !checkVersion(version, '1.21'))) && } - {gen && values.includes(value) && value.startsWith('minecraft:') && - {Octicon.link_external}} - - } -} - -type MenuAction = { - label: string, - description?: string, - icon: keyof typeof Octicon, - onSelect: () => unknown, -} - -type TreeNodeProps = { - schema: INode, - path: ModelPath, - value: any, - lang: string, - version: VersionId, - states: BlockStateRegistry, - ctx: Record, - compare?: any, - label?: string | ComponentChildren, - actions?: MenuAction[], - children?: ComponentChildren, -} -function TreeNode({ label, schema, path, value, lang, version, states, ctx, actions, children }: TreeNodeProps) { - const type = schema.type(path) - const category = schema.category(path) - const context = path.getContext().join('.') - - const [active, setActive] = useFocus() - const onContextMenu = (evt: MouseEvent) => { - evt.preventDefault() - setActive() - } - - const newCtx: Record = { ...ctx, depth: (ctx.depth ?? 0) + 1 } - delete newCtx.index - const [prefix, suffix, body] = schema.hook(renderHtml, path, value, lang, version, states, newCtx) - return
-
- - - {children} - {prefix} - - {suffix} -
- {body &&
{body}
} -
-} - -const MemoedTreeNode = memo(TreeNode, (prev, next) => { - return prev.schema === next.schema - && prev.lang === next.lang - && prev.path.equals(next.path) - && deepEqual(prev.ctx, next.ctx) - && deepEqual(prev.value, next.value) -}) - -function isEnum(value?: ValidationOption | EnumOption): value is EnumOption { - return !!(value as any)?.enum -} - -function hashString(str: string) { - var hash = 0, i, chr - for (i = 0; i < str.length; i++) { - chr = str.charCodeAt(i) - hash = ((hash << 5) - hash) + chr - hash |= 0 - } - return hash -} - -function pathLocale(lang: string, path: Path, ...params: string[]) { - const ctx = path.getContext() - for (let i = 0; i < ctx.length; i += 1) { - const key = ctx.slice(i).join('.') - const result = localize(lang, key, ...params) - if (key !== result) { - return result - } - } - return ctx[ctx.length - 1] -} - -function ErrorPopup({ lang, path, nested }: { lang: string, path: ModelPath, nested?: boolean }) { - if (path.model instanceof ModelWrapper) { - path = path.model.map(path).withModel(path.model) - } - const e = nested - ? path.model.errors.getAll().filter(e => e.path.startsWith(path)) - : path.model.errors.get(path, true) - if (e.length === 0) return null - const message = localize(lang, e[0].error, ...(e[0].params ?? [])) - return popupIcon('node-error', 'issue_opened', message) -} - -function HelpPopup({ lang, path }: { lang: string, path: Path }) { - const key = path.contextPush('help').getContext().join('.') - const message = localize(lang, key) - if (message === key) return null - return popupIcon('node-help', 'info', message) -} - -const popupIcon = (type: string, icon: keyof typeof Octicon, popup: string) => { - const [active, setActive] = useFocus() - - return
setActive()}> - {Octicon[icon]} - {popup} -
-} - -function isDecorated(context: string | undefined, value: any) { - return context === 'feature' - && value?.type?.replace(/^minecraft:/, '') === 'decorated' - && isObject(value?.config) -} - -function createDecoratorsWrapper(originalFields: NodeChildren, path: ModelPath, value: any) { - const decorators: any[] = [] - const feature = iterateNestedDecorators(value, decorators) - const fields = { - type: originalFields.type, - config: ObjectNode({ - decorators: ListNode(CachedDecorator), - feature: CachedFeature, - }, { context: 'feature.decorated' }), - } - const schema = ObjectNode(fields, { context: 'feature' }) - const featurePath = new Path(['config', 'feature']) - const decoratorsPath = new Path(['config', 'decorators']) - const model = path.getModel() - const wrapper: ModelWrapper = new ModelWrapper(schema, path => { - if (path.startsWith(featurePath)) { - return new Path([...[...Array(decorators.length - 1)].flatMap(() => ['config', 'feature']), ...path.modelArr]) - } else if (path.startsWith(decoratorsPath)) { - if (path.modelArr.length === 2) { - return new Path([]) - } - const index = path.modelArr[2] - if (typeof index === 'number') { - return new Path([...[...Array(index)].flatMap(() => ['config', 'feature']), 'config', 'decorator', ...path.modelArr.slice(3)]) - } - } - return path - }, path => { - if (path.equals(decoratorsPath)) { - const newDecorators: any[] = [] - iterateNestedDecorators(model.data, newDecorators) - return newDecorators - } - return model.get(wrapper.map(path)) - }, (path, value, silent) => { - if (path.startsWith(featurePath)) { - const newDecorators: any[] = [] - iterateNestedDecorators(model.data, newDecorators) - const newPath =new Path([...[...Array(newDecorators.length - 1)].flatMap(() => ['config', 'feature']), ...path.modelArr]) - return model.set(newPath, value, silent) - } else if (path.startsWith(decoratorsPath)) { - const index = path.modelArr[2] - if (path.modelArr.length === 2) { - const feature = wrapper.get(featurePath) - return model.set(new Path(), produceNestedDecorators(feature, value), silent) - } else if (typeof index === 'number') { - if (path.modelArr.length === 3 && value === undefined) { - const feature = wrapper.get(featurePath) - const newDecorators: any[] = [] - iterateNestedDecorators(model.data, newDecorators) - newDecorators.splice(index, 1) - const newValue = produceNestedDecorators(feature, newDecorators) - return model.set(new Path(), newValue, silent) - } else { - const newPath = new Path([...[...Array(index)].flatMap(() => ['config', 'feature']), 'config', 'decorator', ...path.modelArr.slice(3)]) - return model.set(newPath, value, silent) - } - } - } - model.set(path, value, silent) - }) - wrapper.data = { - type: model.data.type, - config: { - decorators, - feature, - }, - } - wrapper.errors = model.errors - return { fields, wrapper } -} - -function iterateNestedDecorators(value: any, decorators: any[]): any { - if (value?.type?.replace(/^minecraft:/, '') !== 'decorated') { - return value - } - if (!isObject(value?.config)) { - return value - } - decorators.push({ id: decorators.length, node: value.config.decorator }) - return iterateNestedDecorators(value.config.feature ?? '', decorators) -} - -function produceNestedDecorators(feature: any, decorators: any[]): any { - if (decorators.length === 0) return feature - return { - type: 'minecraft:decorated', - config: { - decorator: decorators.shift().node, - feature: produceNestedDecorators(feature, decorators), - }, - } -} diff --git a/src/app/schema/transformOutput.ts b/src/app/schema/transformOutput.ts deleted file mode 100644 index b88aca7f..00000000 --- a/src/app/schema/transformOutput.ts +++ /dev/null @@ -1,67 +0,0 @@ -import type { DataModel, Hook } from '@mcschema/core' -import { ModelPath, relativePath } from '@mcschema/core' -import type { BlockStateRegistry } from '../services/index.js' - -export function getOutput(model: DataModel, blockStates: BlockStateRegistry): any { - return model.schema.hook(transformOutput, new ModelPath(model), model.data, { blockStates }) -} - -export type OutputProps = { - blockStates: BlockStateRegistry, -} -export const transformOutput: Hook<[any, OutputProps], any> = { - base({}, _, value) { - return value - }, - - choice({ switchNode }, path, value, props) { - return switchNode.hook(this, path, value, props) - }, - - list({ children }, path, value, props) { - if (!Array.isArray(value)) return value - const res = value.map((obj, index) => - children.hook(this, path.push(index), obj.node, props) - ) - for (const a of Object.getOwnPropertySymbols(value)) { - res[a as any] = value[a as any] - } - return res - }, - - map({ children, config }, path, value, props) { - if (value === undefined) return undefined - const blockState = config.validation?.validator === 'block_state_map'? props.blockStates?.[relativePath(path, config.validation.params.id).get()] : null - const res: any = {} - Object.keys(value).forEach(f => { - if (blockState) { - if (!Object.keys(blockState.properties ?? {}).includes(f)) return - } - res[f] = children.hook(this, path.push(f), value[f], props) - }) - for (const a of Object.getOwnPropertySymbols(value)) { - res[a as any] = value[a] - } - return res - }, - - object({ getActiveFields }, path, value, props) { - if (value === undefined || value === null || typeof value !== 'object') { - return value - } - const res: any = {} - const activeFields = getActiveFields(path) - Object.keys(activeFields) - .filter(k => activeFields[k].enabled(path)) - .forEach(f => { - const out = activeFields[f].hook(this, path.push(f), value[f], props) - if (out !== undefined && out !== null) { - res[f] = out - } - }) - for (const a of Object.getOwnPropertySymbols(value)) { - res[a as any] = value[a] - } - return res - }, -} diff --git a/src/app/services/DataFetcher.ts b/src/app/services/DataFetcher.ts index 830c811e..bf5059f3 100644 --- a/src/app/services/DataFetcher.ts +++ b/src/app/services/DataFetcher.ts @@ -1,20 +1,13 @@ -import type { CollectionRegistry } from '@mcschema/core' import config from '../Config.js' import { Store } from '../Store.js' import { message } from '../Utils.js' -import type { BlockStateRegistry, VersionId } from './Schemas.js' +import type { VersionId } from './Schemas.js' import { checkVersion } from './Schemas.js' const CACHE_NAME = 'misode-v2' const CACHE_LATEST_VERSION = 'cached_latest_version' const CACHE_PATCH = 'misode_cache_patch' -type Version = { - id: string, - ref?: string, - dynamic?: boolean, -} - declare var __LATEST_VERSION__: string export const latestVersion = __LATEST_VERSION__ ?? '' const mcmetaUrl = 'https://raw.githubusercontent.com/misode/mcmeta' @@ -46,51 +39,10 @@ async function validateCache(version: RefInfo) { } } -export async function fetchData(versionId: string, collectionTarget: CollectionRegistry, blockStateTarget: BlockStateRegistry) { - const version = config.versions.find(v => v.id === versionId) as Version | undefined - if (!version) { - console.error(`[fetchData] Unknown version ${version} in ${JSON.stringify(config.versions)}`) - return - } - - await validateCache(version) - - await Promise.all([ - _fetchRegistries(version, collectionTarget), - _fetchBlockStateMap(version, blockStateTarget), - ]) -} - -async function _fetchRegistries(version: Version, target: CollectionRegistry) { - console.debug(`[fetchRegistries] ${version.id}`) - try { - const data = await cachedFetch(`${mcmeta(version, 'summary')}/registries/data.min.json`) - for (const id in data) { - target.register(id, data[id].map((e: string) => 'minecraft:' + e)) - } - } catch (e) { - console.warn('Error occurred while fetching registries:', message(e)) - } -} - -async function _fetchBlockStateMap(version: Version, target: BlockStateRegistry) { - console.debug(`[fetchBlockStateMap] ${version.id}`) - try { - const data = await cachedFetch(`${mcmeta(version, 'summary')}/blocks/data.min.json`) - for (const id in data) { - target['minecraft:' + id] = { - properties: data[id][0], - default: data[id][1], - } - } - } catch (e) { - console.warn('Error occurred while fetching block state map:', message(e)) - } -} - export async function fetchRegistries(versionId: VersionId) { console.debug(`[fetchRegistries] ${versionId}`) const version = config.versions.find(v => v.id === versionId)! + await validateCache(version) try { const data = await cachedFetch(`${mcmeta(version, 'summary')}/registries/data.min.json`) const result = new Map() @@ -103,10 +55,16 @@ export async function fetchRegistries(versionId: VersionId) { } } +export interface BlockStateData { + properties: Record + default: Record +} + export async function fetchBlockStates(versionId: VersionId) { console.debug(`[fetchBlockStates] ${versionId}`) const version = config.versions.find(v => v.id === versionId)! - const result = new Map, default: Record}>() + const result = new Map() + await validateCache(version) try { const data = await cachedFetch(`${mcmeta(version, 'summary')}/blocks/data.min.json`) for (const id in data) { @@ -128,6 +86,7 @@ export async function fetchItemComponents(versionId: VersionId) { if (!checkVersion(versionId, '1.20.5')) { return result } + await validateCache(version) try { const data = await cachedFetch>>(`${mcmeta(version, 'summary')}/item_components/data.min.json`) for (const [id, components] of Object.entries(data)) { @@ -152,6 +111,7 @@ export async function fetchItemComponents(versionId: VersionId) { export async function fetchPreset(versionId: VersionId, registry: string, id: string) { console.debug(`[fetchPreset] ${versionId} ${registry} ${id}`) const version = config.versions.find(v => v.id === versionId)! + await validateCache(version) try { let url if (id.startsWith('immersive_weathering:')) { diff --git a/src/app/services/Schemas.ts b/src/app/services/Schemas.ts index f56ae22c..752ddb04 100644 --- a/src/app/services/Schemas.ts +++ b/src/app/services/Schemas.ts @@ -1,77 +1,27 @@ -import type { CollectionRegistry, INode, SchemaRegistry } from '@mcschema/core' -import { ChoiceNode, DataModel, Reference, StringNode } from '@mcschema/core' import config from '../Config.js' -import { initPartners } from '../partners/index.js' import { message } from '../Utils.js' -import { fetchData } from './DataFetcher.js' +import type { BlockStateData } from './DataFetcher.js' +import { fetchBlockStates, fetchRegistries } from './DataFetcher.js' export const VersionIds = ['1.15', '1.16', '1.17', '1.18', '1.18.2', '1.19', '1.19.3', '1.19.4', '1.20', '1.20.2', '1.20.3', '1.20.5', '1.21', '1.21.2'] as const export type VersionId = typeof VersionIds[number] export const DEFAULT_VERSION: VersionId = '1.21' -export type BlockStateRegistry = { - [block: string]: { - properties?: { - [key: string]: string[], - }, - default?: { - [key: string]: string, - }, - }, +interface VersionData { + registries: Map + blockStates: Map } -type VersionData = { - collections: CollectionRegistry, - schemas: SchemaRegistry, - blockStates: BlockStateRegistry, -} const Versions: Record> = {} -type ModelData = { - model: DataModel, - version: VersionId, -} -const Models: Record = {} - -const versionGetter: { - [versionId in VersionId]: () => Promise<{ - getCollections: () => CollectionRegistry, - getSchemas: (collections: CollectionRegistry) => SchemaRegistry, - }> -} = { - 1.15: () => import('@mcschema/java-1.15'), - 1.16: () => import('@mcschema/java-1.16'), - 1.17: () => import('@mcschema/java-1.17'), - 1.18: () => import('@mcschema/java-1.18'), - '1.18.2': () => import('@mcschema/java-1.18.2'), - 1.19: () => import('@mcschema/java-1.19'), - '1.19.3': () => import('@mcschema/java-1.19.3'), - '1.19.4': () => import('@mcschema/java-1.19.4'), - '1.20': () => import('@mcschema/java-1.20'), - '1.20.2': () => import('@mcschema/java-1.20.2'), - '1.20.3': () => import('@mcschema/java-1.20.3'), - '1.20.5': () => import('@mcschema/java-1.20.5'), - 1.21: () => import('@mcschema/java-1.21'), - '1.21.2': () => import('@mcschema/java-1.21.2'), -} - -export let CachedDecorator: INode -export let CachedFeature: INode -export let CachedCollections: CollectionRegistry -export let CachedSchemas: SchemaRegistry - async function getVersion(id: VersionId): Promise { if (!Versions[id]) { Versions[id] = (async () => { try { - const mcschema = await versionGetter[id]() - const collections = mcschema.getCollections() - const blockStates: BlockStateRegistry = {} - await fetchData(id, collections, blockStates) - const schemas = mcschema.getSchemas(collections) - initPartners(schemas, collections, id) - Versions[id] = { collections, schemas, blockStates } + const registries = await fetchRegistries(id) + const blockStates= await fetchBlockStates(id) + Versions[id] = { registries, blockStates } return Versions[id] } catch (e) { throw new Error(`Cannot get version "${id}": ${message(e)}`) @@ -82,65 +32,26 @@ async function getVersion(id: VersionId): Promise { return Versions[id] } -export async function getModel(version: VersionId, id: string): Promise { - if (!Models[id] || Models[id].version !== version) { - const versionData = await getVersion(version) - - CachedDecorator = Reference(versionData.schemas, 'configured_decorator') - CachedFeature = ChoiceNode([ - { - type: 'string', - node: StringNode(versionData.collections, { validator: 'resource', params: { pool: '$worldgen/configured_feature' } }), - }, - { - type: 'object', - node: Reference(versionData.schemas, 'configured_feature'), - }, - ], { choiceContext: 'feature' }) - - const schemaName = config.generators.find(g => g.id === id)?.schema - if (!schemaName) { - throw new Error(`Cannot find model ${id}`) - } - try { - const schema = versionData.schemas.get(schemaName) - const model = new DataModel(schema, { wrapLists: true }) - if (Models[id]) { - model.reset(Models[id].model.data, false) - } else { - model.validate(true) - model.history = [JSON.stringify(model.data)] - } - Models[id] = { model, version } - } catch (e) { - const err = new Error(`Cannot get generator "${id}" for version "${version}": ${message(e)}`) - if (e instanceof Error) err.stack = e.stack - throw err - } - } - return Models[id].model -} - -export async function getCollections(version: VersionId): Promise { - const versionData = await getVersion(version) - CachedCollections = versionData.collections - return versionData.collections -} - -export async function getBlockStates(version: VersionId): Promise { +export async function getBlockStates(version: VersionId): Promise> { const versionData = await getVersion(version) return versionData.blockStates } -export async function getSchemas(version: VersionId): Promise { - const versionData = await getVersion(version) - CachedSchemas = versionData.schemas - return versionData.schemas -} - export function checkVersion(versionId: string, minVersionId: string | undefined, maxVersionId?: string) { const version = config.versions.findIndex(v => v.id === versionId) const minVersion = minVersionId ? config.versions.findIndex(v => v.id === minVersionId) : 0 const maxVersion = maxVersionId ? config.versions.findIndex(v => v.id === maxVersionId) : config.versions.length - 1 return minVersion <= version && version <= maxVersion } + +export interface FileModel { + get text(): string + get data(): any +} + +export function createMockFileModel(): FileModel { + return { + text: '{}', + data: {}, + } +} From 60aab0c6b91f5c53f2e6bf53ae72271cc657ccb2 Mon Sep 17 00:00:00 2001 From: Misode Date: Tue, 15 Oct 2024 07:24:12 +0200 Subject: [PATCH 002/119] Initialize spyglass project and load vanilla-mcdoc --- package-lock.json | 931 ++++++++++++++++-- package.json | 2 + .../components/generator/SchemaGenerator.tsx | 5 + src/app/services/DataFetcher.ts | 12 +- src/app/services/Spyglass.ts | 63 ++ tsconfig.json | 2 +- vite.config.js | 6 + 7 files changed, 943 insertions(+), 78 deletions(-) create mode 100644 src/app/services/Spyglass.ts diff --git a/package-lock.json b/package-lock.json index 1ef731fa..3cc57471 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,8 @@ "license": "MIT", "dependencies": { "@giscus/react": "^2.2.3", + "@spyglassmc/core": "^0.4.14", + "@spyglassmc/mcdoc": "^0.3.17", "@zip.js/zip.js": "^2.4.5", "brace": "^0.11.1", "buffer": "^6.0.3", @@ -733,6 +735,38 @@ "node": ">= 8.0.0" } }, + "node_modules/@spyglassmc/core": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@spyglassmc/core/-/core-0.4.14.tgz", + "integrity": "sha512-5PIicwc5a8IubXdHCzm4FBjYmhsGH0xGXIk3A+XyQtPTriC6qVd0cdba5pjRPsmUkGA3S2qE2bj/J0qnNJ5dqA==", + "dependencies": { + "@spyglassmc/locales": "0.3.8", + "base64-arraybuffer": "^1.0.2", + "binary-search": "^1.3.6", + "chokidar": "^3.5.2", + "decompress": "^4.2.1", + "follow-redirects": "^1.14.8", + "ignore": "^5.3.1", + "pako": "^2.0.4", + "rfdc": "^1.3.0", + "vscode-languageserver-textdocument": "^1.0.4", + "whatwg-url": "^14.0.0" + } + }, + "node_modules/@spyglassmc/locales": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@spyglassmc/locales/-/locales-0.3.8.tgz", + "integrity": "sha512-xkoNkiMbrCmQkdpIedfvr12irHYSL5i8hZiBeDrjPmxN3hXa5+iZrCTeHgO1iEYiuNbKIyxaSpVNAXqj5c4ShA==" + }, + "node_modules/@spyglassmc/mcdoc": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@spyglassmc/mcdoc/-/mcdoc-0.3.17.tgz", + "integrity": "sha512-qX0pamJ6VNzq1F7Ea5lpUY/iQIu8C46bp0XzvQn4rHGKyrl6rty5wo7K9H8gmvuE6CXuq3ion+nP47Dpny8Fqg==", + "dependencies": { + "@spyglassmc/core": "0.4.14", + "@spyglassmc/locales": "0.3.8" + } + }, "node_modules/@types/diff": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.2.2.tgz", @@ -1082,7 +1116,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -1171,6 +1204,14 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -1194,11 +1235,24 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true, "engines": { "node": ">=8" } }, + "node_modules/binary-search": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/binary-search/-/binary-search-1.3.6.tgz", + "integrity": "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA==" + }, + "node_modules/bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "dependencies": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, "node_modules/brace": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/brace/-/brace-0.11.1.tgz", @@ -1218,7 +1272,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, "dependencies": { "fill-range": "^7.1.1" }, @@ -1281,6 +1334,33 @@ "ieee754": "^1.2.1" } }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==" + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1345,7 +1425,6 @@ "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, "funding": [ { "type": "individual", @@ -1489,6 +1568,95 @@ } } }, + "node_modules/decompress": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", + "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", + "dependencies": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "dependencies": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "dependencies": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-tarbz2/node_modules/file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==", + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "dependencies": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==", + "dependencies": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/decompress-unzip/node_modules/file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -1604,6 +1772,14 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/esbuild": { "version": "0.15.16", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.16.tgz", @@ -2364,6 +2540,14 @@ "reusify": "^1.0.4" } }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "dependencies": { + "pend": "~1.2.0" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -2376,11 +2560,18 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==", + "engines": { + "node": ">=4" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -2407,6 +2598,25 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, "node_modules/fraction.js": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.6.tgz", @@ -2420,6 +2630,11 @@ "url": "https://github.com/sponsors/rawify" } }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2430,7 +2645,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -2470,6 +2684,18 @@ "node": "6.* || 8.* || >= 10.*" } }, + "node_modules/get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==", + "dependencies": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/giscus": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/giscus/-/giscus-1.2.3.tgz", @@ -2507,7 +2733,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -2547,8 +2772,7 @@ "node_modules/graceful-fs": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" }, "node_modules/has": { "version": "1.0.3", @@ -2612,10 +2836,9 @@ ] }, "node_modules/ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true, + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "engines": { "node": ">= 4" } @@ -2658,14 +2881,12 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -2709,7 +2930,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -2727,7 +2947,6 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -2735,15 +2954,27 @@ "node": ">=0.10.0" } }, + "node_modules/is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==" + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, "engines": { "node": ">=0.12.0" } }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-wsl": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", @@ -2756,6 +2987,11 @@ "node": ">=8" } }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -2911,6 +3147,25 @@ "lz-string": "bin/bin.js" } }, + "node_modules/make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/make-dir/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==", + "engines": { + "node": ">=4" + } + }, "node_modules/marked": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.10.tgz", @@ -3017,7 +3272,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -3052,7 +3306,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "dependencies": { "wrappy": "1" } @@ -3141,6 +3394,11 @@ "node": ">=8" } }, + "node_modules/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + }, "node_modules/picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -3151,7 +3409,6 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, "engines": { "node": ">=8.6" }, @@ -3163,7 +3420,25 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "dependencies": { + "pinkie": "^2.0.0" + }, "engines": { "node": ">=0.10.0" } @@ -3336,11 +3611,15 @@ "node": ">= 0.8.0" } }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "node_modules/punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true, + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "engines": { "node": ">=6" } @@ -3401,11 +3680,24 @@ "pify": "^2.3.0" } }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -3569,8 +3861,7 @@ "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "node_modules/scheduler": { "version": "0.20.2", @@ -3582,6 +3873,23 @@ "object-assign": "^4.1.1" } }, + "node_modules/seek-bzip": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", + "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", + "dependencies": { + "commander": "^2.8.1" + }, + "bin": { + "seek-bunzip": "bin/seek-bunzip", + "seek-table": "bin/seek-bzip-table" + } + }, + "node_modules/seek-bzip/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, "node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -3660,6 +3968,14 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -3686,6 +4002,14 @@ "node": ">=8" } }, + "node_modules/strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "dependencies": { + "is-natural-number": "^4.0.1" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -3813,6 +4137,23 @@ "node": ">=10.13.0" } }, + "node_modules/tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "dependencies": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -3840,6 +4181,16 @@ "node": ">=0.8" } }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "node_modules/to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -3853,7 +4204,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -3861,6 +4211,17 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -3925,6 +4286,38 @@ "node": ">=4.2.0" } }, + "node_modules/unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "dependencies": { + "buffer": "^5.2.1", + "through": "^2.3.8" + } + }, + "node_modules/unbzip2-stream/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, "node_modules/update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", @@ -3967,8 +4360,7 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "node_modules/v8-compile-cache": { "version": "2.3.0", @@ -4078,6 +4470,31 @@ "node": ">= 10.0.0" } }, + "node_modules/vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==" + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "dependencies": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -4155,8 +4572,15 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } }, "node_modules/y18n": { "version": "5.0.8", @@ -4202,6 +4626,15 @@ "engines": { "node": ">=12" } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } } }, "dependencies": { @@ -4725,6 +5158,38 @@ "picomatch": "^2.2.2" } }, + "@spyglassmc/core": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/@spyglassmc/core/-/core-0.4.14.tgz", + "integrity": "sha512-5PIicwc5a8IubXdHCzm4FBjYmhsGH0xGXIk3A+XyQtPTriC6qVd0cdba5pjRPsmUkGA3S2qE2bj/J0qnNJ5dqA==", + "requires": { + "@spyglassmc/locales": "0.3.8", + "base64-arraybuffer": "^1.0.2", + "binary-search": "^1.3.6", + "chokidar": "^3.5.2", + "decompress": "^4.2.1", + "follow-redirects": "^1.14.8", + "ignore": "^5.3.1", + "pako": "^2.0.4", + "rfdc": "^1.3.0", + "vscode-languageserver-textdocument": "^1.0.4", + "whatwg-url": "^14.0.0" + } + }, + "@spyglassmc/locales": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@spyglassmc/locales/-/locales-0.3.8.tgz", + "integrity": "sha512-xkoNkiMbrCmQkdpIedfvr12irHYSL5i8hZiBeDrjPmxN3hXa5+iZrCTeHgO1iEYiuNbKIyxaSpVNAXqj5c4ShA==" + }, + "@spyglassmc/mcdoc": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@spyglassmc/mcdoc/-/mcdoc-0.3.17.tgz", + "integrity": "sha512-qX0pamJ6VNzq1F7Ea5lpUY/iQIu8C46bp0XzvQn4rHGKyrl6rty5wo7K9H8gmvuE6CXuq3ion+nP47Dpny8Fqg==", + "requires": { + "@spyglassmc/core": "0.4.14", + "@spyglassmc/locales": "0.3.8" + } + }, "@types/diff": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.2.2.tgz", @@ -4958,7 +5423,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", - "dev": true, "requires": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -5016,6 +5480,11 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==" + }, "base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -5024,8 +5493,21 @@ "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==" + }, + "binary-search": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/binary-search/-/binary-search-1.3.6.tgz", + "integrity": "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA==" + }, + "bl": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz", + "integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } }, "brace": { "version": "0.11.1", @@ -5046,7 +5528,6 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, "requires": { "fill-range": "^7.1.1" } @@ -5072,6 +5553,30 @@ "ieee754": "^1.2.1" } }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==" + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==" + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==" + }, "callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -5110,7 +5615,6 @@ "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, "requires": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -5217,6 +5721,78 @@ "ms": "2.1.2" } }, + "decompress": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-4.2.1.tgz", + "integrity": "sha512-e48kc2IjU+2Zw8cTb6VZcJQ3lgVbS4uuB1TfCHbiZIP/haNXm+SVyhu+87jts5/3ROpd82GSVCoNs/z8l4ZOaQ==", + "requires": { + "decompress-tar": "^4.0.0", + "decompress-tarbz2": "^4.0.0", + "decompress-targz": "^4.0.0", + "decompress-unzip": "^4.0.1", + "graceful-fs": "^4.1.10", + "make-dir": "^1.0.0", + "pify": "^2.3.0", + "strip-dirs": "^2.0.0" + } + }, + "decompress-tar": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-4.1.1.tgz", + "integrity": "sha512-JdJMaCrGpB5fESVyxwpCx4Jdj2AagLmv3y58Qy4GE6HMVjWz1FeVQk1Ct4Kye7PftcdOo/7U7UKzYBJgqnGeUQ==", + "requires": { + "file-type": "^5.2.0", + "is-stream": "^1.1.0", + "tar-stream": "^1.5.2" + } + }, + "decompress-tarbz2": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz", + "integrity": "sha512-s88xLzf1r81ICXLAVQVzaN6ZmX4A6U4z2nMbOwobxkLoIIfjVMBg7TeguTUXkKeXni795B6y5rnvDw7rxhAq9A==", + "requires": { + "decompress-tar": "^4.1.0", + "file-type": "^6.1.0", + "is-stream": "^1.1.0", + "seek-bzip": "^1.0.5", + "unbzip2-stream": "^1.0.9" + }, + "dependencies": { + "file-type": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-6.2.0.tgz", + "integrity": "sha512-YPcTBDV+2Tm0VqjybVd32MHdlEGAtuxS3VAYsumFokDSMG+ROT5wawGlnHDoz7bfMcMDt9hxuXvXwoKUx2fkOg==" + } + } + }, + "decompress-targz": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-4.1.1.tgz", + "integrity": "sha512-4z81Znfr6chWnRDNfFNqLwPvm4db3WuZkqV+UgXQzSngG3CEKdBkw5jrv3axjjL96glyiiKjsxJG3X6WBZwX3w==", + "requires": { + "decompress-tar": "^4.1.1", + "file-type": "^5.2.0", + "is-stream": "^1.1.0" + } + }, + "decompress-unzip": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-4.0.1.tgz", + "integrity": "sha512-1fqeluvxgnn86MOh66u8FjbtJpAFv5wgCT9Iw8rcBqQcCo5tO8eiJw7NNTrvt9n4CRBVq7CstiS922oPgyGLrw==", + "requires": { + "file-type": "^3.8.0", + "get-stream": "^2.2.0", + "pify": "^2.3.0", + "yauzl": "^2.4.2" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==" + } + } + }, "deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -5316,6 +5892,14 @@ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, "esbuild": { "version": "0.15.16", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.16.tgz", @@ -5788,6 +6372,14 @@ "reusify": "^1.0.4" } }, + "fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "requires": { + "pend": "~1.2.0" + } + }, "file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", @@ -5797,11 +6389,15 @@ "flat-cache": "^3.0.4" } }, + "file-type": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-5.2.0.tgz", + "integrity": "sha512-Iq1nJ6D2+yIO4c8HHg4fyVb8mAJieo1Oloy1mLLaB2PvezNedhBVm+QU7g0qM42aiMbRXTxKKwGD17rjKNJYVQ==" + }, "fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, "requires": { "to-regex-range": "^5.0.1" } @@ -5822,12 +6418,22 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, + "follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==" + }, "fraction.js": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.6.tgz", "integrity": "sha512-n2aZ9tNfYDwaHhvFTkhFErqOMIb8uyzSQ+vGJBjZyanAKZVbGUQ1sngfk9FdkBw7G26O7AgNjLcecLffD1c7eg==", "dev": true }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -5838,7 +6444,6 @@ "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, "optional": true }, "function-bind": { @@ -5865,6 +6470,15 @@ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, + "get-stream": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz", + "integrity": "sha512-AUGhbbemXxrZJRD5cDvKtQxLuYaIbNtDTK8YqupCI393Q2KSTreEsLUN3ZxAWFGiKTzL6nKuzfcIvieflUX9qA==", + "requires": { + "object-assign": "^4.0.1", + "pinkie-promise": "^2.0.0" + } + }, "giscus": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/giscus/-/giscus-1.2.3.tgz", @@ -5896,7 +6510,6 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, "requires": { "is-glob": "^4.0.1" } @@ -5924,8 +6537,7 @@ "graceful-fs": { "version": "4.2.8", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz", - "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", - "dev": true + "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==" }, "has": { "version": "1.0.3", @@ -5963,10 +6575,9 @@ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" }, "ignore": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.0.tgz", - "integrity": "sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ==", - "dev": true + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==" }, "import-fresh": { "version": "3.3.0", @@ -5997,14 +6608,12 @@ "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, "requires": { "binary-extensions": "^2.0.0" } @@ -6032,8 +6641,7 @@ "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, "is-fullwidth-code-point": { "version": "3.0.0", @@ -6045,16 +6653,24 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, "requires": { "is-extglob": "^2.1.1" } }, + "is-natural-number": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-4.0.1.tgz", + "integrity": "sha512-Y4LTamMe0DDQIIAlaer9eKebAlDSV6huy+TWhJVPlzZh2o4tRP5SQWFlLn5N0To4mDD22/qdOq+veo1cSISLgQ==" + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==" }, "is-wsl": { "version": "2.2.0", @@ -6065,6 +6681,11 @@ "is-docker": "^2.0.0" } }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -6190,6 +6811,21 @@ "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", "integrity": "sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=" }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==" + } + } + }, "marked": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.10.tgz", @@ -6268,8 +6904,7 @@ "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, "normalize-range": { "version": "0.1.2", @@ -6292,7 +6927,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, "requires": { "wrappy": "1" } @@ -6360,6 +6994,11 @@ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==" + }, "picocolors": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", @@ -6369,14 +7008,25 @@ "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" }, "pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==", + "requires": { + "pinkie": "^2.0.0" + } }, "pirates": { "version": "4.0.6", @@ -6469,11 +7119,15 @@ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, "punycode": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", - "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", - "dev": true + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" }, "queue-microtask": { "version": "1.2.3", @@ -6511,11 +7165,24 @@ "pify": "^2.3.0" } }, + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, "requires": { "picomatch": "^2.2.1" } @@ -6615,8 +7282,7 @@ "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, "scheduler": { "version": "0.20.2", @@ -6628,6 +7294,21 @@ "object-assign": "^4.1.1" } }, + "seek-bzip": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz", + "integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==", + "requires": { + "commander": "^2.8.1" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + } + } + }, "semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -6687,6 +7368,14 @@ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", @@ -6707,6 +7396,14 @@ "ansi-regex": "^5.0.1" } }, + "strip-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-2.1.0.tgz", + "integrity": "sha512-JOCxOeKLm2CAS73y/U4ZeZPTkE+gNVCzKt7Eox84Iej1LT/2pTWYpZKJuxwQpvX1LiZb1xokNR7RLfuBAa7T3g==", + "requires": { + "is-natural-number": "^4.0.1" + } + }, "strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -6800,6 +7497,20 @@ } } }, + "tar-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz", + "integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==", + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.2.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.1", + "xtend": "^4.0.0" + } + }, "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -6824,6 +7535,16 @@ "thenify": ">= 3.1.0 < 4" } }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==" + }, "to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -6834,11 +7555,18 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, "requires": { "is-number": "^7.0.0" } }, + "tr46": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz", + "integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==", + "requires": { + "punycode": "^2.3.1" + } + }, "ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", @@ -6881,6 +7609,26 @@ "integrity": "sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==", "dev": true }, + "unbzip2-stream": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", + "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", + "requires": { + "buffer": "^5.2.1", + "through": "^2.3.8" + }, + "dependencies": { + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + } + } + }, "update-browserslist-db": { "version": "1.0.13", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", @@ -6903,8 +7651,7 @@ "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" }, "v8-compile-cache": { "version": "2.3.0", @@ -6966,6 +7713,25 @@ } } }, + "vscode-languageserver-textdocument": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", + "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==" + }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" + }, + "whatwg-url": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz", + "integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==", + "requires": { + "tr46": "^5.0.0", + "webidl-conversions": "^7.0.0" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -7021,8 +7787,12 @@ "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" }, "y18n": { "version": "5.0.8", @@ -7056,6 +7826,15 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz", "integrity": "sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==", "dev": true + }, + "yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "requires": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } } } } diff --git a/package.json b/package.json index e1485b94..9ba12431 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,8 @@ "license": "MIT", "dependencies": { "@giscus/react": "^2.2.3", + "@spyglassmc/core": "^0.4.14", + "@spyglassmc/mcdoc": "^0.3.17", "@zip.js/zip.js": "^2.4.5", "brace": "^0.11.1", "buffer": "^6.0.3", diff --git a/src/app/components/generator/SchemaGenerator.tsx b/src/app/components/generator/SchemaGenerator.tsx index a1014a8f..0872c960 100644 --- a/src/app/components/generator/SchemaGenerator.tsx +++ b/src/app/components/generator/SchemaGenerator.tsx @@ -7,6 +7,7 @@ import { DRAFT_PROJECT, useLocale, useProject, useVersion } from '../../contexts import { AsyncCancel, useActiveTimeout, useAsync, useSearchParam } from '../../hooks/index.js' import type { FileModel, VersionId } from '../../services/index.js' import { checkVersion, createMockFileModel, fetchPreset, fetchRegistries, getSnippet, shareSnippet } from '../../services/index.js' +import { setupSpyglass } from '../../services/Spyglass.js' import { Store } from '../../Store.js' import { cleanUrl, deepEqual, genPath } from '../../Utils.js' import { Ad, Btn, BtnMenu, ErrorPanel, FileCreation, FileRenaming, Footer, HasPreview, Octicon, PreviewPanel, ProjectCreation, ProjectDeletion, ProjectPanel, SearchList, SourcePanel, TextInput, Tree, VersionSwitcher } from '../index.js' @@ -30,6 +31,10 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) { useEffect(() => Store.visitGenerator(gen.id), [gen.id]) + useEffect(() => { + setupSpyglass() + }, []) + const [currentPreset, setCurrentPreset] = useSearchParam('preset') const [sharedSnippetId, setSharedSnippetId] = useSearchParam(SHARE_KEY) const backup = useMemo(() => Store.getBackup(gen.id), [gen.id]) diff --git a/src/app/services/DataFetcher.ts b/src/app/services/DataFetcher.ts index bf5059f3..748aeb4c 100644 --- a/src/app/services/DataFetcher.ts +++ b/src/app/services/DataFetcher.ts @@ -16,6 +16,7 @@ const changesUrl = 'https://raw.githubusercontent.com/misode/technical-changes' const fixesUrl = 'https://raw.githubusercontent.com/misode/mcfixes' const versionDiffUrl = 'https://mcmeta-diff.misode.workers.dev' const whatsNewUrl = 'https://whats-new.misode.workers.dev' +const vanillaMcdocUrl = 'https://proxy.misode.workers.dev/mcdoc' type McmetaTypes = 'summary' | 'data' | 'data-json' | 'assets' | 'assets-json' | 'registries' | 'atlas' @@ -39,6 +40,15 @@ async function validateCache(version: RefInfo) { } } +export async function fetchVanillaMcdoc() { + try { + // TODO: enable refresh + return cachedFetch(vanillaMcdocUrl, { decode: res => res.arrayBuffer(), refresh: false }) + } catch (e) { + throw new Error(`Error occured while fetching vanilla-mcdoc: ${message(e)}`) + } +} + export async function fetchRegistries(versionId: VersionId) { console.debug(`[fetchRegistries] ${versionId}`) const version = config.versions.find(v => v.id === versionId)! @@ -51,7 +61,7 @@ export async function fetchRegistries(versionId: VersionId) { } return result } catch (e) { - throw new Error(`Error occurred while fetching registries (2): ${message(e)}`) + throw new Error(`Error occurred while fetching registries: ${message(e)}`) } } diff --git a/src/app/services/Spyglass.ts b/src/app/services/Spyglass.ts new file mode 100644 index 00000000..373320f2 --- /dev/null +++ b/src/app/services/Spyglass.ts @@ -0,0 +1,63 @@ +import * as core from '@spyglassmc/core' +import { BrowserExternals } from '@spyglassmc/core/lib/browser.js' +import * as mcdoc from '@spyglassmc/mcdoc' +import * as zip from '@zip.js/zip.js' +import { fetchVanillaMcdoc } from './index.js' + +const externals: core.Externals = { + ...BrowserExternals, + archive: { + ...BrowserExternals.archive, + async decompressBall(buffer, { stripLevel } = {}) { + const reader = new zip.ZipReader(new zip.BlobReader(new Blob([buffer]))) + const entries = await reader.getEntries() + return await Promise.all(entries.map(async e => { + const data = await e.getData?.(new zip.Uint8ArrayWriter()) + const path = stripLevel === 1 ? e.filename.substring(e.filename.indexOf('/') + 1) : e.filename + const type = e.directory ? 'dir' : 'file' + return { data, path, mtime: '', type, mode: 0 } + })) + }, + }, +} + +export async function setupSpyglass() { + const logger: core.Logger = console + const profilers = new core.ProfilerFactory(logger, [ + 'project#init', + 'project#ready', + 'misode#setup', + ]) + const profiler = profilers.get('misode#setup') + const service = new core.Service({ + logger, + profilers, + project: { + cacheRoot: 'file:cache/', + projectRoots: ['file:project/'], + externals: externals, + defaultConfig: core.ConfigService.merge(core.VanillaConfig, { + env: { dependencies: ['@vanilla-mcdoc'] }, + }), + initializers: [mcdoc.initialize, initialize], + }, + }) + await service.project.ready() + profiler.task('Project ready') + await service.project.cacheService.save() + profiler.task('Save cache') + profiler.finalize() + + service.logger.info(service.project.symbols.global) +} + +const initialize: core.ProjectInitializer = async (ctx) => { + const { meta, externals, cacheRoot } = ctx + + meta.registerDependencyProvider('@vanilla-mcdoc', async () => { + const uri: string = new core.Uri('downloads/vanilla-mcdoc.tar.gz', cacheRoot).toString() + const buffer = await fetchVanillaMcdoc() + await core.fileUtil.writeFile(externals, uri, new Uint8Array(buffer)) + return { info: { startDepth: 1 }, uri } + }) +} diff --git a/tsconfig.json b/tsconfig.json index 014f1760..8709a132 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "target": "es6", + "target": "es2021", "module": "node16", "lib": ["dom","esnext"], "moduleResolution": "node16", diff --git a/vite.config.js b/vite.config.js index dd13a1e8..4e566310 100644 --- a/vite.config.js +++ b/vite.config.js @@ -19,8 +19,14 @@ export default defineConfig({ { find: 'react/jsx-runtime', replacement: 'preact/jsx-runtime' }, ], }, + optimizeDeps: { + esbuildOptions: { + target: 'es2021', + }, + }, build: { sourcemap: true, + target: 'es2021', rollupOptions: { plugins: [ html({ From 7dbd533abb60b43339c708823bc5ef061e53abdb Mon Sep 17 00:00:00 2001 From: Misode Date: Tue, 15 Oct 2024 23:25:56 +0200 Subject: [PATCH 003/119] Add mcmeta-summary symbol registrar and initialize remaining --- package-lock.json | 88 ++++++++++++ package.json | 6 +- .../components/generator/SchemaGenerator.tsx | 4 +- src/app/services/DataFetcher.ts | 8 ++ src/app/services/Spyglass.ts | 132 +++++++++++++++++- 5 files changed, 231 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3cc57471..a3105a5f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,11 @@ "dependencies": { "@giscus/react": "^2.2.3", "@spyglassmc/core": "^0.4.14", + "@spyglassmc/java-edition": "^0.3.17", + "@spyglassmc/json": "^0.3.16", + "@spyglassmc/locales": "^0.3.8", "@spyglassmc/mcdoc": "^0.3.17", + "@spyglassmc/nbt": "^0.3.17", "@zip.js/zip.js": "^2.4.5", "brace": "^0.11.1", "buffer": "^6.0.3", @@ -753,6 +757,29 @@ "whatwg-url": "^14.0.0" } }, + "node_modules/@spyglassmc/java-edition": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@spyglassmc/java-edition/-/java-edition-0.3.17.tgz", + "integrity": "sha512-XO7bX/xowN21lwdtqP+6NsGAtfrdXWRcXoe8ByHUxHqtFXwp1ifSY7Lg76nlUm/FSOMM2QXUEh3QDj2Wr0wJyA==", + "dependencies": { + "@spyglassmc/core": "0.4.14", + "@spyglassmc/json": "0.3.16", + "@spyglassmc/locales": "0.3.8", + "@spyglassmc/mcdoc": "0.3.17", + "@spyglassmc/mcfunction": "0.2.16", + "@spyglassmc/nbt": "0.3.17" + } + }, + "node_modules/@spyglassmc/json": { + "version": "0.3.16", + "resolved": "https://registry.npmjs.org/@spyglassmc/json/-/json-0.3.16.tgz", + "integrity": "sha512-rBOeXWjPn1xsuaYECqkX+iclNf0EYqCq6jj8zb1+9IeaEeYSVOEUevKvYNqtk0++5UPBruXbBAOuJI08GRMQWQ==", + "dependencies": { + "@spyglassmc/core": "0.4.14", + "@spyglassmc/locales": "0.3.8", + "@spyglassmc/mcdoc": "0.3.17" + } + }, "node_modules/@spyglassmc/locales": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/@spyglassmc/locales/-/locales-0.3.8.tgz", @@ -767,6 +794,25 @@ "@spyglassmc/locales": "0.3.8" } }, + "node_modules/@spyglassmc/mcfunction": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/@spyglassmc/mcfunction/-/mcfunction-0.2.16.tgz", + "integrity": "sha512-Iwo8Akp/MuIsDkzzCumHfPNK9zgxsVw5sVEq1H6f3RWPJFrnhwx0bQRR80pqjiHhIuli/g2pxv195wsAU1PDHA==", + "dependencies": { + "@spyglassmc/core": "0.4.14", + "@spyglassmc/locales": "0.3.8" + } + }, + "node_modules/@spyglassmc/nbt": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@spyglassmc/nbt/-/nbt-0.3.17.tgz", + "integrity": "sha512-Jk8yjN5HFy/GF6fUjP0oJatz4oNJ1EE6NtfpctjeznQLNG51Xj/FDeJybnKYksM+V/nj7eth9mLyRjkMcTUcAw==", + "dependencies": { + "@spyglassmc/core": "0.4.14", + "@spyglassmc/locales": "0.3.8", + "@spyglassmc/mcdoc": "0.3.17" + } + }, "node_modules/@types/diff": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.2.2.tgz", @@ -5176,6 +5222,29 @@ "whatwg-url": "^14.0.0" } }, + "@spyglassmc/java-edition": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@spyglassmc/java-edition/-/java-edition-0.3.17.tgz", + "integrity": "sha512-XO7bX/xowN21lwdtqP+6NsGAtfrdXWRcXoe8ByHUxHqtFXwp1ifSY7Lg76nlUm/FSOMM2QXUEh3QDj2Wr0wJyA==", + "requires": { + "@spyglassmc/core": "0.4.14", + "@spyglassmc/json": "0.3.16", + "@spyglassmc/locales": "0.3.8", + "@spyglassmc/mcdoc": "0.3.17", + "@spyglassmc/mcfunction": "0.2.16", + "@spyglassmc/nbt": "0.3.17" + } + }, + "@spyglassmc/json": { + "version": "0.3.16", + "resolved": "https://registry.npmjs.org/@spyglassmc/json/-/json-0.3.16.tgz", + "integrity": "sha512-rBOeXWjPn1xsuaYECqkX+iclNf0EYqCq6jj8zb1+9IeaEeYSVOEUevKvYNqtk0++5UPBruXbBAOuJI08GRMQWQ==", + "requires": { + "@spyglassmc/core": "0.4.14", + "@spyglassmc/locales": "0.3.8", + "@spyglassmc/mcdoc": "0.3.17" + } + }, "@spyglassmc/locales": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/@spyglassmc/locales/-/locales-0.3.8.tgz", @@ -5190,6 +5259,25 @@ "@spyglassmc/locales": "0.3.8" } }, + "@spyglassmc/mcfunction": { + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/@spyglassmc/mcfunction/-/mcfunction-0.2.16.tgz", + "integrity": "sha512-Iwo8Akp/MuIsDkzzCumHfPNK9zgxsVw5sVEq1H6f3RWPJFrnhwx0bQRR80pqjiHhIuli/g2pxv195wsAU1PDHA==", + "requires": { + "@spyglassmc/core": "0.4.14", + "@spyglassmc/locales": "0.3.8" + } + }, + "@spyglassmc/nbt": { + "version": "0.3.17", + "resolved": "https://registry.npmjs.org/@spyglassmc/nbt/-/nbt-0.3.17.tgz", + "integrity": "sha512-Jk8yjN5HFy/GF6fUjP0oJatz4oNJ1EE6NtfpctjeznQLNG51Xj/FDeJybnKYksM+V/nj7eth9mLyRjkMcTUcAw==", + "requires": { + "@spyglassmc/core": "0.4.14", + "@spyglassmc/locales": "0.3.8", + "@spyglassmc/mcdoc": "0.3.17" + } + }, "@types/diff": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/@types/diff/-/diff-5.2.2.tgz", diff --git a/package.json b/package.json index 9ba12431..bfda0f0b 100644 --- a/package.json +++ b/package.json @@ -17,15 +17,19 @@ "dependencies": { "@giscus/react": "^2.2.3", "@spyglassmc/core": "^0.4.14", + "@spyglassmc/java-edition": "^0.3.17", + "@spyglassmc/json": "^0.3.16", + "@spyglassmc/locales": "^0.3.8", "@spyglassmc/mcdoc": "^0.3.17", + "@spyglassmc/nbt": "^0.3.17", "@zip.js/zip.js": "^2.4.5", "brace": "^0.11.1", "buffer": "^6.0.3", "comment-json": "^4.1.1", + "deepslate": "^0.22.3", "deepslate-1.18": "npm:deepslate@0.9.0-beta.9", "deepslate-1.18.2": "npm:deepslate@0.9.0", "deepslate-1.20.4": "npm:deepslate@0.20.1", - "deepslate": "^0.22.3", "diff": "^7.0.0", "highlight.js": "^11.5.1", "howler": "^2.2.3", diff --git a/src/app/components/generator/SchemaGenerator.tsx b/src/app/components/generator/SchemaGenerator.tsx index 0872c960..b3c4663b 100644 --- a/src/app/components/generator/SchemaGenerator.tsx +++ b/src/app/components/generator/SchemaGenerator.tsx @@ -32,8 +32,8 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) { useEffect(() => Store.visitGenerator(gen.id), [gen.id]) useEffect(() => { - setupSpyglass() - }, []) + setupSpyglass(version) + }, [version]) const [currentPreset, setCurrentPreset] = useSearchParam('preset') const [sharedSnippetId, setSharedSnippetId] = useSearchParam(SHARE_KEY) diff --git a/src/app/services/DataFetcher.ts b/src/app/services/DataFetcher.ts index 748aeb4c..66ea62ab 100644 --- a/src/app/services/DataFetcher.ts +++ b/src/app/services/DataFetcher.ts @@ -40,6 +40,14 @@ async function validateCache(version: RefInfo) { } } +export function getVersionChecksum(versionId: VersionId) { + const version = config.versions.find(v => v.id === versionId)! + if (version.dynamic) { + return (localStorage.getItem(CACHE_LATEST_VERSION) ?? '').toString() + } + return version.ref +} + export async function fetchVanillaMcdoc() { try { // TODO: enable refresh diff --git a/src/app/services/Spyglass.ts b/src/app/services/Spyglass.ts index 373320f2..f38e45c1 100644 --- a/src/app/services/Spyglass.ts +++ b/src/app/services/Spyglass.ts @@ -1,8 +1,18 @@ import * as core from '@spyglassmc/core' import { BrowserExternals } from '@spyglassmc/core/lib/browser.js' +import type { McmetaSummary } from '@spyglassmc/java-edition/lib/dependency/index.js' +import { Fluids, ReleaseVersion, symbolRegistrar } from '@spyglassmc/java-edition/lib/dependency/index.js' +import * as jeJson from '@spyglassmc/java-edition/lib/json/index.js' +import * as jeMcf from '@spyglassmc/java-edition/lib/mcfunction/index.js' +import * as json from '@spyglassmc/json' +import { localize } from '@spyglassmc/locales' import * as mcdoc from '@spyglassmc/mcdoc' +import * as nbt from '@spyglassmc/nbt' import * as zip from '@zip.js/zip.js' -import { fetchVanillaMcdoc } from './index.js' +import type { ConfigVersion } from '../Config.js' +import siteConfig from '../Config.js' +import type { VersionId } from './index.js' +import { fetchBlockStates, fetchRegistries, fetchVanillaMcdoc, getVersionChecksum } from './index.js' const externals: core.Externals = { ...BrowserExternals, @@ -21,7 +31,9 @@ const externals: core.Externals = { }, } -export async function setupSpyglass() { +export async function setupSpyglass(versionId: VersionId) { + const version = siteConfig.versions.find(v => v.id === versionId)! + const gameVersion = version.ref ?? version.id const logger: core.Logger = console const profilers = new core.ProfilerFactory(logger, [ 'project#init', @@ -37,7 +49,10 @@ export async function setupSpyglass() { projectRoots: ['file:project/'], externals: externals, defaultConfig: core.ConfigService.merge(core.VanillaConfig, { - env: { dependencies: ['@vanilla-mcdoc'] }, + env: { + gameVersion: gameVersion, + dependencies: ['@vanilla-mcdoc'], + }, }), initializers: [mcdoc.initialize, initialize], }, @@ -52,7 +67,7 @@ export async function setupSpyglass() { } const initialize: core.ProjectInitializer = async (ctx) => { - const { meta, externals, cacheRoot } = ctx + const { config, logger, meta, externals, cacheRoot } = ctx meta.registerDependencyProvider('@vanilla-mcdoc', async () => { const uri: string = new core.Uri('downloads/vanilla-mcdoc.tar.gz', cacheRoot).toString() @@ -60,4 +75,113 @@ const initialize: core.ProjectInitializer = async (ctx) => { await core.fileUtil.writeFile(externals, uri, new Uint8Array(buffer)) return { info: { startDepth: 1 }, uri } }) + + const release = config.env.gameVersion as ReleaseVersion + const version = siteConfig.versions.find(v => { + return v.ref ? v.ref === release : v.id === release + }) + if (version === undefined) { + logger.error(`[initialize] Failed finding game version matching ${release}.`) + return + } + + const summary: McmetaSummary = { + registries: Object.fromEntries((await fetchRegistries(version.id)).entries()), + blocks: Object.fromEntries([...(await fetchBlockStates(version.id)).entries()] + .map(([id, data]) => [id, [data.properties, data.default]])), + fluids: Fluids, + commands: { type: 'root', children: {} }, + } + + meta.registerSymbolRegistrar('mcmeta-summary', { + checksum: getVersionChecksum(version.id), + registrar: symbolRegistrar(summary), + }) + + registerAttributes(meta, release) + + json.initialize(ctx) + jeJson.initialize(ctx) + jeMcf.initialize(ctx, summary.commands, release) + nbt.initialize(ctx) + + return { loadedVersion: release } +} + +// Duplicate these from spyglass for now, until they are exported separately +function registerAttributes(meta: core.MetaRegistry, release: ReleaseVersion) { + mcdoc.runtime.registerAttribute(meta, 'since', mcdoc.runtime.attribute.validator.string, { + filterElement: (config, ctx) => { + if (!config.startsWith('1.')) { + ctx.logger.warn(`Invalid mcdoc attribute for "since": ${config}`) + return true + } + return ReleaseVersion.cmp(release, config as ReleaseVersion) >= 0 + }, + }) + mcdoc.runtime.registerAttribute(meta, 'until', mcdoc.runtime.attribute.validator.string, { + filterElement: (config, ctx) => { + if (!config.startsWith('1.')) { + ctx.logger.warn(`Invalid mcdoc attribute for "until": ${config}`) + return true + } + return ReleaseVersion.cmp(release, config as ReleaseVersion) < 0 + }, + }) + mcdoc.runtime.registerAttribute( + meta, + 'deprecated', + mcdoc.runtime.attribute.validator.optional(mcdoc.runtime.attribute.validator.string), + { + mapField: (config, field, ctx) => { + if (config === undefined) { + return { ...field, deprecated: true } + } + if (!config.startsWith('1.')) { + ctx.logger.warn(`Invalid mcdoc attribute for "deprecated": ${config}`) + return field + } + if (ReleaseVersion.cmp(release, config as ReleaseVersion) >= 0) { + return { ...field, deprecated: true } + } + return field + }, + }, + ) + const packFormats = new Map() + for (const version of siteConfig.versions) { + packFormats.set(version.pack_format, version) + } + mcdoc.runtime.registerAttribute(meta, 'pack_format', () => undefined, { + checker: (_, typeDef) => { + if (typeDef.kind !== 'literal' || typeof typeDef.value.value !== 'number') { + return undefined + } + const target = typeDef.value.value + return (node, ctx) => { + const targetVersion = packFormats.get(target) + if (!targetVersion) { + ctx.err.report( + localize('java-edition.pack-format.unsupported', target), + node, + core.ErrorSeverity.Warning, + ) + } else if (targetVersion.id !== release) { + ctx.err.report( + localize('java-edition.pack-format.not-loaded', target, release), + node, + core.ErrorSeverity.Warning, + ) + } + } + }, + numericCompleter: (_, ctx) => { + return [...packFormats.values()].map((v, i) => ({ + range: core.Range.create(ctx.offset), + label: `${v.pack_format}`, + labelSuffix: ` (${v.id})`, + sortText: `${i}`.padStart(4, '0'), + } as core.CompletionItem)) + }, + }) } From 77d6323219aa5858b2e881f3a464d1b43ccdd1e7 Mon Sep 17 00:00:00 2001 From: Misode Date: Wed, 16 Oct 2024 04:36:59 +0200 Subject: [PATCH 004/119] Use spyglass DocAndNode to store current file data --- src/app/Config.ts | 2 +- .../customized/CustomizedGenerator.ts | 4 +- .../components/customized/CustomizedModel.ts | 2 +- src/app/components/generator/FileCreation.tsx | 9 +- .../components/generator/GeneratorCard.tsx | 4 +- .../components/generator/GeneratorList.tsx | 2 +- src/app/components/generator/PreviewPanel.tsx | 32 ++--- .../components/generator/SchemaGenerator.tsx | 48 ++++--- src/app/components/generator/SourcePanel.tsx | 49 ++++--- src/app/components/generator/Tree.tsx | 8 +- .../previews/BiomeSourcePreview.tsx | 13 +- .../components/previews/BlockStatePreview.tsx | 9 +- .../components/previews/DecoratorPreview.tsx | 11 +- .../previews/DensityFunctionPreview.tsx | 9 +- src/app/components/previews/LootTable.ts | 2 +- src/app/components/previews/LootTable1204.ts | 2 +- .../components/previews/LootTablePreview.tsx | 8 +- src/app/components/previews/ModelPreview.tsx | 9 +- src/app/components/previews/NoisePreview.tsx | 9 +- .../previews/NoiseSettingsPreview.tsx | 13 +- src/app/components/previews/RecipePreview.tsx | 10 +- .../previews/StructureSetPreview.tsx | 9 +- src/app/components/previews/index.ts | 4 +- src/app/pages/Customized.tsx | 6 +- src/app/services/DataFetcher.ts | 4 +- src/app/services/Resources.ts | 2 +- src/app/services/Resources1204.ts | 2 +- src/app/services/Schemas.ts | 57 -------- src/app/services/Sharing.ts | 2 +- src/app/services/Spyglass.ts | 128 +++++++++++------- src/app/services/Versions.ts | 13 ++ src/app/services/index.ts | 2 +- 32 files changed, 244 insertions(+), 240 deletions(-) delete mode 100644 src/app/services/Schemas.ts create mode 100644 src/app/services/Versions.ts diff --git a/src/app/Config.ts b/src/app/Config.ts index f1e92638..7f799e5f 100644 --- a/src/app/Config.ts +++ b/src/app/Config.ts @@ -1,5 +1,5 @@ import config from '../config.json' -import type { VersionId } from './services/Schemas.js' +import type { VersionId } from './services/Versions.js' export interface ConfigLanguage { code: string, diff --git a/src/app/components/customized/CustomizedGenerator.ts b/src/app/components/customized/CustomizedGenerator.ts index 55f2d03a..eec763ff 100644 --- a/src/app/components/customized/CustomizedGenerator.ts +++ b/src/app/components/customized/CustomizedGenerator.ts @@ -1,7 +1,7 @@ import { Identifier } from 'deepslate' -import { deepClone, deepEqual } from '../../Utils.js' import { fetchAllPresets, fetchBlockStates } from '../../services/DataFetcher.js' -import type { VersionId } from '../../services/Schemas.js' +import type { VersionId } from '../../services/Versions.js' +import { deepClone, deepEqual } from '../../Utils.js' import type { CustomizedOreModel } from './CustomizedModel.js' import { CustomizedModel } from './CustomizedModel.js' diff --git a/src/app/components/customized/CustomizedModel.ts b/src/app/components/customized/CustomizedModel.ts index 68f2ded0..da9851e4 100644 --- a/src/app/components/customized/CustomizedModel.ts +++ b/src/app/components/customized/CustomizedModel.ts @@ -1,4 +1,4 @@ -import type { VersionId } from '../../services/Schemas.js' +import type { VersionId } from '../../services/Versions.js' export interface CustomizedOreModel { size: number, diff --git a/src/app/components/generator/FileCreation.tsx b/src/app/components/generator/FileCreation.tsx index 740bbab8..bd349105 100644 --- a/src/app/components/generator/FileCreation.tsx +++ b/src/app/components/generator/FileCreation.tsx @@ -1,18 +1,18 @@ +import type { DocAndNode } from '@spyglassmc/core' import { useState } from 'preact/hooks' import { Analytics } from '../../Analytics.js' import { useLocale, useProject } from '../../contexts/index.js' -import type { FileModel } from '../../services/index.js' import { Btn } from '../Btn.js' import { TextInput } from '../forms/index.js' import { Modal } from '../Modal.js' interface Props { - model: FileModel, + docAndNode: DocAndNode, id: string, method: string, onClose: () => void, } -export function FileCreation({ model, id, method, onClose }: Props) { +export function FileCreation({ docAndNode, id, method, onClose }: Props) { const { locale } = useLocale() const { projects, project, updateFile } = useProject() const [fileId, setFileId] = useState(id === 'pack_mcmeta' ? 'pack' : '') @@ -29,7 +29,8 @@ export function FileCreation({ model, id, method, onClose }: Props) { return } Analytics.saveProjectFile(id, projects.length, project.files.length, method as any) - updateFile(id, undefined, { type: id, id: fileId, data: model.data }) + const data = JSON.parse(docAndNode.doc.getText()) + updateFile(id, undefined, { type: id, id: fileId, data }) onClose() } diff --git a/src/app/components/generator/GeneratorCard.tsx b/src/app/components/generator/GeneratorCard.tsx index 0ddc039a..dc03e8e6 100644 --- a/src/app/components/generator/GeneratorCard.tsx +++ b/src/app/components/generator/GeneratorCard.tsx @@ -2,8 +2,8 @@ import { useMemo } from 'preact/hooks' import type { ConfigGenerator } from '../../Config.js' import config from '../../Config.js' import { useLocale } from '../../contexts/Locale.jsx' -import type { VersionId } from '../../services/Schemas.js' -import { checkVersion } from '../../services/Schemas.js' +import type { VersionId } from '../../services/Versions.js' +import { checkVersion } from '../../services/Versions.js' import { cleanUrl } from '../../Utils.js' import { Badge, Card, Icons, ToolCard } from '../index.js' diff --git a/src/app/components/generator/GeneratorList.tsx b/src/app/components/generator/GeneratorList.tsx index 7faf0cb9..13addca2 100644 --- a/src/app/components/generator/GeneratorList.tsx +++ b/src/app/components/generator/GeneratorList.tsx @@ -2,7 +2,7 @@ import { useMemo, useState } from 'preact/hooks' import type { ConfigGenerator } from '../../Config.js' import config from '../../Config.js' import { useLocale, useVersion } from '../../contexts/index.js' -import { checkVersion } from '../../services/Schemas.js' +import { checkVersion } from '../../services/Versions.js' import { GeneratorCard, TextInput, VersionSwitcher } from '../index.js' interface Props { diff --git a/src/app/components/generator/PreviewPanel.tsx b/src/app/components/generator/PreviewPanel.tsx index c2576361..f8222fcc 100644 --- a/src/app/components/generator/PreviewPanel.tsx +++ b/src/app/components/generator/PreviewPanel.tsx @@ -1,59 +1,59 @@ +import type { DocAndNode } from '@spyglassmc/core' import { useVersion } from '../../contexts/Version.jsx' -import type { FileModel } from '../../services/index.js' import { checkVersion } from '../../services/index.js' import { BiomeSourcePreview, BlockStatePreview, DecoratorPreview, DensityFunctionPreview, LootTablePreview, ModelPreview, NoisePreview, NoiseSettingsPreview, RecipePreview, StructureSetPreview } from '../previews/index.js' -export const HasPreview = ['loot_table', 'recipe', 'dimension', 'worldgen/density_function', 'worldgen/noise', 'worldgen/noise_settings', 'worldgen/configured_feature', 'worldgen/placed_feature', 'worldgen/structure_set', 'block_definition', 'model'] +export const HasPreview = ['loot_table', 'recipe', 'dimension', 'worldgen/density_function', 'worldgen/noise', 'worldgen/noise_settings', 'worldgen/configured_feature', 'worldgen/placed_feature', 'worldgen/structure_set', 'block_definition', 'docAndNode'] type PreviewPanelProps = { - model: FileModel | undefined, + docAndNode: DocAndNode | undefined, id: string, shown: boolean, onError: (message: string) => unknown, } -export function PreviewPanel({ model, id, shown }: PreviewPanelProps) { +export function PreviewPanel({ docAndNode, id, shown }: PreviewPanelProps) { const { version } = useVersion() - if (!model) return <> + if (!docAndNode) return <> if (id === 'loot_table') { - return + return } if (id === 'recipe') { - return + return } - if (id === 'dimension' && model.data.generator?.type?.endsWith('noise')) { - return + if (id === 'dimension' && JSON.parse(docAndNode.doc.getText()).generator?.type?.endsWith('noise')) { + return } if (id === 'worldgen/density_function') { - return + return } if (id === 'worldgen/noise') { - return + return } if (id === 'worldgen/noise_settings' && checkVersion(version, '1.18')) { - return + return } if ((id === 'worldgen/placed_feature' || (id === 'worldgen/configured_feature' && checkVersion(version, '1.16', '1.17')))) { - return + return } if (id === 'worldgen/structure_set' && checkVersion(version, '1.19')) { - return + return } if (id === 'block_definition') { - return + return } if (id === 'model') { - return + return } return <> diff --git a/src/app/components/generator/SchemaGenerator.tsx b/src/app/components/generator/SchemaGenerator.tsx index b3c4663b..c017d42b 100644 --- a/src/app/components/generator/SchemaGenerator.tsx +++ b/src/app/components/generator/SchemaGenerator.tsx @@ -5,11 +5,11 @@ import type { ConfigGenerator } from '../../Config.js' import config from '../../Config.js' import { DRAFT_PROJECT, useLocale, useProject, useVersion } from '../../contexts/index.js' import { AsyncCancel, useActiveTimeout, useAsync, useSearchParam } from '../../hooks/index.js' -import type { FileModel, VersionId } from '../../services/index.js' -import { checkVersion, createMockFileModel, fetchPreset, fetchRegistries, getSnippet, shareSnippet } from '../../services/index.js' -import { setupSpyglass } from '../../services/Spyglass.js' +import type { VersionId } from '../../services/index.js' +import { checkVersion, fetchPreset, fetchRegistries, getSnippet, shareSnippet } from '../../services/index.js' +import { Spyglass } from '../../services/Spyglass.js' import { Store } from '../../Store.js' -import { cleanUrl, deepEqual, genPath } from '../../Utils.js' +import { cleanUrl, genPath } from '../../Utils.js' import { Ad, Btn, BtnMenu, ErrorPanel, FileCreation, FileRenaming, Footer, HasPreview, Octicon, PreviewPanel, ProjectCreation, ProjectDeletion, ProjectPanel, SearchList, SourcePanel, TextInput, Tree, VersionSwitcher } from '../index.js' export const SHARE_KEY = 'share' @@ -31,10 +31,15 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) { useEffect(() => Store.visitGenerator(gen.id), [gen.id]) - useEffect(() => { - setupSpyglass(version) + const { value: spyglass, loading: spyglassLoading } = useAsync(() => { + return Spyglass.initialize(version) }, [version]) + const uri = useMemo(() => { + // TODO: return different uri when project file is open + return spyglass?.getUnsavedFileUri(gen) + }, [spyglass, gen.id]) + const [currentPreset, setCurrentPreset] = useSearchParam('preset') const [sharedSnippetId, setSharedSnippetId] = useSearchParam(SHARE_KEY) const backup = useMemo(() => Store.getBackup(gen.id), [gen.id]) @@ -45,7 +50,10 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) { } } - const {} = useAsync(async () => { + const { value: docAndNode } = useAsync(async () => { + if (spyglassLoading || !spyglass || !uri) { + return AsyncCancel + } let data: unknown = undefined if (currentPreset && sharedSnippetId) { setSharedSnippetId(undefined) @@ -83,14 +91,12 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) { } data = file.data } - if (data) { - // TODO: set file contents to data - } + const docAndNode = await spyglass.setFileContents(uri, JSON.stringify(data ?? {})) Analytics.setGenerator(gen.id) - return {} - }, [gen.id, version, sharedSnippetId, currentPreset, project.name, file?.id]) + return docAndNode + }, [gen.id, version, sharedSnippetId, currentPreset, project.name, file?.id, spyglass, spyglassLoading]) - const model: FileModel = createMockFileModel() + const { doc } = docAndNode ?? {} // TODO: when contents of file change: // - remove preset and share id from url @@ -184,13 +190,13 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) { setShareShown(true) copySharedId() } else { - // TODO: get contents from file, and compare to default of type - if (deepEqual(model.data, {})) { + // TODO: check if files hasn't been modified compared to the default + if (false) { setShareUrl(`${location.origin}/${gen.url}/?version=${version}`) setShareShown(true) - } else { + } else if (doc) { setShareLoading(true) - shareSnippet(gen.id, version, model.data, previewShown) + shareSnippet(gen.id, version, JSON.parse(doc.getText()), previewShown) .then(({ id, length, compressed, rate }) => { Analytics.createSnippet(gen.id, id, version, length, compressed, rate) const url = `${location.origin}/${gen.url}/?${SHARE_KEY}=${id}` @@ -306,7 +312,7 @@ export function SchemaGenerator({ gen, allowedVersions }: Props) { {error && setError(null)} />} - + {docAndNode && }