Skip to main content

Send Message to Game Server

Send messages directly to the game server from an endless room. This is used for server-side game logic, database operations, matchmaking requests, and other server-side processing.

Method

MoitribeSDK('game-id', 'endlessmessagetogameserver', params, callback)

Parameters

ParameterTypeRequiredDescription
messageDataArrayBufferYesMessage data to send to server
isReliablebooleanNoWhether message must be delivered (default: true)

Response Format

{
success: boolean;
msg?: string;
}

Examples

JavaScript Example

// Send score to server for validation and storage
function submitScoreToServer(score, level, achievements) {
const scoreData = {
type: 'submit_score',
score: score,
level: level,
achievements: achievements,
timestamp: Date.now(),
playerToken: getPlayerAuthToken()
};

const encoder = new TextEncoder();
const messageData = encoder.encode(JSON.stringify(scoreData));

MoitribeSDK('my-game', 'endlessmessagetogameserver', {
messageData: messageData.buffer,
isReliable: true // Score submission must be reliable
}, (result) => {
if (result.success) {
console.log('Score submitted to server successfully');
} else {
console.error('Failed to submit score:', result.msg);
}
});
}

// Request matchmaking for new players
function requestMatchmaking(gameMode, skillLevel) {
const matchData = {
type: 'request_matchmaking',
gameMode: gameMode,
skillLevel: skillLevel,
currentRoomId: getCurrentRoomId(),
timestamp: Date.now()
};

const encoder = new TextEncoder();
const messageData = encoder.encode(JSON.stringify(matchData));

MoitribeSDK('my-game', 'endlessmessagetogameserver', {
messageData: messageData.buffer,
isReliable: true
}, (result) => {
console.log('Matchmaking request sent:', result.success);
});
}

// Report player behavior
function reportPlayer(playerId, reason, description) {
const reportData = {
type: 'report_player',
reportedPlayerId: playerId,
reason: reason,
description: description,
reporterId: getCurrentPlayerId(),
timestamp: Date.now(),
evidence: collectEvidence()
};

const encoder = new TextEncoder();
const messageData = encoder.encode(JSON.stringify(reportData));

MoitribeSDK('my-game', 'endlessmessagetogameserver', {
messageData: messageData.buffer,
isReliable: true
}, (result) => {
if (result.success) {
showNotification('Report submitted successfully');
} else {
showError('Failed to submit report');
}
});
}

TypeScript Example

import MoitribeSDK from '@veniso/moitribe-js';

// Server message types
interface ServerMessage {
type: 'save_progress' | 'load_progress' | 'purchase_item' | 'unlock_achievement';
data: any;
playerId: string;
timestamp: number;
}

// Save game progress to server
function saveGameProgress(progressData: GameProgress): void {
const serverMessage: ServerMessage = {
type: 'save_progress',
data: progressData,
playerId: getCurrentPlayerId(),
timestamp: Date.now()
};

const messageData = encodeServerMessage(serverMessage);

MoitribeSDK('my-game', 'endlessmessagetogameserver', {
messageData: messageData,
isReliable: true
}, (result: any) => {
if (result.success) {
console.log('Game progress saved to server');
updateLastSavedTime();
} else {
console.error('Failed to save progress:', result.msg);
showSaveError();
}
});
}

// Request inventory from server
function requestInventory(): void {
const requestData: ServerMessage = {
type: 'load_progress',
data: { requestType: 'inventory' },
playerId: getCurrentPlayerId(),
timestamp: Date.now()
};

const messageData = encodeServerMessage(requestData);

MoitribeSDK('my-game', 'endlessmessagetogameserver', {
messageData: messageData,
isReliable: true
}, (result: any) => {
console.log('Inventory request sent:', result.success);
});
}

// Purchase in-game item
function purchaseItem(itemId: string, currency: string, price: number): void {
const purchaseData: ServerMessage = {
type: 'purchase_item',
data: {
itemId: itemId,
currency: currency,
price: price,
playerBalance: getPlayerBalance()
},
playerId: getCurrentPlayerId(),
timestamp: Date.now()
};

const messageData = encodeServerMessage(purchaseData);

MoitribeSDK('my-game', 'endlessmessagetogameserver', {
messageData: messageData,
isReliable: true
}, (result: any) => {
if (result.success) {
console.log('Purchase request sent to server');
showProcessingPurchase();
} else {
console.error('Purchase failed:', result.msg);
showPurchaseError();
}
});
}

// Helper function to encode server messages
function encodeServerMessage(message: ServerMessage): ArrayBuffer {
const json = JSON.stringify(message);
const encoder = new TextEncoder();
return encoder.encode(json).buffer;
}

Common Use Cases

Game State Persistence

// Save game state periodically
function saveGameStateToServer() {
const gameState = {
type: 'save_game_state',
roomState: getCurrentRoomState(),
playerStates: getAllPlayerStates(),
gameProgress: getGameProgress(),
timestamp: Date.now()
};

const encoder = new TextEncoder();
const messageData = encoder.encode(JSON.stringify(gameState));

MoitribeSDK('my-game', 'endlessmessagetogameserver', {
messageData: messageData.buffer,
isReliable: true
});
}

// Auto-save every 30 seconds
setInterval(saveGameStateToServer, 30000);

Analytics and Telemetry

// Send gameplay analytics
function sendAnalyticsEvent(eventName, eventData) {
const analyticsData = {
type: 'analytics',
eventName: eventName,
eventData: eventData,
sessionId: getSessionId(),
playerId: getCurrentPlayerId(),
roomId: getCurrentRoomId(),
timestamp: Date.now(),
clientVersion: getClientVersion()
};

const encoder = new TextEncoder();
const messageData = encoder.encode(JSON.stringify(analyticsData));

MoitribeSDK('my-game', 'endlessmessagetogameserver', {
messageData: messageData.buffer,
isReliable: false // Analytics can be unreliable
});
}

// Usage examples
sendAnalyticsEvent('level_completed', { level: 5, time: 120, stars: 3 });
sendAnalyticsEvent('item_collected', { itemType: 'coin', value: 10 });
sendAnalyticsEvent('player_death', { cause: 'fall', location: 'mountain' });

Anti-Cheat Validation

// Validate player actions server-side
function validatePlayerAction(action, data) {
const validationData = {
type: 'validate_action',
action: action,
data: data,
playerId: getCurrentPlayerId(),
position: getPlayerPosition(),
timestamp: Date.now(),
checksum: calculateActionChecksum(action, data)
};

const encoder = new TextEncoder();
const messageData = encoder.encode(JSON.stringify(validationData));

MoitribeSDK('my-game', 'endlessmessagetogameserver', {
messageData: messageData.buffer,
isReliable: true
});
}

// Usage
validatePlayerAction('jump', { height: 2.5, distance: 3.0 });
validatePlayerAction('attack', { target: 'enemy123', damage: 25 });

Server-Side Game Logic

// Request server-side dice roll
function requestServerDiceRoll(sides, count) {
const rollRequest = {
type: 'dice_roll',
sides: sides,
count: count,
playerId: getCurrentPlayerId(),
timestamp: Date.now()
};

const encoder = new TextEncoder();
const messageData = encoder.encode(JSON.stringify(rollRequest));

MoitribeSDK('my-game', 'endlessmessagetogameserver', {
messageData: messageData.buffer,
isReliable: true
});
}

// Request server-controlled random event
function triggerRandomEvent(eventType, weights) {
const eventData = {
type: 'random_event',
eventType: eventType,
weights: weights,
roomId: getCurrentRoomId(),
timestamp: Date.now()
};

const encoder = new TextEncoder();
const messageData = encoder.encode(JSON.stringify(eventData));

MoitribeSDK('my-game', 'endlessmessagetogameserver', {
messageData: messageData.buffer,
isReliable: true
});
}

Data Formats

Binary Messages

// Send compact binary data for performance
function sendBinaryGameData() {
const buffer = new ArrayBuffer(16);
const view = new DataView(buffer);

view.setUint8(0, 1); // Message type: game_update
view.setUint32(1, getPlayerId()); // Player ID (4 bytes)
view.setFloat32(5, getScore()); // Score (4 bytes)
view.setFloat32(9, getHealth()); // Health (4 bytes)
view.setUint16(13, getLevel()); // Level (2 bytes)

MoitribeSDK('my-game', 'endlessmessagetogameserver', {
messageData: buffer,
isReliable: true
});
}

Structured JSON

// Send complex structured data
function sendComplexGameData() {
const complexData = {
type: 'complex_update',
player: {
id: getCurrentPlayerId(),
stats: getPlayerStats(),
inventory: getPlayerInventory(),
achievements: getPlayerAchievements()
},
room: {
id: getCurrentRoomId(),
state: getRoomState(),
events: getRecentEvents()
},
timestamp: Date.now()
};

const encoder = new TextEncoder();
const messageData = encoder.encode(JSON.stringify(complexData));

MoitribeSDK('my-game', 'endlessmessagetogameserver', {
messageData: messageData.buffer,
isReliable: true
});
}

Error Handling

function sendToServerWithErrorHandling(messageData, isReliable = true) {
MoitribeSDK('my-game', 'endlessmessagetogameserver', {
messageData,
isReliable
}, (result) => {
if (!result.success) {
console.error('Server message failed:', result.msg);

// Handle specific errors
if (result.msg?.includes('unauthorized')) {
// Refresh authentication token
refreshToken(() => {
// Retry the message
sendToServerWithErrorHandling(messageData, isReliable);
});
} else if (result.msg?.includes('rate_limited')) {
// Wait and retry
setTimeout(() => {
sendToServerWithErrorHandling(messageData, isReliable);
}, 5000);
} else if (result.msg?.includes('invalid_data')) {
console.error('Server rejected message data');
// Fix data format and retry
}
}
});
}

Performance Considerations

Message Batching

// Batch multiple server requests
const serverMessageQueue = [];

function queueServerMessage(message) {
serverMessageQueue.push(message);
}

function flushServerQueue() {
if (serverMessageQueue.length === 0) return;

const batchData = {
type: 'batch',
messages: serverMessageQueue.splice(0), // Clear queue
timestamp: Date.now()
};

const encoder = new TextEncoder();
const messageData = encoder.encode(JSON.stringify(batchData));

MoitribeSDK('my-game', 'endlessmessagetogameserver', {
messageData: messageData.buffer,
isReliable: true
});
}

// Flush queue periodically
setInterval(flushServerQueue, 1000);

Rate Limiting

const serverMessageTimestamps = [];
const SERVER_RATE_LIMIT = 10; // 10 messages per second

function sendWithServerRateLimit(messageData, isReliable = true) {
const now = Date.now();

// Remove old timestamps (older than 1 second)
const recentTimestamps = serverMessageTimestamps.filter(t => now - t < 1000);

if (recentTimestamps.length < SERVER_RATE_LIMIT) {
MoitribeSDK('my-game', 'endlessmessagetogameserver', {
messageData,
isReliable
});

serverMessageTimestamps.push(now);
} else {
// Queue the message for later
queueServerMessage(messageData);
}
}

Best Practices

Authentication

function sendAuthenticatedMessage(messageType, data) {
const authData = {
type: messageType,
data: data,
playerId: getCurrentPlayerId(),
authToken: getCurrentAuthToken(),
timestamp: Date.now(),
checksum: calculateMessageChecksum(messageType, data)
};

const encoder = new TextEncoder();
const messageData = encoder.encode(JSON.stringify(authData));

MoitribeSDK('my-game', 'endlessmessagetogameserver', {
messageData: messageData.buffer,
isReliable: true
});
}

Retry Logic

function sendWithRetry(messageData, maxRetries = 3, retryDelay = 1000) {
let attempts = 0;

function attemptSend() {
attempts++;

MoitribeSDK('my-game', 'endlessmessagetogameserver', {
messageData,
isReliable: true
}, (result) => {
if (result.success) {
console.log('Message sent to server successfully');
} else if (attempts < maxRetries) {
console.log(`Retrying server message (${attempts}/${maxRetries})`);
setTimeout(attemptSend, retryDelay * attempts);
} else {
console.error('Failed to send to server after max retries');
}
});
}

attemptSend();
}

Next Steps

Security Tip

Always authenticate server messages and validate data on both client and server sides to prevent cheating and unauthorized actions.