Friday, June 27, 2025
spot_img

Scorching Replace Not Reflecting New Belongings or Logic After Recreation Restart on Android – Cocos Creator


I’ve applied the Cocos Creator Scorching Replace system for my Android mission. The replace course of appears to work nice, the information are efficiently downloaded from the distant server, and I reset/restart the sport after the replace.

Nonetheless, after restarting, the sport nonetheless runs with the previous belongings and logic. The newly downloaded information don’t appear to take impact.

import { _decorator, assetManager, Part, instantiate, JsonAsset, Node, Prefab, sys, SpriteFrame, Texture2D, AudioClip, Sprite, AudioSource, native, Asset, sport, director, AssetManager, Label, ProgressBar, Button } from ‘cc’;

import { NATIVE } from ‘cc/env’;

const { ccclass, property } = _decorator;

@ccclass(‘RemoteEntryLoader’)

export class RemoteEntryLoader extends Part {
@property(Asset)
manifestUrl: Asset = null!;

@property(Label)
statusLabel: Label = null!;

@property(ProgressBar)
progressBar: ProgressBar = null!;

@property(Button)
checkUpdateBtn: Button = null!;

@property(Button)
retryBtn: Button = null!;

non-public assetsManager: any = null;
non-public storagePath: string = ‘’;
// non-public manifestUrl: string = ‘’;
non-public updating: boolean = false;

non-public canRetry: boolean = false;
non-public updateListener: any = null;

onLoad() {
// Solely initialize on native platforms
if (!NATIVE) {
this.statusLabel.string = ‘Scorching replace is just obtainable on native platforms’;
return;
}

// Setup paths - customise these on your mission
this.storagePath = ((native.fileUtils && native.fileUtils.getWritablePath) ? 
    native.fileUtils.getWritablePath() : "https://discussion board.cocosengine.org/") + 'hot-update/';

// Your distant manifest URL - exchange together with your server URL
// this.manifestUrl="https://thanisthani.github.io/CocosHotUpdate/remote-assets/mission.manifest";

this.initHotUpdate();
this.setupUI();

}

non-public initHotUpdate(): void {
if (!NATIVE) return;

attempt {

  if (NATIVE) {
    const hotUpdateRoot = native.fileUtils.getWritablePath() + 'hot-update/';
    console.log('Scorching replace listing exists:', native.fileUtils.isDirectoryExist(hotUpdateRoot));
    console.log('Manifest exists:', native.fileUtils.isFileExist(hotUpdateRoot + 'mission.manifest'));
    
    // Checklist information in sizzling replace listing
    const information = native.fileUtils.listFiles(hotUpdateRoot);
    console.log('Recordsdata in sizzling replace listing:', information);
}

     // Guarantee storage listing exists
     if (!native.fileUtils.isDirectoryExist(this.storagePath)) {
      native.fileUtils.createDirectory(this.storagePath);
  }

    // Create AssetsManager occasion
    this.assetsManager = new native.AssetsManager(this.manifestUrl.nativeUrl, this.storagePath);
    
    // Arrange search paths for warm up to date belongings
    this.setupSearchPaths();
    
    // Configure AssetsManager
    this.assetsManager.setMaxConcurrentTask(5); // Restrict concurrent downloads
    
    // Set model comparability perform (optionally available)
    this.assetsManager.setVersionCompareHandle((versionA: string, versionB: string) => {
        return this.compareVersion(versionA, versionB);
    });
    
    // Set file verification callback (optionally available however really helpful)
    this.assetsManager.setVerifyCallback((path: string, asset: any) => {
        return this.verifyAsset(path, asset);
    });
    
    // Set replace occasion listener
    this.updateListener = (occasion: any) => this.updateCallback(occasion);
    this.assetsManager.setEventCallback(this.updateListener);
    
    this.statusLabel.string = 'Scorching replace initialized';
    
} catch (error) {
    console.error('Did not initialize sizzling replace:', error);
    this.statusLabel.string = 'Did not initialize sizzling replace';
}

}

non-public setupSearchPaths(): void {
if (!NATIVE || !this.assetsManager) return;

attempt {
  if (this.assetsManager.getState() === native.AssetsManager.State.UNINITED) {
                    console.log("loadLocalManifest is named")
                    if (this.manifestUrl && this.manifestUrl.nativeUrl) {
                        this.assetsManager.loadLocalManifest(this.manifestUrl.nativeUrl);
                    }
                }
    // Get sizzling replace search paths from native manifest
    const localManifest = this.assetsManager.getLocalManifest();
    if (!localManifest || !localManifest.isLoaded()) {
      console.log("Did not load bundled manifest");
      throw new Error('Did not load bundled manifest');
      
  }

    if (localManifest && localManifest.isLoaded()) {
      console.log("localManifest is loaded");
        const hotUpdateSearchPaths = localManifest.getSearchPaths();
        const searchPaths = native.fileUtils.getSearchPaths();
        
        // Insert sizzling replace paths at the start for precedence
        Array.prototype.unshift.apply(searchPaths, hotUpdateSearchPaths);
        native.fileUtils.setSearchPaths(searchPaths);
        
        console.log('Search paths up to date:', searchPaths);
    }
} catch (error) {
    console.error('Did not setup search paths:', error);
}

}

non-public setupUI(): void {
// Setup button callbacks
if (this.checkUpdateBtn) {
this.checkUpdateBtn.node.on(‘click on’, this.checkForUpdate, this);
}

if (this.retryBtn) {
    this.retryBtn.node.on('click on', this.retry, this);
    this.retryBtn.node.energetic = false;
}

}

non-public checkForUpdate(): void

non-public retry(): void {
if (!this.canRetry) return;

this.canRetry = false;
this.retryBtn.node.energetic = false;
this.statusLabel.string = 'Retrying failed downloads...';

// Retry downloading failed belongings
this.assetsManager.downloadFailedAssets();

}

non-public updateCallback(occasion: any): void {
const eventCode = occasion.getEventCode();
console.log(“replace eventCode is”, eventCode);

change (eventCode) {
    case native.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
        this.statusLabel.string = 'No native manifest file discovered';
        this.onUpdateFinished(false);
        break;
        
    case native.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
        this.statusLabel.string = 'Did not obtain manifest';
        this.onUpdateFinished(false);
        break;
        
    case native.EventAssetsManager.ERROR_PARSE_MANIFEST:
        this.statusLabel.string = 'Did not parse manifest';
        this.onUpdateFinished(false);
        break;
        
    case native.EventAssetsManager.NEW_VERSION_FOUND:
        this.statusLabel.string = 'New model discovered, beginning obtain...';
        this.assetsManager.replace();
        break;
        
    case native.EventAssetsManager.ALREADY_UP_TO_DATE:
        this.statusLabel.string = 'Already updated';
        this.onUpdateFinished(true);
        break;
        
    case native.EventAssetsManager.UPDATE_PROGRESSION:
        this.handleUpdateProgress(occasion);
        break;
        
    case native.EventAssetsManager.ASSET_UPDATED:
        // Particular person asset up to date
        break;
        
    case native.EventAssetsManager.ERROR_UPDATING:
        this.statusLabel.string = 'Replace error: ' + occasion.getMessage();
        this.onUpdateFinished(false);
        break;
        
    case native.EventAssetsManager.UPDATE_FINISHED:
        this.statusLabel.string = 'Replace accomplished! Restart required.';
        const searchPaths = native.fileUtils.getSearchPaths();
        console.log("searchPaths is", searchPaths);
        const hotUpdatePath = this.storagePath;
        
        // Take away if exists, then add at starting
        const index = searchPaths.indexOf(hotUpdatePath);
        if (index > -1) searchPaths.splice(index, 1);
        searchPaths.unshift(hotUpdatePath);
        
        native.fileUtils.setSearchPaths(searchPaths);
        console.log("up to date searchPaths is", searchPaths);
        
        // Save restart flag
        sys.localStorage.setItem('hotUpdateReady', 'true');
        sys.localStorage.setItem('hotUpdatePath', hotUpdatePath);

        this.onUpdateFinished(true, true);
        break;
        
    case native.EventAssetsManager.UPDATE_FAILED:
        this.statusLabel.string = 'Replace failed: ' + occasion.getMessage();
        this.canRetry = true;
        this.retryBtn.node.energetic = true;
        this.onUpdateFinished(false);
        break;
        
    case native.EventAssetsManager.ERROR_DECOMPRESS:
        this.statusLabel.string = 'Decompression failed';
        this.onUpdateFinished(false);
        break;
}

}

non-public handleUpdateProgress(occasion: any): void {
const p.c = occasion.getPercent();
const filePercent = occasion.getPercentByFile();
const downloadedBytes = occasion.getDownloadedBytes();
const totalBytes = occasion.getTotalBytes();
const downloadedFiles = occasion.getDownloadedFiles();
const totalFiles = occasion.getTotalFiles();

// Replace progress bar (utilizing byte progress)
this.progressBar.progress = p.c / 100;

// Replace standing label with detailed progress
this.statusLabel.string = `Downloading... ${Math.flooring(p.c)}%n` +
    `Recordsdata: ${downloadedFiles}/${totalFiles}n` +
    `Dimension: ${this.formatBytes(downloadedBytes)}/${this.formatBytes(totalBytes)}`;

    console.log(`Downloading... ${Math.flooring(p.c)}%n` +
    `Recordsdata: ${downloadedFiles}/${totalFiles}n` +
    `Dimension: ${this.formatBytes(downloadedBytes)}/${this.formatBytes(totalBytes)}`)

}

non-public onUpdateFinished(success: boolean, needRestart: boolean = false): void {
this.updating = false;
this.checkUpdateBtn.node.energetic = true;

if (needRestart) {
    // Present restart button or robotically restart
    this.showRestartOption();
}

}

non-public showRestartOption(): void {
// You’ll be able to present a restart dialog right here
// For now, we’ll simply add a restart button performance
this.statusLabel.string = ‘Replace accomplished! Faucet to restart.’;
this.checkUpdateBtn.getComponentInChildren(Label)!.string = ‘Restart Recreation’;
this.checkUpdateBtn.node.off(‘click on’, this.checkForUpdate, this);
this.checkUpdateBtn.node.on(‘click on’, this.restartGame, this);
}

non-public restartGame(): void {
console.log(“restartGame is named”);
// Clear up earlier than restart
if (this.assetsManager) {
this.assetsManager.setEventCallback(null);
}

// Restart the sport
sport.restart();

}

non-public compareVersion(versionA: string, versionB: string): quantity {
// Customized model comparability logic
// Return > 0 if versionA > versionB
// Return 0 if versionA == versionB
// Return

const parseVersion = (model: string) =>  0);
;

const vA = parseVersion(versionA);
const vB = parseVersion(versionB);

for (let i = 0; i 

}

non-public verifyAsset(filePath: string, asset: any): boolean {
// Asset verification logic
// You’ll be able to implement MD5 examine right here if wanted
// For now, simply return true to skip verification
return true;
}

non-public formatBytes(bytes: quantity): string {
if (bytes === 0) return ‘0 B’;
const okay = 1024;
const sizes = [‘B’, ‘KB’, ‘MB’, ‘GB’];
const i = Math.flooring(Math.log(bytes) / Math.log(okay));
return parseFloat((bytes / Math.pow(okay, i)).toFixed(2)) + ’ ’ + sizes[i];
}

onDestroy(): void {
// Clear up
if (this.assetsManager && this.updateListener) {
this.assetsManager.setEventCallback(null);
}
}

}

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

- Advertisement -spot_img

Latest Articles