Ngoài việc truy cập các cửa hàng dữ liệu từ API Engine trong Studio hoặc các trò chơi trực tiếp (DataStoreService), bạn có thể sử dụng API Open Cloud để truy cập cửa hàng dữ liệu tiêu chuẩn và cửa hàng dữ liệu có thứ tự từ các script và công cụ bên ngoài.
Việc truy cập Open Cloud vào các cửa hàng dữ liệu của bạn mở ra nhiều trường hợp sử dụng tiềm năng, bao gồm:
- Một cổng hỗ trợ khách hàng cho phép đội ngũ của bạn trực tiếp xử lý các yêu cầu hỗ trợ, chẳng hạn như chỉnh sửa kho đồ của người dùng hoặc phát hành hoàn tiền
- Bảng xếp hạng toàn cầu mà bạn có thể hiển thị trên một trang web bên ngoài
- Cập nhật lược đồ với các script đọc các mục từ cửa hàng dữ liệu hiện tại, ánh xạ nó đến lược đồ mới và ghi các mục trở lại một cửa hàng dữ liệu mới
Các ví dụ trên trang này cho thấy cách xây dựng một cổng hỗ trợ kho đồ của người dùng và một bảng xếp hạng bên ngoài với Node.js và Python, nhưng hãy sử dụng ngôn ngữ nào mà bạn thích; API Open Cloud hỗ trợ bất kỳ ngôn ngữ lập trình nào có thể gửi yêu cầu HTTP.
Sự khác biệt so với API Engine
Mặc dù các API Open Cloud truy cập vào cùng một cửa hàng dữ liệu cơ bản và tương tự như làm việc với DataStoreService, có một vài điểm khác biệt chính:
ID vũ trụ: Khác với API Engine, các API Open Cloud không trạng thái và có thể đến từ bất kỳ đâu, vì vậy bạn phải luôn cung cấp ID vũ trụ, là định danh duy nhất của trò chơi của bạn.
Quyền riêng biệt cho việc tạo và cập nhật: API Engine tạo các mục mới nếu chúng không tồn tại khi bạn gọi DataStore:SetAsync(), nhưng các phương thức Open Cloud để tạo và cập nhật các mục là riêng biệt. Các quyền riêng biệt có thể an toàn hơn và linh hoạt hơn trong một số tình huống. Ví dụ, bạn có thể muốn công cụ hỗ trợ khách hàng của mình chỉ có thể chỉnh sửa hồ sơ người dùng hiện có, không phải tạo một hồ sơ mới.
Tuần tự hóa dữ liệu: Tất cả các điểm cuối Open Cloud yêu cầu bạn phải tuần tự hóa dữ liệu trước khi gửi. Tuần tự hóa có nghĩa là chuyển đổi một đối tượng thành chuỗi. Tự động đảo ngược là bước ngược lại, chuyển đổi một chuỗi thành đối tượng. API Engine tự động tuần tự hóa và tự động đảo ngược nội dung mục, nhưng đối với Open Cloud, bạn phải tạo hoặc phân tích mục của mình thành và từ JSON một cách độc lập.
Quyền truy cập
Cửa hàng dữ liệu thường lưu trữ thông tin nhạy cảm, chẳng hạn như hồ sơ người dùng và tiền tệ ảo. Để duy trì an ninh, mỗi phương thức Open Cloud có các quyền tương ứng, được gọi là phạm vi, mà bạn phải thêm vào khóa API của mình, chẳng hạn như phạm vi universe-datastores.control:list cho phương thức Danh sách cửa hàng dữ liệu. Nếu bạn không thêm các quyền yêu cầu, yêu cầu API của bạn sẽ trả về lỗi. Xem tài liệu tham khảo để biết các phạm vi yêu cầu cho mỗi điểm cuối.
Để biết thêm thông tin về quản lý quyền truy cập, xem Quản lý khóa API.
Cổng hỗ trợ kho đồ của người dùng
Ví dụ này sử dụng một cửa hàng dữ liệu có tên Inventory và một lược đồ cho mỗi mục là "userId": {"currency": number, "weapon": string, "level": number}. Khóa là userId.
Các phạm vi yêu cầu
Khi tạo một khóa API cho ví dụ này, hãy thêm các phạm vi sau vào khóa của bạn:
- universe-datastores.objects:list
- universe-datastores.objects:read
- universe-datastores.objects:update
Tùy chọn, thêm quyền chỉ cho cửa hàng dữ liệu Inventory, đặt một hạn chế địa chỉ IP và đặt ngày hết hạn.
Thêm script cho cổng hỗ trợ kho đồ của người dùng
Sau khi tạo khóa API với các quyền cần thiết cho ứng dụng ví dụ, bạn có thể tạo một script để thực hiện các yêu cầu đến các điểm cuối. Các script này lấy 10 mục đầu tiên trong cửa hàng dữ liệu, tăng giá trị currency cho mỗi mục lên 10, và sau đó cập nhật từng mục. Đối với một cửa hàng dữ liệu lớn hơn, bạn sẽ cần xử lý phân trang bằng các tham số truy vấn maxPageSize và pageToken.
incrementCurrency.js
const apiKey = process.env.API_KEY;
if (!apiKey) {
throw new Error('Biến môi trường API_KEY không được thiết lập.');
}
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) // Nội dung phải là một chuỗi
});
return response;
}
(async () => {
try {
const entries = await listEntries(universeId, dataStoreId);
for (const entry of entries.dataStoreEntries) {
const path = entry.path;
console.log(`\nĐang xử lý mục: ${path}`);
const currentData = await getEntry(path);
currentData.value.currency += 10;
const payload = { value: currentData.value };
const updateResponse = await updateEntry(path, payload);
console.log(`Trạng thái: ${updateResponse.status}`);
console.log(`Phản hồi: ${await updateResponse.text()}`);
}
} catch (error) {
console.error('Đã xảy ra lỗi trong quá trình thực thi:', error);
}
})();
Để kiểm tra, đặt biến môi trường API_KEY, cài đặt các phụ thuộc, và chạy script:
export API_KEY=<your_key>node incrementCurrency.js
Bảng xếp hạng bên ngoài
Ví dụ này tạo một danh sách người dùng đã được xác định trước cho mục đích demo, nhưng để nó hữu ích trong một trò chơi thực tế, bạn sẽ cần một cửa hàng dữ liệu thực sự của người dùng.
Các phạm vi yêu cầu
Khi tạo một khóa API cho ví dụ này, hãy thêm các phạm vi sau vào khóa của bạn:
- universe.ordered-data-store.scope.entry:read
- universe.ordered-data-store.scope.entry:write
Thêm script cho bảng xếp hạng
Sau khi tạo khóa API với các quyền cần thiết cho ứng dụng ví dụ, bạn có thể tạo một script để thực hiện các yêu cầu đến các điểm cuối. Các script này thêm một số mục mẫu vào cửa hàng dữ liệu có thứ tự với các số ngẫu nhiên và sau đó lấy chúng từ giá trị cao nhất đến thấp nhất. Đối với một cửa hàng dữ liệu lớn hơn, bạn sẽ cần xử lý phân trang bằng các tham số truy vấn maxPageSize và 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(`Lỗi 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('Lỗi: Biến môi trường API_KEY không được thiết lập.');
process.exit(1);
}
const entryNames = ['Ragdoll', 'Balinese', 'Tabby', 'Siamese'];
console.log('Đang tạo dữ liệu mẫu...');
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(`Không thể tạo mục cho "${name}": ${error.message}`);
}
}
console.log('\nĐang lấy danh sách mục đã sắp xếp...');
try {
const playerScoresResponse = await listOrderedEntries(universeId, orderedDataStoreId);
console.log(playerScoresResponse.status);
const responseText = await playerScoresResponse.text();
console.log(responseText);
} catch (error) {
console.error(`Không thể danh sách các mục: ${error.message}`);
}
}
main();
Để kiểm tra, đặt biến môi trường API_KEY, cài đặt các phụ thuộc, và chạy script:
export API_KEY=<your_key>node leaderboard.js