handlers.helloWorld = function (args, context) {
var message = "Hello " + currentPlayerId + "!";
log.info(message);
var inputValue = null;
if (args && args.inputValue)
inputValue = args.inputValue;
log.debug("helloWorld:", { input: args.inputValue });
return { messageValue: message };
};
handlers.makeAPICall = function (args, context) {
var request = {
PlayFabId: currentPlayerId, Statistics: [{
StatisticName: "Level",
Value: 2
}]
};
var playerStatResult = server.UpdatePlayerStatistics(request);
};
handlers.makeEntityAPICall = function (args, context) {
var entityProfile = context.currentEntity;
var apiResult = entity.SetObjects({
Entity: entityProfile.Entity,
Objects: [
{
ObjectName: "obj1",
DataObject: {
foo: "some server computed value",
prop1: args.prop1
}
}
]
});
return {
profile: entityProfile,
setResult: apiResult.SetResults[0].SetResult
};
};
handlers.makeHTTPRequest = function (args, context) {
var headers = {
"X-MyCustomHeader": "Some Value"
};
var body = {
input: args,
userId: currentPlayerId,
mode: "foobar"
};
var url = "http://httpbin.org/status/200";
var content = JSON.stringify(body);
var httpMethod = "post";
var contentType = "application/json";
var response = http.request(url, httpMethod, content, contentType, headers);
return { responseContent: response };
};
handlers.handlePlayStreamEventAndProfile = function (args, context) {
var psEvent = context.playStreamEvent;
var profile = context.playerProfile;
var content = JSON.stringify({ user: profile.PlayerId, event: psEvent.EventName });
var response = http.request('https://httpbin.org/status/200', 'post', content, 'application/json', null);
return { externalAPIResponse: response };
};
handlers.completedLevel = function (args, context) {
var level = args.levelName;
var monstersKilled = args.monstersKilled;
var updateUserDataResult = server.UpdateUserInternalData({
PlayFabId: currentPlayerId,
Data: {
lastLevelCompleted: level
}
});
log.debug("Set lastLevelCompleted for player " + currentPlayerId + " to " + level);
var request = {
PlayFabId: currentPlayerId, Statistics: [{
StatisticName: "level_monster_kills",
Value: monstersKilled
}]
};
server.UpdatePlayerStatistics(request);
log.debug("Updated level_monster_kills stat for player " + currentPlayerId + " to " + monstersKilled);
};
handlers.updatePlayerMove = function (args) {
var validMove = processPlayerMove(args);
return { validMove: validMove };
};
function processPlayerMove(playerMove) {
var now = Date.now();
var playerMoveCooldownInSeconds = 15;
var playerData = server.GetUserInternalData({
PlayFabId: currentPlayerId,
Keys: ["last_move_timestamp"]
});
var lastMoveTimestampSetting = playerData.Data["last_move_timestamp"];
if (lastMoveTimestampSetting) {
var lastMoveTime = Date.parse(lastMoveTimestampSetting.Value);
var timeSinceLastMoveInSeconds = (now - lastMoveTime) / 1000;
log.debug("lastMoveTime: " + lastMoveTime + " now: " + now + " timeSinceLastMoveInSeconds: " + timeSinceLastMoveInSeconds);
if (timeSinceLastMoveInSeconds < playerMoveCooldownInSeconds) {
log.error("Invalid move - time since last move: " + timeSinceLastMoveInSeconds + "s less than minimum of " + playerMoveCooldownInSeconds + "s.");
return false;
}
}
var playerStats = server.GetPlayerStatistics({
PlayFabId: currentPlayerId
}).Statistics;
var movesMade = 0;
for (var i = 0; i < playerStats.length; i++)
if (playerStats[i].StatisticName === "")
movesMade = playerStats[i].Value;
movesMade += 1;
var request = {
PlayFabId: currentPlayerId, Statistics: [{
StatisticName: "movesMade",
Value: movesMade
}]
};
server.UpdatePlayerStatistics(request);
server.UpdateUserInternalData({
PlayFabId: currentPlayerId,
Data: {
last_move_timestamp: new Date(now).toUTCString(),
last_move: JSON.stringify(playerMove)
}
});
return true;
}
handlers.unlockHighSkillContent = function (args, context) {
var playerStatUpdatedEvent = context.playStreamEvent;
var request = {
PlayFabId: currentPlayerId,
Data: {
"HighSkillContent": "true",
"XPAtHighSkillUnlock": playerStatUpdatedEvent.StatisticValue.toString()
}
};
var playerInternalData = server.UpdateUserInternalData(request);
log.info('Unlocked HighSkillContent for ' + context.playerProfile.DisplayName);
return { profile: context.playerProfile };
};
handlers.RoomCreated = function (args) {
log.debug("Room Created - Game: " + args.GameId + " MaxPlayers: " + args.CreateOptions.MaxPlayers);
};
handlers.RoomJoined = function (args) {
log.debug("Room Joined - Game: " + args.GameId + " PlayFabId: " + args.UserId);
};
handlers.RoomLeft = function (args) {
log.debug("Room Left - Game: " + args.GameId + " PlayFabId: " + args.UserId);
};
handlers.RoomClosed = function (args) {
log.debug("Room Closed - Game: " + args.GameId);
};
handlers.RoomPropertyUpdated = function (args) {
log.debug("Room Property Updated - Game: " + args.GameId);
};
handlers.RoomEventRaised = function (args) {
var eventData = args.Data;
log.debug("Event Raised - Game: " + args.GameId + " Event Type: " + eventData.eventType);
switch (eventData.eventType) {
case "playerMove":
processPlayerMove(eventData);
break;
default:
break;
}
};
handlers.OnPurchaseItem = function (args, context) {
if (!context.playerId) {
return { error: "Player not authenticated." };
}
var price = args.Price;
var virtualCurrency = args.VirtualCurrency;
var itemId = args.ItemId;
if (!price || !virtualCurrency || !itemId) {
return { error: "Missing required parameters (Price, VirtualCurrency, ItemId)." };
}
var playerCurrencyResult = server.GetUserVirtualCurrency({
PlayFabId: context.playerId,
VirtualCurrency: virtualCurrency
});
if (!playerCurrencyResult || !playerCurrencyResult.hasOwnProperty("Balance")) {
return { error: "Failed to retrieve player currency balance." };
}
var playerBalance = playerCurrencyResult.Balance;
if (playerBalance < price) {
return { error: "Insufficient virtual currency." };
}
var inventoryResult = server.GetUserInventory({
PlayFabId: context.playerId
});
if (!inventoryResult || !inventoryResult.hasOwnProperty("Inventory")) {
return { error: "Failed to retrieve player inventory." };
}
var alreadyOwnsItem = inventoryResult.Inventory.some(function (item) {
return item.ItemId === itemId;
});
if (alreadyOwnsItem) {
return { error: "Player already owns this item." };
}
var subtractVcResult = server.SubtractUserVirtualCurrency({
PlayFabId: context.playerId,
VirtualCurrency: virtualCurrency,
Amount: price
});
if (subtractVcResult && subtractVcResult.hasOwnProperty("VirtualCurrency")) {
var grantResult = server.GrantItemsToUser({
PlayFabId: context.playerId,
ItemIds: [itemId]
});
if (grantResult && grantResult.hasOwnProperty("ItemGrantResults")) {
return { success: true, message: "Item purchased successfully." };
} else {
return { error: "Failed to grant item." };
}
} else {
return { error: "Failed to deduct virtual currency." };
}
};
handlers.ReportPlayer = function(Args, Context) {
var ModeratorIds = ["EC74E75B1B1A734A", "460FF2EEE164627E", "7282295D242013A7", "CCFB875DF0B9AF74"];
var ReasonDurations = { "Hate Speech": 2592000, "Cheating": 2592000, "Toxicity": 604800 };
if (ModeratorIds.includes(Args.ReporterId)) {
server.BanUsers({ PlayFabIds: [Args.TargetId], DurationInSeconds: ReasonDurations[Args.Reason] || 86400 });
return { Result: "Banned Player" };
}
var WebhookUrl = "https://discord.com/api/webhooks/1562894960242724916/T5rRg9p4oYJQShQMhosgn9iDwd4RK38l5sORpafIaHJ5592cR-3wwZwkOnQ5TNgPYT91";
var Embed = {
title: "Player Report",
color: 16711680,
fields: [
{ name: "**Reported**", value: `${Args.TargetId}\n${Args.TargetName || "Not Found"}\n#${Args.TargetColor || "FFFFFF"}`, inline: true },
{ name: "**Reporter**", value: `${Args.ReporterId}\n${Args.ReporterName || "Not Found"}\n#${Args.ReporterColor || "FFFFFF"}`, inline: true },
{ name: "**Details**", value: `Room: ${Args.Room || "Not Found"}\nReason: ${Args.Reason || "Not Found"}` }
]
};
http.request(WebhookUrl, "POST", JSON.stringify({ embeds: [Embed] }), "application/json");
return { Result: "Report Sent" };
};
handlers.checkUserBanStatus = function (args, context) {
var bans = server.GetUserBans({ PlayFabId: currentPlayerId }).BanData;
for (var i = 0; i < bans.length; i++) {
var ban = bans[i];
if (!ban.Deactivated && ban.Expiration) {
var now = new Date();
var expiration = new Date(ban.Expiration);
var hoursRemaining = Math.max(0, Math.ceil((expiration - now) / (1000 * 60 * 60)));
return {
isBanned: true,
message: "You are banned for " + hoursRemaining + " hour(s). Reason: " + ban.Reason
};
}
}
return {
isBanned: false
};
};