public int BindingKarmaCost() { Gear objFocusGear = GearObject; // Each Focus costs an amount of Karma equal to their Force x speicific Karma cost. string strFocusName = objFocusGear.Name; string strFocusExtra = objFocusGear.Extra; decimal decExtraKarmaCost = 0; //TODO: Oh god I hate putting in this kind of behaviour but we don't have anything else handy that supports altering focus cost. if (strFocusName.EndsWith(", Individualized, Complete", StringComparison.Ordinal)) { decExtraKarmaCost = -2; strFocusName = strFocusName.Replace(", Individualized, Complete", string.Empty); } else if (strFocusName.EndsWith(", Individualized, Partial", StringComparison.Ordinal)) { decExtraKarmaCost = -1; strFocusName = strFocusName.Replace(", Individualized, Partial", string.Empty); } int intPosition = strFocusName.IndexOf('('); if (intPosition > -1) { strFocusName = strFocusName.Substring(0, intPosition - 1); } intPosition = strFocusName.IndexOf(','); if (intPosition > -1) { strFocusName = strFocusName.Substring(0, intPosition); } decimal decKarmaMultiplier = 1; CharacterSettings characterObjectSettings = GearObject.CharacterObject.Settings; switch (strFocusName) { case "Qi Focus": decKarmaMultiplier = characterObjectSettings.KarmaQiFocus; break; case "Sustaining Focus": decKarmaMultiplier = characterObjectSettings.KarmaSustainingFocus; break; case "Counterspelling Focus": decKarmaMultiplier = characterObjectSettings.KarmaCounterspellingFocus; break; case "Banishing Focus": decKarmaMultiplier = characterObjectSettings.KarmaBanishingFocus; break; case "Binding Focus": decKarmaMultiplier = characterObjectSettings.KarmaBindingFocus; break; case "Weapon Focus": decKarmaMultiplier = characterObjectSettings.KarmaWeaponFocus; break; case "Spellcasting Focus": decKarmaMultiplier = characterObjectSettings.KarmaSpellcastingFocus; break; case "Ritual Spellcasting Focus": decKarmaMultiplier = characterObjectSettings.KarmaRitualSpellcastingFocus; break; case "Spell Shaping Focus": decKarmaMultiplier = characterObjectSettings.KarmaSpellShapingFocus; break; case "Summoning Focus": decKarmaMultiplier = characterObjectSettings.KarmaSummoningFocus; break; case "Alchemical Focus": decKarmaMultiplier = characterObjectSettings.KarmaAlchemicalFocus; break; case "Centering Focus": decKarmaMultiplier = characterObjectSettings.KarmaCenteringFocus; break; case "Masking Focus": decKarmaMultiplier = characterObjectSettings.KarmaMaskingFocus; break; case "Disenchanting Focus": decKarmaMultiplier = characterObjectSettings.KarmaDisenchantingFocus; break; case "Power Focus": decKarmaMultiplier = characterObjectSettings.KarmaPowerFocus; break; case "Flexible Signature Focus": decKarmaMultiplier = characterObjectSettings.KarmaFlexibleSignatureFocus; break; } if (string.IsNullOrWhiteSpace(strFocusExtra)) { foreach (Improvement objLoopImprovement in GearObject.CharacterObject.Improvements.Where( x => x.ImprovedName == strFocusName && string.IsNullOrEmpty(x.Target) && x.Enabled)) { switch (objLoopImprovement.ImproveType) { case Improvement.ImprovementType.FocusBindingKarmaCost: decExtraKarmaCost += objLoopImprovement.Value; break; case Improvement.ImprovementType.FocusBindingKarmaMultiplier: decKarmaMultiplier += objLoopImprovement.Value; break; } } } else { foreach (Improvement objLoopImprovement in GearObject.CharacterObject.Improvements.Where( x => x.ImprovedName == strFocusName && (string.IsNullOrEmpty(x.Target) || x.Target.Contains(strFocusExtra)) && x.Enabled)) { switch (objLoopImprovement.ImproveType) { case Improvement.ImprovementType.FocusBindingKarmaCost: decExtraKarmaCost += objLoopImprovement.Value; break; case Improvement.ImprovementType.FocusBindingKarmaMultiplier: decKarmaMultiplier += objLoopImprovement.Value; break; } } } return((Rating * decKarmaMultiplier + decExtraKarmaCost).StandardRound()); }
/// <summary> /// Spawns a new player character and transfers the connection's control into the new body. /// If existingMind is null, creates the new mind and assigns it to the new body. /// /// Fires server and client side player spawn hooks. /// </summary> /// <param name="connection">connection to give control to the new player character</param> /// <param name="occupation">occupation of the new player character</param> /// <param name="characterSettings">settings of the new player character</param> /// <param name="existingMind">existing mind to transfer to the new player, if null new mind will be created /// and assigned to the new player character</param> /// <param name="spawnPos">world position to spawn at</param> /// <param name="spawnItems">If spawning a player, should the player spawn without the defined initial equipment for their occupation?</param> /// <param name="willDestroyOldBody">if true, indicates the old body is going to be destroyed rather than pooled, /// thus we shouldn't send any network message which reference's the old body's ID since it won't exist.</param> /// /// <returns>the spawned object</returns> private static GameObject ServerSpawnInternal(NetworkConnection connection, Occupation occupation, CharacterSettings characterSettings, Mind existingMind, Vector3Int?spawnPos = null, bool spawnItems = true, bool willDestroyOldBody = false, bool showBanner = true) { //determine where to spawn them if (spawnPos == null) { Transform spawnTransform; //Spawn normal location for special jobs or if less than 2 minutes passed if (GameManager.Instance.stationTime < ARRIVALS_SPAWN_TIME || occupation.LateSpawnIsArrivals == false) { spawnTransform = SpawnPoint.GetRandomPointForJob(occupation.JobType); } else { spawnTransform = SpawnPoint.GetRandomPointForLateSpawn(); //Fallback to assistant spawn location if none found for late join if (spawnTransform == null && occupation.JobType != JobType.NULL) { spawnTransform = SpawnPoint.GetRandomPointForJob(JobType.ASSISTANT); } } if (spawnTransform == null) { Logger.LogErrorFormat( "Unable to determine spawn position for connection {0} occupation {1}. Cannot spawn player.", Category.EntitySpawn, connection.address, occupation.DisplayName); return(null); } spawnPos = spawnTransform.transform.position.CutToInt(); } //create the player object var newPlayer = ServerCreatePlayer(spawnPos.GetValueOrDefault(), occupation.SpecialPlayerPrefab); var newPlayerScript = newPlayer.GetComponent <PlayerScript>(); //get the old body if they have one. var oldBody = existingMind?.GetCurrentMob(); //transfer control to the player object ServerTransferPlayer(connection, newPlayer, oldBody, Event.PlayerSpawned, characterSettings, willDestroyOldBody); if (existingMind == null) { //create the mind of the player Mind.Create(newPlayer, occupation); } else { //transfer the mind to the new body existingMind.SetNewBody(newPlayerScript); } var ps = newPlayer.GetComponent <PlayerScript>(); var connectedPlayer = PlayerList.Instance.Get(connection); connectedPlayer.Name = ps.playerName; connectedPlayer.Job = ps.mind.occupation.JobType; UpdateConnectedPlayersMessage.Send(); //fire all hooks var info = SpawnInfo.Player(occupation, characterSettings, CustomNetworkManager.Instance.humanPlayerPrefab, SpawnDestination.At(spawnPos), spawnItems: spawnItems); Spawn._ServerFireClientServerSpawnHooks(SpawnResult.Single(info, newPlayer)); if (occupation != null && showBanner) { SpawnBannerMessage.Send( newPlayer, occupation.DisplayName, occupation.SpawnSound.AssetAddress, occupation.TextColor, occupation.BackgroundColor, occupation.PlaySound); } if (info.SpawnItems) { newPlayer.GetComponent <DynamicItemStorage>()?.SetUpOccupation(occupation); } return(newPlayer); }
public static void ServerTransferPlayerToNewBody(NetworkConnection conn, GameObject newBody, GameObject oldBody, Event eventType, CharacterSettings characterSettings, bool willDestroyOldBody = false) { ServerTransferPlayer(conn, newBody, oldBody, eventType, characterSettings, willDestroyOldBody); }
public static void ClonePlayer(NetworkConnection conn, short playerControllerId, JobType jobType, CharacterSettings characterSettings, GameObject oldBody, GameObject spawnSpot) { GameObject player = CreateMob(spawnSpot, CustomNetworkManager.Instance.humanPlayerPrefab); TransferPlayer(conn, playerControllerId, player, oldBody, EVENT.PlayerSpawned, characterSettings); var playerScript = player.GetComponent <PlayerScript>(); var oldPlayerScript = oldBody.GetComponent <PlayerScript>(); oldPlayerScript.mind.SetNewBody(playerScript); }
public static GameObject SpawnPlayerGhost(NetworkConnection conn, short playerControllerId, GameObject oldBody, CharacterSettings characterSettings) { GameObject ghost = CreateMob(oldBody, CustomNetworkManager.Instance.ghostPrefab); TransferPlayer(conn, playerControllerId, ghost, oldBody, EVENT.GhostSpawned, characterSettings); return(ghost); }
public PlayerInfo(InputDevice dev, CharacterSettings cs, TeamSettings ts) { input = dev; charSettings = cs; teamSettings = ts; }
/// <summary> /// Server-side only. For use when a player has only joined (as a JoinedViewer) and /// is not in control of any mobs. Spawns the joined viewer as the indicated occupation and transfers control to it. /// Note that this doesn't take into account game mode or antags, it just spawns whatever is requested. /// </summary> /// <param name="joinedViewer">viewer who should control the player</param> /// <param name="occupation">occupation to spawn as</param> /// <param name="characterSettings">settings to use for the character</param> /// <returns>the game object of the spawned player</returns> public static GameObject ServerSpawnPlayer(JoinedViewer joinedViewer, Occupation occupation, CharacterSettings characterSettings) { NetworkConnection conn = joinedViewer.connectionToClient; // TODO: add a nice cutscene/animation for the respawn transition var newPlayer = ServerSpawnInternal(conn, occupation, characterSettings, null); if (newPlayer) { if (occupation.JobType != JobType.SYNDICATE && occupation.JobType != JobType.AI) { SecurityRecordsManager.Instance.AddRecord(newPlayer.GetComponent <PlayerScript>(), occupation.JobType); } } if (SpawnEvent != null) { SpawnEventArgs args = new SpawnEventArgs() { player = newPlayer }; SpawnEvent.Invoke(null, args); } return(newPlayer); }
/// <summary> /// Updates the state of the bold button /// </summary> void UpdateBoldState(CharacterSettings settings) { UpdateToggleButtonCheckedState(_btnBold, settings.Bold); }
/// <summary> /// Updates the state of the italic button /// </summary> void UpdateItalicState(CharacterSettings settings) { UpdateToggleButtonCheckedState(_btnItalic, settings.Italics); }
/******************** Public Interface ********************/ public void SetPlayerSettings(InputDevice device, CharacterSettings charSet, TeamSettings teamSet) { input = device; charSettings = charSet; teamSettings = teamSet; }
/// <summary> /// Updates the selected item in the font list. /// </summary> void UpdateSelectedFontSize(CharacterSettings settings) { _cmbFontSizes.SelectedValue = settings.FontSize.HasValue ? settings.FontSize.Value.Points : 12.0; }
/// <summary> /// Spawn a player with the specified occupation /// </summary> /// <param name="occupation">Occupation details to use to spawn this player</param> /// <param name="characterSettings">settings to use for this player</param> /// <param name="playerPrefab">Prefab to use to spawn this player</param> /// <param name="spawnDestination">destinaton to spawn at</param> /// <param name="spawnItems">whether player should spawn naked or with their default loadout</param> /// <returns>the newly created GameObject</returns> /// <returns></returns> public static SpawnInfo Player(Occupation occupation, CharacterSettings characterSettings, GameObject playerPrefab, SpawnDestination spawnDestination, bool spawnItems = false) { return(new SpawnInfo(SpawnType.Player, SpawnablePrefab.For(playerPrefab), spawnDestination, null, 1, occupation, characterSettings: characterSettings, spawnItems: spawnItems)); }
/// <summary> /// Spawn a ghost with the specified occupation /// </summary> /// <param name="occupation">Occupation details to use to spawn this ghost</param> /// <param name="characterSettings">settings to use for this ghost</param> /// <param name="ghostPrefab">Prefab to use to spawn this ghost</param> /// <param name="spawnDestination">destinaton to spawn at</param> /// <returns>the newly created GameObject</returns> /// <returns></returns> public static SpawnInfo Ghost(Occupation occupation, CharacterSettings characterSettings, GameObject ghostPrefab, SpawnDestination spawnDestination) { return(new SpawnInfo(SpawnType.Ghost, SpawnablePrefab.For(ghostPrefab), spawnDestination, null, 1, occupation, characterSettings: characterSettings)); }
public void SetupCharacterData(CharacterSettings Character) { ThisCharacter = Character; StartCoroutine(WaitForPlayerinitialisation()); }
private PlayerSpawnRequest(Occupation requestedOccupation, JoinedViewer joinedViewer, CharacterSettings characterSettings) { RequestedOccupation = requestedOccupation; JoinedViewer = joinedViewer; CharacterSettings = characterSettings; }
public static void RespawnPlayer(NetworkConnection conn, short playerControllerId, JobType jobType, CharacterSettings characterSettings, GameObject oldBody) { GameObject player = CreatePlayer(jobType); TransferPlayer(conn, playerControllerId, player, oldBody, EVENT.PlayerSpawned, characterSettings); }
/// <summary> /// Create a new player spawn info indicating a request to spawn with the /// selected occupation and settings. /// </summary> /// <returns></returns> public static PlayerSpawnRequest RequestOccupation(JoinedViewer requestedBy, Occupation requestedOccupation, CharacterSettings characterSettings) { return(new PlayerSpawnRequest(requestedOccupation, requestedBy, characterSettings)); }
public static void SpawnPlayerGhost(NetworkConnection conn, short playerControllerId, GameObject oldBody, CharacterSettings characterSettings) { GameObject ghost = CreateGhost(oldBody); TransferPlayer(conn, playerControllerId, ghost, oldBody, EVENT.GhostSpawned, characterSettings); }
/**************** Configuration Funcs ****************/ public void AddPlayer(InputDevice input, CharacterSettings charSet, TeamSettings teamSet) { PlayerInfo new_player = new PlayerInfo(input, charSet, teamSet); players.Add(new_player); }
/// <summary> /// Connects a client to a character or redirects a logged out ConnectedPlayer. /// </summary> /// <param name="conn">The client's NetworkConnection. If logged out the playerlist will return an invalid connectedplayer</param> /// <param name="playerControllerId">ID of the client player to be transfered. If logged out it's empty.</param> /// <param name="newBody">The character gameobject to be transfered into.</param> /// <param name="oldBody">The old body of the character.</param> /// <param name="eventType">Event type for the player sync.</param> public static void TransferPlayer(NetworkConnection conn, short playerControllerId, GameObject newBody, GameObject oldBody, EVENT eventType, CharacterSettings characterSettings) { var connectedPlayer = PlayerList.Instance.Get(conn); if (connectedPlayer == ConnectedPlayer.Invalid) //this isn't an online player { PlayerList.Instance.UpdateLoggedOffPlayer(newBody, oldBody); NetworkServer.Spawn(newBody); } else { PlayerList.Instance.UpdatePlayer(conn, newBody); NetworkServer.ReplacePlayerForConnection(conn, newBody, playerControllerId); TriggerEventMessage.Send(newBody, eventType); } var playerScript = newBody.GetComponent <PlayerScript>(); if (playerScript.PlayerSync != null) { playerScript.PlayerSync.NotifyPlayers(true); } // If the player is inside a container, send a ClosetHandlerMessage. // The ClosetHandlerMessage will attach the container to the transfered player. var playerObjectBehavior = newBody.GetComponent <ObjectBehaviour>(); if (playerObjectBehavior && playerObjectBehavior.parentContainer) { ClosetHandlerMessage.Send(newBody, playerObjectBehavior.parentContainer.gameObject); } CustomNetworkManager.Instance.SyncPlayerData(newBody); if (characterSettings != null) { playerScript.characterSettings = characterSettings; } }
public void UndoRagdoll() { CharacterSettings.ActivateRagDoll(transform, true, true); EnableAnimationSystem(); }
private async Task DoImport() { TreeNode objSelectedNode = treCharacterList.SelectedNode; if (objSelectedNode == null || objSelectedNode.Level <= 0) { return; } int intIndex = Convert.ToInt32(objSelectedNode.Tag, GlobalSettings.InvariantCultureInfo); if (intIndex < 0 || intIndex >= _lstCharacterCache.Count) { return; } HeroLabCharacterCache objCache = _lstCharacterCache[intIndex]; if (objCache == null) { return; } string strFile = objCache.FilePath; string strCharacterId = objCache.CharacterId; if (string.IsNullOrEmpty(strFile) || string.IsNullOrEmpty(strCharacterId)) { return; } using (CursorWait.New(this)) { bool blnLoaded = false; Character objCharacter = new Character(); try { Program.OpenCharacters.Add(objCharacter); CharacterSettings objHeroLabSettings = SettingsManager.LoadedCharacterSettings.Values.FirstOrDefault( x => x.Name == objCache.SettingsName && x.BuildMethod == objCache.BuildMethod); if (objHeroLabSettings != null) { objCharacter.SettingsKey = objHeroLabSettings.DictionaryKey; } else { objHeroLabSettings = SettingsManager.LoadedCharacterSettings.Values.FirstOrDefault( x => x.Name.Contains(objCache.SettingsName) && x.BuildMethod == objCache.BuildMethod); if (objHeroLabSettings != null) { objCharacter.SettingsKey = objHeroLabSettings.DictionaryKey; } else { (bool blnSuccess, CharacterSettings objDefaultCharacterSettings) = await SettingsManager.LoadedCharacterSettings.TryGetValueAsync( GlobalSettings.DefaultCharacterSetting); if (blnSuccess && objCache.BuildMethod.UsesPriorityTables() == objDefaultCharacterSettings.BuildMethod.UsesPriorityTables()) { objCharacter.SettingsKey = objDefaultCharacterSettings.DictionaryKey; } else { objCharacter.SettingsKey = SettingsManager.LoadedCharacterSettings.Values .FirstOrDefault( x => x.BuiltInOption && x.BuildMethod == objCache.BuildMethod) ?.DictionaryKey ?? SettingsManager.LoadedCharacterSettings.Values .FirstOrDefault( x => x.BuiltInOption && x.BuildMethod.UsesPriorityTables() == objCache.BuildMethod .UsesPriorityTables()) ?.DictionaryKey ?? GlobalSettings.DefaultCharacterSetting; } } } DialogResult ePickBPResult = await this.DoThreadSafeFunc(ShowBPAsync); async ValueTask <DialogResult> ShowBPAsync() { using (SelectBuildMethod frmPickBP = new SelectBuildMethod(objCharacter, true)) { await frmPickBP.ShowDialogSafeAsync(this); return(frmPickBP.DialogResult); } } if (ePickBPResult != DialogResult.OK) { return; } //Timekeeper.Start("load_file"); if (!await objCharacter.LoadFromHeroLabFileAsync(strFile, strCharacterId, objCharacter.SettingsKey)) { return; } blnLoaded = true; //Timekeeper.Finish("load_file"); await Program.OpenCharacter(objCharacter); } finally { cmdImport.Enabled = true; cmdSelectFile.Enabled = true; if (!blnLoaded) { Program.OpenCharacters.Remove(objCharacter); } } } Close(); }
public static void RespawnPlayer(NetworkConnection conn, short playerControllerId, JobType jobType, CharacterSettings characterSettings, GameObject oldBody) { GameObject player = CreatePlayer(jobType); TransferPlayer(conn, playerControllerId, player, oldBody, EVENT.PlayerSpawned, characterSettings); new Mind(player, jobType); var equipment = player.GetComponent <Equipment>(); var playerScript = player.GetComponent <PlayerScript>(); var connectedPlayer = PlayerList.Instance.Get(conn); connectedPlayer.Name = playerScript.playerName; UpdateConnectedPlayersMessage.Send(); PlayerList.Instance.TryAddScores(playerScript.playerName); equipment.SetPlayerLoadOuts(); if (jobType != JobType.SYNDICATE && jobType != JobType.AI) { SecurityRecordsManager.Instance.AddRecord(playerScript, jobType); } }
private void LoadSettings() { currentCharacter = PlayerManager.CurrentCharacterSettings; PopulateAllDropdowns(); DoInitChecks(); }
/// <summary> /// Connects a client to a character or redirects a logged out ConnectedPlayer. /// </summary> /// <param name="conn">The client's NetworkConnection. If logged out the playerlist will return an invalid connectedplayer</param> /// <param name="playerControllerId">ID of the client player to be transfered. If logged out it's empty.</param> /// <param name="newBody">The character gameobject to be transfered into.</param> /// <param name="oldBody">The old body of the character.</param> /// <param name="eventType">Event type for the player sync.</param> public static void TransferPlayer(NetworkConnection conn, short playerControllerId, GameObject newBody, GameObject oldBody, EVENT eventType, CharacterSettings characterSettings) { var oldPlayerNetworkActions = oldBody.GetComponent <PlayerNetworkActions>(); if (oldPlayerNetworkActions) { oldPlayerNetworkActions.RpcBeforeBodyTransfer(); } var connectedPlayer = PlayerList.Instance.Get(conn); if (connectedPlayer == ConnectedPlayer.Invalid) //this isn't an online player { PlayerList.Instance.UpdateLoggedOffPlayer(newBody, oldBody); NetworkServer.Spawn(newBody); } else { PlayerList.Instance.UpdatePlayer(conn, newBody); NetworkServer.ReplacePlayerForConnection(conn, newBody, playerControllerId); NetworkServer.ReplacePlayerForConnection(new NetworkConnection(), oldBody, 0); TriggerEventMessage.Send(newBody, eventType); } var playerScript = newBody.GetComponent <PlayerScript>(); if (playerScript.PlayerSync != null) { playerScript.PlayerSync.NotifyPlayers(true); } // If the player is inside a container, send a ClosetHandlerMessage. // The ClosetHandlerMessage will attach the container to the transfered player. var playerObjectBehavior = newBody.GetComponent <ObjectBehaviour>(); if (playerObjectBehavior && playerObjectBehavior.parentContainer) { ClosetHandlerMessage.Send(newBody, playerObjectBehavior.parentContainer.gameObject); } bool newMob = false; if (characterSettings != null) { playerScript.characterSettings = characterSettings; playerScript.playerName = characterSettings.Name; newBody.name = characterSettings.Name; var playerSprites = newBody.GetComponent <PlayerSprites>(); if (playerSprites) { playerSprites.OnCharacterSettingsChange(characterSettings); } newMob = true; } var healthStateMonitor = newBody.GetComponent <HealthStateMonitor>(); if (healthStateMonitor) { healthStateMonitor.ProcessClientUpdateRequest(newBody); } CustomNetworkManager.Instance.SyncPlayerData(newBody); CustomNetworkManager.Instance.SyncCharSprites(newBody, newMob); }
public static PlayerCustomisationMessage SendTo(GameObject equipmentObject, GameObject recipient, CharacterSettings Character = null) { var msg = CreateMsg(equipmentObject, Character); msg.SendTo(recipient); return(msg); }
/// <summary> /// Server-side only. For use when a player has only joined (as a JoinedViewer) and /// is not in control of any mobs. Spawns the joined viewer as the indicated occupation and transfers control to it. /// Note that this doesn't take into account game mode or antags, it just spawns whatever is requested. /// </summary> /// <param name="request">holds the request data</param> /// <param name="joinedViewer">viewer who should control the player</param> /// <param name="occupation">occupation to spawn as</param> /// <param name="characterSettings">settings to use for the character</param> /// <returns>the game object of the spawned player</returns> public static GameObject ServerSpawnPlayer(PlayerSpawnRequest request, JoinedViewer joinedViewer, Occupation occupation, CharacterSettings characterSettings, bool showBanner = true) { if (ValidateCharacter(request) == false) { return(null); } NetworkConnection conn = joinedViewer.connectionToClient; // TODO: add a nice cutscene/animation for the respawn transition var newPlayer = ServerSpawnInternal(conn, occupation, characterSettings, null, showBanner: showBanner); if (newPlayer != null && occupation.IsCrewmember) { CrewManifestManager.Instance.AddMember(newPlayer.GetComponent <PlayerScript>(), occupation.JobType); } if (SpawnEvent != null) { SpawnEventArgs args = new SpawnEventArgs() { player = newPlayer }; SpawnEvent.Invoke(null, args); } return(newPlayer); }
void Start() { _character = GetComponent <CharacterAnimator>(); _settings = GetComponent <CharacterSettings>(); _timeStationary = 0; }
/// <summary> /// Server-side only. Transfers control of a player object to the indicated connection. /// </summary> /// <param name="conn">The client's NetworkConnection. If logged out the playerlist will return an invalid connectedplayer</param> /// <param name="newBody">The character gameobject to be transfered into.</param> /// <param name="oldBody">The old body of the character.</param> /// <param name="eventType">Event type for the player sync.</param> /// <param name="characterSettings">settings, ignored if transferring to an existing player body</param> /// <param name="willDestroyOldBody">if true, indicates the old body is going to be destroyed rather than pooled, /// thus we shouldn't send any network message which reference's the old body's ID since it won't exist.</param> private static void ServerTransferPlayer(NetworkConnection conn, GameObject newBody, GameObject oldBody, Event eventType, CharacterSettings characterSettings, bool willDestroyOldBody = false) { if (oldBody) { var oldPlayerNetworkActions = oldBody.GetComponent <PlayerNetworkActions>(); if (oldPlayerNetworkActions) { oldPlayerNetworkActions.RpcBeforeBodyTransfer(); } //no longer can observe their inventory oldBody.GetComponent <DynamicItemStorage>()?.ServerRemoveObserverPlayer(oldBody); } var netIdentity = newBody.GetComponent <NetworkIdentity>(); if (netIdentity.connectionToClient != null) { CustomNetworkManager.Instance.OnServerDisconnect(netIdentity.connectionToClient); } var connectedPlayer = PlayerList.Instance.Get(conn); if (connectedPlayer == ConnectedPlayer.Invalid) //this isn't an online player { PlayerList.Instance.UpdateLoggedOffPlayer(newBody, oldBody); NetworkServer.Spawn(newBody); } else { PlayerList.Instance.UpdatePlayer(conn, newBody); NetworkServer.ReplacePlayerForConnection(conn, newBody); //NOTE: With mirror upgrade 04 Feb 2020, it appears we no longer need to do what has been //commented out below. Below appears to have been an attempt to give authority back to server //But it's implicitly given such authority by the ReplacePlayerForConnection call - that call //now removes authority for the player's old object // if (oldBody) // { // NetworkServer.ReplacePlayerForConnection(new NetworkConnectionToClient(0), oldBody); // } TriggerEventMessage.SendTo(newBody, eventType); //can observe their new inventory var dynamicItemStorage = newBody.GetComponent <DynamicItemStorage>(); if (dynamicItemStorage != null) { dynamicItemStorage.ServerAddObserverPlayer(newBody); PlayerPopulateInventoryUIMessage.Send(dynamicItemStorage, newBody); } } // If the player is inside a container, send a ClosetHandlerMessage. // The ClosetHandlerMessage will attach the container to the transfered player. var playerObjectBehavior = newBody.GetComponent <ObjectBehaviour>(); if (playerObjectBehavior && playerObjectBehavior.parentContainer) { FollowCameraMessage.Send(newBody, playerObjectBehavior.parentContainer.gameObject); } if (characterSettings != null) { var playerScript = newBody.GetComponent <PlayerScript>(); playerScript.characterSettings = characterSettings; playerScript.playerName = playerScript.PlayerState != PlayerScript.PlayerStates.Ai ? characterSettings.Name : characterSettings.AiName; newBody.name = characterSettings.Name; var playerSprites = newBody.GetComponent <PlayerSprites>(); if (playerSprites) { playerSprites.OnCharacterSettingsChange(characterSettings); } } }
public static async Task <bool> ValidateUser(FirebaseUser user, Action <string> successAction, Action <string> errorAction) { if (GameData.IsHeadlessServer) { return(false); } await user.ReloadAsync(); if (!user.IsEmailVerified) { errorAction?.Invoke("Email Not Verified"); return(false); } HttpRequestMessage req = new HttpRequestMessage(HttpMethod.Get, ServerData.UserFirestoreURL); req.Headers.Add("Authorization", $"Bearer {ServerData.IdToken}"); CancellationToken cancellationToken = new CancellationTokenSource(120000).Token; HttpResponseMessage response; try { response = await ServerData.HttpClient.SendAsync(req, cancellationToken); } catch (Exception e) { Logger.LogError($"Error Accessing Firestore: {e.Message}", Category.DatabaseAPI); errorAction?.Invoke($"Error Accessing Firestore: {e.Message}"); return(false); } string content = await response.Content.ReadAsStringAsync(); FireStoreResponse fr = JsonUtility.FromJson <FireStoreResponse>(content); FireStoreCharacter fireStoreChar = fr.fields.character; CharacterSettings characterSettings; var settingsValid = false; if (fireStoreChar == null) { // Make a new character since there isn't one in the database characterSettings = new CharacterSettings { Name = StringManager.GetRandomMaleName(), Username = user.DisplayName }; } else { string unescapedJson = Regex.Unescape(fireStoreChar.stringValue); Logger.Log(unescapedJson); try { characterSettings = JsonConvert.DeserializeObject <CharacterSettings>(unescapedJson); } catch (Exception e) { characterSettings = new CharacterSettings(); } // Validate and correct settings in case the customization options change settingsValid = true; } if (!settingsValid) { // Upload the corrected settings so they are valid next time bool updateSuccess = await UpdateCharacterProfile(characterSettings); if (!updateSuccess) { Logger.LogError($"Error when updating character", Category.DatabaseAPI); errorAction?.Invoke("Error when updating character"); return(false); } } // In case PlayerPrefs doesn't already have the settings string jsonChar = JsonConvert.SerializeObject(characterSettings); PlayerPrefs.SetString("currentcharacter", jsonChar); PlayerManager.CurrentCharacterSettings = characterSettings; successAction?.Invoke("Login success"); PlayerPrefs.SetString("lastLogin", user.Email); PlayerPrefs.Save(); return(true); }