Add more CloudScript functions, start of EnterMatchmaking

This commit is contained in:
AeonLucid
2022-01-07 22:29:20 +01:00
parent 27649724c8
commit 93926eedf8
58 changed files with 1004 additions and 299 deletions
@@ -22,6 +22,7 @@ public class ClientController : Controller
private const int AppIdDefault = 480;
private const int AppIdCycleBeta = 1600361;
private readonly ILogger<ClientController> _logger;
private readonly PlayFabSettings _settings;
private readonly AuthTokenService _authTokenService;
private readonly DbUserService _userService;
@@ -29,7 +30,8 @@ public class ClientController : Controller
private readonly UserDataService _userDataService;
private readonly TitleDataService _titleDataService;
public ClientController(IOptions<PlayFabSettings> settings,
public ClientController(ILogger<ClientController> logger,
IOptions<PlayFabSettings> settings,
AuthTokenService authTokenService,
DbUserService userService,
DbEntityService entityService,
@@ -37,6 +39,7 @@ public class ClientController : Controller
TitleDataService titleDataService)
{
_settings = settings.Value;
_logger = logger;
_authTokenService = authTokenService;
_userService = userService;
_entityService = entityService;
@@ -113,6 +116,11 @@ public class ClientController : Controller
}
});
}
_logger.LogWarning("Invalid steam ticket specified, IsValid {IsValid}, HasValidSignature {Sig}, AppId {AppId}",
ticket.IsValid,
ticket.HasValidSignature,
ticket.AppId);
}
return BadRequest(new ClientResponse
@@ -2,10 +2,8 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Prospect.Server.Api.Models.Client;
using Prospect.Server.Api.Models.CloudScript;
using Prospect.Server.Api.Models.CloudScript.Data;
using Prospect.Server.Api.Services.Auth.Entity;
using Prospect.Server.Api.Services.Auth.Extensions;
using Prospect.Server.Api.Services.CloudScript;
namespace Prospect.Server.Api.Controllers;
@@ -15,289 +13,36 @@ namespace Prospect.Server.Api.Controllers;
public class CloudScriptController : Controller
{
private readonly ILogger<CloudScriptController> _logger;
private readonly CloudScriptService _cloudScriptService;
public CloudScriptController(ILogger<CloudScriptController> logger)
public CloudScriptController(ILogger<CloudScriptController> logger, CloudScriptService cloudScriptService)
{
_logger = logger;
_cloudScriptService = cloudScriptService;
}
[HttpPost("ExecuteFunction")]
[Produces(MediaTypeNames.Application.Json)]
public IActionResult ExecuteFunction(FExecuteFunctionRequest request)
public async Task<IActionResult> ExecuteFunction(FExecuteFunctionRequest request)
{
_logger.LogInformation("Executing function {Function}", request.FunctionName);
_logger.LogDebug("Executing CloudScript function {Function}", request.FunctionName);
object result = null;
switch (request.FunctionName)
var result = await _cloudScriptService.ExecuteAsync(request.FunctionName, request.FunctionParameter, request.GeneratePlayStreamEvent);
if (result != null)
{
case "RequestMaintenanceModeState":
result = new
return Ok(new ClientResponse<FExecuteFunctionResult>
{
Code = 200,
Status = "OK",
Data = new FExecuteFunctionResult
{
enabled = false
};
break;
case "GetCharacterVanity":
result = new
{
userId = User.FindAuthUserId(),
error = (object) null,
returnVanity = new
{
userId = User.FindAuthUserId(),
head_item = new
{
id = "Black02M_Head1",
materialIndex = 0,
},
boots_item = new
{
id = "StarterOutfit01_Boots_M",
materialIndex = 0,
},
chest_item = new
{
id = "StarterOutfit01_Chest_M",
materialIndex = 0,
},
glove_item = new
{
id = "StarterOutfit01_Gloves_M",
materialIndex = 0,
},
base_suit_item = new
{
id = "StarterOutfit01M_BaseSuit",
materialIndex = 0,
},
melee_weapon_item = new
{
id = "Melee_Omega",
materialIndex = 0,
},
body_type = 1,
archetype_id = "TheProspector",
slot_index = 0
}
};
break;
case "SetMatchAllowJoin":
result = new
{
sessionId = (object)null,
success = false
};
break;
case "GetFriendList":
// TODO: ?
result = new
{
};
break;
case "GetPlayerSets":
result = new
{
success = true,
entries = new []
{
new
{
setData = new
{
id = "",
userId = User.FindAuthUserId(),
kit = "",
shield = "",
helmet = "",
weaponOne = "",
weaponTwo = "",
bag = "",
bagItemsAsJsonStr = "",
safeItemsAsJsonStr = ""
},
items = Array.Empty<object>()
}
}
};
break;
case "RequestFactionProgression":
result = new
{
factions = new []
{
new
{
factionId = "ICA",
currentProgression = 0
},
new
{
factionId = "Korolev",
currentProgression = 0
},
new
{
factionId = "Osiris",
currentProgression = 0
},
},
userId = User.FindAuthUserId(),
error = ""
};
break;
case "GetPlayersInventoriesLimits":
result = new
{
success = true,
entries = new []
{
new {
userId = User.FindAuthUserId(),
inventoryStashLimit = 75,
inventoryBagLimit = 300,
inventorySafeLimit = 5
}
}
};
break;
case "UpdateRetentionBonus":
result = new
{
playerData = new
{
daysClaimed = 0,
lastClaimTime = new
{
seconds = 1635033600
}
},
userId = User.FindAuthUserId(),
error = (object)null
};
break;
case "GetCraftingInProgressData":
result = new FYGetCraftingInProgressDataResult
{
UserId = User.FindAuthUserId(),
Error = null,
ItemCurrentlyBeingCrafted = new FYItemCurrentlyBeingCrafted
{
ItemId = null,
ItemRarity = -1,
PurchaseAmount = -1,
UtcTimestampWhenCraftingStarted = new FYTimestamp
{
Seconds = 0
}
}
};
break;
case "RequestPlayerContracts":
result = new FYGetPlayerContractsResult
{
UserId = User.FindAuthUserId(),
Error = null,
ActiveContracts = new List<FYActiveContractPlayerData>(),
FactionsContracts = new FYFactionsContractsData
{
Boards = new List<FYFactionContractsData>
{
new FYFactionContractsData
{
FactionId = "ICA",
Contracts = new List<FYFactionContractData>
{
new FYFactionContractData
{
ContractId = "NEW-Easy-ICA-Gather-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Medium-ICA-Uplink-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Hard-ICA-Uplink-1",
ContractIsLockedDueToLowFactionReputation = false
}
}
},
new FYFactionContractsData
{
FactionId = "Korolev",
Contracts = new List<FYFactionContractData>
{
new FYFactionContractData
{
ContractId = "NEW-Easy-KOR-Mine-4",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Medium-KOR-Mine-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Hard-KOR-PvP-6",
ContractIsLockedDueToLowFactionReputation = false
}
}
},
new FYFactionContractsData
{
FactionId = "Osiris",
Contracts = new List<FYFactionContractData>
{
new FYFactionContractData
{
ContractId = "NEW-Easy-Osiris-Brightcaps-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Medium-Osiris-Gather-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Hard-Osiris-Gather-7",
ContractIsLockedDueToLowFactionReputation = false
}
}
}
},
LastBoardRefreshTimeUtc = new FYTimestamp
{
Seconds = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds()
}
},
RefreshHours24UtcFromBackend = 12
};
break;
default:
_logger.LogWarning("Missing function {Function}", request.FunctionName);
result = new
{
};
break;
ExecutionTimeMilliseconds = 12,
FunctionName = request.FunctionName,
FunctionResult = result
}
});
}
return Ok(new ClientResponse<FExecuteFunctionResult>
{
Code = 200,
Status = "OK",
Data = new FExecuteFunctionResult
{
ExecutionTimeMilliseconds = 12,
FunctionName = request.FunctionName,
FunctionResult = result
}
});
return StatusCode(500);
}
}
+8
View File
@@ -0,0 +1,8 @@
using Microsoft.AspNetCore.SignalR;
namespace Prospect.Server.Api.Hubs;
public class CycleHub : Hub
{
}
@@ -18,5 +18,5 @@ public class FEntityKey
// Not in PlayFab SDK
[JsonPropertyName("TypeString")]
public string TypeString { get; set; } = null!;
public string? TypeString { get; set; } = null!;
}
@@ -23,7 +23,7 @@ public class FExecuteFunctionRequest
/// The name of the CloudScript function to execute
/// </summary>
[JsonPropertyName("FunctionName")]
public string? FunctionName { get; set; }
public string FunctionName { get; set; } = null!;
/// <summary>
/// [optional] Object that is passed in to the function as the FunctionArgument field of the FunctionExecutionContext data structure
@@ -38,5 +38,5 @@ public class FExecuteFunctionRequest
/// </summary>
[JsonPropertyName("GeneratePlayStreamEvent")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
public bool? GeneratePlayStreamEvent { get; set; }
public bool GeneratePlayStreamEvent { get; set; }
}
@@ -4,7 +4,7 @@
"commandName": "Project",
"dotnetRunMessages": "true",
"launchBrowser": false,
"applicationUrl": "http://localhost:5000",
"applicationUrl": "http://localhost:5000;https://localhost:5443",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
@@ -9,6 +9,7 @@
<ItemGroup>
<PackageReference Include="MongoDB.Driver" Version="2.14.1" />
<PackageReference Include="Serilog.AspNetCore" Version="4.1.0" />
<PackageReference Include="Sigil" Version="5.0.0" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="6.15.0" />
</ItemGroup>
@@ -0,0 +1,22 @@
using System.Runtime.Serialization;
namespace Prospect.Server.Api.Services.CloudScript;
public class CloudScriptException : Exception
{
public CloudScriptException()
{
}
protected CloudScriptException(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
public CloudScriptException(string? message) : base(message)
{
}
public CloudScriptException(string? message, Exception? innerException) : base(message, innerException)
{
}
}
@@ -0,0 +1,12 @@
namespace Prospect.Server.Api.Services.CloudScript;
[AttributeUsage(AttributeTargets.Class)]
public class CloudScriptFunction : Attribute
{
public CloudScriptFunction(string name)
{
Name = name;
}
public string Name { get; }
}
@@ -0,0 +1,80 @@
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;
using System.Reflection;
namespace Prospect.Server.Api.Services.CloudScript;
public record CloudScriptFunctionData(Type Clazz, Type RequestType, bool ReturnsObject, Func<object, object, Task> Delegate);
public class CloudScriptFunctionLoader
{
private readonly ILogger<CloudScriptFunctionLoader> _logger;
private readonly Dictionary<string, CloudScriptFunctionData> _methods;
public CloudScriptFunctionLoader(ILogger<CloudScriptFunctionLoader> logger)
{
_logger = logger;
_methods = LoadMethods();
}
public bool TryGetFunction(string name, [MaybeNullWhen(false)] out CloudScriptFunctionData functionData)
{
return _methods.TryGetValue(name, out functionData);
}
private Dictionary<string, CloudScriptFunctionData> LoadMethods()
{
var result = new Dictionary<string, CloudScriptFunctionData>();
var genericInterface = typeof(ICloudScriptFunction<,>);
foreach (var clazz in typeof(CloudScriptFunctionLoader).Assembly.GetTypes())
{
var attribute = clazz.GetCustomAttribute<CloudScriptFunction>();
if (attribute == null)
{
continue;
}
var clazzInterface = clazz.GetInterfaces().FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == genericInterface);
if (clazzInterface != null)
{
var genericTypes = clazzInterface.GetGenericArguments();
var typeReq = genericTypes[0];
var typeRes = genericTypes[1];
var method = clazz.GetMethod("ExecuteAsync", new []{ typeReq });
if (method == null)
{
_logger.LogWarning("ExecuteAsync method not found for class {Class}", clazz.FullName);
continue;
}
// Expression.
var argInstance = Expression.Parameter(typeof(object), "instance");
var argRequest = Expression.Parameter(typeof(object), "request");
var invokeReturn = Expression.Label(typeof(Task));
var invokeArgs = new Expression[]
{
Expression.Convert(argRequest, typeReq)
};
var invokeCall = Expression.Call(Expression.Convert(argInstance, clazz), method, invokeArgs);
var invoke = Expression.Block(
Expression.Return(invokeReturn, invokeCall),
Expression.Label(invokeReturn, Expression.Default(typeof(Task)))
);
var lambda = Expression.Lambda<Func<object, object, Task>>(invoke, argInstance, argRequest).Compile();
// Store lambda expression.
result.Add(attribute.Name, new CloudScriptFunctionData(clazz, typeReq, true, lambda));
}
}
return result;
}
}
@@ -0,0 +1,49 @@
using System.Text.Json;
namespace Prospect.Server.Api.Services.CloudScript;
public class CloudScriptService
{
private readonly ILogger<CloudScriptService> _logger;
private readonly IServiceScopeFactory _serviceScopeFactory;
private readonly CloudScriptFunctionLoader _functionLoader;
public CloudScriptService(ILogger<CloudScriptService> logger, IServiceScopeFactory serviceScopeFactory, CloudScriptFunctionLoader functionLoader)
{
_logger = logger;
_serviceScopeFactory = serviceScopeFactory;
_functionLoader = functionLoader;
}
public async Task<object?> ExecuteAsync(string name, string? parameter, bool generatePlayStreamEvent)
{
if (!_functionLoader.TryGetFunction(name, out var function))
{
_logger.LogWarning("Function {Function} is missing", name);
return null;
}
if (parameter == null)
{
_logger.LogWarning("Function {Function} was called without a parameter", name);
return null;
}
using (var scope = _serviceScopeFactory.CreateScope())
{
var functionClazz = ActivatorUtilities.CreateInstance(scope.ServiceProvider, function.Clazz);
var functionParam = JsonSerializer.Deserialize(parameter, function.RequestType);
if (functionParam == null)
{
_logger.LogWarning("Function {Function} deserialization returned null", name);
return null;
}
var functionTask = function.Delegate(functionClazz, functionParam);
await functionTask;
return (object)((dynamic)functionTask).Result;
}
}
}
@@ -0,0 +1,22 @@
using Prospect.Server.Api.Services.CloudScript.Models;
namespace Prospect.Server.Api.Services.CloudScript.Functions;
[CloudScriptFunction("EnterMatchmaking")]
public class EnterMatchmaking : ICloudScriptFunction<FYEnterMatchAzureFunction, FYEnterMatchAzureFunctionResult>
{
public Task<FYEnterMatchAzureFunctionResult> ExecuteAsync(FYEnterMatchAzureFunction request)
{
return Task.FromResult(new FYEnterMatchAzureFunctionResult
{
Success = true,
Address = "127.0.0.1",
ErrorMessage = "",
Port = 30229,
ShardIndex = 0,
SingleplayerStation = false,
MaintenanceMode = false,
SessionTimeJoinDelay = 0
});
}
}
@@ -0,0 +1,67 @@
using Prospect.Server.Api.Services.Auth.Extensions;
using Prospect.Server.Api.Services.CloudScript.Models;
namespace Prospect.Server.Api.Services.CloudScript.Functions;
[CloudScriptFunction("GetCharacterVanity")]
public class GetCharacterVanity : ICloudScriptFunction<FYGetCharacterVanityRequest, object?>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public GetCharacterVanity(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public Task<object?> ExecuteAsync(FYGetCharacterVanityRequest request)
{
var context = _httpContextAccessor.HttpContext;
if (context == null)
{
return Task.FromResult<object?>(null);
}
return Task.FromResult<object?>(new
{
userId = context.User.FindAuthUserId(),
error = (object?)null,
returnVanity = new
{
userId = context.User.FindAuthUserId(),
head_item = new
{
id = "Black02M_Head1",
materialIndex = 0,
},
boots_item = new
{
id = "StarterOutfit01_Boots_M",
materialIndex = 0,
},
chest_item = new
{
id = "StarterOutfit01_Chest_M",
materialIndex = 0,
},
glove_item = new
{
id = "StarterOutfit01_Gloves_M",
materialIndex = 0,
},
base_suit_item = new
{
id = "StarterOutfit01M_BaseSuit",
materialIndex = 0,
},
melee_weapon_item = new
{
id = "Melee_Omega",
materialIndex = 0,
},
body_type = 1,
archetype_id = "TheProspector",
slot_index = 0
}
});
}
}
@@ -0,0 +1,41 @@
using Prospect.Server.Api.Services.Auth.Extensions;
using Prospect.Server.Api.Services.CloudScript.Models;
using Prospect.Server.Api.Services.CloudScript.Models.Data;
namespace Prospect.Server.Api.Services.CloudScript.Functions;
[CloudScriptFunction("GetCraftingInProgressData")]
public class GetCraftingInProgressData : ICloudScriptFunction<FYGetCraftingInProgressDataRequest, FYGetCraftingInProgressDataResult>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public GetCraftingInProgressData(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public Task<FYGetCraftingInProgressDataResult> ExecuteAsync(FYGetCraftingInProgressDataRequest request)
{
var context = _httpContextAccessor.HttpContext;
if (context == null)
{
throw new CloudScriptException("CloudScript was not called within a http request");
}
return Task.FromResult(new FYGetCraftingInProgressDataResult
{
UserId = context.User.FindAuthUserId(),
Error = string.Empty,
ItemCurrentlyBeingCrafted = new FYItemCurrentlyBeingCrafted
{
ItemId = null,
ItemRarity = -1,
PurchaseAmount = -1,
UtcTimestampWhenCraftingStarted = new FYTimestamp
{
Seconds = 0
}
}
});
}
}
@@ -0,0 +1,15 @@
using Prospect.Server.Api.Services.CloudScript.Models;
namespace Prospect.Server.Api.Services.CloudScript.Functions;
[CloudScriptFunction("GetFriendList")]
public class GetFriendList : ICloudScriptFunction<FYBaseSocialRequest, object?>
{
public Task<object?> ExecuteAsync(FYBaseSocialRequest request)
{
return Task.FromResult<object?>(new
{
});
}
}
@@ -0,0 +1,49 @@
using Prospect.Server.Api.Services.Auth.Extensions;
using Prospect.Server.Api.Services.CloudScript.Models;
namespace Prospect.Server.Api.Services.CloudScript.Functions;
[CloudScriptFunction("GetPlayerSets")]
public class GetPlayerSets : ICloudScriptFunction<FYGetPlayersSets, object?>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public GetPlayerSets(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public Task<object?> ExecuteAsync(FYGetPlayersSets request)
{
var context = _httpContextAccessor.HttpContext;
if (context == null)
{
return Task.FromResult<object?>(null);
}
return Task.FromResult<object?>(new
{
success = true,
entries = new []
{
new
{
setData = new
{
id = "",
userId = context.User.FindAuthUserId(),
kit = "",
shield = "",
helmet = "",
weaponOne = "",
weaponTwo = "",
bag = "",
bagItemsAsJsonStr = "",
safeItemsAsJsonStr = ""
},
items = Array.Empty<object>()
}
}
});
}
}
@@ -0,0 +1,38 @@
using Prospect.Server.Api.Services.Auth.Extensions;
using Prospect.Server.Api.Services.CloudScript.Models;
namespace Prospect.Server.Api.Services.CloudScript.Functions;
[CloudScriptFunction("GetPlayersInventoriesLimits")]
public class GetPlayersInventoriesLimits : ICloudScriptFunction<FYGetPlayersInventoriesLimitsRequest, object?>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public GetPlayersInventoriesLimits(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public Task<object?> ExecuteAsync(FYGetPlayersInventoriesLimitsRequest request)
{
var context = _httpContextAccessor.HttpContext;
if (context == null)
{
return Task.FromResult<object?>(null);
}
return Task.FromResult<object?>(new
{
success = true,
entries = new []
{
new {
userId = context.User.FindAuthUserId(),
inventoryStashLimit = 75,
inventoryBagLimit = 300,
inventorySafeLimit = 5
}
}
});
}
}
@@ -0,0 +1,16 @@
using Prospect.Server.Api.Services.CloudScript.Models;
namespace Prospect.Server.Api.Services.CloudScript.Functions;
[CloudScriptFunction("GetSignalRConnection")]
public class GetSignalRConnection : ICloudScriptFunction<FYGetSignalRConnection, FYGetSignalRConnectionResult>
{
public Task<FYGetSignalRConnectionResult> ExecuteAsync(FYGetSignalRConnection request)
{
return Task.FromResult(new FYGetSignalRConnectionResult
{
Url = "https://localhost:5443/signalr/?hub=pubsub",
AccessToken = "TEST"
});
}
}
@@ -0,0 +1,48 @@
using Prospect.Server.Api.Services.Auth.Extensions;
using Prospect.Server.Api.Services.CloudScript.Models;
namespace Prospect.Server.Api.Services.CloudScript.Functions;
[CloudScriptFunction("RequestFactionProgression")]
public class RequestFactionProgression : ICloudScriptFunction<FYQueryFactionProgressionRequest, object?>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public RequestFactionProgression(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public Task<object?> ExecuteAsync(FYQueryFactionProgressionRequest request)
{
var context = _httpContextAccessor.HttpContext;
if (context == null)
{
return Task.FromResult<object?>(null);
}
return Task.FromResult<object?>(new
{
factions = new []
{
new
{
factionId = "ICA",
currentProgression = 0
},
new
{
factionId = "Korolev",
currentProgression = 0
},
new
{
factionId = "Osiris",
currentProgression = 0
},
},
userId = context.User.FindAuthUserId(),
error = ""
});
}
}
@@ -0,0 +1,15 @@
using Prospect.Server.Api.Services.CloudScript.Models;
namespace Prospect.Server.Api.Services.CloudScript.Functions;
[CloudScriptFunction("RequestMaintenanceModeState")]
public class RequestMaintenanceModeState : ICloudScriptFunction<FYMaintenanceModeState, FYRequestMaintenanceModeStateResult>
{
public Task<FYRequestMaintenanceModeStateResult> ExecuteAsync(FYMaintenanceModeState request)
{
return Task.FromResult(new FYRequestMaintenanceModeStateResult
{
Enabled = false
});
}
}
@@ -0,0 +1,109 @@
using Prospect.Server.Api.Services.Auth.Extensions;
using Prospect.Server.Api.Services.CloudScript.Models;
using Prospect.Server.Api.Services.CloudScript.Models.Data;
namespace Prospect.Server.Api.Services.CloudScript.Functions;
[CloudScriptFunction("RequestPlayerContracts")]
public class RequestPlayerContracts : ICloudScriptFunction<FYGetPlayerContractsRequest, FYGetPlayerContractsResult>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public RequestPlayerContracts(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public Task<FYGetPlayerContractsResult> ExecuteAsync(FYGetPlayerContractsRequest request)
{
var context = _httpContextAccessor.HttpContext;
if (context == null)
{
throw new CloudScriptException("CloudScript was not called within a http request");
}
return Task.FromResult(new FYGetPlayerContractsResult
{
UserId = context.User.FindAuthUserId(),
Error = null,
ActiveContracts = new List<FYActiveContractPlayerData>(),
FactionsContracts = new FYFactionsContractsData
{
Boards = new List<FYFactionContractsData>
{
new FYFactionContractsData
{
FactionId = "ICA",
Contracts = new List<FYFactionContractData>
{
new FYFactionContractData
{
ContractId = "NEW-Easy-ICA-Gather-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Medium-ICA-Uplink-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Hard-ICA-Uplink-1",
ContractIsLockedDueToLowFactionReputation = false
}
}
},
new FYFactionContractsData
{
FactionId = "Korolev",
Contracts = new List<FYFactionContractData>
{
new FYFactionContractData
{
ContractId = "NEW-Easy-KOR-Mine-4",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Medium-KOR-Mine-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Hard-KOR-PvP-6",
ContractIsLockedDueToLowFactionReputation = false
}
}
},
new FYFactionContractsData
{
FactionId = "Osiris",
Contracts = new List<FYFactionContractData>
{
new FYFactionContractData
{
ContractId = "NEW-Easy-Osiris-Brightcaps-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Medium-Osiris-Gather-1",
ContractIsLockedDueToLowFactionReputation = false
},
new FYFactionContractData
{
ContractId = "NEW-Hard-Osiris-Gather-7",
ContractIsLockedDueToLowFactionReputation = false
}
}
}
},
LastBoardRefreshTimeUtc = new FYTimestamp
{
Seconds = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds()
}
},
RefreshHours24UtcFromBackend = 12
});
}
}
@@ -0,0 +1,16 @@
using Prospect.Server.Api.Services.CloudScript.Models;
namespace Prospect.Server.Api.Services.CloudScript.Functions;
[CloudScriptFunction("SetMatchAllowJoin")]
public class SetMatchAllowJoin : ICloudScriptFunction<FYSetAllowJoinRequest, object?>
{
public Task<object?> ExecuteAsync(FYSetAllowJoinRequest request)
{
return Task.FromResult<object?>(new
{
sessionId = (object?)null,
success = false
});
}
}
@@ -0,0 +1,12 @@
using Prospect.Server.Api.Services.CloudScript.Models;
namespace Prospect.Server.Api.Services.CloudScript.Functions;
[CloudScriptFunction("UpdatePlayerPresenceState")]
public class UpdatePlayerPresenceState : ICloudScriptFunction<FYUpdatePlayerPresenceStateRequest, object>
{
public Task<object> ExecuteAsync(FYUpdatePlayerPresenceStateRequest request)
{
return Task.FromResult<object>(new { });
}
}
@@ -0,0 +1,38 @@
using Prospect.Server.Api.Services.Auth.Extensions;
using Prospect.Server.Api.Services.CloudScript.Models;
namespace Prospect.Server.Api.Services.CloudScript.Functions;
[CloudScriptFunction("UpdateRetentionBonus")]
public class UpdateRetentionBonus : ICloudScriptFunction<FYRetentionBonusRequest, object?>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public UpdateRetentionBonus(IHttpContextAccessor httpContextAccessor)
{
_httpContextAccessor = httpContextAccessor;
}
public Task<object?> ExecuteAsync(FYRetentionBonusRequest request)
{
var context = _httpContextAccessor.HttpContext;
if (context == null)
{
return Task.FromResult<object?>(null);
}
return Task.FromResult<object?>(new
{
playerData = new
{
daysClaimed = 0,
lastClaimTime = new
{
seconds = 1635033600
}
},
userId = context.User.FindAuthUserId(),
error = (object?)null
});
}
}
@@ -0,0 +1,15 @@
using Prospect.Server.Api.Services.CloudScript.Models;
namespace Prospect.Server.Api.Services.CloudScript.Functions;
[CloudScriptFunction("VivoxLogin")]
public class VivoxLogin : ICloudScriptFunction<FYVivoxLoginTokenRequest, FYVivoxJoinData>
{
public Task<FYVivoxJoinData> ExecuteAsync(FYVivoxLoginTokenRequest request)
{
return Task.FromResult(new FYVivoxJoinData
{
});
}
}
@@ -0,0 +1,15 @@
using Prospect.Server.Api.Services.CloudScript.Models;
namespace Prospect.Server.Api.Services.CloudScript.Functions;
[CloudScriptFunction("VivoxSettings")]
public class VivoxSettings : ICloudScriptFunction<FYEmptyRequest, FYVivoxSettingsData>
{
public Task<FYVivoxSettingsData> ExecuteAsync(FYEmptyRequest request)
{
return Task.FromResult(new FYVivoxSettingsData
{
});
}
}
@@ -0,0 +1,6 @@
namespace Prospect.Server.Api.Services.CloudScript;
public interface ICloudScriptFunction<TReq, TRes>
{
Task<TRes> ExecuteAsync(TReq request);
}
@@ -1,6 +1,6 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.CloudScript.Data;
namespace Prospect.Server.Api.Services.CloudScript.Models.Data;
public class FYActiveContractPlayerData
{
@@ -1,6 +1,6 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.CloudScript.Data;
namespace Prospect.Server.Api.Services.CloudScript.Models.Data;
public class FYFactionContractData
{
@@ -1,6 +1,6 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.CloudScript.Data;
namespace Prospect.Server.Api.Services.CloudScript.Models.Data;
public class FYFactionContractsData
{
@@ -1,6 +1,6 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.CloudScript.Data;
namespace Prospect.Server.Api.Services.CloudScript.Models.Data;
public class FYFactionsContractsData
{
@@ -1,11 +1,11 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.CloudScript.Data;
namespace Prospect.Server.Api.Services.CloudScript.Models.Data;
public class FYItemCurrentlyBeingCrafted
{
[JsonPropertyName("itemId")]
public string ItemId { get; set; } = null!;
public string? ItemId { get; set; }
[JsonPropertyName("itemRarity")]
public int ItemRarity { get; set; }
@@ -0,0 +1,7 @@
namespace Prospect.Server.Api.Services.CloudScript.Models.Data;
public class FYPurchaseInventoryInsuranceRequest
{
// m_insuranceId
// m_itemIds
}
@@ -1,6 +1,6 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Models.CloudScript.Data;
namespace Prospect.Server.Api.Services.CloudScript.Models.Data;
public class FYTimestamp
{
@@ -0,0 +1,18 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Services.CloudScript.Models.Data;
public class FYVivoxJoinTokenRequest
{
[JsonPropertyName("userName")]
public string? Username { get; set; }
[JsonPropertyName("channel")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Channel { get; set; }
// TODO: channelType
// TODO: hasText
// TODO: hasAudio
// TODO: channelId
}
@@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYBaseSocialRequest
{
[JsonPropertyName("targetPlayFabId")]
public string? TargetPlayFabId { get; set; }
}
@@ -0,0 +1,6 @@
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYEmptyRequest
{
}
@@ -0,0 +1,28 @@
using System.Text.Json.Serialization;
using Prospect.Server.Api.Services.CloudScript.Models.Data;
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYEnterMatchAzureFunction
{
[JsonPropertyName("optimalRegion")]
public string? OptimalRegion { get; set; }
[JsonPropertyName("isMatch")]
public bool IsMatch { get; set; }
[JsonPropertyName("bypassMaintenanceMode")]
public bool BypassMaintenanceMode { get; set; }
[JsonPropertyName("debugOption")]
public string? DebugOption { get; set; }
[JsonPropertyName("mapName")]
public string? MapName { get; set; }
[JsonPropertyName("squad_id")]
public string? SquadId { get; set; }
[JsonPropertyName("purchaseInventoryInsurances")]
public List<FYPurchaseInventoryInsuranceRequest>? PurchaseInventoryInsurances { get; set; }
}
@@ -0,0 +1,30 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYEnterMatchAzureFunctionResult
{
[JsonPropertyName("success")]
public bool Success { get; set; }
[JsonPropertyName("address")]
public string? Address { get; set; }
[JsonPropertyName("errorMessage")]
public string? ErrorMessage { get; set; }
[JsonPropertyName("port")]
public int Port { get; set; }
[JsonPropertyName("sharedIndex")]
public int ShardIndex { get; set; }
[JsonPropertyName("singleplayerStation")]
public bool SingleplayerStation { get; set; }
[JsonPropertyName("maintenanceMode")]
public bool MaintenanceMode { get; set; }
[JsonPropertyName("sessionTimeJoinDelay")]
public float SessionTimeJoinDelay { get; set; }
}
@@ -0,0 +1,6 @@
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYGetCharacterVanityRequest
{
}
@@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYGetCraftingInProgressDataRequest
{
[JsonPropertyName("userId")]
public string? UserId { get; set; }
}
@@ -1,7 +1,7 @@
using System.Text.Json.Serialization;
using Prospect.Server.Api.Models.CloudScript.Data;
using Prospect.Server.Api.Services.CloudScript.Models.Data;
namespace Prospect.Server.Api.Models.CloudScript;
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYGetCraftingInProgressDataResult
{
@@ -0,0 +1,6 @@
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYGetPlayerContractsRequest
{
}
@@ -1,7 +1,7 @@
using System.Text.Json.Serialization;
using Prospect.Server.Api.Models.CloudScript.Data;
using Prospect.Server.Api.Services.CloudScript.Models.Data;
namespace Prospect.Server.Api.Models.CloudScript;
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYGetPlayerContractsResult
{
@@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYGetPlayersInventoriesLimitsRequest
{
[JsonPropertyName("userIds")]
public List<string>? UserIds { get; set; }
}
@@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYGetPlayersSets
{
[JsonPropertyName("userIds")]
public List<string>? UserIds { get; set; }
}
@@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYGetSignalRConnection
{
[JsonPropertyName("userId")]
public string UserId { get; set; }
}
@@ -0,0 +1,12 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYGetSignalRConnectionResult
{
[JsonPropertyName("url")]
public string Url { get; set; } = null!;
[JsonPropertyName("accessToken")]
public string AccessToken { get; set; } = null!;
}
@@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYMaintenanceModeState
{
[JsonPropertyName("bypassMaintenanceMode")]
public bool BypassMaintenanceMode { get; set; }
}
@@ -0,0 +1,6 @@
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYQueryFactionProgressionRequest
{
}
@@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYRequestMaintenanceModeStateResult
{
[JsonPropertyName("enabled")]
public bool Enabled { get; set; }
}
@@ -0,0 +1,6 @@
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYRetentionBonusRequest
{
}
@@ -0,0 +1,12 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYSetAllowJoinRequest
{
[JsonPropertyName("sessionId")]
public string? SessionId { get; set; }
[JsonPropertyName("allowJoin")]
public bool AllowJoin { get; set; }
}
@@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYUpdatePlayerPresenceStateRequest
{
[JsonPropertyName("inMatch")]
public bool InMatch { get; set; }
}
@@ -0,0 +1,15 @@
using System.Text.Json.Serialization;
using Prospect.Server.Api.Services.CloudScript.Models.Data;
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYVivoxJoinData
{
[JsonPropertyName("request")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public FYVivoxJoinTokenRequest? Request { get; set; }
[JsonPropertyName("token")]
[JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public string? Token { get; set; }
}
@@ -0,0 +1,9 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYVivoxLoginTokenRequest
{
[JsonPropertyName("username")]
public string? Username { get; set; }
}
@@ -0,0 +1,15 @@
using System.Text.Json.Serialization;
namespace Prospect.Server.Api.Services.CloudScript.Models;
public class FYVivoxSettingsData
{
[JsonPropertyName("vivoxServer")]
public string? VivoxServer { get; set; }
[JsonPropertyName("vivoxDomain")]
public string? VivoxDomain { get; set; }
[JsonPropertyName("vivoxIssuer")]
public string? VivoxIssuer { get; set; }
}
+10
View File
@@ -1,7 +1,9 @@
using Prospect.Server.Api.Config;
using Prospect.Server.Api.Converters;
using Prospect.Server.Api.Hubs;
using Prospect.Server.Api.Middleware;
using Prospect.Server.Api.Services.Auth;
using Prospect.Server.Api.Services.CloudScript;
using Prospect.Server.Api.Services.Database;
using Prospect.Server.Api.Services.Qos;
using Prospect.Server.Api.Services.UserData;
@@ -36,6 +38,9 @@ public class Startup
services.AddHostedService<QosService>();
services.AddSingleton<QosServer>();
services.AddScoped<CloudScriptService>();
services.AddSingleton<CloudScriptFunctionLoader>();
services.AddAuthentication(_ =>
{
@@ -43,6 +48,10 @@ public class Startup
.AddUserAuthentication(_ => {})
.AddEntityAuthentication(_ => {});
services.AddHttpContextAccessor();
services.AddSignalR();
services.AddControllers().AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new DateTimeConverter());
@@ -64,6 +73,7 @@ public class Startup
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapHub<CycleHub>("/signalr");
});
}
}