diff --git a/config.d.ts b/config.d.ts index 48a767b..28c11e1 100644 --- a/config.d.ts +++ b/config.d.ts @@ -14,10 +14,12 @@ export interface Config { gdkUserId?: string fixInventoryItemRenderer?: boolean buildFolder?: string + fileExtension?: string } ui_analyzer?: { enabled?: boolean + generate_path?: string imports?: string[] } diff --git a/package.json b/package.json index 0cee075..2391aa7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "asajs", - "version": "4.0.13", + "version": "4.0.16-indev", "description": "Create your Minecraft JSON-UI resource packs using JavaScript", "keywords": [ "Minecraft", diff --git a/src/analyzer/custom-ui.ts b/src/analyzer/custom-ui.ts deleted file mode 100644 index e69de29..0000000 diff --git a/src/analyzer/generate-code.ts b/src/analyzer/generate-code.ts new file mode 100644 index 0000000..dc9789b --- /dev/null +++ b/src/analyzer/generate-code.ts @@ -0,0 +1,105 @@ +import path from "node:path" +import fs from "fs" +import { config } from "../compilers/Configuration.js" + +interface Element { + file: string + type: string + extends?: { + name: string + namespace: string + } + children?: string[] +} + +interface Database { + [key: string]: Element +} + +const importType = 'import { Type, MemoryModify, ModifyUI } from "asajs"' + +function toCamelCase(str: string) { + return str.replace(/[-_]\w/g, m => m[1].toUpperCase()) +} + +export function genCustomCode(pack_folder: string) { + const database = JSON.parse(fs.readFileSync(path.join("database", `${pack_folder}-defs.json`), "utf-8")) + const Elements: string[] = [] + const json: Record> = {} + const UI = [ + "type UI = {", + ...Object.entries(database).map(args => { + const [key, element] = <[string, Database]>args + const typeName = `${key[0].toUpperCase()}${toCamelCase(key).slice(1)}` + const filepaths: Record = {} + Elements.push( + [ + `type ${typeName} = {`, + ...Object.entries(element).map(([elementPath, elementData]) => { + filepaths[elementPath] = elementData.file + return ` "${elementPath}": {\n type: Type.${elementData.type.toUpperCase()},\n children: ${elementData.children ? elementData.children.map(c => `"${c}"`).join(" | ") : "string"}\n },` + }), + "}", + ].join("\n"), + ) + json[key] = { + ...(json[key] || {}), + ...filepaths, + } + return ` "${key}": ${typeName},` + }), + "}", + ].join("\n") + + const paths = `const paths = ${JSON.stringify(json, null, 4)}` + + if (config.ui_analyzer?.generate_path) { + if (!fs.existsSync(config.ui_analyzer?.generate_path)) { + fs.mkdirSync(config.ui_analyzer?.generate_path, { recursive: true }) + } + } + + fs.writeFileSync( + path.join(config.ui_analyzer?.generate_path || "database", `${pack_folder}.ts`), + [ + importType, + `type Namespace = keyof UI +type Element = Extract +type ElementInfos> = UI[T][K] +// @ts-ignore +type GetType> = ElementInfos["type"] +// @ts-ignore +type GetChilds> = ElementInfos["children"] + +export default function Modify>(namespace: T, name: K) { + // @ts-ignore + const getPath = paths[namespace][name] + // @ts-ignore + const memoryUI = MemoryModify[getPath]?.[name] + // @ts-ignore + if (memoryUI) return memoryUI as ModifyUI, GetChilds> + const path = paths[namespace] + if (!path) { + throw new Error(\`Namespace '\${namespace}' does not exist\`) + // @ts-ignore + } else if (typeof path !== "string" && !getPath) { + throw new Error(\`Element '\${name}' does not exist in namespace '\${namespace}'\`) + } + // @ts-ignore + const modifyUI = new ModifyUI, GetChilds>( + namespace, + name, + // @ts-ignore + typeof path === "string" ? path : getPath, + ) + // @ts-ignore + ;(MemoryModify[getPath] ||= {})[name] = modifyUI + return modifyUI +}`, + paths, + UI, + ...Elements, + ].join("\n\n"), + "utf-8", + ) +} diff --git a/src/analyzer/generate-ui-defs.ts b/src/analyzer/generate-ui-defs.ts new file mode 100644 index 0000000..4f7c2cb --- /dev/null +++ b/src/analyzer/generate-ui-defs.ts @@ -0,0 +1,134 @@ +import path from "path" +import { uiFiles } from "./utils.js" +import fs from "fs" +import { paths } from "../types/vanilla/paths.js" +import { vanilladefs } from "./vanilladefs.js" + +type Namespace = string +type ElementPath = string + +interface ScanElement { + file: string + type?: string + extends?: { + name: string + namespace?: string + } + children?: string[] +} + +const map = new Map() +Object.entries(paths).forEach(([namespace, path]) => { + map.set(path, namespace) +}) + +export function generateUIDefs(pack_folder: string) { + const uiMap = new Map>() + uiFiles(pack_folder).forEach(file => { + try { + const fileContent: Record = JSON.parse( + fs.readFileSync(path.join("custom", pack_folder, file), "utf-8"), + ) + if (fileContent["file_signature"]) delete fileContent["file_signature"] + + let n = fileContent["namespace"] + if (n) delete fileContent["namespace"] + else n = map.get(file) + const namespace = n + + const elementMap = new Map() + + function scanElement(elements: Array<[string, any]>, prefix: string = "") { + const childElement: string[] = [] + elements.forEach(([element, properties]: [string, any]) => { + if (properties.anim_type) return + + const [name, extend] = element.split("@") + if (name.startsWith("$")) return + if (name.startsWith("$")) return + childElement.push(name) + const elementPath = `${prefix}${name}` + let extendsName: string | undefined + let extendsNamespace: string | undefined + if (extend) { + const [extnamespace, name] = extend.split(".") + if (name) { + extendsName = name + extendsNamespace = extnamespace + } else { + extendsName = extnamespace + extendsNamespace = namespace + } + } + + const controls = properties.controls + const out: any = { + file, + } + + if (controls) { + const children = scanElement( + controls.map((c: string) => Object.entries(c)[0]), + `${prefix}${name}/`, + ) + + if (children.length) out.children = children + } + + if (properties.type) out.type = properties.type + if (extendsName && extendsNamespace) + out.extends = { name: extendsName, namespace: extendsNamespace } + + elementMap.set(elementPath, out) + }) + return childElement + } + scanElement(Object.entries(fileContent)) + uiMap.set(namespace, elementMap) + } catch (error) {} + }) + + function scanElementType(name: string, namespace: string) { + const element = uiMap.get(namespace)?.get(name) + if (element) { + if (element.type) return element.type + else { + const extend = element.extends + if (extend) return scanElementType(extend.name, extend.namespace!) + } + } + return vanilladefs[namespace]?.[name]?.type + } + + uiMap.entries().forEach(([namespace, elementsMap]) => { + elementsMap.entries().forEach(([name, { file, type, extends: extend }]) => { + if (type) return + else { + if (extend) { + const type = scanElementType(extend.name, extend.namespace!) + if (type) { + elementsMap.set(name, { + ...elementsMap.get(name)!, + type, + }) + } else elementsMap.delete(name) + } else { + const elementDefs = vanilladefs[namespace]?.[name] + if (elementDefs) { + elementsMap.set(name, { + ...elementsMap.get(name)!, + type: elementDefs.type, + }) + } else { + elementsMap.delete(name) + } + } + } + }) + + if (!elementsMap.size) uiMap.delete(namespace) + }) + + if (!fs.existsSync("database")) fs.mkdirSync("database") + fs.writeFileSync(path.join("database", `${pack_folder}-defs.json`), JSON.stringify(uiMap, null, 4), "utf-8") +} diff --git a/src/analyzer/rebaseUIFiles.ts b/src/analyzer/rebaseUIFiles.ts new file mode 100644 index 0000000..da7922e --- /dev/null +++ b/src/analyzer/rebaseUIFiles.ts @@ -0,0 +1,50 @@ +import fs from "fs" +import path from "path" +import { parse } from "jsonc-parser" +import { uiFiles } from "./utils.js" + +export function rebaseUIFiles(pack_folder: string) { + const ui = uiFiles(pack_folder) + const targetDir = path.join("custom", pack_folder) + + ui.add("ui/_ui_defs.json") + ui.add("ui/_global_variables.json") + + if (!fs.existsSync(targetDir)) return + + const processDirectory = (currentDir: string) => { + const entries = fs.readdirSync(currentDir, { withFileTypes: true }) + + for (const entry of entries) { + const fullPath = path.join(currentDir, entry.name) + + if (entry.isDirectory()) { + processDirectory(fullPath) + + if (fs.readdirSync(fullPath).length === 0) { + fs.rmdirSync(fullPath) + } + } else if (entry.isFile()) { + const relativePath = fullPath.replace(targetDir + path.sep, "") + const normalizedPath = relativePath.split(path.sep).join("/") + + if (!ui.has(normalizedPath)) { + fs.rmSync(fullPath, { force: true }) + } else { + try { + const fileContent = fs.readFileSync(fullPath, "utf-8") + const parsedData = parse(fileContent) + + if (parsedData !== undefined) { + fs.writeFileSync(fullPath, JSON.stringify(parsedData, null, 4), "utf-8") + } + } catch (error) { + console.error(`Parser error: ${fullPath}`, error) + } + } + } + } + } + + processDirectory(targetDir) +} diff --git a/src/analyzer/utils.ts b/src/analyzer/utils.ts new file mode 100644 index 0000000..3bfb771 --- /dev/null +++ b/src/analyzer/utils.ts @@ -0,0 +1,20 @@ +import { paths } from "../types/vanilla/paths.js" +import fs from "fs" +import path from "path" +import jsonc from "jsonc-parser" + +export const vanilla_ui_defs = Object.values(paths) +const vanillaUIDefsMap = new Map>() + +export function readUIDefs(pack_folder: string): string[] { + const { ui_defs } = jsonc.parse(fs.readFileSync(path.join("custom", pack_folder, "ui/_ui_defs.json"), "utf-8")) + return ui_defs +} + +export function uiFiles(pack_folder: string): Set { + if (vanillaUIDefsMap.has(pack_folder)) return vanillaUIDefsMap.get(pack_folder)! + const ui_defs = readUIDefs(pack_folder) + const set = new Set(ui_defs.concat(...vanilla_ui_defs)) + vanillaUIDefsMap.set(pack_folder, set) + return set +} diff --git a/src/compilers/Configuration.ts b/src/compilers/Configuration.ts index 8cd79ee..1691f3e 100644 --- a/src/compilers/Configuration.ts +++ b/src/compilers/Configuration.ts @@ -3,6 +3,9 @@ import path from "path" import jsonc from "jsonc-parser" import { Config, RetBindingValue } from "../../config.js" import { createRequire } from "module" +import { rebaseUIFiles } from "../analyzer/rebaseUIFiles.js" +import { generateUIDefs } from "../analyzer/generate-ui-defs.js" +import { genCustomCode } from "../analyzer/generate-code.js" const options: Record = {} @@ -64,5 +67,20 @@ export const buildFolder = config.compiler?.buildFolder || "build" export const bindingFuntions = config.binding_functions if (!fs.existsSync(".gitignore")) { - fs.writeFileSync(".gitignore", `node_modules`, "utf-8") + fs.writeFileSync(".gitignore", "node_modules\ncustom", "utf-8") +} + +if (config.ui_analyzer?.enabled) { + config.ui_analyzer.imports?.forEach(v => { + if (!fs.existsSync(path.join(config.ui_analyzer?.generate_path || "database", `${v}.ts`))) { + if (!fs.existsSync(path.join("database", `${v}-defs.json`))) { + if (fs.existsSync(path.join("custom", v, "ui/_ui_defs.json"))) { + rebaseUIFiles(v) + generateUIDefs(v) + } else throw new Error(`${v} ui_defs.json not found`) + } + + genCustomCode(v) + } + }) } diff --git a/src/components/UI.ts b/src/components/UI.ts index 71aa1d9..c66036d 100644 --- a/src/components/UI.ts +++ b/src/components/UI.ts @@ -14,6 +14,7 @@ import { RandomString, ResolveBinding } from "./Utils.js" import { RandomNamespace } from "../compilers/Random.js" import util from "node:util" +import { config } from "../compilers/Configuration.js" interface ExtendUI { name: string @@ -60,7 +61,8 @@ export class UI extends Class this.name = name?.match(/^(\w|\/)+/)?.[0] || RandomString(16) this.namespace = namespace || RandomNamespace() - if (!path) this.path = `asajs/${this.namespace}.json` + if (!path) + this.path = `asajs/${this.namespace}${config.compiler?.fileExtension ? (config.compiler.fileExtension.startsWith(".") ? config.compiler.fileExtension : `.${config.compiler.fileExtension}`) : ".json"}` else this.path = path this.extendable = this.name.search("/") === -1 @@ -125,12 +127,12 @@ export class UI extends Class child: UI, properties?: Properties, name?: string, - callback?: (name: string) => void, + callback?: (name: string, parent: UI) => void, ) { if (this === child) throw new Error("Cannot add a child to itself") const childName = name || RandomString(16) this.controls.set(childName, [child, properties || {}]) - callback?.(childName) + callback?.(childName, this) return this } diff --git a/src/components/Utils.ts b/src/components/Utils.ts index 32b83ba..0135c24 100644 --- a/src/components/Utils.ts +++ b/src/components/Utils.ts @@ -133,10 +133,11 @@ export function ResolveBinding(cache: Map, ...bindings: Binding binding.source_property_name = out } } - - binding.binding_type = BindingType.VIEW - + binding.binding_type ||= BindingType.VIEW if (!binding.target_property_name) throw new Error("Binding must have a target property name") + } else if (binding.binding_collection_name) { + if (Object.keys(binding).length > 1) binding.binding_type ||= BindingType.COLLECTION + else binding.binding_type ||= BindingType.COLLECTION_DETAILS } result.push(binding) } @@ -196,7 +197,10 @@ export function b(input: string): CompileBinding { // Quick Elements export function Modify>(namespace: T, name: K) { // @ts-ignore - const memoryUI = MemoryModify[paths[namespace][name]]?.[name] + const getPath = paths[namespace] || paths[namespace][name] + + // @ts-ignore + const memoryUI = MemoryModify[getPath]?.[name] // @ts-ignore if (memoryUI) return memoryUI as ModifyUI, VanillaElementChilds> const path = paths[namespace] @@ -204,7 +208,7 @@ export function Modify>(namespace: T, if (!path) { throw new Error(`Namespace '${namespace}' does not exist`) // @ts-ignore - } else if (typeof path !== "string" && !paths[namespace][name]) { + } else if (typeof path !== "string" && !getPath) { throw new Error(`Element '${name}' does not exist in namespace '${namespace}'`) } // @ts-ignore @@ -212,10 +216,10 @@ export function Modify>(namespace: T, namespace, name, // @ts-ignore - typeof path === "string" ? path : paths[namespace][name], + typeof path === "string" ? path : getPath, ) // @ts-ignore - ;(MemoryModify[paths[namespace][name]] ||= {})[name] = modifyUI + ;(MemoryModify[getPath] ||= {})[name] = modifyUI return modifyUI } diff --git a/src/index.ts b/src/index.ts index 239aff6..d169504 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,5 @@ -import "./compilers/Configuration.js" import "./compilers/PreCompile.js" +import "./compilers/Configuration.js" import "./compilers/ui/builder.js" import "./compilers/ui/installer.js" @@ -17,3 +17,5 @@ export { ArrayName, Operation } from "./types/properties/index.js" export * from "./compilers/bindings/Binary.js" export { API } from "./components/API.js" + +export { MemoryModify } from "./compilers/Memory.js" diff --git a/src/types/vanilla/paths.ts b/src/types/vanilla/paths.ts index 989a533..ef859a5 100644 --- a/src/types/vanilla/paths.ts +++ b/src/types/vanilla/paths.ts @@ -1,210 +1,210 @@ export const paths = { - "achievement": "ui/achievement_screen.json", - "add_external_server": "ui/add_external_server_screen.json", - "adhoc_inprogress": "ui/adhoc_inprogess_screen.json", - "adhoc": "ui/adhoc_screen.json", - "anvil": "ui/anvil_screen.json", - "anvil_pocket": "ui/anvil_screen_pocket.json", - "authentication_modals": "ui/authentication_modals.json", - "authentication": "ui/authentication_screen.json", - "auto_save_info": "ui/auto_save_info_screen.json", - "beacon": "ui/beacon_screen.json", - "beacon_pocket": "ui/beacon_screen_pocket.json", - "blast_furnace": "ui/blast_furnace_screen.json", - "book": "ui/book_screen.json", - "brewing_stand": "ui/brewing_stand_screen.json", - "brewing_stand_pocket": "ui/brewing_stand_screen_pocket.json", - "bundle_purchase_warning": "ui/bundle_purchase_warning_screen.json", - "cartography": "ui/cartography_screen.json", - "cartography_pocket": "ui/cartography_screen_pocket.json", - "chalkboard": "ui/chalkboard_screen.json", - "chat": "ui/chat_screen.json", - "chat_settings": "ui/chat_settings_menu_screen.json", - "chest": "ui/chest_screen.json", - "choose_realm": "ui/choose_realm_screen.json", - "coin_purchase": "ui/coin_purchase_screen.json", - "command_block": "ui/command_block_screen.json", - "confirm_delete_account": "ui/confirm_delete_account_screen.json", - "content_log": "ui/content_log.json", - "content_log_history": "ui/content_log_history_screen.json", - "crafter_pocket": "ui/crafter_screen_pocket.json", - "create_world_upsell": "ui/create_world_upsell_screen.json", - "credits": "ui/credits_screen.json", - "csb_purchase_error": "ui/csb_purchase_error_screen.json", - "csb": "ui/csb_screen.json", - "csb_content": "ui/csb_sections/content_section.json", - "csb_banner": "ui/csb_sections/csb_banner.json", - "csb_buy": "ui/csb_sections/csb_buy_now_screen.json", - "common_csb": "ui/csb_sections/csb_common.json", - "csb_purchase_amazondevicewarning": "ui/csb_sections/csb_purchase_amazondevicewarning_screen.json", - "csb_purchase_warning": "ui/csb_sections/csb_purchase_warning_screen.json", - "csb_subscription_panel": "ui/csb_sections/csb_subscription_panel.json", - "csb_upsell": "ui/csb_sections/csb_upsell_dialog.json", - "csb_packs": "ui/csb_sections/csb_view_packs_screen.json", - "csb_welcome": "ui/csb_sections/csb_welcome_screen.json", - "csb_faq": "ui/csb_sections/faq_section.json", - "csb_landing": "ui/csb_sections/landing_section.json", - "custom_templates": "ui/custom_templates_screen.json", - "world_conversion_complete": "ui/world_conversion_complete_screen.json", - "day_one_experience_intro": "ui/day_one_experience_intro_screen.json", - "day_one_experience": "ui/day_one_experience_screen.json", - "death": "ui/death_screen.json", - "debug_screen": "ui/debug_screen.json", - "dev_console": "ui/dev_console_screen.json", - "disconnect": "ui/disconnect_screen.json", - "display_logged_error": "ui/display_logged_error_screen.json", - "discovery_dialog": "ui/edu_discovery_dialog.json", - "edu_featured": "ui/edu_featured.json", - "edu_quit_button": "ui/edu_pause_screen_pause_button.json", - "persona_emote": "ui/emote_wheel_screen.json", - "enchanting": "ui/enchanting_screen.json", - "enchanting_pocket": "ui/enchanting_screen_pocket.json", - "encyclopedia": "ui/encyclopedia_screen.json", - "expanded_skin_pack": "ui/expanded_skin_pack_screen.json", - "feed_common": "ui/feed_common.json", - "file_upload": "ui/file_upload_screen.json", - "furnace": "ui/furnace_screen.json", - "furnace_pocket": "ui/furnace_screen_pocket.json", - "game_tip": "ui/game_tip_screen.json", - "gamepad_disconnected": "ui/gamepad_disconnected.json", - "gameplay": "ui/gameplay_common.json", - "gathering_info": "ui/gathering_info_screen.json", - "globalpause": "ui/global_pause_screen.json", - "grindstone": "ui/grindstone_screen.json", - "grindstone_pocket": "ui/grindstone_screen_pocket.json", - "gamma_calibration": "ui/gamma_calibration_screen.json", - "horse": "ui/horse_screen.json", - "horse_pocket": "ui/horse_screen_pocket.json", - "how_to_play_common": "ui/how_to_play_common.json", - "how_to_play": "ui/how_to_play_screen.json", - "hud": "ui/hud_screen.json", - "host_options": "ui/host_options_screen.json", - "bed": "ui/in_bed_screen.json", - "im_reader": "ui/immersive_reader.json", - "crafting": "ui/inventory_screen.json", - "crafting_pocket": "ui/inventory_screen_pocket.json", - "invite": "ui/invite_screen.json", - "jigsaw_editor": "ui/jigsaw_editor_screen.json", - "late_join": "ui/late_join_pregame_screen.json", - "library_modal": "ui/library_modal_screen.json", - "local_world_picker": "ui/local_world_picker_screen.json", - "loom": "ui/loom_screen.json", - "loom_pocket": "ui/loom_screen_pocket.json", - "manage_feed": "ui/manage_feed_screen.json", - "manifest_validation": "ui/manifest_validation_screen.json", - "sdl_label": "ui/marketplace_sdl/sdl_label.json", - "sdl_dropdowns": "ui/marketplace_sdl/sdl_dropdowns.json", - "sdl_image_row": "ui/marketplace_sdl/sdl_image_row.json", - "sdl_text_row": "ui/marketplace_sdl/sdl_text_row.json", - "mob_effect": "ui/mob_effect_screen.json", - "non_xbl_user_management": "ui/non_xbl_user_management_screen.json", - "npc_interact": "ui/npc_interact_screen.json", - "online_safety": "ui/online_safety_screen.json", - "pack_settings": "ui/pack_settings_screen.json", - "panorama": "ui/panorama_screen.json", - "patch_notes": "ui/patch_notes_screen.json", - "pause": "ui/pause_screen.json", - "pdp": "ui/pdp_screen.json", - "pdp_screenshots": "ui/pdp_screenshots_section.json", - "permissions": "ui/permissions_screen.json", - "persona_cast_character_screen": "ui/persona_cast_character_screen.json", - "persona_common": "ui/persona_common.json", - "persona_popups": "ui/persona_popups.json", - "play": "ui/play_screen.json", - "perf_turtle": "ui/perf_turtle.json", - "pocket_containers": "ui/pocket_containers.json", - "popup_dialog": "ui/popup_dialog.json", - "portfolio": "ui/portfolio_screen.json", - "progress": "ui/progress_screen.json", - "rating_prompt": "ui/rating_prompt.json", - "realms_common": "ui/realms_common.json", - "realms_create": "ui/realms_create.json", - "realms_pending_invitations": "ui/realms_pending_invitations.json", - "realms_slots": "ui/realms_slots_screen.json", - "realms_settings": "ui/realms_settings_screen.json", - "realms_allowlist": "ui/realms_allowlist.json", - "realms_invite_link_settings": "ui/realms_invite_link_settings_screen.json", - "realms_plus_ended": "ui/realms_plus_ended_screen.json", - "realmsPlus": "ui/realmsPlus_screen.json", - "realmsPlus_content": "ui/realmsPlus_sections/content_section.json", - "realmsPlus_faq": "ui/realmsPlus_sections/faq_section.json", - "realmsPlus_landing": "ui/realmsPlus_sections/landing_section.json", - "realmsPlus_buy": "ui/realmsPlus_sections/realmsPlus_buy_now_screen.json", - "realmsPlus_packs": "ui/realmsPlus_sections/realmsPlus_view_packs_screen.json", - "realmsPlus_purchase_warning": "ui/realmsPlus_sections/realmsPlus_purchase_warning_screen.json", - "realms_stories_transition": "ui/realms_stories_transition_screen.json", - "redstone": "ui/redstone_screen.json", - "resource_packs": "ui/resource_packs_screen.json", - "safe_zone": "ui/safe_zone_screen.json", - "storage_migration_common": "ui/storage_migration_common.json", - "storage_migration_generic": "ui/storage_migration_generic_screen.json", - "scoreboard": "ui/scoreboards.json", - "screenshot": "ui/screenshot_screen.json", - "select_world": "ui/select_world_screen.json", - "server_form": "ui/server_form.json", - "settings": "ui/settings_screen.json", - "controls_section": "ui/settings_sections/controls_section.json", - "general_section": "ui/settings_sections/general_section.json", - "realms_world_section": "ui/settings_sections/realms_world_section.json", - "settings_common": "ui/settings_sections/settings_common.json", - "world_section": "ui/settings_sections/world_section.json", - "social_section": "ui/settings_sections/social_section.json", - "sidebar_navigation": "ui/sidebar_navigation.json", - "sign": "ui/sign_screen.json", - "simple_inprogress": "ui/simple_inprogress_screen.json", - "skin_pack_purchase": "ui/skin_pack_purchase_screen.json", - "skin_picker": "ui/skin_picker_screen.json", - "smithing_table": "ui/smithing_table_screen.json", - "smithing_table_2": "ui/smithing_table_2_screen.json", - "smithing_table_pocket": "ui/smithing_table_screen_pocket.json", - "smithing_table_2_pocket": "ui/smithing_table_2_screen_pocket.json", - "smoker": "ui/smoker_screen.json", - "start": "ui/start_screen.json", - "stonecutter": "ui/stonecutter_screen.json", - "stonecutter_pocket": "ui/stonecutter_screen_pocket.json", - "storage_management": "ui/storage_management.json", - "storage_management_popup": "ui/storage_management_popup.json", - "common_store": "ui/store_common.json", - "store_layout": "ui/store_data_driven_screen.json", - "filter_menu": "ui/store_filter_menu_screen.json", - "store_inventory": "ui/store_inventory_screen.json", - "store_item_list": "ui/store_item_list_screen.json", - "store_progress": "ui/store_progress_screen.json", - "promo_timeline": "ui/store_promo_timeline_screen.json", - "store_sale_item_list": "ui/store_sales_item_list_screen.json", - "store_search": "ui/store_search_screen.json", - "sort_menu": "ui/store_sort_menu_screen.json", - "structure_editor": "ui/structure_editor_screen.json", - "submit_feedback": "ui/submit_feedback_screen.json", - "tabbed_upsell": "ui/tabbed_upsell_screen.json", - "thanks_for_testing": "ui/thanks_for_testing_screen.json", - "third_party_store": "ui/third_party_store_screen.json", - "toast_screen": "ui/toast_screen.json", - "token_faq": "ui/token_faq_screen.json", - "trade": "ui/trade_screen.json", - "trade_pocket": "ui/trade_screen_pocket.json", - "trade2": "ui/trade_2_screen.json", - "trade2_pocket": "ui/trade_2_screen_pocket.json", - "trialUpsell": "ui/trial_upsell_screen.json", - "ugc_viewer": "ui/ugc_viewer_screen.json", - "common_art": "ui/ui_art_assets_common.json", - "common": "ui/ui_common.json", - "common-classic": "ui/ui_common_classic.json", - "edu_common": "ui/ui_edu_common.json", - "purchase_common": "ui/ui_purchase_common.json", - "common_buttons": "ui/ui_template_buttons.json", - "common_dialogs": "ui/ui_template_dialogs.json", - "common_tabs": "ui/ui_template_tabs.json", - "common_toggles": "ui/ui_template_toggles.json", - "friendsbutton": "ui/ui_friendsbutton.json", - "iconbutton": "ui/ui_iconbutton.json", - "update_dimensions": "ui/update_dimensions.json", - "update_version": "ui/update_version.json", - "world_recovery": "ui/world_recovery_screen.json", - "world_templates": "ui/world_templates_screen.json", - "xbl_console_qr_signin": "ui/xbl_console_qr_signin.json", - "xbl_console_signin": "ui/xbl_console_signin.json", - "xbl_console_signin_succeeded": "ui/xbl_console_signin_succeeded.json", - "xbl_immediate_signin": "ui/xbl_immediate_signin.json", - "win10_trial_conversion": "ui/win10_trial_conversion_screen.json" -} \ No newline at end of file + achievement: "ui/achievement_screen.json", + add_external_server: "ui/add_external_server_screen.json", + adhoc_inprogress: "ui/adhoc_inprogess_screen.json", + adhoc: "ui/adhoc_screen.json", + anvil: "ui/anvil_screen.json", + anvil_pocket: "ui/anvil_screen_pocket.json", + authentication_modals: "ui/authentication_modals.json", + authentication: "ui/authentication_screen.json", + auto_save_info: "ui/auto_save_info_screen.json", + beacon: "ui/beacon_screen.json", + beacon_pocket: "ui/beacon_screen_pocket.json", + blast_furnace: "ui/blast_furnace_screen.json", + book: "ui/book_screen.json", + brewing_stand: "ui/brewing_stand_screen.json", + brewing_stand_pocket: "ui/brewing_stand_screen_pocket.json", + bundle_purchase_warning: "ui/bundle_purchase_warning_screen.json", + cartography: "ui/cartography_screen.json", + cartography_pocket: "ui/cartography_screen_pocket.json", + chalkboard: "ui/chalkboard_screen.json", + chat: "ui/chat_screen.json", + chat_settings: "ui/chat_settings_menu_screen.json", + chest: "ui/chest_screen.json", + choose_realm: "ui/choose_realm_screen.json", + coin_purchase: "ui/coin_purchase_screen.json", + command_block: "ui/command_block_screen.json", + confirm_delete_account: "ui/confirm_delete_account_screen.json", + content_log: "ui/content_log.json", + content_log_history: "ui/content_log_history_screen.json", + crafter_pocket: "ui/crafter_screen_pocket.json", + create_world_upsell: "ui/create_world_upsell_screen.json", + credits: "ui/credits_screen.json", + csb_purchase_error: "ui/csb_purchase_error_screen.json", + csb: "ui/csb_screen.json", + csb_content: "ui/csb_sections/content_section.json", + csb_banner: "ui/csb_sections/csb_banner.json", + csb_buy: "ui/csb_sections/csb_buy_now_screen.json", + common_csb: "ui/csb_sections/csb_common.json", + csb_purchase_amazondevicewarning: "ui/csb_sections/csb_purchase_amazondevicewarning_screen.json", + csb_purchase_warning: "ui/csb_sections/csb_purchase_warning_screen.json", + csb_subscription_panel: "ui/csb_sections/csb_subscription_panel.json", + csb_upsell: "ui/csb_sections/csb_upsell_dialog.json", + csb_packs: "ui/csb_sections/csb_view_packs_screen.json", + csb_welcome: "ui/csb_sections/csb_welcome_screen.json", + csb_faq: "ui/csb_sections/faq_section.json", + csb_landing: "ui/csb_sections/landing_section.json", + custom_templates: "ui/custom_templates_screen.json", + world_conversion_complete: "ui/world_conversion_complete_screen.json", + day_one_experience_intro: "ui/day_one_experience_intro_screen.json", + day_one_experience: "ui/day_one_experience_screen.json", + death: "ui/death_screen.json", + debug_screen: "ui/debug_screen.json", + dev_console: "ui/dev_console_screen.json", + disconnect: "ui/disconnect_screen.json", + display_logged_error: "ui/display_logged_error_screen.json", + discovery_dialog: "ui/edu_discovery_dialog.json", + edu_featured: "ui/edu_featured.json", + edu_quit_button: "ui/edu_pause_screen_pause_button.json", + persona_emote: "ui/emote_wheel_screen.json", + enchanting: "ui/enchanting_screen.json", + enchanting_pocket: "ui/enchanting_screen_pocket.json", + encyclopedia: "ui/encyclopedia_screen.json", + expanded_skin_pack: "ui/expanded_skin_pack_screen.json", + feed_common: "ui/feed_common.json", + file_upload: "ui/file_upload_screen.json", + furnace: "ui/furnace_screen.json", + furnace_pocket: "ui/furnace_screen_pocket.json", + game_tip: "ui/game_tip_screen.json", + gamepad_disconnected: "ui/gamepad_disconnected.json", + gameplay: "ui/gameplay_common.json", + gathering_info: "ui/gathering_info_screen.json", + globalpause: "ui/global_pause_screen.json", + grindstone: "ui/grindstone_screen.json", + grindstone_pocket: "ui/grindstone_screen_pocket.json", + gamma_calibration: "ui/gamma_calibration_screen.json", + horse: "ui/horse_screen.json", + horse_pocket: "ui/horse_screen_pocket.json", + how_to_play_common: "ui/how_to_play_common.json", + how_to_play: "ui/how_to_play_screen.json", + hud: "ui/hud_screen.json", + host_options: "ui/host_options_screen.json", + bed: "ui/in_bed_screen.json", + im_reader: "ui/immersive_reader.json", + crafting: "ui/inventory_screen.json", + crafting_pocket: "ui/inventory_screen_pocket.json", + invite: "ui/invite_screen.json", + jigsaw_editor: "ui/jigsaw_editor_screen.json", + late_join: "ui/late_join_pregame_screen.json", + library_modal: "ui/library_modal_screen.json", + local_world_picker: "ui/local_world_picker_screen.json", + loom: "ui/loom_screen.json", + loom_pocket: "ui/loom_screen_pocket.json", + manage_feed: "ui/manage_feed_screen.json", + manifest_validation: "ui/manifest_validation_screen.json", + sdl_label: "ui/marketplace_sdl/sdl_label.json", + sdl_dropdowns: "ui/marketplace_sdl/sdl_dropdowns.json", + sdl_image_row: "ui/marketplace_sdl/sdl_image_row.json", + sdl_text_row: "ui/marketplace_sdl/sdl_text_row.json", + mob_effect: "ui/mob_effect_screen.json", + non_xbl_user_management: "ui/non_xbl_user_management_screen.json", + npc_interact: "ui/npc_interact_screen.json", + online_safety: "ui/online_safety_screen.json", + pack_settings: "ui/pack_settings_screen.json", + panorama: "ui/panorama_screen.json", + patch_notes: "ui/patch_notes_screen.json", + pause: "ui/pause_screen.json", + pdp: "ui/pdp_screen.json", + pdp_screenshots: "ui/pdp_screenshots_section.json", + permissions: "ui/permissions_screen.json", + persona_cast_character_screen: "ui/persona_cast_character_screen.json", + persona_common: "ui/persona_common.json", + persona_popups: "ui/persona_popups.json", + play: "ui/play_screen.json", + perf_turtle: "ui/perf_turtle.json", + pocket_containers: "ui/pocket_containers.json", + popup_dialog: "ui/popup_dialog.json", + portfolio: "ui/portfolio_screen.json", + progress: "ui/progress_screen.json", + rating_prompt: "ui/rating_prompt.json", + realms_common: "ui/realms_common.json", + realms_create: "ui/realms_create.json", + realms_pending_invitations: "ui/realms_pending_invitations.json", + realms_slots: "ui/realms_slots_screen.json", + realms_settings: "ui/realms_settings_screen.json", + realms_allowlist: "ui/realms_allowlist.json", + realms_invite_link_settings: "ui/realms_invite_link_settings_screen.json", + realms_plus_ended: "ui/realms_plus_ended_screen.json", + realmsPlus: "ui/realmsPlus_screen.json", + realmsPlus_content: "ui/realmsPlus_sections/content_section.json", + realmsPlus_faq: "ui/realmsPlus_sections/faq_section.json", + realmsPlus_landing: "ui/realmsPlus_sections/landing_section.json", + realmsPlus_buy: "ui/realmsPlus_sections/realmsPlus_buy_now_screen.json", + realmsPlus_packs: "ui/realmsPlus_sections/realmsPlus_view_packs_screen.json", + realmsPlus_purchase_warning: "ui/realmsPlus_sections/realmsPlus_purchase_warning_screen.json", + realms_stories_transition: "ui/realms_stories_transition_screen.json", + redstone: "ui/redstone_screen.json", + resource_packs: "ui/resource_packs_screen.json", + safe_zone: "ui/safe_zone_screen.json", + storage_migration_common: "ui/storage_migration_common.json", + storage_migration_generic: "ui/storage_migration_generic_screen.json", + scoreboard: "ui/scoreboards.json", + screenshot: "ui/screenshot_screen.json", + select_world: "ui/select_world_screen.json", + server_form: "ui/server_form.json", + settings: "ui/settings_screen.json", + controls_section: "ui/settings_sections/controls_section.json", + general_section: "ui/settings_sections/general_section.json", + realms_world_section: "ui/settings_sections/realms_world_section.json", + settings_common: "ui/settings_sections/settings_common.json", + world_section: "ui/settings_sections/world_section.json", + social_section: "ui/settings_sections/social_section.json", + sidebar_navigation: "ui/sidebar_navigation.json", + sign: "ui/sign_screen.json", + simple_inprogress: "ui/simple_inprogress_screen.json", + skin_pack_purchase: "ui/skin_pack_purchase_screen.json", + skin_picker: "ui/skin_picker_screen.json", + smithing_table: "ui/smithing_table_screen.json", + smithing_table_2: "ui/smithing_table_2_screen.json", + smithing_table_pocket: "ui/smithing_table_screen_pocket.json", + smithing_table_2_pocket: "ui/smithing_table_2_screen_pocket.json", + smoker: "ui/smoker_screen.json", + start: "ui/start_screen.json", + stonecutter: "ui/stonecutter_screen.json", + stonecutter_pocket: "ui/stonecutter_screen_pocket.json", + storage_management: "ui/storage_management.json", + storage_management_popup: "ui/storage_management_popup.json", + common_store: "ui/store_common.json", + store_layout: "ui/store_data_driven_screen.json", + filter_menu: "ui/store_filter_menu_screen.json", + store_inventory: "ui/store_inventory_screen.json", + store_item_list: "ui/store_item_list_screen.json", + store_progress: "ui/store_progress_screen.json", + promo_timeline: "ui/store_promo_timeline_screen.json", + store_sale_item_list: "ui/store_sales_item_list_screen.json", + store_search: "ui/store_search_screen.json", + sort_menu: "ui/store_sort_menu_screen.json", + structure_editor: "ui/structure_editor_screen.json", + submit_feedback: "ui/submit_feedback_screen.json", + tabbed_upsell: "ui/tabbed_upsell_screen.json", + thanks_for_testing: "ui/thanks_for_testing_screen.json", + third_party_store: "ui/third_party_store_screen.json", + toast_screen: "ui/toast_screen.json", + token_faq: "ui/token_faq_screen.json", + trade: "ui/trade_screen.json", + trade_pocket: "ui/trade_screen_pocket.json", + trade2: "ui/trade_2_screen.json", + trade2_pocket: "ui/trade_2_screen_pocket.json", + trialUpsell: "ui/trial_upsell_screen.json", + ugc_viewer: "ui/ugc_viewer_screen.json", + common_art: "ui/ui_art_assets_common.json", + common: "ui/ui_common.json", + "common-classic": "ui/ui_common_classic.json", + edu_common: "ui/ui_edu_common.json", + purchase_common: "ui/ui_purchase_common.json", + common_buttons: "ui/ui_template_buttons.json", + common_dialogs: "ui/ui_template_dialogs.json", + common_tabs: "ui/ui_template_tabs.json", + common_toggles: "ui/ui_template_toggles.json", + friendsbutton: "ui/ui_friendsbutton.json", + iconbutton: "ui/ui_iconbutton.json", + update_dimensions: "ui/update_dimensions.json", + update_version: "ui/update_version.json", + world_recovery: "ui/world_recovery_screen.json", + world_templates: "ui/world_templates_screen.json", + xbl_console_qr_signin: "ui/xbl_console_qr_signin.json", + xbl_console_signin: "ui/xbl_console_signin.json", + xbl_console_signin_succeeded: "ui/xbl_console_signin_succeeded.json", + xbl_immediate_signin: "ui/xbl_immediate_signin.json", + win10_trial_conversion: "ui/win10_trial_conversion_screen.json", +}