PKi\Ƶmeta.xml net.openwg.gameface 1.1.6 net.openwg.gameface Generate res_map.json file with mod items for ingame UiResourceManager, provide Gameface injector and wrappers PKi\res/PKi\res/gui/PKi\ res/scripts/PKi\res/gui/flash/PKi\res/gui/gameface/PKi\res/scripts/client/PKi\66&res/scripts/client/openwg_gameface.pyc mic@sddlZddlZddlZddlZddlZddlZddlZddlZyddlZ Wne k rddl Z nXddl m Z mZddlmZddlmZmZddlmZdddd d d fZejd Zejejed kZer+dndZdZdZdfdYZeZ dZ!dZ"dZ#d e fdYZ$d efdYZ%e&e&e&dZ'dS(iN(t DynAccessortINVALID_RES_ID(t ViewModel(tArraytfillStringsArray(t CURRENT_REALMton_readyt res_id_by_keytres_ids_by_maskt gf_mod_injecttModDynAccessortModInjectModeltOPENWG_GAMEFACEtRUsgui/unbound/gen/res_map.jsonsgui/unbound/res_map.jsonsmods/configs/res_maptres_map_restartt ResMapManagercBskeZdZdZdZdZdZdZedZ edZ egdZ RS( sCManager for building, validating, and applying custom resource map.c Cs tj|_t|_i|_d}xmtjddj D]R}t j j |j rA|j jdd}t j j |sqAn|}PqAqAW|stjddSt j jt j j|t}t|j}t|j|}| r4| r4t j j|r0t j||jndSy-|j||}|s`tjddSWntk rtjddSXy-|j||}|rtjd dSWntk rtjd dSXt|_|jt j jt rt jt ndS( sInitializes the ResMapManager. Sets up the validation event, locates config files from file system and game VFS, builds and validates the resource map, and triggers client restart if needed. s ../paths.xmltPathss./tsres_mods directory not found!NsCannot build modded res_mapsFailed to build res_map.jsons.Stored new res_map.json, restarting client nowsFailed to validate res_map.json(!tEventt SafeEventtonResMapValidatedtFalsetisResMapValidatedt items_mappingtNonetResMgrt openSectiontvaluestostpathtisdirtasStringtreplacetloggerterrortnormpathtjointRES_MAP_FILE_PATHtlisttconfig_files_in_real_fstconfig_files_in_game_vfstisfiletremovetrestart_clientt_build_resource_mapt Exceptiont exceptiont_validate_resource_maptinfotTruetRESTART_FLAG_FILE( tselft res_mods_dirRtmod_folder_pathtres_map_file_patht configs_fst configs_vfst resource_maptclient_restarting((spython\openwg_gameface.pyt__init__,sV    !           c CsgtjdD]}|jdrd|^q}d }x*|D]"}|j|t}|rBPqBqBW|stjd|d Sy%|jdd}t j |}Wnt k rtj dd SXxy|D]q}yDt |d/} t j| } | r|j| |nWd QXWqtk r@tj d |qqXqWx|D]}y\tj|} | d k rtj|rt j | j} | r|j| |qnWqLtk rtj d |qLqLXqLW|S( sXBuilds the resource map by merging original resource map items and mod items. Args: configs_fs (list): Config files found in the real filesystem. configs_vfs (list): Config files found in the game VFS. Returns: dict or None: Final merged resource map dictionary or None on failure. s res/packagessgui-partsres/packages/%ss0Cannot find res_map.json in game GUI packages %ss,}t}s"Failed to deserialize res_map.jsontrNs+Failed to read mod config file from FS (%s)s,Failed to read mod config file from VFS (%s)(Rtlistdirt startswithRtread_file_from_packageR%R!R"R tjsontloadst ValueErrorR.topentloadt_add_mod_items_to_resource_mapR-RRtisFiletasBinary( R3R7R8txtpackagestresource_map_datatpackageR9t file_patht file_handlet mod_itemstvfs_file((spython\openwg_gameface.pyR,vsT 2             cCsx|D]}d|kr,tjdqn|d}|d=||jkrbtjd|qnt|}||j|Rt ensure_asciit separatorst,t:R=Ntw(R]R^(tsortedtitemst collectionst OrderedDictRAtdumpsRRRtdirnameRtmakedirsRR)RDtreadtwriteR+( R3R9R6t sorted_datat ordered_dicttlatest_file_datatres_map_foldert old_file_datat file_existsRN((spython\openwg_gameface.pyR/s"  cCsy?tjjtrtSttd}|jdWdQXWntk r_tj dnXt j t j tt jtS(sTriggers client restart if it has not been restarted before by as. Returns: bool: True if restart was triggered, False otherwise. R_RNsCant write RESTART_FLAG_FILE(RRR)R2RRDRhR-R!R"t GameCentert notifyRestarttBigWorldtworldDrawEnabledt restartGameR1(R3RN((spython\openwg_gameface.pyR+s    cCswtjj|sdStj|L}|j}x6|jD]+}||jjkr>|j|jSq>WWdQXdS(sReads a file from a game package. Args: package_path (str): Path to the .pkg file. file_path (str): Relative file path inside the package. Returns: str or None: File contents if found, else None. N( RRR)tzipfiletZipFiletlowertfilelisttfilenameRg(t package_pathRMtzip_filetfile_path_lowertzip_info((spython\openwg_gameface.pyR@ s  ccstjjtrxstjtD]_}|jdr"tjjtjjt|jdd}tjj |r|Vqq"q"WndS(sYields mod config files from the real file system. Yields: str: Full path to each JSON config file found. s.jsons\t/N( RRRtMOD_CONFIGS_PATHR>tendswithR#R$R R)(t file_nameRM((spython\openwg_gameface.pyR' s -ccstd|D}tjt}|dk rtjtrx}|jD]l}tjj tjj t|j j dd}||krMtj |r|j||VqqMqMWndS(sYields mod config files from the game VFS (virtual filesystem). Args: config_files (list, optional): Already-known config file names. Yields: str: VFS path to each new config file found. css|]}|jVqdS(N(Rv(t.0RI((spython\openwg_gameface.pys 9ss\R}N(R&RRR~RtisDirtkeysRRR#R$RvR RGtappend(t config_filestvfs_dirtvfs_itemRM((spython\openwg_gameface.pyR(.s 3  ( t__name__t __module__t__doc__R;R,RFR/R+t staticmethodR@R'R((((spython\openwg_gameface.pyR)s J @  & ccs9x2tjD]'}||kr |tj|fVq q WdS(sFinds all modIDs that contain the given substring. Args: mask (str): Substring to match inside item IDs. Yields: tuple[str, int]: (modID, UiResourceManager itemID) N(tmanagerR(tmaskRX((spython\openwg_gameface.pyRGs  cCstjj|tS(sRetrieves the UiResourceManager itemID for a specific modID. Args: key (str): The modID identifier. Returns: int or INVALID_RES_ID: Corresponding UiResourceManager itemID or INVALID_RES_ID if not found. (RRtgetR(RX((spython\openwg_gameface.pyRUs cCs#tjr|Stj|7_dS(sExecutes a callback when the res_map is validated. Args: callback (Callable): Function to call once the res_map is validated. N(RRR(tcallback((spython\openwg_gameface.pyRas cBs,eZdZdZdedZdZRS(sCustom dynamic accessor for accessing mod UiResourceManager itemID. Extends DynAccessor to defer setting resId until the res_map is validated. t__modIDRcCs0tt|j|||_t|jdS(sInitializes the ModDynAccessor with a given modID and optional resID. Args: modID (str): Identifier of the mod-defined UI resource item. resID (int): Initial resource ID (default is INVALID_RES_ID). N(tsuperR R;t_ModDynAccessor__modIDRt _setResID(R3tmodIDtresID((spython\openwg_gameface.pyR;us cCst|j|_dS(sSets the internal resId once the res_map has been validated. This method retrieves the correct UiResourceManager itemID for the stored modID and assigns it to the base DynAccessor's internal resId field. N(RRt_DynAccessor__resId(R3((spython\openwg_gameface.pyRs(R(RRRt __slots__RR;R(((spython\openwg_gameface.pyR ms cBs)eZdZddddZdZRS(s;ViewModel that provides resources for the JS-side injector.cCs||_t|_t|p!g|jt|_t|pCg|jt|_t|peg|jtt|jdddddS(srInitializes the ModInjectModel. Args: name (str): A unique name of your model used to link it from JS styles (list, optional): A list of style URLs for injection. scripts (list, optional): A list of script URLs for injection. modules (list, optional): A list of script URLs acts as modules for injection. t propertiesitcommandsiN( t_nameRt_stylesRt_scriptst_modulesRR R;(R3tnametstylestscriptstmodules((spython\openwg_gameface.pyR;s    cCsctt|j|jd|j|jd|j|jd|j|jd|jdS(s!Initializes ViewModel properties.RRRRN( RR t _initializet_addStringPropertyRt_addArrayPropertyRRR(R3((spython\openwg_gameface.pyRs N(RRRRR;R(((spython\openwg_gameface.pyR scCs#|jdt||||dS(sAdds the inject model as a property to another ViewModel. This makes the resource lists available to the JS-side injector. Args: model (ViewModel): The target ViewModel to which the injector model will be added. name (str): A unique name of your model used to link it from JS styles (list, optional): A list of style URLs. scripts (list, optional): A list of script URLs. modules (list, optional): A list of script URLs acts as modules for injection. R N(t_addViewModelPropertyR (tmodelRRRR((spython\openwg_gameface.pyR s ((RbRAtloggingRRtRqRRtWGCRot ImportErrortLGCtgui.impl.gen_utilsRRtframeworks.wulfRtframeworks.wulf.view.arrayRRtrealmRt__all__t getLoggerR!tsetLeveltINFOtIS_LESTAR%R~R2RRRRRR R RR (((spython\openwg_gameface.pyts@               PKi\res/gui/gameface/js/PKi\res/gui/gameface/mods/PKi\y 6$$res/gui/gameface/js/index.js// It is initial script file for all GF views // It is automatically read on the c++ side with variable substitution // As a variable template, this string format is used: <%= variable %> // If you want add new variable you need to add logic to gf_view_impl.cpp (GFViewImpl::onDomBuilt) const documentCssRules = [ ` body { overflow-wrap: <%= overflowWrap %>; } `, ]; window.__feature = '<%= __feature %>'; window.__featureId = Number('<%= __featureId %>' || 0); if (document.styleSheets.length === 0) { document.head.appendChild(document.createElement('style')); } const documentStyle = document.styleSheets[0]; documentCssRules.forEach((cssRule) => documentStyle.insertRule(cssRule, documentStyle.cssRules.length)); window.isDomBuilt = true; window.engine.on('self.onScaleUpdated', (scale) => { document.documentElement.style.fontSize = `${scale}px`; }); // ========================================================================================= // Gameface Resource Injector // ----------------------------------------------------------------------------------------- // This script is loaded into every Gameface view. Its primary responsibility is to // dynamically inject resources (CSS, JS, ES modules), provided by mods, into the // active view. // // How it works: // 1. The script listens for new subViews being added. // 2. For each subView, it checks for the presence of a `ModInjectModel`. // 3. If the model exists, the script injects all associated resources into the DOM: // - CSS files via tags. // - JS files and ES modules via