Skip to content
1381 words 7 min read

Data Migration ​

Data migration refers to the process of migrating data from one system or database to another system or database. Data migration is an important part of data management and can be used in scenarios such as data backup, data recovery, data integration, and data migration.
Here, data migration refers to migrating the specified lower-version data in LOICollectionA to the corresponding higher version of LOICollectionA.

WARNING

Before data migration, please make sure Python 3.10.0 or above is properly installed and the server is configured

For upgrading from version 1.4.6 to version 1.4.7 ​

  1. Download the migrate147.py file and place it in the plugin root directory
  2. After that, run python migrate147.py in the command line to complete the migration
  3. After the migration is complete, the new settings.db file will contain all the migrated data

For upgrading from version 1.6.1 to version 1.6.2 ​

  1. Download the migrate162.py file and place it in the plugin root directory
  2. After that, run python migrate162.py in the command line to complete the migration
  3. After the migration is complete, the new settings.db file will contain all the migrated data

For upgrading from version 1.6.5 to version 1.7.0 ​

  1. Download the migrate170.py file and place it in the plugin root directory
  2. After that, run python migrate170.py in the command line to complete the migration
  3. After the migration is complete, all module data will be migrated

For upgrading from version 1.9.2 to version 1.10.0 ​

  1. Download the migrate1100.py file and place it in the plugin root directory
  2. After that, run python migrate1100.py in the command line to complete the migration
  3. After the migration is complete, all module data will be migrated

For upgrading from version 1.14.0 to version 1.15.0 ​

WARNING

1.15.0 no longer provides automatic migration scripts. The interface data of Menu and Shop needs to be migrated manually.

  1. Before upgrading, please back up config.json, menu.json, and shop.json in the plugins/LOICollectionA/config directory.
  2. After the upgrade, Menu and Shop no longer read menu.json / shop.json. Please refer to the examples in Data Files to manually rewrite the old data as menu.lcui and shop.lcui, and place them in the plugins/LOICollectionA/config directory. The examples already declare their variables with let; if you wrote the scripts from older examples, add let before upgrading to 1.17.0 — see below.
  3. If you have customized GuiPath, please confirm that ServerConfig.Plugins.Menu.GuiPath and ServerConfig.Plugins.Shop.GuiPath in config.json point to the newly created lcui files (defaulting to menu.lcui and shop.lcui respectively).
  4. The data files of other modules (such as notice.json and cdk.json) and database files are not affected; the interfaces of other modules are now loaded from the plugin's built-in gui directory and do not need migration.

For upgrading from version 1.15.1 to version 1.16.0 ​

WARNING

1.16.0 introduces a script sandbox and authorization mechanism. Earlier versions had no permission.json, and scripts could freely run mc::runCmd, read and write GUI data, and navigate to other scripts. After upgrading these calls are denied by default, so scripts you wrote (such as menu.lcui / shop.lcui) must be granted authorization to keep working.

  1. permission.json is a new file in 1.16.0, located in plugins/LOICollectionA/gui/, with a deny-by-default policy (defaultPolicy: "deny"). It governs mc::runCmd, GUIManager::value/request/callback, and cross-script navigation via GUIManager::open. Authorization for built-in scripts (blacklist, wallet, etc.) ships with the plugin and needs no action.

  2. If your menu.lcui / shop.lcui invokes any of the above, fill in the allowlists under scripts.menu / scripts.shop based on what the script actually calls: commands go in commands.templates (with commands.allow set to true), data ids go in gui.values / gui.requests / gui.callbacks.

  3. If the script contains cross-script navigation such as GUIManager::open("<other script id>", ...), also declare the target in gui.navigations, for example:

    json
    "menu": {
        "enabled": true,
        "commands": { "allow": true, "templates": [] },
        "gui": {
            "values": [],
            "requests": [],
            "callbacks": [],
            "navigations": ["wallet", "market"]
        }
    }
  4. Opening a script's own form (GUIManager::open("wallet", ...) inside wallet) is unaffected and needs no grant.

  5. 1.16.0 also introduces a bytecode cache: compiled scripts are stored next to the source as .lcp and reused on later starts to skip compilation. The plugin generates and invalidates it automatically; deleting one only causes a recompile on the next start and does not affect correctness.

  6. If the log shows is not allowed for script after upgrading, a capability is missing its grant — add the script id from the message to the matching allowlist.

For upgrading from version 1.16.0 to version 1.17.0 ​

WARNING

1.17.0 replaces the data layer with block storage (BlockRepository + TypedTable, see Architecture Overview). The plugin does not replay old data automatically at start-up: tables written by older versions are no longer read, so you must either run the migration script by hand or re-enter the data yourself.

  1. Back up the whole plugins/LOICollectionA/data directory (and config, gui) before upgrading.

  2. Download scripts/migrate/migrate_block.py and put it in the plugin root directory (the parent of plugins/LOICollectionA/, where the script looks for the database files by default).

  3. Run a dry run first to confirm which tables and how many rows will be migrated:

    bash
    python migrate_block.py --data-dir plugins/LOICollectionA/data --dry-run
  4. Once the output looks right, drop --dry-run to perform the migration for real:

    bash
    python migrate_block.py --data-dir plugins/LOICollectionA/data
  5. The script rewrites the legacy SQLiteStorage key/value tables in place into the block model's block / prop / link / meta structure, routing by file: tables in blacklist.db, mute.db, tpa.db, chat.db and market.db are migrated inside their own file, while tables registered against the shared SettingsDB service (Market, MarketTax, Language, Pvp, Chat, Tpa, Wallet, and their siblings) are migrated inside settings.db. Every domain column is preserved; the col_<rootId> side table and the schema: / sidecol: fingerprints are rebuilt by the plugin the first time it opens the database.

  6. Two legacy tables are intentionally not migrated: Notice (the current build stores notices as JSON, not SQLite) and Language inside statistics.db (the current code only reads the Language table in settings.db, which is the authoritative copy). Both are left untouched on disk.

  7. If you prefer not to use the script, you can migrate manually instead: on the first start after upgrading, the plugin creates the block-model system tables (dict / block / prop / link / meta) in every .db file and then runs on empty data.

  8. Without a migration your old data is still not deleted — it stays in the legacy tables of each database file (tables named after the feature, such as Wallet, Blacklist, Market). To keep it, export those tables with a SQLite tool and re-enter the data through the in-game UI or commands.

  9. notice.json, cdk.json and config.json remain plain JSON files and are unaffected — no migration needed.

  10. Scripts you wrote yourself (config/menu.lcui, config/shop.lcui, and any script you edited under gui) are usually copies of older examples and therefore use keyword-less bare assignments. Every variable binding must be declared with let; a bare assignment no longer creates a variable, so such a script fails to load with Variable 'xxx' is not declared; write 'let xxx = ...' to introduce it and is not enabled (the start-up log shows it at ERROR [LOICollectionA] level). Add let to the first assignment of every variable:

    lcui
    // before the upgrade
    button1 = new MenuItemData();
    form = new MenuForm("main", "Menu Example");
    
    // after the upgrade
    let button1 = new MenuItemData();
    let form = new MenuForm("main", "Menu Example");

    Only the first binding needs let: later re-assignments (button1.permission = 0;), member writes (form.button(...)) and index writes stay as they are; a typed declaration is written let x: int = 0; and must provide an initial value. There is no need to delete the .lcp cache by hand after editing a script — the plugin invalidates it from the source content and recompiles. See entries 59 and 60 of Error Handling for this class of error.

TIP

If the history does not matter, you can delete the .db files under plugins/LOICollectionA/data and let the plugin rebuild empty databases — back them up first.

LOICollectionA · A ready-to-use multifunctional plugin set for LeviLamina