Offene Cloud-Datenbanken

*Dieser Inhalt wurde mit KI (Beta) übersetzt und kann Fehler enthalten. Um diese Seite auf Englisch zu sehen, klicke hier.

Neben dem Zugriff auf Datenbanken über die Engine API in Studio oder Live-Spielen (DataStoreService) können Sie die Open Cloud APIs verwenden, um auf Standard-Datenbanken und geordneten Datenbanken von externen Skripten und anderen Tools zuzugreifen.

Der Zugriff auf Ihre Datenbanken über die Open Cloud eröffnet viele potenzielle Anwendungsfälle, darunter:

  • Ein Kundenservice-Portal, das es Ihrem Team ermöglicht, Supportanfragen direkt zu bearbeiten, wie z.B. das Ändern von Benutzerinventaren oder das Ausstellen von Rückerstattungen
  • Globale Bestenlisten, die Sie auf einer externen Website anzeigen können
  • Schema-Updates mit Skripten, die Einträge aus der aktuellen Datenbank lesen, sie auf das neue Schema abbilden und die Einträge in eine neue Datenbank zurückschreiben

Die Beispiele auf dieser Seite zeigen, wie man ein Benutzerinventar-Support-Portal und eine externe Bestenliste mit Node.js und Python erstellt, aber verwenden Sie die Sprache, die Sie bevorzugen; die Open Cloud APIs unterstützen jede Programmiersprache, die eine HTTP-Anfrage senden kann.

Unterschiede zur Engine API

Obwohl die Open Cloud APIs auf dieselben zugrunde liegenden Datenbanken zugreifen und ähnlich wie die Arbeit mit DataStoreService sind, gibt es einige wichtige Unterschiede:

  • Universum-ID: Im Gegensatz zur Engine API sind die Open Cloud APIs zustandslos und können von überall kommen, daher müssen Sie immer die Universum-ID, die eindeutige Kennung Ihres Spiels, angeben.

  • Getrennte Berechtigungen für das Erstellen und Aktualisieren: Die Engine API erstellt neue Einträge, wenn sie nicht existieren, wenn Sie DataStore:SetAsync() aufrufen, aber die Open Cloud-Methoden zum Erstellen und Aktualisieren von Einträgen sind getrennt. Getrennte Berechtigungen können in bestimmten Situationen sicherer und flexibler sein. Zum Beispiel möchten Sie vielleicht, dass Ihr Kundenservicetool nur das Profil eines bestehenden Benutzers bearbeiten kann, nicht ein neues erstellen.

  • Datenserialisierung: Alle Open Cloud-Endpunkte erfordern, dass Sie Daten vor dem Senden serialisieren. Serialisierung bedeutet, ein Objekt in eine Zeichenkette umzuwandeln. Deserialisierung ist das Gegenteil, das Umwandeln einer Zeichenkette in ein Objekt. Die Engine API serialisiert und deserialisiert den Inhalt von Einträgen automatisch, aber für Open Cloud müssen Sie Ihren Eintrag selbst in JSON generieren oder parsen.

Nicht-finite Zahlen

Datenbankeinträge, die über die Engine API geschrieben werden, können nicht-finite Luau-Zahlen enthalten. Da JSON diese Zahlen nicht darstellen kann, ersetzen Open Cloud-Antworten sie durch getaggte JSON-Objekte im zurückgegebenen Eintragswert:

  • Positive Unendlichkeit (inf): {"m": null, "t": "numeric", "v": "inf"}
  • Negative Unendlichkeit (-inf): {"m": null, "t": "numeric", "v": "-inf"}
  • NaN (nan): {"m": null, "t": "numeric", "v": "nan"}

Berechtigungen

Datenbanken speichern oft sensible Informationen, wie Benutzerprofile und virtuelle Währungen. Um die Sicherheit zu gewährleisten, hat jede Open Cloud-Methode entsprechende Berechtigungen, die Scopes genannt werden, die Sie zu Ihrem API-Schlüssel hinzufügen müssen, wie z.B. den universe-datastores.control:list Scope für die List Data Stores Methode. Wenn Sie die erforderlichen Berechtigungen nicht hinzufügen, gibt Ihr API-Aufruf einen Fehler zurück. Siehe die Referenzdokumentation für die erforderlichen Scopes für jeden Endpunkt.

Für weitere Informationen zur Verwaltung von Berechtigungen siehe API-Schlüssel verwalten.

Benutzerinventar-Support-Portal

Dieses Beispiel verwendet eine Datenbank namens Inventory und ein Schema für jeden Eintrag von "userId": {"currency": number, "weapon": string, "level": number}. Der Schlüssel ist userId.

Erforderliche Scopes

Beim Erstellen eines API-Schlüssels für dieses Beispiel fügen Sie die folgenden Scopes zu Ihrem Schlüssel hinzu:

  • universe-datastores.objects:list
  • universe-datastores.objects:read
  • universe-datastores.objects:update

Optional können Sie die Berechtigungen nur für die Inventory-Datenbank hinzufügen, eine IP-Adressbeschränkung festlegen und ein Ablaufdatum setzen.

Skripte für das Benutzerinventar-Support-Portal hinzufügen

Nachdem Sie den API-Schlüssel mit den für die Beispielanwendung erforderlichen Berechtigungen erstellt haben, können Sie ein Skript erstellen, um Anfragen an die Endpunkte zu stellen. Diese Skripte holen die ersten 10 Einträge in der Datenbank, erhöhen den currency-Wert für jeden um 10 und aktualisieren dann jeden Eintrag. Für eine größere Datenbank müssten Sie sich mit Seitenumbruch unter Verwendung der maxPageSize und pageToken Abfrageparameter befassen.

incrementCurrency.js
const apiKey = process.env.API_KEY;
if (!apiKey) {
throw new Error('Die Umgebungsvariable API_KEY ist nicht gesetzt.');
}
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) // Der Body muss eine Zeichenkette sein
});
return response;
}
(async () => {
try {
const entries = await listEntries(universeId, dataStoreId);
for (const entry of entries.dataStoreEntries) {
const path = entry.path;
console.log(`\nVerarbeite Eintrag: ${path}`);
const currentData = await getEntry(path);
currentData.value.currency += 10;
const payload = { value: currentData.value };
const updateResponse = await updateEntry(path, payload);
console.log(`Status: ${updateResponse.status}`);
console.log(`Antwort: ${await updateResponse.text()}`);
}
} catch (error) {
console.error('Ein Fehler ist während der Ausführung aufgetreten:', error);
}
})();

Um zu testen, setzen Sie die Umgebungsvariable API_KEY, installieren Sie die Abhängigkeiten und führen Sie das Skript aus:

export API_KEY=<your_key>
node incrementCurrency.js

Externe persistente Bestenliste

Dieses Beispiel erstellt eine vordefinierte Liste von Benutzern zu Demonstrationszwecken, aber um in einem echten Spiel nützlich zu sein, bräuchten Sie eine tatsächliche Datenbank von Benutzern.

Erforderliche Scopes

Beim Erstellen eines API-Schlüssels für dieses Beispiel fügen Sie die folgenden Scopes zu Ihrem Schlüssel hinzu:

  • universe.ordered-data-store.scope.entry:read
  • universe.ordered-data-store.scope.entry:write

Skripte für die Bestenliste hinzufügen

Nachdem Sie den API-Schlüssel mit den für die Beispielanwendung erforderlichen Berechtigungen erstellt haben, können Sie ein Skript erstellen, um Anfragen an die Endpunkte zu stellen. Diese Skripte fügen einige Beispiel-Einträge zur geordneten Datenbank mit zufälligen Zahlen hinzu und rufen sie dann von höchstem zu niedrigstem Wert ab. Für eine größere Datenbank müssten Sie sich mit Seitenumbruch unter Verwendung der maxPageSize und pageToken Abfrageparameter befassen.

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(`API-Fehler (${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('Fehler: Die Umgebungsvariable API_KEY ist nicht gesetzt.');
process.exit(1);
}
const entryNames = ['Ragdoll', 'Balinese', 'Tabby', 'Siamese'];
console.log('Erstelle Beispieldaten...');
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(`Fehler beim Erstellen des Eintrags für "${name}": ${error.message}`);
}
}
console.log('\nHole sortierte Liste der Einträge...');
try {
const playerScoresResponse = await listOrderedEntries(universeId, orderedDataStoreId);
console.log(playerScoresResponse.status);
const responseText = await playerScoresResponse.text();
console.log(responseText);
} catch (error) {
console.error(`Fehler beim Auflisten der Einträge: ${error.message}`);
}
}
main();

Um zu testen, setzen Sie die Umgebungsvariable API_KEY, installieren Sie die Abhängigkeiten und führen Sie das Skript aus:

export API_KEY=<your_key>
node leaderboard.js
©2026 Roblox Corporation. Roblox, das Roblox-Logo und "Powering Imagination" gehören zu unseren eingetragenen und nicht eingetragenen Markenzeichen in den USA und anderen Ländern.