Compare commits
7
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
57a45d91df | ||
|
|
c6b2330e1d | ||
|
|
922deb8397 | ||
|
|
f4d93c9e71 | ||
|
|
9737316dbc | ||
|
|
b0822c34cd | ||
|
|
310e2bf7e9 |
+27
-10
@@ -9,21 +9,38 @@ Guide pour **installer le client et jouer sur le serveur privé**. Tu n'installe
|
||||
|
||||
---
|
||||
|
||||
## Ce que l'hébergeur doit te fournir
|
||||
1. **`LoaderPack.zip`** (le loader qui redirige le jeu vers le serveur privé).
|
||||
2. **`certificate.crt`** (le certificat **public** du serveur — sans clé privée, safe à partager).
|
||||
## Fichiers à télécharger (dans la release)
|
||||
Les 2 fichiers sont dispo dans la **release Gitea** :
|
||||
👉 **https://git.nfteam.ovh/neckfire/the-cycle/releases/tag/friends-client**
|
||||
|
||||
1. **`LoaderPack.zip`** — le loader qui redirige le jeu vers le serveur privé (build b8 / Saison 2).
|
||||
2. **`certificate.crt`** — le certificat **public** du serveur (sans clé privée, safe).
|
||||
|
||||
Télécharge les deux depuis la page de release avant de commencer.
|
||||
|
||||
---
|
||||
|
||||
## Étapes (Windows)
|
||||
|
||||
### 1. Installer le client Saison 2
|
||||
Deux options :
|
||||
- **Simple** : installe The Cycle: Frontier depuis ta bibliothèque Steam (`steam://install/868270`).
|
||||
- **Recommandé (client Saison 2 exact)** via la console Steam :
|
||||
1. Steam ouvert, `Win+R` → `steam://nav/console`.
|
||||
2. Va sur les manifests SteamDB du dépôt 868271, cherche `4623363103423775682` (client S2 v2.7.2).
|
||||
3. Copie la commande **Steam console** et colle-la dans la console Steam → le téléchargement démarre.
|
||||
### 1. Installer le client Saison 2 (via la console Steam)
|
||||
1. Steam ouvert, `Win+R` → tape `steam://nav/console` → Entrée (la **console Steam** s'ouvre).
|
||||
2. Colle **exactement** cette commande → Entrée :
|
||||
```
|
||||
download_depot 868270 868271 4623363103423775682
|
||||
```
|
||||
(`868270` = le jeu, `868271` = le dépôt client, `4623363103423775682` = manifest **Saison 2 v2.7.2**.)
|
||||
3. Le téléchargement démarre (⚠️ **pas de barre de progression**, sois patient — plusieurs Go).
|
||||
4. À la fin, Steam affiche **« Depot download complete »** + le **chemin du dossier**
|
||||
(ex. `...\Steam\steamapps\content\app_868270\depot_868271`). **Ce dossier = ton install du jeu.**
|
||||
|
||||
> Il faut **avoir eu The Cycle: Frontier dans ta bibliothèque Steam** avant, sinon → erreur `missing license`.
|
||||
|
||||
> **Pas assez d'espace sur le disque principal ?** `download_depot` écrit toujours dans `...\Steam\steamapps\content`. Pour le mettre sur un autre disque : ferme Steam, supprime `...\Steam\steamapps\content`, puis en **cmd admin** :
|
||||
> ```
|
||||
> mkdir "D:\SteamContent"
|
||||
> mklink /J "C:\Program Files (x86)\Steam\steamapps\content" "D:\SteamContent"
|
||||
> ```
|
||||
> Rouvre Steam et relance la commande → le jeu ira sur `D:\`.
|
||||
|
||||
### 2. Installer le LoaderPack
|
||||
1. Va dans le dossier du jeu → **`Prospect\Binaries\Win64`**.
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Prospect.Server.Api.Services.Auth.Extensions;
|
||||
using Prospect.Server.Api.Services.CloudScript;
|
||||
using Prospect.Server.Api.Services.UserData;
|
||||
|
||||
public class ClientsideFriendsImportRequest
|
||||
{
|
||||
@@ -18,15 +21,33 @@ public class ClientsideFriendsImportResponse
|
||||
public class ClientsideFriendsImportFunction : ICloudScriptFunction<ClientsideFriendsImportRequest, ClientsideFriendsImportResponse>
|
||||
{
|
||||
private readonly ILogger<ClientsideFriendsImportFunction> _logger;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly UserDataService _userDataService;
|
||||
|
||||
public ClientsideFriendsImportFunction(ILogger<ClientsideFriendsImportFunction> logger)
|
||||
public ClientsideFriendsImportFunction(ILogger<ClientsideFriendsImportFunction> logger, IHttpContextAccessor httpContextAccessor, UserDataService userDataService)
|
||||
{
|
||||
_logger = logger;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_userDataService = userDataService;
|
||||
}
|
||||
|
||||
public async Task<ClientsideFriendsImportResponse> ExecuteAsync(ClientsideFriendsImportRequest request)
|
||||
{
|
||||
_logger.LogInformation("Processing friends import");
|
||||
var context = _httpContextAccessor.HttpContext;
|
||||
if (context == null)
|
||||
{
|
||||
throw new CloudScriptException("CloudScript was not called within a http request");
|
||||
}
|
||||
var userId = context.User.FindAuthUserId();
|
||||
|
||||
// Persist the platform friend ids the client imports (Steam ids) so GetFriendList
|
||||
// can later resolve which of them actually play on this server.
|
||||
var ids = request.UserIDs ?? Array.Empty<string>();
|
||||
await _userDataService.UpdateAsync(userId, userId, new Dictionary<string, string>
|
||||
{
|
||||
["ImportedSteamFriends"] = JsonSerializer.Serialize(ids),
|
||||
});
|
||||
_logger.LogInformation("Imported {Count} {Platform} friend id(s) for user {User}", ids.Length, request.Platform, userId);
|
||||
|
||||
return new ClientsideFriendsImportResponse{};
|
||||
}
|
||||
|
||||
@@ -1,15 +1,71 @@
|
||||
using Prospect.Server.Api.Services.CloudScript.Models;
|
||||
using System.Text.Json;
|
||||
using Prospect.Server.Api.Services.Auth.Extensions;
|
||||
using Prospect.Server.Api.Services.CloudScript.Models;
|
||||
using Prospect.Server.Api.Services.Database;
|
||||
using Prospect.Server.Api.Services.Database.Models;
|
||||
using Prospect.Server.Api.Services.UserData;
|
||||
|
||||
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
|
||||
{
|
||||
private readonly ILogger<GetFriendList> _logger;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly UserDataService _userDataService;
|
||||
private readonly DbUserService _userService;
|
||||
|
||||
});
|
||||
public GetFriendList(ILogger<GetFriendList> logger, IHttpContextAccessor httpContextAccessor, UserDataService userDataService, DbUserService userService)
|
||||
{
|
||||
_logger = logger;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_userDataService = userDataService;
|
||||
_userService = userService;
|
||||
}
|
||||
|
||||
public async Task<object?> ExecuteAsync(FYBaseSocialRequest request)
|
||||
{
|
||||
var context = _httpContextAccessor.HttpContext;
|
||||
if (context == null)
|
||||
{
|
||||
throw new CloudScriptException("CloudScript was not called within a http request");
|
||||
}
|
||||
var userId = context.User.FindAuthUserId();
|
||||
|
||||
// Resolve the imported Steam friends (persisted by ClientsideFriendsImport) to the
|
||||
// players that actually exist on this server. It's a private server, so only friends
|
||||
// who have logged in here will show up.
|
||||
var steamIds = new List<string>();
|
||||
var userData = await _userDataService.FindAsync(userId, userId, new List<string> { "ImportedSteamFriends" });
|
||||
if (userData.TryGetValue("ImportedSteamFriends", out var rec) && !string.IsNullOrWhiteSpace(rec.Value))
|
||||
{
|
||||
try { steamIds = JsonSerializer.Deserialize<List<string>>(rec.Value) ?? new List<string>(); }
|
||||
catch { /* ignore malformed */ }
|
||||
}
|
||||
|
||||
var friends = new List<object>();
|
||||
if (steamIds.Count > 0)
|
||||
{
|
||||
var players = await _userService.FindManyAsync(PlayFabUserAuthType.Steam, steamIds);
|
||||
foreach (var player in players)
|
||||
{
|
||||
if (player.Id == userId) continue; // never list yourself
|
||||
friends.Add(new
|
||||
{
|
||||
profile = new
|
||||
{
|
||||
playerId = player.Id,
|
||||
displayName = player.DisplayName,
|
||||
avatarUrl = "",
|
||||
},
|
||||
onlineState = 0, // EYUserState — real presence tracking is a later phase
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: the exact response shape the client expects is not yet confirmed; this is a
|
||||
// best-effort structure. The log lets us verify resolution while we validate in game.
|
||||
_logger.LogInformation("GetFriendList for {User}: {Count} friend(s) resolved on server", userId, friends.Count);
|
||||
return new { friends };
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ public class RegionObject
|
||||
[JsonPropertyName("region")]
|
||||
public string Region { get; set; }
|
||||
[JsonPropertyName("ping")]
|
||||
public int Ping { get; set; }
|
||||
public long Ping { get; set; } // client sends 2147483648 (int.MaxValue+1) for "no ping" -> must be long or deserialization 500s
|
||||
[JsonPropertyName("instanceType")]
|
||||
public int InstanceType { get; set; }
|
||||
}
|
||||
|
||||
@@ -43,4 +43,18 @@ public class DbUserService : BaseDbService<PlayFabUser>
|
||||
return await FindAsync(type, key) ??
|
||||
await CreateAsync(type, key);
|
||||
}
|
||||
|
||||
// Resolve several auth keys (e.g. a batch of Steam IDs) to the players that exist on
|
||||
// this server in a single query. Used by the friends list to keep only the imported
|
||||
// Steam friends who have actually played here.
|
||||
public async Task<List<PlayFabUser>> FindManyAsync(PlayFabUserAuthType type, IReadOnlyCollection<string> keys)
|
||||
{
|
||||
if (keys == null || keys.Count == 0)
|
||||
{
|
||||
return new List<PlayFabUser>();
|
||||
}
|
||||
var wanted = new HashSet<string>(keys);
|
||||
return await Collection.Find(user => user.Auth.Any(auth =>
|
||||
auth.Type == type && wanted.Contains(auth.Key))).ToListAsync();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user