diff --git a/Refresh.GameServer/Authentication/TokenGame.cs b/Refresh.GameServer/Authentication/TokenGame.cs index b9c1b78e..4b79c67a 100644 --- a/Refresh.GameServer/Authentication/TokenGame.cs +++ b/Refresh.GameServer/Authentication/TokenGame.cs @@ -10,6 +10,7 @@ public enum TokenGame LittleBigPlanetVita = 3, LittleBigPlanetPSP = 4, Website = 5, + BetaBuild = 6, } public static class TokenGameExtensions @@ -22,6 +23,7 @@ public static int ToSerializedGame(this TokenGame game) TokenGame.LittleBigPlanet3 => 2, TokenGame.LittleBigPlanetVita => 1, TokenGame.LittleBigPlanetPSP => 0, + TokenGame.BetaBuild => 1, // treat beta levels as LBP2 for now. TokenGame.Website => throw new InvalidOperationException("https://osuhow.com/"), _ => throw new ArgumentOutOfRangeException(), }; @@ -59,6 +61,12 @@ public static bool CanPlay(this TokenGame game, GameLevel level) if (level.GameVersion != TokenGame.LittleBigPlanetPSP) return false; + break; + // Isolate beta builds' levels + case TokenGame.BetaBuild: + if (level.GameVersion != TokenGame.BetaBuild) + return false; + break; //Allow all for website case TokenGame.Website: diff --git a/Refresh.GameServer/Authentication/TokenGameUtility.cs b/Refresh.GameServer/Authentication/TokenGameUtility.cs index dbcf19a9..8eb5fccb 100644 --- a/Refresh.GameServer/Authentication/TokenGameUtility.cs +++ b/Refresh.GameServer/Authentication/TokenGameUtility.cs @@ -24,11 +24,6 @@ public static class TokenGameUtility "NPJA00052", // JP Digital "BCJS30018", // JP Disc - - // Betas/Debug/Prerelease - "BCET70002", // EU "Online Trial" Beta Test - "BCET70011", // EU Water Beta Test - "NPUA70045", // US Demo }; private static readonly string[] LittleBigPlanet2Titles = @@ -53,11 +48,6 @@ public static class TokenGameUtility "BCJS30058", // JP Disc // missing japan digital? - - // Betas/Debug/Prerelease - "NPUA70117", // US Private Beta - "BCET70055", // LBP Hub (real title id) - "NPEA00449", // LBP HUB (sent title id) }; // PS4 title ids are not here on purpose. @@ -86,11 +76,6 @@ public static class TokenGameUtility "NPJG00073", // JP Digital "NPHG00033", // Asia Digital - - // Betas/Debug/Prerelease - "NPUG70064", // US Demo - "NPEG90019", // EU Demo - "NPHG00035", // Asia Demo }; private static readonly string[] LittleBigPlanetVitaTitles = @@ -106,8 +91,26 @@ public static class TokenGameUtility "PCSC00013", // JP Digital "VCJS10006", // JP Cartridge + }; + + private static readonly string[] BetaBuildTitles = + { + // LBP1 + "BCET70002", // EU "Online Trial" Beta Test + "BCET70011", // EU Water Beta Test + "NPUA70045", // US Demo + + // LBP2 + "NPUA70117", // US Private Beta + "BCET70055", // LBP Hub (real title id) + "NPEA00449", // LBP HUB (sent title id) + + // PSP + "NPUG70064", // US Demo + "NPEG90019", // EU Demo + "NPHG00035", // Asia Demo - // Betas/Debug/Prerelease + // Vita "PCSA00061", // US Beta "PCSF00152", // EU Beta }; @@ -119,6 +122,7 @@ public static class TokenGameUtility if (LittleBigPlanet3Titles.Contains(titleId)) return TokenGame.LittleBigPlanet3; if (LittleBigPlanetPSPTitles.Contains(titleId)) return TokenGame.LittleBigPlanetPSP; if (LittleBigPlanetVitaTitles.Contains(titleId)) return TokenGame.LittleBigPlanetVita; + if (BetaBuildTitles.Contains(titleId)) return TokenGame.BetaBuild; return null; } diff --git a/Refresh.GameServer/Database/GameDatabaseContext.Users.cs b/Refresh.GameServer/Database/GameDatabaseContext.Users.cs index c56e1085..5bcc65f3 100644 --- a/Refresh.GameServer/Database/GameDatabaseContext.Users.cs +++ b/Refresh.GameServer/Database/GameDatabaseContext.Users.cs @@ -96,6 +96,9 @@ public void UpdateUserData(GameUser user, SerializedUpdateData data, TokenGame g case TokenGame.LittleBigPlanetVita: user.VitaPlanetsHash = data.PlanetsHash; break; + case TokenGame.BetaBuild: + user.BetaPlanetsHash = data.PlanetsHash; + break; } // ReSharper disable once InvertIf @@ -131,6 +134,9 @@ public void UpdateUserData(GameUser user, SerializedUpdateData data, TokenGame g //so we separate PSP icons to another field user.PspIconHash = data.IconHash; break; + case TokenGame.BetaBuild: + user.BetaIconHash = data.IconHash; + break; } }); } @@ -331,7 +337,6 @@ public void SetForceMatch(GameUser user, GameUser target) }); } - #if DEBUG public void ForceUserTokenGame(Token token, TokenGame game) { this._realm.Write(() => @@ -347,5 +352,4 @@ public void ForceUserTokenPlatform(Token token, TokenPlatform platform) token.TokenPlatform = platform; }); } - #endif } \ No newline at end of file diff --git a/Refresh.GameServer/Database/GameDatabaseProvider.cs b/Refresh.GameServer/Database/GameDatabaseProvider.cs index 0a264f12..487f56f3 100644 --- a/Refresh.GameServer/Database/GameDatabaseProvider.cs +++ b/Refresh.GameServer/Database/GameDatabaseProvider.cs @@ -33,7 +33,7 @@ protected GameDatabaseProvider(IDateTimeProvider time) this._time = time; } - protected override ulong SchemaVersion => 115; + protected override ulong SchemaVersion => 116; protected override string Filename => "refreshGameServer.realm"; @@ -365,6 +365,7 @@ protected override void Migrate(Migration migration, ulong oldVersion) TokenGame.LittleBigPlanet3 => TokenPlatform.PS3, TokenGame.LittleBigPlanetVita => TokenPlatform.Vita, TokenGame.LittleBigPlanetPSP => TokenPlatform.PSP, + TokenGame.BetaBuild => TokenPlatform.RPCS3, TokenGame.Website => throw new InvalidOperationException($"what? score id {newScore.ScoreId} by {newScore.Players[0].Username} is fucked"), _ => throw new ArgumentOutOfRangeException(), }; diff --git a/Refresh.GameServer/Endpoints/Game/DataTypes/Response/GameUserResponse.cs b/Refresh.GameServer/Endpoints/Game/DataTypes/Response/GameUserResponse.cs index a27ca108..86010fdc 100644 --- a/Refresh.GameServer/Endpoints/Game/DataTypes/Response/GameUserResponse.cs +++ b/Refresh.GameServer/Endpoints/Game/DataTypes/Response/GameUserResponse.cs @@ -120,6 +120,7 @@ private void FillInExtraData(GameUser old, TokenGame gameVersion, GameDatabaseCo TokenGame.LittleBigPlanetVita => old.VitaPlanetsHash, TokenGame.LittleBigPlanetPSP => "0", TokenGame.Website => "0", + TokenGame.BetaBuild => old.BetaPlanetsHash, _ => throw new ArgumentOutOfRangeException(nameof(gameVersion), gameVersion, null), }; @@ -175,6 +176,20 @@ private void FillInExtraData(GameUser old, TokenGame gameVersion, GameDatabaseCo this.FavouriteLevels = new SerializedMinimalFavouriteLevelList(new SerializedMinimalLevelList(favouriteLevels, favouriteLevels.Count, favouriteLevels.Count)); break; } + case TokenGame.BetaBuild: + { + // only beta levels + this.UsedSlots = old.PublishedLevels.Count(x => x._GameVersion == (int)TokenGame.BetaBuild); + this.FreeSlots = MaximumLevels - this.UsedSlotsLBP2; + + // use the same values for LBP3 and LBP2 since they're all shared under one count + this.UsedSlotsLBP3 = this.UsedSlots; + this.FreeSlotsLBP3 = this.FreeSlots; + + this.UsedSlotsLBP2 = this.UsedSlots; + this.FreeSlotsLBP2 = this.FreeSlots; + break; + } case TokenGame.Website: break; default: throw new ArgumentOutOfRangeException(nameof(gameVersion), gameVersion, null); diff --git a/Refresh.GameServer/Endpoints/Game/Handshake/AuthenticationEndpoints.cs b/Refresh.GameServer/Endpoints/Game/Handshake/AuthenticationEndpoints.cs index 1b0241bc..6a755c4c 100644 --- a/Refresh.GameServer/Endpoints/Game/Handshake/AuthenticationEndpoints.cs +++ b/Refresh.GameServer/Endpoints/Game/Handshake/AuthenticationEndpoints.cs @@ -133,7 +133,13 @@ public class AuthenticationEndpoints : EndpointGroup } } - TokenGame? game = TokenGameUtility.FromTitleId(ticket.TitleId); + TokenGame? game = null; + + // check if we're connecting from a beta build + bool parsedBeta = byte.TryParse(context.QueryString.Get("beta"), out byte isBeta); + if (parsedBeta && isBeta == 1) game = TokenGame.BetaBuild; + + game ??= TokenGameUtility.FromTitleId(ticket.TitleId); if (platform == null) { diff --git a/Refresh.GameServer/Extensions/LevelEnumerableExtensions.cs b/Refresh.GameServer/Extensions/LevelEnumerableExtensions.cs index efbdd001..5932940d 100644 --- a/Refresh.GameServer/Extensions/LevelEnumerableExtensions.cs +++ b/Refresh.GameServer/Extensions/LevelEnumerableExtensions.cs @@ -15,6 +15,7 @@ public static IEnumerable FilterByGameVersion(this IEnumerable levels.Where(l => l._GameVersion <= (int)TokenGame.LittleBigPlanet3), TokenGame.LittleBigPlanetVita => levels.Where(l => l._GameVersion == (int)TokenGame.LittleBigPlanetVita), TokenGame.LittleBigPlanetPSP => levels.Where(l => l._GameVersion == (int)TokenGame.LittleBigPlanetPSP), + TokenGame.BetaBuild => levels.Where(l => l._GameVersion == (int)TokenGame.BetaBuild), TokenGame.Website => levels, _ => throw new ArgumentOutOfRangeException(nameof(gameVersion), gameVersion, null), }; @@ -27,6 +28,7 @@ public static IQueryable FilterByGameVersion(this IQueryable levels.Where(l => l._GameVersion <= (int)TokenGame.LittleBigPlanet3), TokenGame.LittleBigPlanetVita => levels.Where(l => l._GameVersion == (int)TokenGame.LittleBigPlanetVita), TokenGame.LittleBigPlanetPSP => levels.Where(l => l._GameVersion == (int)TokenGame.LittleBigPlanetPSP), + TokenGame.BetaBuild => levels.Where(l => l._GameVersion == (int)TokenGame.BetaBuild), TokenGame.Website => levels, _ => throw new ArgumentOutOfRangeException(nameof(gameVersion), gameVersion, null), }; @@ -36,14 +38,19 @@ public static IQueryable FilterByLevelFilterSettings(this IQueryable< if (levelFilterSettings.ExcludeMyLevels && user != null) levels = levels.Where(l => l.Publisher != user); - levels = levelFilterSettings.GameFilterType switch { - GameFilterType.LittleBigPlanet1 => levels.Where(l => l._GameVersion == (int)TokenGame.LittleBigPlanet1), - GameFilterType.LittleBigPlanet2 => levels.Where(l => l._GameVersion == (int)TokenGame.LittleBigPlanet2), - //NOTE: ideally this should be .Where(l => l._GameVersion == (int)TokenGame.LittleBigPlane1 || l._GameVersion == (int)TokenGame.LittleBigPlane2) - // however, there should be no differences in all real-world cases - GameFilterType.Both => levels, - _ => throw new ArgumentOutOfRangeException(), - }; + // Don't allow beta builds to use this filtering option + // If the client specifies this option then it will filter out *all* levels. + if (levelFilterSettings.GameVersion != TokenGame.BetaBuild) + { + levels = levelFilterSettings.GameFilterType switch { + GameFilterType.LittleBigPlanet1 => levels.Where(l => l._GameVersion == (int)TokenGame.LittleBigPlanet1), + GameFilterType.LittleBigPlanet2 => levels.Where(l => l._GameVersion == (int)TokenGame.LittleBigPlanet2), + //NOTE: ideally this should be .Where(l => l._GameVersion == (int)TokenGame.LittleBigPlane1 || l._GameVersion == (int)TokenGame.LittleBigPlane2) + // however, there should be no differences in all real-world cases + GameFilterType.Both => levels, + _ => throw new ArgumentOutOfRangeException(), + }; + } if (levelFilterSettings.Players != 0) levels = levels.Where(l => l.MaxPlayers >= levelFilterSettings.Players && l.MinPlayers <= levelFilterSettings.Players); @@ -68,14 +75,19 @@ public static IEnumerable FilterByLevelFilterSettings(this IEnumerabl if (levelFilterSettings.ExcludeMyLevels && user != null) levels = levels.Where(l => l.Publisher != user); - levels = levelFilterSettings.GameFilterType switch { - GameFilterType.LittleBigPlanet1 => levels.Where(l => l._GameVersion == (int)TokenGame.LittleBigPlanet1), - GameFilterType.LittleBigPlanet2 => levels.Where(l => l._GameVersion == (int)TokenGame.LittleBigPlanet2), - //NOTE: ideally this should be .Where(l => l._GameVersion == (int)TokenGame.LittleBigPlane1 || l._GameVersion == (int)TokenGame.LittleBigPlane2) - // however, there should be no differences in all real-world cases - GameFilterType.Both => levels, - _ => throw new ArgumentOutOfRangeException(), - }; + // Don't allow beta builds to use this filtering option + // If the client specifies this option then it will filter out *all* levels. + if (levelFilterSettings.GameVersion != TokenGame.BetaBuild) + { + levels = levelFilterSettings.GameFilterType switch { + GameFilterType.LittleBigPlanet1 => levels.Where(l => l._GameVersion == (int)TokenGame.LittleBigPlanet1), + GameFilterType.LittleBigPlanet2 => levels.Where(l => l._GameVersion == (int)TokenGame.LittleBigPlanet2), + //NOTE: ideally this should be .Where(l => l._GameVersion == (int)TokenGame.LittleBigPlane1 || l._GameVersion == (int)TokenGame.LittleBigPlane2) + // however, there should be no differences in all real-world cases + GameFilterType.Both => levels, + _ => throw new ArgumentOutOfRangeException(), + }; + } if (levelFilterSettings.Players != 0) levels = levels.Where(l => l.MaxPlayers >= levelFilterSettings.Players && l.MinPlayers <= levelFilterSettings.Players); diff --git a/Refresh.GameServer/Services/CommandService.cs b/Refresh.GameServer/Services/CommandService.cs index 503079cf..f8fd662b 100644 --- a/Refresh.GameServer/Services/CommandService.cs +++ b/Refresh.GameServer/Services/CommandService.cs @@ -133,6 +133,16 @@ public void HandleCommand(CommandInvocation command, GameDatabaseContext databas } break; } + case "beta": + { + database.ForceUserTokenGame(token, TokenGame.BetaBuild); + break; + } + case "revoketoken": + { + database.RevokeToken(token); + break; + } #if DEBUG case "tokengame": { diff --git a/Refresh.GameServer/Services/GuidCheckerService.cs b/Refresh.GameServer/Services/GuidCheckerService.cs index 4fd81757..37d49780 100644 --- a/Refresh.GameServer/Services/GuidCheckerService.cs +++ b/Refresh.GameServer/Services/GuidCheckerService.cs @@ -60,6 +60,7 @@ public bool IsTextureGuid(TokenGame game, long guid) TokenGame.LittleBigPlanet3 => this._validMainlineTextureGuids.TryGetValue(guid, out _), TokenGame.LittleBigPlanetVita => this._validVitaTextureGuids.TryGetValue(guid, out _), TokenGame.LittleBigPlanetPSP => guid is >= 0 and <= 63, //PSP avatar GUIDs can be g0 - g63 + TokenGame.BetaBuild => this._validMainlineTextureGuids.TryGetValue(guid, out _), _ => throw new ArgumentOutOfRangeException(nameof(game), game, null), }; } diff --git a/Refresh.GameServer/Types/UserData/GameUser.cs b/Refresh.GameServer/Types/UserData/GameUser.cs index efa52791..ed21a1fe 100644 --- a/Refresh.GameServer/Types/UserData/GameUser.cs +++ b/Refresh.GameServer/Types/UserData/GameUser.cs @@ -43,6 +43,10 @@ public partial class GameUser : IRealmObject, IRateLimitUser /// Vita GUIDs do not map to mainline GUIDs, so we dont want someone to set their Vita icon, and it map to an invalid GUID on PS3. /// public string VitaIconHash { get; set; } = "0"; + /// + /// The , except only for clients in beta mode. + /// + public string BetaIconHash { get; set; } = "0"; public string Description { get; set; } = ""; public GameLocation Location { get; set; } = GameLocation.Zero; @@ -77,6 +81,7 @@ public partial class GameUser : IRealmObject, IRateLimitUser public IList IpVerificationRequests { get; } #nullable restore + public string BetaPlanetsHash { get; set; } = "0"; public string Lbp2PlanetsHash { get; set; } = "0"; public string Lbp3PlanetsHash { get; set; } = "0"; public string VitaPlanetsHash { get; set; } = "0";