Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pjv:laboratoare:2024:a04 [2024/11/18 11:42]
alexandru.gradinaru [Cerinte]
pjv:laboratoare:2024:a04 [2025/11/26 03:29] (current)
andrei.lapusteanu
Line 8: Line 8:
   * - prezentare exemple de pe github/​tutoriale (in special SpaceRumble probabil care are majoritatea elementelor din cerinta ..    * - prezentare exemple de pe github/​tutoriale (in special SpaceRumble probabil care are majoritatea elementelor din cerinta .. 
 [[https://​github.com/​PlayFab/​PlayFab-Samples/​tree/​master/​Samples/​Unity/​SpaceRumble]]) [[https://​github.com/​PlayFab/​PlayFab-Samples/​tree/​master/​Samples/​Unity/​SpaceRumble]])
 +    * Nu mai e valid repo 🥲  ​
  
-  
- 
-</​hidden>​ 
 ==== Cerinte ===== ==== Cerinte =====
  
Line 26: Line 24:
 Bonus: interfata grafica pentru selectarea personajului/​avatarului si a leaderboardului Bonus: interfata grafica pentru selectarea personajului/​avatarului si a leaderboardului
  
-<note tip>Daca nu ati mai lucrat cu Playfabsugestia este sa plecati ​de la scena de tip Example ​in Unity intrucat este ceva boostraping ​de facut</note>+Andrei-L: 
 +  * Ceva de adaugat/​scos?​ 
 +  * Pentru ca am scris destul de detaliat conceptele + code examples -- sa crestem putin dificultatea?​ Sau sa dam alt bonus? 
 +  * Putem si taia din ce am scris o parte si sa-i lasam pe ei sa faca singuri 
 +  * Eu as propune sa pastram ce task-uri avem deja, dar sa mai adaugam cateva in plus :). Ceea ce e deja aici ii ajuta ca un jumpstartdupa care pentru sisteme noi sa caute ei. Posibile exemple: 
 +    * Sa foloseasca scheduled tasks pentru a automatiza niste procese din joc 
 +    * Nu am atins deloc sistemul ​de economie din PlayFab, dar PlayFab cer adugarea unui credit card (chiar daca esti pe tier-ul free) pentru a-l folosi :(.  
 +    * In PlayFab exista sistemul de Groups, de ex. pot crea clans sau roluri per membru (dar nu-mi vine in cap un exemplu bun de utilizare acum) 
 +    * Propun sa implementeze ceva cu Content -> Title Data. Aici poti defini configs pe server/​backend ... si sa faca ceva logica de joc. Exemplu: Sa aiba 2 scene de joc, iar in Title Data sa existe un key-value pair care specifica current game mode, clientul sa-l citeasca ​la runtime si sa porneasca ​scena corecta pe baza informatiei fetched 
 +    * O alta idee ar putea fi sa faca ceva cu player segments. Sistemul asta poate defini o cohorta de player pe baza de reguli (ex. players which logged ​in the past 14 days) ... doar ca trebuie o idee ce sa faca cu asta 
 +    * Login mai custom 🤔 Like Google, Facebook, etc. Dar nu cunosc complexitatea 
 +    * PlayFab se poate lega cu add-ons, (Dashboard -> Add-ons), de ex. pot face ceva cu SMTP, asta e util de ex. daca un user isi face cont via email + pass, PlayFab ii trimite apoi un email de verificare. Sau cu asta pot face Rules/Scheduled tasks pentru marketing. Hm, poate e o idee. In Dashboard -> Content -exista Email Templates. 
 ===== Documentatie video ====== ===== Documentatie video ======
 +
 Gasiti pe MS Teams inregistrat Gasiti pe MS Teams inregistrat
  
 ===== Documentatie text ====== ===== Documentatie text ======
  
 +==== Introducere în PlayFab ====
  
-==== PlayFab ==== +PlayFab este unul dintre serviicile web dedicate jocurilor video, oferit de Microsoft, similar cu alte servicii de la AWS, Epic Online Services, Unity, Steam si altele. Este un backend as a service (BaaS) care oferă funcționalități esențiale pentru jocuri: autentificare,​ date persistente pentru playeri, leaderboard-uri,​ matchmaking,​ economy, etc.
- +
-PlayFab este unul dintre serviicile web dedicate jocurilor video, oferit de Microsoft, similar cu alte servicii de la AWS, Epic Online Services, Unity, Steam si altele.+
  
 In general aceste servicii vin deja cu un SDK implementat pentru motoarele grafice cunoscute (Unity, Unreal etc), dar se pot utiliza si direct prin cereri HTTP intr-o arhitectura REST. SDK-ul este in general un wrapper peste un REST API. In general aceste servicii vin deja cu un SDK implementat pentru motoarele grafice cunoscute (Unity, Unreal etc), dar se pot utiliza si direct prin cereri HTTP intr-o arhitectura REST. SDK-ul este in general un wrapper peste un REST API.
 +
 +Resurse oficiale:
 +
 +  * [[https://​playfab.com/​|Site oficial PlayFab]]
 +  * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​|Documentație oficială Microsoft]]
 +  * [[https://​github.com/​PlayFab/​UnitySDK|PlayFab Unity SDK pe GitHub]]
 +
 +==== Instalarea și configurarea SDK-ului ====
 +
 +=== 1. Crearea unui cont PlayFab ===
 +
 +  * Accesați [[https://​developer.playfab.com/​|PlayFab Developer Portal]]
 +  * Creați-vă un cont
 +  * Creați un nou Title (proiect/​joc) - veți primi un Title ID unic
 +
 +=== 2. Import PlayFab SDK ===
 +
 +  * Accesați pagina de GitHub a SDK-ului pentru Unity, [[https://​github.com/​PlayFab/​UnitySDK|Unity SDK]]
 +  * Urmați pașii de la secțiunea //3. Installing or Upgrading the PlayFab UnitySdk//
 +    * Recomandăm să integrați Unity package-ul pentru **PlayFab Unity Editor Extensions**
 +    * Din Unity, puteți apoi să instalați SDK-ul -- găsiți fereastra de setup în Window → Window → Editor Extensions
 +
 +<note tip>
 +Găsiți mai multe detalii, dacă aveți nevoie, în [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​sdks/​unity3d/​quickstart|Quickstart:​ PlayFab Client library for C# in Unity]]
 +</​note>​
 +
 +==== Concepte PlayFab ====
 +
 +=== Autentificare ===
 +
 +Primul pas pentru folosirea oricarui serviciu dedicat este autentificare. Procesul este simplificat prin folosirea SDK-ului.
 +
 +PlayFab acceptă o varietate de furnizori de autentificare (Microsoft, Facebook, Google etc). Pentru development și testare rapidă, cel mai simplu este **LoginWithCustomID** care folosește device ID-ul:
 +
 +<code csharp>
 +void LoginWithCustomId()
 +{
 +    var request = new LoginWithCustomIDRequest
 +    {
 +        CreateAccount = true,  // Should be true if account does *not* exist (does a sort of create-and-login).
 +        CustomId = PlayFabSettings.DeviceUniqueIdentifier
 +    };
 +    ​
 +    PlayFabClientAPI.LoginWithCustomID(request,​
 +        result => Debug.Log($"​Login successful! PlayFabId: {result.PlayFabId}"​),​
 +        error => Debug.LogError($"​Error:​ {error.GenerateErrorReport()}"​)
 +    );
 +}
 +</​code>​
 +
 +<​note>​
 +Pentru alte metode de autentificare (Facebook, Google, etc), consultați [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​identity/​player-identity/​platform-specific-authentication/​|documentația oficială]].
 +</​note>​
 +
 +=== Player Data ===
 +
 +PlayFab oferă mai multe tipuri de stocare pentru date asociate playerilor:
 +
 +**User Data (client R/W, server R/W)**
 +  * Date la care clientul are acces complet
 +  * Exemple: preferințe setări joc, cosmetics, etc.
 +  * Nu este indicat să le folosiți pentru date critice/​sensibile (progres, currency)
 +
 +**User Read-Only Data (client read-only, server R/W)**
 +  * Date pe care doar serverul le poate modifica (R/W)
 +  * Clientul poate doar să le citească (read-only)
 +  * Utilizare: progres quest-uri, achievement-uri
 +
 +**Internal Data (server R/W only)**
 +  * Complet invizibil pentru client - nu poate fi nici citit
 +  * Accesibil doar din CloudScript prin ''​server.GetUserInternalData''​ / ''​UpdateUserInternalData''​
 +  * Utilizare: date pentru logica de backend (cooldowns, timestamps server-side,​ rate limiting)
 +
 +**Exemplu User Data:**
 +
 +<​note>​Pentru interacțiunea cu sistemul **User Data** ne vom folosi de API-ul clientului, ''​PlayFabClientAPI''​.</​note>​
 +
 +<code csharp>
 +void SavePlayerString(string playerStr)
 +{
 +    var request = new UpdateUserDataRequest
 +    {
 +        Data = new Dictionary<​string,​ string>
 +        {
 +            { "​SomeStringValue",​ playerStr }
 +        }
 +    };
 +    PlayFabClientAPI.UpdateUserData(request,​
 +        result => Debug.Log("​Data has been saved remotely!"​),​
 +        error => Debug.LogError(error.GenerateErrorReport())
 +    );
 +}
 +
 +void LoadPlayerString()
 +{
 +    PlayFabClientAPI.GetUserData(new GetUserDataRequest(),​
 +        result =>
 +        {
 +            if (result.Data.TryGetValue("​SomeStringValue",​ out var data))
 +            {
 +                string fetchedStr = data.Value;
 +                Debug.Log($"​Fetched data: {fetchedStr}"​);​
 +            }
 +        },
 +        error => Debug.LogError(error.GenerateErrorReport())
 +    );
 +}
 +</​code>​
 +
 +<note tip>
 +Datele stocate pot fi vizualizate pe dashboard: Mergeți la secțiunea **Players**,​ găsiți player-ul pentru care ați scris datele, accesați tab-ul **Player Data**.
 +</​note>​
 +
 +<​note>​
 +Mai multe detalii: [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​player-progression/​player-data|Player Data]]
 +</​note>​
 +
 +=== CloudScript ===
 +
 +CloudScript permite executarea de cod **pe serverele PlayFab**, nu pe client. Esențial pentru validare server-side și prevenirea cheating-ului.
 +
 +**De ce CloudScript?​** Pentru orice logică critică (quest progress, achievements,​ currency) avem nevoie de validare server-side.
 +
 +<note important>​
 +În producție, recomandăm folosirea **Azure Functions** (C#) în loc de CloudScript (JavaScript) pentru logică backend complexă. Acestea oferă mai multă flexibilitate,​ debugging mai bun și support pentru limbaje moderne. Setup-ul pentru Azure Functions este însă mai complex și depășește scope-ul acestui laborator, astfel că vom folosi CloudScript clasic (JavaScript) pentru simplitate.
 +</​note>​
 +
 +<note important>​
 +CloudScript nu este exclusiv pentru a scrie/citi din date ale player-ului. Puteți efectua multe alte operațiuni,​ de exemplu grant de item sau virtual currency, schimbare date generale ale proiectului PlayFab (Title Data), etc.
 +</​note>​
 +
 +**Exemplu utilizare:​**
 +
 +1. Pentru a scrie cod backend in CloudScript:​
 +  * Dashboard → Automation → CloudScript → Revisions (Legacy)
 +  * Scrieți codul JavaScript
 +  * Apăsați **Upload new revision**
 +  * Bifați **Deploy this revision after save**, apăsați **Save and deploy** ​
 +
 +<code javascript>​
 +handlers.IncrementCounter = function(args,​ context) {
 +    var res = server.GetUserReadOnlyData({
 +        PlayFabId: currentPlayerId,​
 +        Keys: ["​Counter"​]
 +    });
 +    ​
 +    var count = 0;
 +    if (res.Data["​Counter"​] !== undefined) {
 +        count = JSON.parse(res.Data["​Counter"​].Value);​
 +    }
 +    count++;
 +    ​
 +    server.UpdateUserReadOnlyData({
 +        PlayFabId: currentPlayerId,​
 +        Data: { "​Counter":​ count }
 +    });
 +    ​
 +    return count;
 +};
 +</​code>​
 +
 +2. Apel CloudScript function din Unity:
 +
 +<code csharp>
 +void CallCloudScript()
 +{
 +    PlayFabClientAPI.ExecuteCloudScript(new ExecuteCloudScriptRequest
 +    {
 +        FunctionName = "​IncrementCounter"​
 +    },
 +    result => Debug.Log($"​Counter:​ {result.FunctionResult}"​),​
 +    error => Debug.LogError(error.GenerateErrorReport())
 +    );
 +}
 +</​code>​
 +
 +<note tip>
 +Pentru debugging, folosiți ''​log.info("​message"​)''​ în CloudScript. Verificați output-ul în **Dashboard → Title Overview → PlayStream Monitor**.
 +</​note>​
 +
 +<​note>​
 +Mai multe detalii: [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​features/​automation/​cloudscript/​quickstart|CloudScript Quickstart]]
 +</​note>​
 +
 +=== Event Automation ===
 +
 +PlayFab poate declanșa automat CloudScript functions în două moduri:
 +
 +**Rules (PlayStream Events)** - se execută când anumite evenimente apar în joc:
 +  * Player login/​logout
 +  * Statistic updated
 +  * Player data changed
 +  * Item purchased
 +  * Custom events definite de voi
 +  * Util pentru a reacționa (aproape) **instant** la acțiunile playerilor
 +
 +**Scheduled Tasks** - se execută periodic la intervale fixe:
 +  * Daily/​weekly/​monthly rewards
 +  * Season resets
 +  * Leaderboard cleanup
 +  * Maintenance tasks
 +  * Util pentru task-uri **recurente** independente de acțiunile playerilor
 +
 +**Exemplu de utilizare Rules:**
 +
 +Puteți crea o regulă care să incrementeze automat un counter de login-uri de fiecare dată când un player se autentifică:​
 +  * **Automation → Rules → New Rule**
 +  * Event Type: ''​player_logged_in''​
 +  * Actions → Execute Entity Cloud Script
 +  * Function Name: ''​updatePlayerLogins''​ (presupunem că există funcția în CloudScript)
 +
 +Astfel, de fiecare dată când un player face login, PlayFab va apela automat funcția CloudScript fără să fie nevoie de apel explicit din client.
 +
 +**Exemplu de utilizare Scheduled Tasks:**
 +
 +Puteți crea un task care să reseteze daily rewards pentru toți playerii la miezul nopții:
 +  * **Automation → Scheduled Tasks → New Task**
 +  * Schedule type: Recurring (ex: Daily la 00:00 UTC)
 +  * Type of task: Run Cloud Script function one
 +  * Function Name: ''​resetDailyRewards''​ (presupunem că există funcția în CloudScript)
 +
 +<note tip>
 +Verificați execuția task-urilor în **Automation → Scheduled Tasks (scroll în josul paginii)** pentru debugging.
 +</​note>​
 +
 +<​note>​
 +Mai multe detalii:
 +  * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​data-analytics/​acting-data/​scheduled-tasks|Scheduled Tasks]]
 +  * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​data-analytics/​acting-data/​action-rules-quickstart|Actions and rules quickstart]]
 +</​note>​
 +
 +=== Statistics și Leaderboards ===
 +
 +PlayFab folosește două concepte separate pentru datele jucătorilor ce țin de scor, progres, etc., **statistics** și **leaderboard-uri** -- dar în backend-ul din PlayFab acestea sunt (destul de) legate și utilitatea acestora constă în sinergia dintre cele două concepte.
 +
 +**Statistics** = valori numerice tracked per player (high scores, kills, wins, etc.)
 +  * Se creează în **Leaderboards → Statistics → New statistic**
 +  * Setări de interes:
 +    * **Statistic name** - numele statisticii (ex: "​HighScore"​)
 +    * **Aggregation method** - cum se calculează valoarea:
 +      * Last - ultima valoare
 +      * Max - cea mai mare (pentru high scores)
 +      * Min - cea mai mică (pentru best times)
 +      * Sum - se însumează toate valorile
 +    * **Statistic frequency** - Manual / Day / Week / Month (când se resetează statistica - PlayFab face asta automat)
 +
 +**Leaderboards** = clasamente bazate pe statistici
 +  * Se creează în **Leaderboards → Leaderboards → New leaderboard**
 +  * Trebuie linked la o statistică existentă (**Linked statistic name**)
 +  * Leaderboard-ul se actualizează automat când se modifică statistica
 +
 +Pentru a putea folosi API-ul de stats/​leaderboards pe clienți (să le permiteți actualizarea acestora):
 +  * **Settings → API Features**
 +  * Bifați "Allow client to post player statistics"​
 +
 +<​note>​
 +În mod ideal această setare este destul de **sensibilă**,​ întrucât permite jucătorilor actualizarea acestor valori - în scop didactic este OK.
 +</​note>​
 +
 +**Update statistică din Unity:**
 +
 +<code csharp>
 +using PlayFab;
 +using PlayFab.ProgressionModels;​
 +
 +void SubmitScore(int score)
 +{
 +    var request = new UpdateStatisticsRequest
 +    {
 +        Entity = new EntityKey
 +        {
 +            Id = "<​Entity_ID>", ​ // Player'​s entity ID (from login response).
 +            Type = "​title_player_account"​
 +        },
 +        Statistics = new List<​StatisticUpdate>​
 +        {
 +            new StatisticUpdate
 +            {
 +                Name = "​HighScore",​
 +                Scores = new List<​string>​ { score.ToString() }
 +            }
 +        }
 +    };
 +    ​
 +    PlayFabProgressionAPI.UpdateStatistics(request,​
 +        result => Debug.Log("​Statistic updated!"​),​
 +        error => Debug.LogError(error.GenerateErrorReport())
 +    );
 +}
 +</​code>​
 +
 +**Citire leaderboard:​**
 +
 +<code csharp>
 +using PlayFab;
 +using PlayFab.ProgressionModels;​
 +
 +private void GetLeaderboard()
 +{
 +    var request = new GetEntityLeaderboardRequest
 +    {
 +        LeaderboardName = "​HighScore_Leaderboard",​
 +        StartingPosition = 1,  // 1 = beginning of leaderboard (not 0!).
 +        PageSize = 10          // Min 1, max 100.
 +    };
 +    PlayFabProgressionAPI.GetLeaderboard(request,​
 +        result =>
 +        {
 +            foreach (var entry in result.Rankings)
 +            {
 +                Debug.Log($"​{entry.Rank}. {entry.DisplayName}:​ {entry.Scores[0]}"​);​
 +            }
 +        },
 +        error => Debug.LogError(error.GenerateErrorReport())
 +    );
 +}
 +</​code>​
 +
 +**Citire leaderboard în jurul playerului:​**
 +
 +<code csharp>
 +using PlayFab;
 +using PlayFab.ProgressionModels;​
 +
 +void GetLeaderboardAroundPlayer()
 +{
 +    var request = new GetLeaderboardAroundEntityRequest
 +    {
 +        Entity = new EntityKey
 +        {
 +            Id = "<​Entity_ID>", ​    // Player'​s entity ID (from login response).
 +            Type = "​title_player_account"​
 +        },
 +        LeaderboardName = "​HighScore_Leaderboard",​
 +        MaxSurroundingEntries = 10  // Number of entries above and below (these are split ~half/​half).
 +    };
 +    PlayFabProgressionAPI.GetLeaderboardAroundEntity(request,​
 +        result =>
 +        {
 +            foreach (var entry in result.Rankings)
 +            {
 +                Debug.Log($"​{entry.Rank}. {entry.DisplayName}:​ {entry.Scores[0]}"​);​
 +            }
 +        },
 +        error => Debug.LogError(error.GenerateErrorReport())
 +    );
 +}
 +</​code>​
 +
 +<note tip>
 +Pentru a obține Entity ID-ul playerului după login, folosiți ''​result.EntityToken.Entity.Id''​ din response-ul de la LoginWithCustomID.
 +</​note>​
 +
 +<note tip>
 +Vizualizați statisticile în **Leaderboards → Statistics** și leaderboard-ul în **Leaderboards → Leaderboards**.
 +</​note>​
 +
 +<​note>​
 +Mai multe detalii: ​
 +
 +[Statistics]
 +  * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​player-progression/​statistics|Azure PlayFab Statistics overview]]
 +  * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​player-progression/​statistics/​quickstart-statistics|Quickstart statistics]]
 +  * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​player-progression/​statistics/​create-basic-statistics|Create a basic statistic]]
 +[Leaderboards]
 +  * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​community/​leaderboards|Azure PlayFab Leaderboards overview]]
 +  * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​community/​leaderboards/​quickstart-leaderboards|Quickstart leaderboards]]
 +  * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​community/​leaderboards/​create-basic-leaderboard|Create a basic leaderboard]]
 +</​note>​
 +==== Resurse utile ====
 +
 +**Documentație:​**
 +  * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​identity/​player-identity/​platform-specific-authentication/​|Authentication]]
 +  * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​player-progression/​player-data|Player Data]]
 +  * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​features/​automation/​cloudscript/​quickstart|CloudScript]]
 +  * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​player-progression/​statistics|Statistics overview]]
 +  * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​community/​leaderboards|Leaderboards overview]]
 +  * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​data-analytics/​acting-data/​scheduled-tasks|Scheduled Tasks]]
 +  * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​data-analytics/​acting-data/​action-rules-quickstart|Actions and rules quickstart]]
 +
 +**Exemple:​**
 +  * [[https://​github.com/​PlayFab/​PlayFab-Samples|PlayFab Samples]]
 +  * [[https://​github.com/​PlayFab/​CloudScriptSamples|CloudScript Samples]]
 +
 +**Support:​**
 +  * [[https://​discord.com/​invite/​msftgamedev|PlayFab Community (Discord)]]
 +
 +==== ~~~~~~~~~~~~~~~~~ OLD TEXT ~~~~~~~~~~~~~~~~~ ====
 +
 +<note tip>Daca nu ati mai lucrat cu Playfab, sugestia este sa plecati de la o scena de tip sample in Unity intrucat este ceva boostraping de facut - vedeti mai jos in documentatie </​note>​
  
 Asadar, primul pas pentru folosirea oricarui serviciu dedicat este autentificare. Procesul este simplificat prin folosirea SDK-ului. Asadar, primul pas pentru folosirea oricarui serviciu dedicat este autentificare. Procesul este simplificat prin folosirea SDK-ului.
Line 51: Line 451:
  
 Cateva link-uri utile: Cateva link-uri utile:
-  * [[https://github.com/PlayFab/​PlayFab-Samples/tree/master/Samples/Unity|Unity samples]]+  * [[https://learn.microsoft.com/en-us/gaming/playfab/resources/playfab-samples|Playfab ​samples]]
   * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​features/​authentication/​|Informatii / tutoriale Autentificare]]   * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​features/​authentication/​|Informatii / tutoriale Autentificare]]
   * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​features/​new-leaderboards-statistics/​leaderboards/​|Leaderboards]]   * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​features/​new-leaderboards-statistics/​leaderboards/​|Leaderboards]]
   * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​features/​data/​|PlayerData]]   * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​features/​data/​|PlayerData]]
   * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​features/​automation/​|Automation]]   * [[https://​learn.microsoft.com/​en-us/​gaming/​playfab/​features/​automation/​|Automation]]
 +
 +</​hidden>​
pjv/laboratoare/2024/a04.1731922921.txt.gz · Last modified: 2024/11/18 11:42 by alexandru.gradinaru
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0