Engine API'sinden Studio veya canlı oyunlar üzerinden veri depolarına erişmenin yanı sıra (DataStoreService), dış betikler ve diğer araçlar aracılığıyla standart ve sıralı veri depolarına erişmek için Açık Bulut API'lerini kullanabilirsiniz.
Veri depolarınıza Açık Bulut erişimi, aşağıdakiler de dahil olmak üzere birçok potansiyel kullanım durumunu açar:
- Kullanıcı envanterlerini değiştirme veya geri ödeme verme gibi destek taleplerini doğrudan ekibinizin ele almasına olanak tanıyan bir müşteri destek portalı
- Dış bir web sitesinde görüntüleyebileceğiniz küresel liderlik tabloları
- Mevcut veri deposundan girişleri okuyan, bunları yeni şemaya eşleyen ve girişleri yeni bir veri deposuna geri yazan betiklerle şema güncellemeleri
Bu sayfadaki örnekler, Node.js ve Python ile bir kullanıcı envanteri destek portalı ve bir dış liderlik tablosu oluşturmanın nasıl yapılacağını göstermektedir, ancak tercih ettiğiniz dili kullanabilirsiniz; Açık Bulut API'leri, bir HTTP isteği gönderebilen herhangi bir programlama dilini destekler.
Engine API'sinden Farklar
Açık Bulut API'leri, aynı temel veri depolarına erişse de ve DataStoreService ile çalışmaya benzer olsa da, birkaç önemli fark vardır:
Evrensel ID: Engine API'sinin aksine, Açık Bulut API'leri durumsuzdur ve her yerden gelebilir, bu nedenle her zaman evrensel ID'yi, oyununuzun benzersiz tanımlayıcısını sağlamanız gerekir.
Oluşturma ve güncelleme için ayrı izinler: Engine API, DataStore:SetAsync() çağrıldığında mevcut değilse yeni girişler oluşturur, ancak Açık Bulut yöntemleri için giriş oluşturma ve güncelleme ayrı ayrılmıştır. Ayrı izinler, belirli durumlarda daha güvenli ve daha esnek olabilir. Örneğin, müşteri destek aracınızın yalnızca mevcut bir kullanıcının profilini düzenlemesini, yeni bir tane oluşturmasını istemeyebilirsiniz.
Veri serileştirme: Tüm Açık Bulut uç noktaları, verileri göndermeden önce serileştirmenizi gerektirir. Serileştirme, bir nesneyi bir dizeye dönüştürme anlamına gelir. Serileştirmeden çıkarma ise tersidir, bir dizeyi bir nesneye dönüştürmektir. Engine API, giriş içeriğini otomatik olarak serileştirir ve serileştirmeden çıkarır, ancak Açık Bulut için girişinizi JSON'a kendiniz oluşturmanız veya ayrıştırmanız gerekir.
Sonsuz Olmayan Sayılar
Engine API aracılığıyla yazılan veri deposu girişleri, sonsuz olmayan Luau sayıları içerebilir. JSON bu sayıları temsil edemediğinden, Açık Bulut yanıtları bunları döndürülen giriş değerinde etiketli JSON nesneleri ile değiştirir:
- Pozitif sonsuz (inf): {"m": null, "t": "numeric", "v": "inf"}
- Negatif sonsuz (-inf): {"m": null, "t": "numeric", "v": "-inf"}
- NaN (nan): {"m": null, "t": "numeric", "v": "nan"}
İzinler
Veri depoları genellikle kullanıcı profilleri ve sanal para birimi gibi hassas bilgileri saklar. Güvenliği sağlamak için, her Açık Bulut yönteminin, API anahtarınıza eklemeniz gereken karşılık gelen izinleri, yani kapsamları vardır; örneğin, Veri Depolarını Listele yöntemi için universe-datastores.control:list kapsamı. Gerekli izinleri eklemezseniz, API çağrınız bir hata döndürür. Her uç nokta için gerekli kapsamlar hakkında daha fazla bilgi için referans belgelerine bakın.
İzinleri yönetme hakkında daha fazla bilgi için API anahtarlarını yönet sayfasına bakın.
Kullanıcı envanteri destek portalı
Bu örnek, her giriş için "userId": {"currency": number, "weapon": string, "level": number} şemasına sahip Inventory adında bir veri deposu kullanır. Anahtar userId'dir.
Gerekli kapsamlar
Bu örnek için API Anahtarı oluştururken anahtarınıza aşağıdaki kapsamları ekleyin:
- universe-datastores.objects:list
- universe-datastores.objects:read
- universe-datastores.objects:update
İsteğe bağlı olarak, yalnızca Inventory veri deposu için izinleri ekleyebilir, bir IP adresi kısıtlaması ayarlayabilir ve bir son kullanma tarihi belirleyebilirsiniz.
Kullanıcı envanteri destek portalı için betikler ekleyin
Örnek uygulama için gerekli izinlere sahip API anahtarını oluşturduktan sonra, uç noktalara istek yapmak için bir betik oluşturabilirsiniz. Bu betikler, veri deposundaki ilk 10 girişi alır, her birinin currency değerini 10 artırır ve ardından her girişi günceller. Daha büyük bir veri deposu için, maxPageSize ve pageToken sorgu parametrelerini kullanarak sayfalandırma ile başa çıkmanız gerekecektir.
const apiKey = process.env.API_KEY;
if (!apiKey) {
throw new Error('API_KEY ortam değişkeni ayarlanmamış.');
}
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) // Gövde bir dize olmalıdır
});
return response;
}
(async () => {
try {
const entries = await listEntries(universeId, dataStoreId);
for (const entry of entries.dataStoreEntries) {
const path = entry.path;
console.log(`\nİşleniyor giriş: ${path}`);
const currentData = await getEntry(path);
currentData.value.currency += 10;
const payload = { value: currentData.value };
const updateResponse = await updateEntry(path, payload);
console.log(`Durum: ${updateResponse.status}`);
console.log(`Yanıt: ${await updateResponse.text()}`);
}
} catch (error) {
console.error('Çalışma sırasında bir hata oluştu:', error);
}
})();Test etmek için, API_KEY ortam değişkenini ayarlayın, bağımlılıkları yükleyin ve betiği çalıştırın:
export API_KEY=<your_key>
node incrementCurrency.jsDış kalıcı liderlik tablosu
Bu örnek, demo amaçları için önceden tanımlanmış bir kullanıcı listesi oluşturur, ancak gerçek bir oyunda faydalı olması için gerçek bir kullanıcı veri deposuna ihtiyacınız olacaktır.
Gerekli kapsamlar
Bu örnek için API Anahtarı oluştururken anahtarınıza aşağıdaki kapsamları ekleyin:
- universe.ordered-data-store.scope.entry:read
- universe.ordered-data-store.scope.entry:write
Liderlik tablosu için betikler ekleyin
Örnek uygulama için gerekli izinlere sahip API anahtarını oluşturduktan sonra, uç noktalara istek yapmak için bir betik oluşturabilirsiniz. Bu betikler, sıralı veri deposuna rastgele sayılarla bazı örnek girişler ekler ve ardından bunları en yüksekten en düşüğe doğru alır. Daha büyük bir veri deposu için, maxPageSize ve pageToken sorgu parametrelerini kullanarak sayfalandırma ile başa çıkmanız gerekecektir.
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 Hatası (${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('Hata: API_KEY ortam değişkeni ayarlanmamış.');
process.exit(1);
}
const entryNames = ['Ragdoll', 'Balinese', 'Tabby', 'Siamese'];
console.log('Örnek veriler oluşturuluyor...');
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(`"${name}" için giriş oluşturma başarısız oldu: ${error.message}`);
}
}
console.log('\nSıralı giriş listesini alıyor...');
try {
const playerScoresResponse = await listOrderedEntries(universeId, orderedDataStoreId);
console.log(playerScoresResponse.status);
const responseText = await playerScoresResponse.text();
console.log(responseText);
} catch (error) {
console.error(`Girişleri listeleme başarısız oldu: ${error.message}`);
}
}
main();Test etmek için, API_KEY ortam değişkenini ayarlayın, bağımlılıkları yükleyin ve betiği çalıştırın:
export API_KEY=<your_key>
node leaderboard.js