In aggiunta all'accesso agli archivi di dati tramite l'API Engine in Studio o nei giochi dal vivo (DataStoreService), puoi utilizzare le API Open Cloud per accedere agli archivi standard e agli archivi di dati ordinati da script esterni e altri strumenti.
L'accesso Open Cloud ai tuoi archivi di dati sblocca molti potenziali casi d'uso, tra cui:
- Un portale di supporto clienti che consente al tuo team di gestire direttamente le richieste di assistenza, come modificare le invenzioni degli utenti o emettere rimborsi
- Classifiche globali che puoi visualizzare su un sito web esterno
- Aggiornamenti dello schema con script che leggono le voci dall'archivio di dati corrente, le mappano al nuovo schema e scrivono le voci in un nuovo archivio di dati
Gli esempi in questa pagina dimostrano come costruire un portale di supporto per l'inventario degli utenti e una classifica esterna con Node.js e Python, ma usa qualunque linguaggio preferisci; le API Open Cloud supportano qualsiasi linguaggio di programmazione in grado di inviare una richiesta HTTP.
Differenze dall'API Engine
Sebbene le API Open Cloud accedano agli stessi archivi di dati sottostanti e siano simili a quelle in DataStoreService, ci sono alcune differenze chiave:
ID Universo: A differenza dell'API Engine, le API Open Cloud sono senza stato e possono provenire da qualsiasi luogo, quindi devi sempre fornire l'ID universo, l'identificatore univoco del tuo gioco.
Permessi separati per creare e aggiornare: L'API Engine crea nuove voci se non esistono quando chiami DataStore:SetAsync(), ma i metodi Open Cloud per creare e aggiornare voci sono separati. Permessi separati possono essere più sicuri e flessibili in certe situazioni. Ad esempio, potresti voler limitare il tuo strumento di supporto clienti a modificare solo il profilo di un utente esistente, senza crearne uno nuovo.
Serializzazione dei dati: Tutti gli endpoint Open Cloud richiedono di serializzare i dati prima di inviarli. La serializzazione significa convertire un oggetto in una stringa. La deserializzazione è l'opposto, convertire una stringa in un oggetto. L'API Engine serializza e deserializza automaticamente il contenuto delle voci, ma per Open Cloud devi generare o analizzare la tua voce in JSON da solo.
Permessi
Gli archivi di dati spesso memorizzano informazioni sensibili, come profili utente e valuta virtuale. Per mantenere la sicurezza, ogni metodo Open Cloud ha permessi corrispondenti, chiamati scopi, che devi aggiungere alla tua chiave API, come lo scopo universe-datastores.control:list per il metodo Elenca Archivi di Dati. Se non aggiungi i permessi richiesti, la tua chiamata API restituirà un errore. Consulta la documentazione di riferimento per gli scopi richiesti per ogni endpoint.
Per ulteriori informazioni sulla gestione dei permessi, consulta Gestisci chiavi API.
Portale di supporto per l'inventario degli utenti
Questo esempio utilizza un archivio di dati chiamato Inventory e uno schema per ciascuna voce di "userId": {"currency": number, "weapon": string, "level": number}. La chiave è userId.
Scopi richiesti
Quando crei una chiave API per questo esempio, aggiungi i seguenti scopi alla tua chiave:
- universe-datastores.objects:list
- universe-datastores.objects:read
- universe-datastores.objects:update
Facoltativamente, aggiungi i permessi solo per l'archivio di dati Inventory, imposta una restrizione per indirizzo IP e imposta una data di scadenza.
Aggiungi script per il portale di supporto per l'inventario degli utenti
Dopo aver creato la chiave API con i permessi richiesti per l'app di esempio, puoi creare uno script per effettuare richieste agli endpoint. Questi script ottengono le prime 10 voci nell'archivio di dati, incrementano il valore currency per ciascuna di esse di 10 e poi aggiornano ciascuna voce. Per un archivio di dati più grande, dovresti occuparti della paginazione utilizzando i parametri di query maxPageSize e pageToken.
incrementCurrency.js
const apiKey = process.env.API_KEY;
if (!apiKey) {
throw new Error('La variabile di ambiente API_KEY non è impostata.');
}
const apiHeaderKey = 'x-api-key';
const universeId = '';
const dataStoreId = 'Inventory';
const baseUrl = 'https://apis.roblox.com/cloud/v2/';
async function listEntries(universe, dataStore) {
const listPath = `universes/${universe}/data-stores/${dataStore}/entries`;
const url = baseUrl + listPath;
const response = await fetch(url, {
headers: { [apiHeaderKey]: apiKey }
});
return response.json();
}
async function getEntry(path) {
const url = baseUrl + path;
const response = await fetch(url, {
headers: { [apiHeaderKey]: apiKey }
});
return response.json();
}
async function updateEntry(path, payload) {
const url = baseUrl + path;
const response = await fetch(url, {
method: 'PATCH',
headers: {
[apiHeaderKey]: apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify(payload) // Il corpo deve essere una stringa
});
return response;
}
(async () => {
try {
const entries = await listEntries(universeId, dataStoreId);
for (const entry of entries.dataStoreEntries) {
const path = entry.path;
console.log(`\nElaborazione voce: ${path}`);
const currentData = await getEntry(path);
currentData.value.currency += 10;
const payload = { value: currentData.value };
const updateResponse = await updateEntry(path, payload);
console.log(`Stato: ${updateResponse.status}`);
console.log(`Risposta: ${await updateResponse.text()}`);
}
} catch (error) {
console.error('Si è verificato un errore durante l'esecuzione:', error);
}
})();
Per testare, imposta la variabile di ambiente API_KEY, installa le dipendenze e esegui lo script:
export API_KEY=<your_key>node incrementCurrency.js
Classifica esterna persistente
Questo esempio crea un elenco predefinito di utenti per scopi dimostrativi, ma per essere utile in un gioco reale, avresti bisogno di un archivio di dati effettivo di utenti.
Scopi richiesti
Quando crei una chiave API per questo esempio, aggiungi i seguenti scopi alla tua chiave:
- universe.ordered-data-store.scope.entry:read
- universe.ordered-data-store.scope.entry:write
Aggiungi script per la classifica
Dopo aver creato la chiave API con i permessi richiesti per l'app di esempio, puoi creare uno script per effettuare richieste agli endpoint. Questi script aggiungono alcune voci di esempio all'archivio di dati ordinati con numeri casuali e poi le recuperano dal valore più alto al più basso. Per un archivio di dati più grande, dovresti occuparti della paginazione utilizzando i parametri di query maxPageSize e pageToken.
leaderboard.js
const apiKey = process.env.API_KEY;
const apiHeaderKey = 'x-api-key';
const universeId = '';
const orderedDataStoreId = 'PlayerScores';
const scopeId = 'global';
const baseUrl = 'https://apis.roblox.com/cloud/v2/';
async function createOrderedEntry(universe, orderedDataStore, entryId, payload) {
const createPath = `universes/${universe}/ordered-data-stores/${orderedDataStore}/scopes/${scopeId}/entries`;
const url = new URL(baseUrl + createPath);
url.searchParams.append('id', entryId);
const response = await fetch(url, {
method: 'POST',
headers: {
[apiHeaderKey]: apiKey,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});
if (!response.ok) {
const errorText = await response.text();
throw new Error(`Errore API (${response.status}): ${errorText}`);
}
return response.text();
}
async function listOrderedEntries(universe, orderedDataStore) {
const listPath = `universes/${universe}/ordered-data-stores/${orderedDataStore}/scopes/${scopeId}/entries`;
const url = new URL(baseUrl + listPath);
url.searchParams.append('orderBy', 'value desc');
return fetch(url, {
headers: {
[apiHeaderKey]: apiKey,
},
});
}
async function main() {
if (!apiKey) {
console.error('Errore: La variabile di ambiente API_KEY non è impostata.');
process.exit(1);
}
const entryNames = ['Ragdoll', 'Balinese', 'Tabby', 'Siamese'];
console.log('Creazione dei dati di esempio...');
for (const name of entryNames) {
try {
const randomValue = Math.floor(Math.random() * 50) + 1;
const payload = { value: randomValue };
const responseText = await createOrderedEntry(universeId, orderedDataStoreId, name, payload);
console.log(responseText);
} catch (error) {
console.error(`Impossibile creare la voce per "${name}": ${error.message}`);
}
}
console.log('\nOttenimento dell\'elenco ordinato delle voci...');
try {
const playerScoresResponse = await listOrderedEntries(universeId, orderedDataStoreId);
console.log(playerScoresResponse.status);
const responseText = await playerScoresResponse.text();
console.log(responseText);
} catch (error) {
console.error(`Impossibile elencare le voci: ${error.message}`);
}
}
main();
Per testare, imposta la variabile di ambiente API_KEY, installa le dipendenze e esegui lo script:
export API_KEY=<your_key>node leaderboard.js