serverWipe

  • community
  • administration
  • by Mad
  • Takaro main
  • all
Version
View export JSON

The ServerWipe module provides administrators with a powerful tool to reset server data. It allows selective wiping of player currency, teleport locations, and waypoints with a single command.

Configuration 4

Settings you fill in when installing the module on a server.

SettingTypeDefaultDescription
wipeCurrency wipeCurrency boolean false Whether to reset all player currency during wipe
wipeTeleports wipeTeleports boolean false Whether to delete all teleport locations during wipe.
wipeStarterKitClaims wipeStarterKitClaims boolean false wipeStarterKitClaims
globalAnnouncement globalAnnouncement string "" Message to broadcast to all players after the wipe
Raw config schema
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "required": [],
  "additionalProperties": false,
  "properties": {
    "wipeCurrency": {
      "title": "wipeCurrency",
      "description": "Whether to reset all player currency during wipe",
      "default": false,
      "type": "boolean"
    },
    "wipeTeleports": {
      "title": "wipeTeleports",
      "description": "Whether to delete all teleport locations during wipe.",
      "default": false,
      "type": "boolean"
    },
    "wipeStarterKitClaims": {
      "title": "wipeStarterKitClaims",
      "description": "wipeStarterKitClaims",
      "default": false,
      "type": "boolean"
    },
    "globalAnnouncement": {
      "title": "globalAnnouncement",
      "description": "Message to broadcast to all players after the wipe",
      "default": "",
      "type": "string"
    }
  }
}
Raw UI schema
{}

Commands 2

Chat commands players trigger in game.

  • wipecontinue

    No help text available

    ArgumentTypeDefaultHelp
    type string help
    confirm boolean false help
    Command source
    // commands/wipe_continue_batch.js
    import { takaro, data, checkPermission, TakaroUserError } from '@takaro/helpers';
    
    // --- Configuration ---
    const PAGE_LIMIT = 100; // Items per fetch
    const BATCH_SIZE = 100; // Items per concurrent processing batch (Adjust lower if timeouts persist)
    const PAGES_PER_RUN = 4; // Number of pages to process per command execution (4 * 100 = 400 items)
    
    // --- State Variable Keys ---
    const STATE_KEYS = {
        currencyPage: 'wipe_cont_currency_page',
        teleportsPage: 'wipe_cont_teleports_page',
        starterKitsPage: 'wipe_cont_starterkits_page',
        teleportsModuleId: 'wipe_cont_teleports_module_id',
        waypointsModuleId: 'wipe_cont_waypoints_module_id'
    };
    
    // --- State Management Helpers ---
    async function getStateVariable(key, gameServerId, moduleId) {
        const existingVar = await takaro.variable.variableControllerSearch({
            filters: { key: [key], gameServerId: [gameServerId], moduleId: [moduleId] },
            limit: 1
        });
        if (existingVar.data.data.length > 0) {
            try { return JSON.parse(existingVar.data.data[0].value) ?? 0; }
            catch (e) { console.error(`State Error (Get: ${key}): ${e}`); return 0; }
        }
        return 0;
    }
    
    async function setStateVariable(key, value, gameServerId, moduleId) {
        const existingVar = await takaro.variable.variableControllerSearch({
            filters: { key: [key], gameServerId: [gameServerId], moduleId: [moduleId] },
            limit: 1
        });
        const valueString = JSON.stringify(value);
        if (existingVar.data.data.length > 0) {
            if (existingVar.data.data[0].value !== valueString) {
                console.log(`State Set: ${key} = ${valueString}`);
                await takaro.variable.variableControllerUpdate(existingVar.data.data[0].id, { value: valueString });
            }
        } else {
            console.log(`State Create: ${key} = ${valueString}`);
            await takaro.variable.variableControllerCreate({ key, value: valueString, gameServerId, moduleId });
        }
    }
    
    // --- Main Function ---
    async function main() {
        const { player, module: mod, gameServerId, arguments: args, pog } = data;
        const wipeType = args.type?.toLowerCase();
    
        // --- Initial Checks ---
        if (!checkPermission(pog, 'SERVER_WIPE')) throw new TakaroUserError('Permission denied.');
        if (!wipeType || !['currency', 'teleports', 'starterkits'].includes(wipeType)) throw new TakaroUserError('Specify type: currency, teleports, or starterkits.');
    
        await player.pm(`Continuing wipe (~${PAGES_PER_RUN * PAGE_LIMIT} items) for: ${wipeType}...`);
        console.log(`Wipe Continue: Starting run for ${wipeType}`);
    
        // --- Determine State Key & Function ---
        let stateKeyPage = '';
        let processingFunction = null;
        let functionArgs = []; // Arguments for the processing function, page added dynamically
    
        switch (wipeType) {
            case 'currency':
                stateKeyPage = STATE_KEYS.currencyPage;
                // Define inline processing function for currency
                processingFunction = async (page, gameServerId) => {
                    let itemsProcessed = 0, errorCount = 0, hasMore = false;
                    const pogsResponse = await takaro.playerOnGameserver.playerOnGameServerControllerSearch({
                        filters: { gameServerId: [gameServerId] }, limit: PAGE_LIMIT, page: page
                    });
                    const pogs = pogsResponse.data.data;
                    const countOnPage = pogs.length;
                    if (!pogs || countOnPage === 0) return { itemsProcessed: 0, errorCount: 0, hasMore: false };
                    hasMore = countOnPage === PAGE_LIMIT;
                    for (let i = 0; i < countOnPage; i += BATCH_SIZE) {
                        const batch = pogs.slice(i, i + BATCH_SIZE);
                        // Set to 0.01 instead of 0 to satisfy API validation
                        const results = await Promise.allSettled(batch.map(p =>
                            takaro.playerOnGameserver.playerOnGameServerControllerSetCurrency(gameServerId, p.playerId, { currency: 0.01 })
                        ));
                        results.forEach(r => {
                            if (r.status === 'fulfilled') {
                                itemsProcessed++;
                            } else {
                                errorCount++;
                                console.error(`Currency Error: ${r.reason?.message || r.reason}`);
                            }
                        });
                    }
                    return { itemsProcessed, errorCount, hasMore };
                };
                functionArgs = [gameServerId]; // Arguments excluding page
                break;
            case 'teleports':
            case 'starterkits': // Combine logic as they both use processVariablePage
                stateKeyPage = (wipeType === 'teleports') ? STATE_KEYS.teleportsPage : STATE_KEYS.starterKitsPage;
                let identifier, typeName;
                if (wipeType === 'teleports') {
                    identifier = await getStateVariable(STATE_KEYS.teleportsModuleId, gameServerId, mod.moduleId);
                    typeName = 'Teleport';
                    if (!identifier) throw new TakaroUserError(`Cannot continue ${wipeType}: Module ID not found in state.`);
                    // TODO: Handle Waypoints logic here if needed
                } else { // starterkits
                    identifier = 'var_key_t_starterkit_lock';
                    typeName = 'Starter Kit';
                }
                // Define inline processing function for variables
                processingFunction = async (page, gameServerId, moduleId, varKeyOrModId, typeNameArg) => {
                    let itemsProcessed = 0, errorCount = 0, hasMore = false;
                    const filters = { gameServerId: [gameServerId] };
                    if (varKeyOrModId.startsWith('var_key_')) {
                        filters.key = [varKeyOrModId.substring(8)];
                        filters.moduleId = [moduleId];
                    } else {
                        filters.moduleId = [varKeyOrModId];
                    }
                    const varsResponse = await takaro.variable.variableControllerSearch({ filters, limit: PAGE_LIMIT, page });
                    const variables = varsResponse.data.data;
                    const countOnPage = variables.length;
                    if (!variables || countOnPage === 0) return { itemsProcessed: 0, errorCount: 0, hasMore: false };
                    hasMore = countOnPage === PAGE_LIMIT;
                    for (let i = 0; i < countOnPage; i += BATCH_SIZE) {
                        const batch = variables.slice(i, i + BATCH_SIZE);
                        const results = await Promise.allSettled(batch.map(v =>
                            takaro.variable.variableControllerDelete(v.id)
                        ));
                        results.forEach(r => {
                            if (r.status === 'fulfilled') {
                                itemsProcessed++;
                            } else {
                                errorCount++;
                                console.error(`${typeNameArg} Delete Error: ${r.reason?.message || r.reason}`);
                            }
                        });
                    }
                    return { itemsProcessed, errorCount, hasMore };
                };
                functionArgs = [gameServerId, mod.moduleId, identifier, typeName]; // Arguments excluding page
                break;
            default:
                throw new TakaroUserError(`Internal error: Unhandled wipe type "${wipeType}"`);
        }
    
        // --- Process Continuation Batches ---
        let itemsProcessedThisRun = 0;
        let errorsThisRun = 0;
        let continueProcessing = true;
        let pagesProcessedThisRun = 0;
    
        try {
            for (let i = 0; i < PAGES_PER_RUN; i++) {
                const currentPage = await getStateVariable(stateKeyPage, gameServerId, mod.moduleId);
    
                if (currentPage === 0) {
                    console.log(`Wipe Continue (${wipeType}): Page is 0, indicating completion.`);
                    continueProcessing = false;
                    break;
                }
    
                console.log(`Wipe Continue (${wipeType}): Attempting page ${currentPage}`);
                await player.pm(`Attempting page ${currentPage + 1} for ${wipeType}...`);
                let pageResult = { itemsProcessed: 0, errorCount: 0, hasMore: false };
    
                try {
                    // Call the processing function with current page prepended to args
                    pageResult = await processingFunction(currentPage, ...functionArgs);
                    pagesProcessedThisRun++;
                } catch (pageError) {
                    console.error(`Wipe Continue (${wipeType}): Error processing page ${currentPage}: ${pageError}`);
                    await player.pm(`Error during ${wipeType} wipe on page ${currentPage + 1}. Use continue command again to retry.`);
                    continueProcessing = true;
                    break;
                }
    
                itemsProcessedThisRun += pageResult.itemsProcessed;
                errorsThisRun += pageResult.errorCount;
                continueProcessing = pageResult.hasMore;
    
                if (!continueProcessing) {
                    console.log(`Wipe Continue (${wipeType}): Reached end at page ${currentPage}.`);
                    await setStateVariable(stateKeyPage, 0, gameServerId, mod.moduleId);
                    break;
                } else {
                    await setStateVariable(stateKeyPage, currentPage + 1, gameServerId, mod.moduleId);
                }
            } // End page loop
    
            // --- Report Results ---
            let summaryMsg = `Continuation batch for ${wipeType} finished.\nProcessed ${itemsProcessedThisRun} items across ${pagesProcessedThisRun} pages this run with ${errorsThisRun} errors.`;
    
            if (continueProcessing) {
                const nextPage = await getStateVariable(stateKeyPage, gameServerId, mod.moduleId);
                summaryMsg += `\nMore items remain. Next page to process: ${nextPage}. Run the command again.`;
            } else {
                summaryMsg += `\nAll items for ${wipeType} complete. Page counter reset.`;
                const currencyPg = await getStateVariable(STATE_KEYS.currencyPage, gameServerId, mod.moduleId);
                const teleportsPg = await getStateVariable(STATE_KEYS.teleportsPage, gameServerId, mod.moduleId);
                const starterKitsPg = await getStateVariable(STATE_KEYS.starterKitsPage, gameServerId, mod.moduleId);
                if (currencyPg === 0 && teleportsPg === 0 && starterKitsPg === 0) {
                    summaryMsg += "\n\nAll wipe tasks appear complete!";
                    if (mod.userConfig.globalAnnouncement?.length > 0) {
                        try {
                            await takaro.gameserver.gameServerControllerSendMessage(gameServerId, { message: mod.userConfig.globalAnnouncement });
                        } catch (error) {
                            console.error(`Announcement Error: ${error}`);
                            await player.pm("Error sending final announcement.");
                        }
                    }
                }
            }
            await player.pm(summaryMsg);
    
        } catch (error) {
            console.error(`Wipe Continue: Error during setup or loop for ${wipeType}: ${error.stack || error.message}`);
            throw new TakaroUserError(`Failed processing continuation batch for ${wipeType}: ${error.message}`);
        }
        console.log(`Wipe Continue: Finished run for type: ${wipeType}`);
    
        return { success: true };
    }
    
    await main();
  • wipe

    Wipe server data according to configuration

    ArgumentTypeDefaultHelp
    confirm boolean false Confirm wipe operation (must be true to execute)
    target string all What to wipe: all, currency, teleports, waypoints, or starterkits
    Command source
    // commands/wipe_start_batch.js
    import { takaro, data, checkPermission, TakaroUserError } from '@takaro/helpers';
    
    // --- Configuration ---
    const PAGE_LIMIT = 100; // Items per fetch
    const BATCH_SIZE = 100; // Items per concurrent processing batch (Adjust lower if timeouts persist)
    const PAGES_PER_RUN = 4; // Number of pages to process per command execution (4 * 100 = 400 items)
    
    // --- State Variable Keys ---
    const STATE_KEYS = {
        currencyPage: 'wipe_cont_currency_page',
        teleportsPage: 'wipe_cont_teleports_page',
        starterKitsPage: 'wipe_cont_starterkits_page',
        teleportsModuleId: 'wipe_cont_teleports_module_id',
        waypointsModuleId: 'wipe_cont_waypoints_module_id'
    };
    
    // --- State Management Helpers ---
    async function getStateVariable(key, gameServerId, moduleId) {
        const existingVar = await takaro.variable.variableControllerSearch({
            filters: { key: [key], gameServerId: [gameServerId], moduleId: [moduleId] },
            limit: 1
        });
        if (existingVar.data.data.length > 0) {
            try { return JSON.parse(existingVar.data.data[0].value) ?? 0; }
            catch (e) { console.error(`State Error (Get: ${key}): ${e}`); return 0; }
        }
        return 0;
    }
    
    async function setStateVariable(key, value, gameServerId, moduleId) {
        const existingVar = await takaro.variable.variableControllerSearch({
            filters: { key: [key], gameServerId: [gameServerId], moduleId: [moduleId] },
            limit: 1
        });
        const valueString = JSON.stringify(value);
        if (existingVar.data.data.length > 0) {
            if (existingVar.data.data[0].value !== valueString) {
                console.log(`State Set: ${key} = ${valueString}`);
                await takaro.variable.variableControllerUpdate(existingVar.data.data[0].id, { value: valueString });
            }
        } else {
            console.log(`State Create: ${key} = ${valueString}`);
            await takaro.variable.variableControllerCreate({ key, value: valueString, gameServerId, moduleId });
        }
    }
    
    // --- Currency wipe helper function ---
    async function wipeCurrency(gameServerId, playerId, currentCurrency) {
        try {
            if (currentCurrency > 0) {
                await takaro.playerOnGameserver.playerOnGameServerControllerDeductCurrency(gameServerId, playerId, { currency: currentCurrency });
            }
            await takaro.playerOnGameserver.playerOnGameServerControllerAddCurrency(gameServerId, playerId, { currency: 0.01 });
            return { success: true };
        } catch (error) {
            console.error(`Currency wipe failed for player ${playerId}: ${error.message}`);
            return { success: false, error };
        }
    }
    
    // --- Main Function ---
    async function main() {
        const { player, module: mod, gameServerId, arguments: args, pog } = data;
        const wipeType = args.target?.toLowerCase();
        const wipeAll = wipeType === 'all';
    
        // --- Initial Checks ---
        if (!checkPermission(pog, 'SERVER_WIPE')) throw new TakaroUserError('Permission denied.');
        if (!args.confirm || args.confirm.toString().toLowerCase() !== 'true') throw new TakaroUserError('Please confirm with `true`. Usage: /wipe {type|all} true');
        if (!wipeType) throw new TakaroUserError('Specify target: all, currency, teleports, or starterkits.');
    
        await player.pm(`Starting initial wipe batch (~${PAGES_PER_RUN * PAGE_LIMIT} items) for: ${wipeType}...`);
    
        // --- Reset State & Find Module IDs ---
        console.log('Wipe Start: Resetting state variables...');
        await setStateVariable(STATE_KEYS.currencyPage, 0, gameServerId, mod.moduleId);
        await setStateVariable(STATE_KEYS.teleportsPage, 0, gameServerId, mod.moduleId);
        await setStateVariable(STATE_KEYS.starterKitsPage, 0, gameServerId, mod.moduleId);
    
        const teleportsModule = await takaro.module.moduleControllerSearch({ filters: { name: ['teleports'] } });
        const teleportsModuleId = teleportsModule.data.data.length > 0 ? teleportsModule.data.data[0].id : null;
        await setStateVariable(STATE_KEYS.teleportsModuleId, teleportsModuleId, gameServerId, mod.moduleId);
    
        const waypointsModule = await takaro.module.moduleControllerSearch({ filters: { name: ['Waypoints'] } });
        const waypointsModuleId = waypointsModule.data.data.length > 0 ? waypointsModule.data.data[0].id : null;
        await setStateVariable(STATE_KEYS.waypointsModuleId, waypointsModuleId, gameServerId, mod.moduleId);
        console.log('Wipe Start: State reset complete.');
    
        // --- Determine Types ---
        const typesToProcess = [];
        if (wipeAll || wipeType === 'currency') typesToProcess.push('currency');
        if (wipeAll || wipeType === 'teleports') typesToProcess.push('teleports');
        if (wipeAll || wipeType === 'starterkits') typesToProcess.push('starterkits');
    
        let overallHasMore = false;
    
        // --- Process Each Type ---
        for (const currentType of typesToProcess) {
            await player.pm(`Processing initial ${PAGES_PER_RUN} pages for ${currentType}...`);
            console.log(`Wipe Start: Processing type ${currentType}`);
    
            let currentPageForType = 0;
            let itemsProcessedThisType = 0;
            let errorsThisType = 0;
            let typeHasMore = false;
            let pagesProcessedThisTypeRun = 0;
    
            for (let pageIndex = 0; pageIndex < PAGES_PER_RUN; pageIndex++) {
                currentPageForType = await getStateVariable(STATE_KEYS[`${currentType}Page`], gameServerId, mod.moduleId);
    
                if (currentPageForType === 0 && pageIndex > 0) {
                    typeHasMore = false;
                    break;
                }
    
                console.log(`Wipe Start (${currentType}): Attempting page ${currentPageForType}`);
                let pageResult = { itemsProcessed: 0, errorCount: 0, hasMore: false };
    
                try {
                    // *** Page Processing Logic ***
                    if (currentType === 'currency') {
                        const pogsResponse = await takaro.playerOnGameserver.playerOnGameServerControllerSearch({
                            filters: { gameServerId: [gameServerId] }, limit: PAGE_LIMIT, page: currentPageForType
                        });
                        const pogs = pogsResponse.data.data;
                        const countOnPage = pogs.length;
                        if (!pogs || countOnPage === 0) {
                            pageResult.hasMore = false;
                        } else {
                            pageResult.hasMore = countOnPage === PAGE_LIMIT;
                            for (let i = 0; i < countOnPage; i += BATCH_SIZE) {
                                const batch = pogs.slice(i, i + BATCH_SIZE);
                                const results = await Promise.allSettled(batch.map(p => wipeCurrency(gameServerId, p.playerId, p.currency)));
                                results.forEach(r => {
                                    if (r.status === 'fulfilled' && r.value.success) {
                                        pageResult.itemsProcessed++;
                                    } else {
                                        pageResult.errorCount++;
                                        console.error(`Currency Error: ${r.reason?.message || r.value?.error?.message || r.reason}`);
                                    }
                                });
                            }
                        }
                    } else if (currentType === 'teleports') {
                        const tpModuleId = await getStateVariable(STATE_KEYS.teleportsModuleId, gameServerId, mod.moduleId);
                        if (!tpModuleId) { await player.pm('Skipping teleports: Module ID not found.'); break; }
                        const varsResponse = await takaro.variable.variableControllerSearch({
                            filters: { gameServerId: [gameServerId], moduleId: [tpModuleId] }, limit: PAGE_LIMIT, page: currentPageForType
                        });
                        const variables = varsResponse.data.data;
                        const countOnPage = variables.length;
                        if (!variables || countOnPage === 0) {
                            pageResult.hasMore = false;
                        } else {
                            pageResult.hasMore = countOnPage === PAGE_LIMIT;
                            for (let i = 0; i < countOnPage; i += BATCH_SIZE) {
                                const batch = variables.slice(i, i + BATCH_SIZE);
                                const results = await Promise.allSettled(batch.map(v =>
                                    takaro.variable.variableControllerDelete(v.id)
                                ));
                                results.forEach(r => {
                                    if (r.status === 'fulfilled') {
                                        pageResult.itemsProcessed++;
                                    } else {
                                        pageResult.errorCount++;
                                        console.error(`Teleports Error: ${r.reason?.message || r.reason}`);
                                    }
                                });
                            }
                        }
                    } else if (currentType === 'starterkits') {
                        const varsResponse = await takaro.variable.variableControllerSearch({
                            filters: { gameServerId: [gameServerId], key: ['t_starterkit_lock'], moduleId: [mod.moduleId] },
                            limit: PAGE_LIMIT, page: currentPageForType
                        });
                        const variables = varsResponse.data.data;
                        const countOnPage = variables.length;
                        if (!variables || countOnPage === 0) {
                            pageResult.hasMore = false;
                        } else {
                            pageResult.hasMore = countOnPage === PAGE_LIMIT;
                            for (let i = 0; i < countOnPage; i += BATCH_SIZE) {
                                const batch = variables.slice(i, i + BATCH_SIZE);
                                const results = await Promise.allSettled(batch.map(v =>
                                    takaro.variable.variableControllerDelete(v.id)
                                ));
                                results.forEach(r => {
                                    if (r.status === 'fulfilled') {
                                        pageResult.itemsProcessed++;
                                    } else {
                                        pageResult.errorCount++;
                                        console.error(`Starter Kits Error: ${r.reason?.message || r.reason}`);
                                    }
                                });
                            }
                        }
                    }
    
                    itemsProcessedThisType += pageResult.itemsProcessed;
                    errorsThisType += pageResult.errorCount;
                    typeHasMore = pageResult.hasMore;
                    pagesProcessedThisTypeRun++;
    
                    if (!typeHasMore) {
                        console.log(`Wipe Start (${currentType}): Reached end at page ${currentPageForType}`);
                        await setStateVariable(STATE_KEYS[`${currentType}Page`], 0, gameServerId, mod.moduleId);
                        break;
                    } else {
                        await setStateVariable(STATE_KEYS[`${currentType}Page`], currentPageForType + 1, gameServerId, mod.moduleId);
                    }
    
                } catch (error) {
                    console.error(`Wipe Start (${currentType}): Error processing page ${currentPageForType}: ${error}`);
                    await player.pm(`Error during ${currentType} wipe on page ${currentPageForType + 1}. Use continue command to retry.`);
                    await setStateVariable(STATE_KEYS[`${currentType}Page`], currentPageForType, gameServerId, mod.moduleId);
                    typeHasMore = true;
                    break;
                }
            } // End page loop (PAGES_PER_RUN)
    
            await player.pm(`Initial batch for ${currentType}: Processed ${itemsProcessedThisType} items across ${pagesProcessedThisTypeRun} pages with ${errorsThisType} errors.`);
            if (typeHasMore) {
                await player.pm(`More ${currentType} items remain. Use /wipecontinue ${currentType}`);
                overallHasMore = true;
            } else {
                await player.pm(`${currentType} wipe completed.`);
            }
        } // End loop over types
    
        // --- Final Message & Announcement ---
        if (!overallHasMore) {
            await player.pm("Initial wipe batch finished, and all targeted items completed.");
            if (wipeAll && mod.userConfig.globalAnnouncement?.length > 0) {
                try {
                    await takaro.gameserver.gameServerControllerSendMessage(gameServerId, { message: mod.userConfig.globalAnnouncement });
                } catch (error) {
                    console.error(`Announcement Error: ${error}`);
                    await player.pm("Error sending final announcement.");
                }
            }
        } else {
            await player.pm("Initial wipe batch finished. Use /wipecontinue {type} for remaining items.");
        }
        console.log('Wipe Start: Finished.');
    
        return { success: true };
    }
    
    await main();

Functions 1

Shared helpers the module's commands, hooks and cron jobs import.

  • wipeHelpers.js

    Function source
    // functions/wipeHelpers.js
    import { takaro } from '@takaro/helpers';
    
    export const PAGE_LIMIT = 100; // How many items to FETCH per page
    export const BATCH_SIZE = 100; // How many items to PROCESS concurrently within a page (Adjust if needed)
    
    // --- State Variable Keys ---
    export const STATE_KEYS = {
        currencyPage: 'wipe_cont_currency_page',
        teleportsPage: 'wipe_cont_teleports_page',
        starterKitsPage: 'wipe_cont_starterkits_page',
        // We also need to store the module IDs found by the start command
        teleportsModuleId: 'wipe_cont_teleports_module_id',
        waypointsModuleId: 'wipe_cont_waypoints_module_id'
    };
    
    // --- Get/Set State ---
    export async function getStateVariable(key, gameServerId, moduleId) {
        const existingVar = await takaro.variable.variableControllerSearch({
            filters: { key: [key], gameServerId: [gameServerId], moduleId: [moduleId] },
            limit: 1
        });
        if (existingVar.data.data.length > 0) {
            try {
                const parsed = JSON.parse(existingVar.data.data[0].value);
                return parsed ?? 0; // Default to 0 if null/undefined after parsing
            } catch (e) {
                console.error(`Wipe Helpers: Error parsing state variable ${key}: ${e}. Defaulting to 0.`);
                return 0;
            }
        }
        console.log(`Wipe Helpers: State variable ${key} not found, defaulting to 0.`);
        return 0; // Default to 0 if variable doesn't exist
    }
    
    export async function setStateVariable(key, value, gameServerId, moduleId) {
        const existingVar = await takaro.variable.variableControllerSearch({
            filters: { key: [key], gameServerId: [gameServerId], moduleId: [moduleId] },
            limit: 1
        });
        const valueString = JSON.stringify(value);
        if (existingVar.data.data.length > 0) {
            if (existingVar.data.data[0].value !== valueString) {
                console.log(`Wipe Helpers: Updating state variable ${key} to ${valueString}`);
                await takaro.variable.variableControllerUpdate(existingVar.data.data[0].id, { value: valueString });
            }
        } else {
            console.log(`Wipe Helpers: Creating state variable ${key} with value ${valueString}`);
            await takaro.variable.variableControllerCreate({
                key: key, value: valueString, gameServerId, moduleId
            });
        }
    }
    
    // --- Process One Page of Currency ---
    export async function processCurrencyPage(page, gameServerId) {
        let itemsProcessed = 0;
        let errorCount = 0;
        let hasMore = false;
    
        console.log(`Wipe Helpers: Processing currency page ${page}`);
    
        const pogsResponse = await takaro.playerOnGameserver.playerOnGameServerControllerSearch({
            filters: { gameServerId: [gameServerId] },
            limit: PAGE_LIMIT,
            page: page
        });
    
        const pogs = pogsResponse.data.data;
        const countOnPage = pogs.length;
        console.log(`Wipe Helpers: Currency page ${page} fetched ${countOnPage} items.`);
    
        if (!pogs || countOnPage === 0) {
            console.log(`Wipe Helpers: Currency page ${page} - No items found.`);
            return { itemsProcessed: 0, errorCount: 0, hasMore: false };
        }
    
        hasMore = countOnPage === PAGE_LIMIT;
    
        for (let i = 0; i < countOnPage; i += BATCH_SIZE) {
            const batch = pogs.slice(i, i + BATCH_SIZE);
            // console.log(`Wipe Helpers: Currency page ${page}, processing batch index ${i} (size ${batch.length})`); // Optional detailed log
            const results = await Promise.allSettled(
                batch.map(pogEntry =>
                    takaro.playerOnGameserver.playerOnGameServerControllerSetCurrency(
                        gameServerId, pogEntry.playerId, { currency: 0.01 }  // Changed from 0 to 0.01
                    )
                )
            );
            results.forEach(result => {
                if (result.status === 'fulfilled') {
                    itemsProcessed++;
                } else {
                    errorCount++;
                    console.error(`Currency Error: ${result.reason?.message || result.reason}`);
                }
            });
        }
        console.log(`Wipe Helpers: Currency page ${page} finished. Processed: ${itemsProcessed}, Errors: ${errorCount}, HasMore: ${hasMore}`);
        return { itemsProcessed, errorCount, hasMore };
    }
    
    // --- Process One Page of Variables ---
    export async function processVariablePage(page, gameServerId, moduleId, variableKeyOrModuleId, typeName) {
        let itemsProcessed = 0;
        let errorCount = 0;
        let hasMore = false;
    
        console.log(`Wipe Helpers: Processing ${typeName} variable page ${page}`);
    
        const filters = { gameServerId: [gameServerId] };
        if (variableKeyOrModuleId.startsWith('var_key_')) {
            filters.key = [variableKeyOrModuleId.substring(8)];
            filters.moduleId = [moduleId]; // Scope to this module when searching by key
        } else if (variableKeyOrModuleId) { // Check if module ID is provided and not null/empty
            filters.moduleId = [variableKeyOrModuleId]; // Use specific module ID
        } else {
            console.error(`Wipe Helpers: Invalid variableKeyOrModuleId for ${typeName}`);
            return { itemsProcessed: 0, errorCount: 0, hasMore: false }; // Cannot process without key/moduleID
        }
    
        const varsResponse = await takaro.variable.variableControllerSearch({
            filters: filters, limit: PAGE_LIMIT, page: page
        });
        const variables = varsResponse.data.data;
        const countOnPage = variables.length;
        console.log(`Wipe Helpers: ${typeName} page ${page} fetched ${countOnPage} items.`);
    
        if (!variables || countOnPage === 0) {
            console.log(`Wipe Helpers: ${typeName} page ${page} - No items found.`);
            return { itemsProcessed: 0, errorCount: 0, hasMore: false };
        }
    
        hasMore = countOnPage === PAGE_LIMIT;
    
        for (let i = 0; i < countOnPage; i += BATCH_SIZE) {
            const batch = variables.slice(i, i + BATCH_SIZE);
            // console.log(`Wipe Helpers: ${typeName} page ${page}, processing batch index ${i} (size ${batch.length})`); // Optional detailed log
            const results = await Promise.allSettled(
                batch.map(variable =>
                    takaro.variable.variableControllerDelete(variable.id)
                )
            );
            results.forEach(result => {
                if (result.status === 'fulfilled') {
                    itemsProcessed++;
                } else {
                    errorCount++;
                    console.error(`${typeName} Delete Error: ${result.reason?.message || result.reason}`);
                }
            });
        }
        console.log(`Wipe Helpers: ${typeName} page ${page} finished. Processed: ${itemsProcessed}, Errors: ${errorCount}, HasMore: ${hasMore}`);
        return { itemsProcessed, errorCount, hasMore };
    }

Permissions 1

Roles you can grant to decide who may use what.

  • SERVER_WIPE

    Permission to wipe server