modify custom ui pack system

This commit is contained in:
Asaki Yuki 2026-02-23 00:18:59 +07:00
parent d1a7399e2f
commit 69a54ace0b
12 changed files with 559 additions and 222 deletions

2
config.d.ts vendored
View file

@ -14,10 +14,12 @@ export interface Config {
gdkUserId?: string gdkUserId?: string
fixInventoryItemRenderer?: boolean fixInventoryItemRenderer?: boolean
buildFolder?: string buildFolder?: string
fileExtension?: string
} }
ui_analyzer?: { ui_analyzer?: {
enabled?: boolean enabled?: boolean
generate_path?: string
imports?: string[] imports?: string[]
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "asajs", "name": "asajs",
"version": "4.0.13", "version": "4.0.16-indev",
"description": "Create your Minecraft JSON-UI resource packs using JavaScript", "description": "Create your Minecraft JSON-UI resource packs using JavaScript",
"keywords": [ "keywords": [
"Minecraft", "Minecraft",

View file

@ -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<string, Record<string, string>> = {}
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<string, string> = {}
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<T extends Namespace> = Extract<keyof UI[T], string>
type ElementInfos<T extends Namespace, K extends Element<T>> = UI[T][K]
// @ts-ignore
type GetType<T extends Namespace, K extends Element<T>> = ElementInfos<T, K>["type"]
// @ts-ignore
type GetChilds<T extends Namespace, K extends Element<T>> = ElementInfos<T, K>["children"]
export default function Modify<T extends Namespace, K extends Element<T>>(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<GetType<T, K>, GetChilds<T, K>>
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<GetType<T, K>, GetChilds<T, K>>(
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",
)
}

View file

@ -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<string, Namespace>()
Object.entries(paths).forEach(([namespace, path]) => {
map.set(path, namespace)
})
export function generateUIDefs(pack_folder: string) {
const uiMap = new Map<Namespace, Map<ElementPath, ScanElement>>()
uiFiles(pack_folder).forEach(file => {
try {
const fileContent: Record<string, unknown> = 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 = <string>n
const elementMap = new Map<ElementPath, ScanElement>()
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")
}

View file

@ -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)
}

20
src/analyzer/utils.ts Normal file
View file

@ -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<string, Set<string>>()
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<string> {
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
}

View file

@ -3,6 +3,9 @@ import path from "path"
import jsonc from "jsonc-parser" import jsonc from "jsonc-parser"
import { Config, RetBindingValue } from "../../config.js" import { Config, RetBindingValue } from "../../config.js"
import { createRequire } from "module" 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<string, unknown> = {} const options: Record<string, unknown> = {}
@ -64,5 +67,20 @@ export const buildFolder = config.compiler?.buildFolder || "build"
export const bindingFuntions = config.binding_functions export const bindingFuntions = config.binding_functions
if (!fs.existsSync(".gitignore")) { 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)
}
})
} }

View file

@ -14,6 +14,7 @@ import { RandomString, ResolveBinding } from "./Utils.js"
import { RandomNamespace } from "../compilers/Random.js" import { RandomNamespace } from "../compilers/Random.js"
import util from "node:util" import util from "node:util"
import { config } from "../compilers/Configuration.js"
interface ExtendUI { interface ExtendUI {
name: string name: string
@ -60,7 +61,8 @@ export class UI<T extends Type, K extends Renderer | null = null> extends Class
this.name = name?.match(/^(\w|\/)+/)?.[0] || RandomString(16) this.name = name?.match(/^(\w|\/)+/)?.[0] || RandomString(16)
this.namespace = namespace || RandomNamespace() 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 else this.path = path
this.extendable = this.name.search("/") === -1 this.extendable = this.name.search("/") === -1
@ -125,12 +127,12 @@ export class UI<T extends Type, K extends Renderer | null = null> extends Class
child: UI<T, K>, child: UI<T, K>,
properties?: Properties<T, K>, properties?: Properties<T, K>,
name?: string, name?: string,
callback?: (name: string) => void, callback?: (name: string, parent: UI<T, K>) => void,
) { ) {
if (this === <any>child) throw new Error("Cannot add a child to itself") if (this === <any>child) throw new Error("Cannot add a child to itself")
const childName = name || RandomString(16) const childName = name || RandomString(16)
this.controls.set(childName, [child, properties || {}]) this.controls.set(childName, [child, properties || {}])
callback?.(childName) callback?.(childName, <any>this)
return this return this
} }

View file

@ -133,10 +133,11 @@ export function ResolveBinding(cache: Map<string, unknown>, ...bindings: Binding
binding.source_property_name = out 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") 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) result.push(binding)
} }
@ -196,7 +197,10 @@ export function b(input: string): CompileBinding {
// Quick Elements // Quick Elements
export function Modify<T extends Namespace, K extends Element<T>>(namespace: T, name: K) { export function Modify<T extends Namespace, K extends Element<T>>(namespace: T, name: K) {
// @ts-ignore // @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 // @ts-ignore
if (memoryUI) return memoryUI as ModifyUI<VanillaType<T, K>, VanillaElementChilds<T, K>> if (memoryUI) return memoryUI as ModifyUI<VanillaType<T, K>, VanillaElementChilds<T, K>>
const path = paths[namespace] const path = paths[namespace]
@ -204,7 +208,7 @@ export function Modify<T extends Namespace, K extends Element<T>>(namespace: T,
if (!path) { if (!path) {
throw new Error(`Namespace '${namespace}' does not exist`) throw new Error(`Namespace '${namespace}' does not exist`)
// @ts-ignore // @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}'`) throw new Error(`Element '${name}' does not exist in namespace '${namespace}'`)
} }
// @ts-ignore // @ts-ignore
@ -212,10 +216,10 @@ export function Modify<T extends Namespace, K extends Element<T>>(namespace: T,
namespace, namespace,
name, name,
// @ts-ignore // @ts-ignore
typeof path === "string" ? path : paths[namespace][name], typeof path === "string" ? path : getPath,
) )
// @ts-ignore // @ts-ignore
;(MemoryModify[paths[namespace][name]] ||= {})[name] = modifyUI ;(MemoryModify[getPath] ||= {})[name] = modifyUI
return modifyUI return modifyUI
} }

View file

@ -1,5 +1,5 @@
import "./compilers/Configuration.js"
import "./compilers/PreCompile.js" import "./compilers/PreCompile.js"
import "./compilers/Configuration.js"
import "./compilers/ui/builder.js" import "./compilers/ui/builder.js"
import "./compilers/ui/installer.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 * from "./compilers/bindings/Binary.js"
export { API } from "./components/API.js" export { API } from "./components/API.js"
export { MemoryModify } from "./compilers/Memory.js"

View file

@ -1,210 +1,210 @@
export const paths = { export const paths = {
"achievement": "ui/achievement_screen.json", achievement: "ui/achievement_screen.json",
"add_external_server": "ui/add_external_server_screen.json", add_external_server: "ui/add_external_server_screen.json",
"adhoc_inprogress": "ui/adhoc_inprogess_screen.json", adhoc_inprogress: "ui/adhoc_inprogess_screen.json",
"adhoc": "ui/adhoc_screen.json", adhoc: "ui/adhoc_screen.json",
"anvil": "ui/anvil_screen.json", anvil: "ui/anvil_screen.json",
"anvil_pocket": "ui/anvil_screen_pocket.json", anvil_pocket: "ui/anvil_screen_pocket.json",
"authentication_modals": "ui/authentication_modals.json", authentication_modals: "ui/authentication_modals.json",
"authentication": "ui/authentication_screen.json", authentication: "ui/authentication_screen.json",
"auto_save_info": "ui/auto_save_info_screen.json", auto_save_info: "ui/auto_save_info_screen.json",
"beacon": "ui/beacon_screen.json", beacon: "ui/beacon_screen.json",
"beacon_pocket": "ui/beacon_screen_pocket.json", beacon_pocket: "ui/beacon_screen_pocket.json",
"blast_furnace": "ui/blast_furnace_screen.json", blast_furnace: "ui/blast_furnace_screen.json",
"book": "ui/book_screen.json", book: "ui/book_screen.json",
"brewing_stand": "ui/brewing_stand_screen.json", brewing_stand: "ui/brewing_stand_screen.json",
"brewing_stand_pocket": "ui/brewing_stand_screen_pocket.json", brewing_stand_pocket: "ui/brewing_stand_screen_pocket.json",
"bundle_purchase_warning": "ui/bundle_purchase_warning_screen.json", bundle_purchase_warning: "ui/bundle_purchase_warning_screen.json",
"cartography": "ui/cartography_screen.json", cartography: "ui/cartography_screen.json",
"cartography_pocket": "ui/cartography_screen_pocket.json", cartography_pocket: "ui/cartography_screen_pocket.json",
"chalkboard": "ui/chalkboard_screen.json", chalkboard: "ui/chalkboard_screen.json",
"chat": "ui/chat_screen.json", chat: "ui/chat_screen.json",
"chat_settings": "ui/chat_settings_menu_screen.json", chat_settings: "ui/chat_settings_menu_screen.json",
"chest": "ui/chest_screen.json", chest: "ui/chest_screen.json",
"choose_realm": "ui/choose_realm_screen.json", choose_realm: "ui/choose_realm_screen.json",
"coin_purchase": "ui/coin_purchase_screen.json", coin_purchase: "ui/coin_purchase_screen.json",
"command_block": "ui/command_block_screen.json", command_block: "ui/command_block_screen.json",
"confirm_delete_account": "ui/confirm_delete_account_screen.json", confirm_delete_account: "ui/confirm_delete_account_screen.json",
"content_log": "ui/content_log.json", content_log: "ui/content_log.json",
"content_log_history": "ui/content_log_history_screen.json", content_log_history: "ui/content_log_history_screen.json",
"crafter_pocket": "ui/crafter_screen_pocket.json", crafter_pocket: "ui/crafter_screen_pocket.json",
"create_world_upsell": "ui/create_world_upsell_screen.json", create_world_upsell: "ui/create_world_upsell_screen.json",
"credits": "ui/credits_screen.json", credits: "ui/credits_screen.json",
"csb_purchase_error": "ui/csb_purchase_error_screen.json", csb_purchase_error: "ui/csb_purchase_error_screen.json",
"csb": "ui/csb_screen.json", csb: "ui/csb_screen.json",
"csb_content": "ui/csb_sections/content_section.json", csb_content: "ui/csb_sections/content_section.json",
"csb_banner": "ui/csb_sections/csb_banner.json", csb_banner: "ui/csb_sections/csb_banner.json",
"csb_buy": "ui/csb_sections/csb_buy_now_screen.json", csb_buy: "ui/csb_sections/csb_buy_now_screen.json",
"common_csb": "ui/csb_sections/csb_common.json", common_csb: "ui/csb_sections/csb_common.json",
"csb_purchase_amazondevicewarning": "ui/csb_sections/csb_purchase_amazondevicewarning_screen.json", csb_purchase_amazondevicewarning: "ui/csb_sections/csb_purchase_amazondevicewarning_screen.json",
"csb_purchase_warning": "ui/csb_sections/csb_purchase_warning_screen.json", csb_purchase_warning: "ui/csb_sections/csb_purchase_warning_screen.json",
"csb_subscription_panel": "ui/csb_sections/csb_subscription_panel.json", csb_subscription_panel: "ui/csb_sections/csb_subscription_panel.json",
"csb_upsell": "ui/csb_sections/csb_upsell_dialog.json", csb_upsell: "ui/csb_sections/csb_upsell_dialog.json",
"csb_packs": "ui/csb_sections/csb_view_packs_screen.json", csb_packs: "ui/csb_sections/csb_view_packs_screen.json",
"csb_welcome": "ui/csb_sections/csb_welcome_screen.json", csb_welcome: "ui/csb_sections/csb_welcome_screen.json",
"csb_faq": "ui/csb_sections/faq_section.json", csb_faq: "ui/csb_sections/faq_section.json",
"csb_landing": "ui/csb_sections/landing_section.json", csb_landing: "ui/csb_sections/landing_section.json",
"custom_templates": "ui/custom_templates_screen.json", custom_templates: "ui/custom_templates_screen.json",
"world_conversion_complete": "ui/world_conversion_complete_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_intro: "ui/day_one_experience_intro_screen.json",
"day_one_experience": "ui/day_one_experience_screen.json", day_one_experience: "ui/day_one_experience_screen.json",
"death": "ui/death_screen.json", death: "ui/death_screen.json",
"debug_screen": "ui/debug_screen.json", debug_screen: "ui/debug_screen.json",
"dev_console": "ui/dev_console_screen.json", dev_console: "ui/dev_console_screen.json",
"disconnect": "ui/disconnect_screen.json", disconnect: "ui/disconnect_screen.json",
"display_logged_error": "ui/display_logged_error_screen.json", display_logged_error: "ui/display_logged_error_screen.json",
"discovery_dialog": "ui/edu_discovery_dialog.json", discovery_dialog: "ui/edu_discovery_dialog.json",
"edu_featured": "ui/edu_featured.json", edu_featured: "ui/edu_featured.json",
"edu_quit_button": "ui/edu_pause_screen_pause_button.json", edu_quit_button: "ui/edu_pause_screen_pause_button.json",
"persona_emote": "ui/emote_wheel_screen.json", persona_emote: "ui/emote_wheel_screen.json",
"enchanting": "ui/enchanting_screen.json", enchanting: "ui/enchanting_screen.json",
"enchanting_pocket": "ui/enchanting_screen_pocket.json", enchanting_pocket: "ui/enchanting_screen_pocket.json",
"encyclopedia": "ui/encyclopedia_screen.json", encyclopedia: "ui/encyclopedia_screen.json",
"expanded_skin_pack": "ui/expanded_skin_pack_screen.json", expanded_skin_pack: "ui/expanded_skin_pack_screen.json",
"feed_common": "ui/feed_common.json", feed_common: "ui/feed_common.json",
"file_upload": "ui/file_upload_screen.json", file_upload: "ui/file_upload_screen.json",
"furnace": "ui/furnace_screen.json", furnace: "ui/furnace_screen.json",
"furnace_pocket": "ui/furnace_screen_pocket.json", furnace_pocket: "ui/furnace_screen_pocket.json",
"game_tip": "ui/game_tip_screen.json", game_tip: "ui/game_tip_screen.json",
"gamepad_disconnected": "ui/gamepad_disconnected.json", gamepad_disconnected: "ui/gamepad_disconnected.json",
"gameplay": "ui/gameplay_common.json", gameplay: "ui/gameplay_common.json",
"gathering_info": "ui/gathering_info_screen.json", gathering_info: "ui/gathering_info_screen.json",
"globalpause": "ui/global_pause_screen.json", globalpause: "ui/global_pause_screen.json",
"grindstone": "ui/grindstone_screen.json", grindstone: "ui/grindstone_screen.json",
"grindstone_pocket": "ui/grindstone_screen_pocket.json", grindstone_pocket: "ui/grindstone_screen_pocket.json",
"gamma_calibration": "ui/gamma_calibration_screen.json", gamma_calibration: "ui/gamma_calibration_screen.json",
"horse": "ui/horse_screen.json", horse: "ui/horse_screen.json",
"horse_pocket": "ui/horse_screen_pocket.json", horse_pocket: "ui/horse_screen_pocket.json",
"how_to_play_common": "ui/how_to_play_common.json", how_to_play_common: "ui/how_to_play_common.json",
"how_to_play": "ui/how_to_play_screen.json", how_to_play: "ui/how_to_play_screen.json",
"hud": "ui/hud_screen.json", hud: "ui/hud_screen.json",
"host_options": "ui/host_options_screen.json", host_options: "ui/host_options_screen.json",
"bed": "ui/in_bed_screen.json", bed: "ui/in_bed_screen.json",
"im_reader": "ui/immersive_reader.json", im_reader: "ui/immersive_reader.json",
"crafting": "ui/inventory_screen.json", crafting: "ui/inventory_screen.json",
"crafting_pocket": "ui/inventory_screen_pocket.json", crafting_pocket: "ui/inventory_screen_pocket.json",
"invite": "ui/invite_screen.json", invite: "ui/invite_screen.json",
"jigsaw_editor": "ui/jigsaw_editor_screen.json", jigsaw_editor: "ui/jigsaw_editor_screen.json",
"late_join": "ui/late_join_pregame_screen.json", late_join: "ui/late_join_pregame_screen.json",
"library_modal": "ui/library_modal_screen.json", library_modal: "ui/library_modal_screen.json",
"local_world_picker": "ui/local_world_picker_screen.json", local_world_picker: "ui/local_world_picker_screen.json",
"loom": "ui/loom_screen.json", loom: "ui/loom_screen.json",
"loom_pocket": "ui/loom_screen_pocket.json", loom_pocket: "ui/loom_screen_pocket.json",
"manage_feed": "ui/manage_feed_screen.json", manage_feed: "ui/manage_feed_screen.json",
"manifest_validation": "ui/manifest_validation_screen.json", manifest_validation: "ui/manifest_validation_screen.json",
"sdl_label": "ui/marketplace_sdl/sdl_label.json", sdl_label: "ui/marketplace_sdl/sdl_label.json",
"sdl_dropdowns": "ui/marketplace_sdl/sdl_dropdowns.json", sdl_dropdowns: "ui/marketplace_sdl/sdl_dropdowns.json",
"sdl_image_row": "ui/marketplace_sdl/sdl_image_row.json", sdl_image_row: "ui/marketplace_sdl/sdl_image_row.json",
"sdl_text_row": "ui/marketplace_sdl/sdl_text_row.json", sdl_text_row: "ui/marketplace_sdl/sdl_text_row.json",
"mob_effect": "ui/mob_effect_screen.json", mob_effect: "ui/mob_effect_screen.json",
"non_xbl_user_management": "ui/non_xbl_user_management_screen.json", non_xbl_user_management: "ui/non_xbl_user_management_screen.json",
"npc_interact": "ui/npc_interact_screen.json", npc_interact: "ui/npc_interact_screen.json",
"online_safety": "ui/online_safety_screen.json", online_safety: "ui/online_safety_screen.json",
"pack_settings": "ui/pack_settings_screen.json", pack_settings: "ui/pack_settings_screen.json",
"panorama": "ui/panorama_screen.json", panorama: "ui/panorama_screen.json",
"patch_notes": "ui/patch_notes_screen.json", patch_notes: "ui/patch_notes_screen.json",
"pause": "ui/pause_screen.json", pause: "ui/pause_screen.json",
"pdp": "ui/pdp_screen.json", pdp: "ui/pdp_screen.json",
"pdp_screenshots": "ui/pdp_screenshots_section.json", pdp_screenshots: "ui/pdp_screenshots_section.json",
"permissions": "ui/permissions_screen.json", permissions: "ui/permissions_screen.json",
"persona_cast_character_screen": "ui/persona_cast_character_screen.json", persona_cast_character_screen: "ui/persona_cast_character_screen.json",
"persona_common": "ui/persona_common.json", persona_common: "ui/persona_common.json",
"persona_popups": "ui/persona_popups.json", persona_popups: "ui/persona_popups.json",
"play": "ui/play_screen.json", play: "ui/play_screen.json",
"perf_turtle": "ui/perf_turtle.json", perf_turtle: "ui/perf_turtle.json",
"pocket_containers": "ui/pocket_containers.json", pocket_containers: "ui/pocket_containers.json",
"popup_dialog": "ui/popup_dialog.json", popup_dialog: "ui/popup_dialog.json",
"portfolio": "ui/portfolio_screen.json", portfolio: "ui/portfolio_screen.json",
"progress": "ui/progress_screen.json", progress: "ui/progress_screen.json",
"rating_prompt": "ui/rating_prompt.json", rating_prompt: "ui/rating_prompt.json",
"realms_common": "ui/realms_common.json", realms_common: "ui/realms_common.json",
"realms_create": "ui/realms_create.json", realms_create: "ui/realms_create.json",
"realms_pending_invitations": "ui/realms_pending_invitations.json", realms_pending_invitations: "ui/realms_pending_invitations.json",
"realms_slots": "ui/realms_slots_screen.json", realms_slots: "ui/realms_slots_screen.json",
"realms_settings": "ui/realms_settings_screen.json", realms_settings: "ui/realms_settings_screen.json",
"realms_allowlist": "ui/realms_allowlist.json", realms_allowlist: "ui/realms_allowlist.json",
"realms_invite_link_settings": "ui/realms_invite_link_settings_screen.json", realms_invite_link_settings: "ui/realms_invite_link_settings_screen.json",
"realms_plus_ended": "ui/realms_plus_ended_screen.json", realms_plus_ended: "ui/realms_plus_ended_screen.json",
"realmsPlus": "ui/realmsPlus_screen.json", realmsPlus: "ui/realmsPlus_screen.json",
"realmsPlus_content": "ui/realmsPlus_sections/content_section.json", realmsPlus_content: "ui/realmsPlus_sections/content_section.json",
"realmsPlus_faq": "ui/realmsPlus_sections/faq_section.json", realmsPlus_faq: "ui/realmsPlus_sections/faq_section.json",
"realmsPlus_landing": "ui/realmsPlus_sections/landing_section.json", realmsPlus_landing: "ui/realmsPlus_sections/landing_section.json",
"realmsPlus_buy": "ui/realmsPlus_sections/realmsPlus_buy_now_screen.json", realmsPlus_buy: "ui/realmsPlus_sections/realmsPlus_buy_now_screen.json",
"realmsPlus_packs": "ui/realmsPlus_sections/realmsPlus_view_packs_screen.json", realmsPlus_packs: "ui/realmsPlus_sections/realmsPlus_view_packs_screen.json",
"realmsPlus_purchase_warning": "ui/realmsPlus_sections/realmsPlus_purchase_warning_screen.json", realmsPlus_purchase_warning: "ui/realmsPlus_sections/realmsPlus_purchase_warning_screen.json",
"realms_stories_transition": "ui/realms_stories_transition_screen.json", realms_stories_transition: "ui/realms_stories_transition_screen.json",
"redstone": "ui/redstone_screen.json", redstone: "ui/redstone_screen.json",
"resource_packs": "ui/resource_packs_screen.json", resource_packs: "ui/resource_packs_screen.json",
"safe_zone": "ui/safe_zone_screen.json", safe_zone: "ui/safe_zone_screen.json",
"storage_migration_common": "ui/storage_migration_common.json", storage_migration_common: "ui/storage_migration_common.json",
"storage_migration_generic": "ui/storage_migration_generic_screen.json", storage_migration_generic: "ui/storage_migration_generic_screen.json",
"scoreboard": "ui/scoreboards.json", scoreboard: "ui/scoreboards.json",
"screenshot": "ui/screenshot_screen.json", screenshot: "ui/screenshot_screen.json",
"select_world": "ui/select_world_screen.json", select_world: "ui/select_world_screen.json",
"server_form": "ui/server_form.json", server_form: "ui/server_form.json",
"settings": "ui/settings_screen.json", settings: "ui/settings_screen.json",
"controls_section": "ui/settings_sections/controls_section.json", controls_section: "ui/settings_sections/controls_section.json",
"general_section": "ui/settings_sections/general_section.json", general_section: "ui/settings_sections/general_section.json",
"realms_world_section": "ui/settings_sections/realms_world_section.json", realms_world_section: "ui/settings_sections/realms_world_section.json",
"settings_common": "ui/settings_sections/settings_common.json", settings_common: "ui/settings_sections/settings_common.json",
"world_section": "ui/settings_sections/world_section.json", world_section: "ui/settings_sections/world_section.json",
"social_section": "ui/settings_sections/social_section.json", social_section: "ui/settings_sections/social_section.json",
"sidebar_navigation": "ui/sidebar_navigation.json", sidebar_navigation: "ui/sidebar_navigation.json",
"sign": "ui/sign_screen.json", sign: "ui/sign_screen.json",
"simple_inprogress": "ui/simple_inprogress_screen.json", simple_inprogress: "ui/simple_inprogress_screen.json",
"skin_pack_purchase": "ui/skin_pack_purchase_screen.json", skin_pack_purchase: "ui/skin_pack_purchase_screen.json",
"skin_picker": "ui/skin_picker_screen.json", skin_picker: "ui/skin_picker_screen.json",
"smithing_table": "ui/smithing_table_screen.json", smithing_table: "ui/smithing_table_screen.json",
"smithing_table_2": "ui/smithing_table_2_screen.json", smithing_table_2: "ui/smithing_table_2_screen.json",
"smithing_table_pocket": "ui/smithing_table_screen_pocket.json", smithing_table_pocket: "ui/smithing_table_screen_pocket.json",
"smithing_table_2_pocket": "ui/smithing_table_2_screen_pocket.json", smithing_table_2_pocket: "ui/smithing_table_2_screen_pocket.json",
"smoker": "ui/smoker_screen.json", smoker: "ui/smoker_screen.json",
"start": "ui/start_screen.json", start: "ui/start_screen.json",
"stonecutter": "ui/stonecutter_screen.json", stonecutter: "ui/stonecutter_screen.json",
"stonecutter_pocket": "ui/stonecutter_screen_pocket.json", stonecutter_pocket: "ui/stonecutter_screen_pocket.json",
"storage_management": "ui/storage_management.json", storage_management: "ui/storage_management.json",
"storage_management_popup": "ui/storage_management_popup.json", storage_management_popup: "ui/storage_management_popup.json",
"common_store": "ui/store_common.json", common_store: "ui/store_common.json",
"store_layout": "ui/store_data_driven_screen.json", store_layout: "ui/store_data_driven_screen.json",
"filter_menu": "ui/store_filter_menu_screen.json", filter_menu: "ui/store_filter_menu_screen.json",
"store_inventory": "ui/store_inventory_screen.json", store_inventory: "ui/store_inventory_screen.json",
"store_item_list": "ui/store_item_list_screen.json", store_item_list: "ui/store_item_list_screen.json",
"store_progress": "ui/store_progress_screen.json", store_progress: "ui/store_progress_screen.json",
"promo_timeline": "ui/store_promo_timeline_screen.json", promo_timeline: "ui/store_promo_timeline_screen.json",
"store_sale_item_list": "ui/store_sales_item_list_screen.json", store_sale_item_list: "ui/store_sales_item_list_screen.json",
"store_search": "ui/store_search_screen.json", store_search: "ui/store_search_screen.json",
"sort_menu": "ui/store_sort_menu_screen.json", sort_menu: "ui/store_sort_menu_screen.json",
"structure_editor": "ui/structure_editor_screen.json", structure_editor: "ui/structure_editor_screen.json",
"submit_feedback": "ui/submit_feedback_screen.json", submit_feedback: "ui/submit_feedback_screen.json",
"tabbed_upsell": "ui/tabbed_upsell_screen.json", tabbed_upsell: "ui/tabbed_upsell_screen.json",
"thanks_for_testing": "ui/thanks_for_testing_screen.json", thanks_for_testing: "ui/thanks_for_testing_screen.json",
"third_party_store": "ui/third_party_store_screen.json", third_party_store: "ui/third_party_store_screen.json",
"toast_screen": "ui/toast_screen.json", toast_screen: "ui/toast_screen.json",
"token_faq": "ui/token_faq_screen.json", token_faq: "ui/token_faq_screen.json",
"trade": "ui/trade_screen.json", trade: "ui/trade_screen.json",
"trade_pocket": "ui/trade_screen_pocket.json", trade_pocket: "ui/trade_screen_pocket.json",
"trade2": "ui/trade_2_screen.json", trade2: "ui/trade_2_screen.json",
"trade2_pocket": "ui/trade_2_screen_pocket.json", trade2_pocket: "ui/trade_2_screen_pocket.json",
"trialUpsell": "ui/trial_upsell_screen.json", trialUpsell: "ui/trial_upsell_screen.json",
"ugc_viewer": "ui/ugc_viewer_screen.json", ugc_viewer: "ui/ugc_viewer_screen.json",
"common_art": "ui/ui_art_assets_common.json", common_art: "ui/ui_art_assets_common.json",
"common": "ui/ui_common.json", common: "ui/ui_common.json",
"common-classic": "ui/ui_common_classic.json", "common-classic": "ui/ui_common_classic.json",
"edu_common": "ui/ui_edu_common.json", edu_common: "ui/ui_edu_common.json",
"purchase_common": "ui/ui_purchase_common.json", purchase_common: "ui/ui_purchase_common.json",
"common_buttons": "ui/ui_template_buttons.json", common_buttons: "ui/ui_template_buttons.json",
"common_dialogs": "ui/ui_template_dialogs.json", common_dialogs: "ui/ui_template_dialogs.json",
"common_tabs": "ui/ui_template_tabs.json", common_tabs: "ui/ui_template_tabs.json",
"common_toggles": "ui/ui_template_toggles.json", common_toggles: "ui/ui_template_toggles.json",
"friendsbutton": "ui/ui_friendsbutton.json", friendsbutton: "ui/ui_friendsbutton.json",
"iconbutton": "ui/ui_iconbutton.json", iconbutton: "ui/ui_iconbutton.json",
"update_dimensions": "ui/update_dimensions.json", update_dimensions: "ui/update_dimensions.json",
"update_version": "ui/update_version.json", update_version: "ui/update_version.json",
"world_recovery": "ui/world_recovery_screen.json", world_recovery: "ui/world_recovery_screen.json",
"world_templates": "ui/world_templates_screen.json", world_templates: "ui/world_templates_screen.json",
"xbl_console_qr_signin": "ui/xbl_console_qr_signin.json", xbl_console_qr_signin: "ui/xbl_console_qr_signin.json",
"xbl_console_signin": "ui/xbl_console_signin.json", xbl_console_signin: "ui/xbl_console_signin.json",
"xbl_console_signin_succeeded": "ui/xbl_console_signin_succeeded.json", xbl_console_signin_succeeded: "ui/xbl_console_signin_succeeded.json",
"xbl_immediate_signin": "ui/xbl_immediate_signin.json", xbl_immediate_signin: "ui/xbl_immediate_signin.json",
"win10_trial_conversion": "ui/win10_trial_conversion_screen.json" win10_trial_conversion: "ui/win10_trial_conversion_screen.json",
} }