public Transform NetworkInstantiateFromPool(Transform prefab, Vector3 pos, Quaternion rot, NetworkConnection authority = null) { int index = PrefabIndex (prefab); if (index < 0) { Debug.LogError ("Prefab " + prefab.name + " is not in poolable set"); return null; } Transform inst = InstantiateInternal (index, prefab.gameObject.tag, prefab.gameObject.layer, pos, rot); if (NetworkServer.active) { if (inst.GetComponent<NetworkIdentity>() == null) { Debug.LogError ("pooler Trying to instantiate a prefab " + prefab.gameObject.name + " without id", prefab); } SendRemoteInstanceToClients (PrefabIndex(prefab), prefab.gameObject.tag, prefab.gameObject.layer, pos, rot); if (authority == null) { Debug.Log ("Spawning " + prefab.gameObject.name + " without client authority " + authority); NetworkServer.Spawn(inst.gameObject); } else { Debug.Log ("Spawning " + prefab.gameObject.name + " with client authority " + authority); NetworkServer.SpawnWithClientAuthority (inst.gameObject, authority); } } else if (NetworkClient.active) { localInstances.Add (inst); // callbacks.Add (func); SendRemoteInstanceToServer (index, prefab.gameObject.tag, prefab.gameObject.layer, pos, rot); } return inst; }
public void ConnectTo (NetworkConnection con) { //Console.WriteLine ("Connecting to {0}", con.ConnectionName); NetworkDevice dev; string specObj; if (con is WirelessConnection) { dev = DevManager.NetworkDevices.OfType<WirelessDevice> ().First (); specObj = (dev as WirelessDevice).APBySSID ((con as WirelessConnection).SSID).ObjectPath; } else if (con is WiredConnection) { dev = DevManager.NetworkDevices.OfType<WiredDevice> ().First (); specObj = "/"; } else { return; } string serviceName; if (con.Owner == ConnectionOwner.System) serviceName = "org.freedesktop.NetworkManagerSystemSettings"; else serviceName = "org.freedesktop.NetworkManagerUserSettings"; string conStr = con.ObjectPath; DevManager.BusObject.ActivateConnection(serviceName, new ObjectPath (conStr), new ObjectPath (dev.ObjectPath), new ObjectPath (specObj)); }
public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId) { Debug.LogWarning("Add Player"); GameObject player = (GameObject)Instantiate(playerPrefab, spawnPosition/*spawnPoints[connectionNumber].position*/, Quaternion.identity); NetworkServer.AddPlayerForConnection(conn, player, playerControllerId); connectionNumber += 1; }
/* * Client Callbacks */ public override void OnLobbyClientConnect(NetworkConnection conn) { connectingCanvas.Hide(); //charCreation = GameObject.Find("CharacterCreation"); //charCreation.SetActive(false); }
public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId) { //base.OnServerAddPlayer(conn, playerControllerId); this.conn = conn; this.playerId = playerControllerId; canvasName.SetActive(true); }
//Called on client when connected to server public override void OnClientConnect(NetworkConnection conn) { base.OnClientConnect(conn); //HandshakeMsg msg = new HandshakeMsg(); //msg.username = this.username; //conn.Send(HandshakeMsg.msgType, msg); }
bool dumbEquals (NetworkConnection dumb){ if (checkingEquality == null) { return false; } else { return dumb.Equals (checkingEquality); } }
public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId) { Vector3 spawnPos = Vector3.right * conn.connectionId; GameObject player =(GameObject) Instantiate(base.playerPrefab, spawnPos, Quaternion.identity); player.name = string.Format("Player {0}", numPlayers+1); NetworkServer.AddPlayerForConnection(conn, player, playerControllerId); }
public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId) { Vector3 playerSpawnPos = new Vector3(0.0F, 0.0F, 0.0F); Vector3 spawnA = new Vector3(0.0F, 0.0F, 0.0F); Vector3 spawnB = new Vector3(0.0F, 0.0F, 0.0F); GameObject[] spawns = GameObject.FindGameObjectsWithTag("spawn"); GameObject[] players = GameObject.FindGameObjectsWithTag("Player"); string target = "Spawn_A"; Quaternion rotation = Quaternion.identity; if (hostConnection != -1 && conn.connectionId != hostConnection) { target = "Spawn_B"; rotation = Quaternion.Euler(rotation.eulerAngles + new Vector3(0.0F, 180.0F, 0.0F)); } else { hostConnection = conn.connectionId; } foreach (GameObject spawn in spawns ) { if (spawn.name == "Spawn_A") spawnA = spawn.transform.position; else spawnB = spawn.transform.position; } if (target == "Spawn_A") playerSpawnPos = spawnA; if (playerSpawnPos.Equals(new Vector3(0.0F, 0.0F, 0.0F)) || target == "Spawn_B") playerSpawnPos = spawnB; GameObject player = (GameObject)GameObject.Instantiate(playerPrefab, playerSpawnPos, rotation); NetworkServer.AddPlayerForConnection(conn, player, playerControllerId); }
public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId) { GameObject player = (GameObject)Instantiate(playerPrefab, Vector3.zero, Quaternion.identity); playerInstances.Add(player); NetworkServer.AddPlayerForConnection(conn, player, playerControllerId); if (playerInstances.Count >= 2) GameMaster.Instance.OnAllPlayersCreated(); }
public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId) { GameObject player = (GameObject)Instantiate(playerPrefab, Vector3.up*15, Quaternion.identity); ClientHub bus = player.GetComponent<ClientHub>(); NetworkServer.AddPlayerForConnection(conn, player, playerControllerId); }
/*[TargetRpc]*/ public void TargetSyncClient(NetworkConnection nc, Vector3 position, Vector3 direction) { if(isServer) return; GetComponent<Transform>().position = position; GetComponent<ProjectileMovement>().setDirection(direction); }
public void ILost(NetworkConnection conn) { int[] __tempKeys = new int[globalScore.Count]; globalScore.Keys.CopyTo(__tempKeys, 0); defeatedList.Add(conn.connectionId); /**/ for (int i = 0; i < globalScore.Count; i++) { //dah um ponto para todos os players vivos if (!defeatedList.Contains(__tempKeys[i])) { SetScore(__tempKeys[i], globalScore[__tempKeys[i]] + 1); } } for (int i = 0; i < gameScenePlayers.Count; i++) { gameScenePlayers[i].GetComponent<PlayerAttributes>().UpdateScoreStats(); } //Debug.Log("Computou os scores novos"); //Debug.Log("Defeated Count: " + defeatedList.Count); /**/ if (defeatedList.Count == globalScore.Count - 1) { //fim do jogo StartCoroutine("EndGame", 2); } }
/*public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId, NetworkReader extraMessageReader) { Debug.Log('on server add player'); OnServerAddPlayer(conn, playerControllerId, extraMessageReader); }*/ public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId) { Debug.Log ("Adding a player to game"); var startingLocation = GetStartPosition (); var player = (GameObject)GameObject.Instantiate(playerPrefab, startingLocation.position, Quaternion.identity); NetworkServer.AddPlayerForConnection(conn, player, playerControllerId); }
public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId) { int index = Random.Range(0, spawnPoints.Length); GameObject player = (GameObject)Instantiate(playerPrefab, spawnPoints[index], Quaternion.identity/*spawnPoints[index].rotation*/); player.GetComponent<Move>().myColor = new Color(Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f)); NetworkServer.AddPlayerForConnection(conn, player, playerControllerId); }
public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId) { playerNumber++; var player = (GameObject)GameObject.Instantiate(playerPrefab, GetSpawnPosition(), Quaternion.identity); //Default implementation NetworkServer.AddPlayerForConnection(conn, player, playerControllerId); //Default implementation try { ScoreManager SM = GetComponentInChildren<ScoreManager>(); foreach (GameObject go in GameObject.FindGameObjectsWithTag("Player")) if (conn.clientOwnedObjects.Contains(go.GetComponent<NetworkIdentity>().netId)) { go.GetComponent<EventManager>().SendScoreEvent(SM.teamOneScore, SM.teamTwoScore); go.GetComponent<PlayerStats>().RpcServerInitTime(Network.time - SM.initServerTime); break; } } catch { Debug.Log("No Score Manager found!"); } // Do the mapHandler code only when on the correct scene //if (onlineScene.Equals("'stinaScene_foolingaroundwithCircles")) { if (onlineScene.Equals("HenrikScene")) { mapCreator MC = GameObject.Find("mapHandler").GetComponent<mapCreator>(); if (playerNumber == 2) { GetComponentInChildren<ScoreManager>().sinkTimer = (float)Network.time; // Only to be done once MC.SinkingSyncing(GetComponentInChildren<ScoreManager>().sinkTimer); } MC.playerConnected(); foreach (GameObject go in GameObject.FindGameObjectsWithTag("Player")) go.GetComponent<PlayerStats>().GenerateTerrain(); //go.GetComponent<PlayerStats>().GenerateTerrain(GetComponentInChildren<ScoreManager>().sinkTimer); } StartCoroutine(PlayerJoined()); }
static int Verify (IPEndPoint ep) { NetworkConnection con = new NetworkConnection (ep); bool active = true; try { for (int i = 0; i < 30; i++) { active = con.IsActive; if (!active) break; Thread.Sleep (1000); } } finally { string quit = Path.Combine (AppDomain.CurrentDomain.BaseDirectory, "quit"); try { File.Create (quit).Close (); } catch { } } if (con.IsActive || active) return 3; return 0; }
public override void OnClientError(NetworkConnection conn, int errorCode) { connectingCanvas.Hide(); StopHost(); popupCanvas.Show("Client Error", errorCode.ToString()); }
/************************** network stuff *****************************/ public override void OnClientConnect(NetworkConnection conn) { connected = true; base.OnClientConnect (conn); Debug.Log ("client is connected"); sendUserConnect (); }
// called when a player is removed for a client public override void OnServerRemovePlayer(NetworkConnection conn, PlayerController player) { if (player.gameObject != null) { NetworkServer.Destroy(player.gameObject); } }
public override void OnConnectFailed(NetworkConnection connection) { if (this.ConnectionFailedCallback != null) { this.ConnectionFailedCallback(connection); } }
public override void OnDisconnected(NetworkConnection connection) { if (this.DisconnectedCallback != null) { this.DisconnectedCallback(connection); } }
public override void OnMessageReceived(NetworkConnection connection, NetworkInMessage message) { if (this.MessageReceivedCallback != null) { this.MessageReceivedCallback(connection, message); } }
public override void OnServerDisconnect(NetworkConnection conn) { base.OnServerDisconnect(conn); Debug.Log("A player has disconnected."); Player player = new Player("", conn); application.UpdatePlayer(player, "disconnect"); }
override public void OnClientDisconnect (NetworkConnection conn) { base.OnClientDisconnect (conn); print ("CLIENT: disconnected from " + conn.address); conn.UnregisterHandler (MsgCode); netDiscovery.shouldConnect = true; }
public override void OnClientDisconnect(NetworkConnection conn) { base.OnClientDisconnect(conn); Debug.Log("Disconnected from server"); GameObject.Find("StatusText").GetComponent<UnityEngine.UI.Text>().text = "Finding Server..."; startDiscovery(); }
public override void OnLobbyClientConnect(NetworkConnection conn) { Debug.Log("Enters Lobby"); Debug.Log(conn.connectionId); GameObject schema = GameObject.Find("Schema"); GameObject cameraTarget = GameObject.Find("CameraTarget"); switch (conn.connectionId) { case 0: schema.transform.rotation = Quaternion.Euler(new Vector3(0,-90,0)); cameraTarget.transform.rotation = Quaternion.Euler(new Vector3(0,0,0)); break; case 1: schema.transform.rotation = Quaternion.Euler(new Vector3(0,0,0)); cameraTarget.transform.rotation = Quaternion.Euler(new Vector3(0,-90,0)); break; case 2: schema.transform.rotation = Quaternion.Euler(new Vector3(0,90,0)); cameraTarget.transform.rotation = Quaternion.Euler(new Vector3(0,180,0)); break; case 3: schema.transform.rotation = Quaternion.Euler(new Vector3(0,180,0)); cameraTarget.transform.rotation = Quaternion.Euler(new Vector3(0,90,0)); break; } }
public override void OnClientConnect(NetworkConnection conn) { base.OnClientConnect(conn); Debug.Log("Client connected at: " + conn.address); if(OnClientConnected != null) OnClientConnected(conn); }
public override void OnClientDisconnect(NetworkConnection conn) { base.OnClientDisconnect(conn); Debug.Log("Client disconnected at: " + conn.address); if(OnPlayerDisconnect != null) OnPlayerDisconnect(conn); }
/// <summary> /// Fonction de recherche de joueur par connexion /// </summary> /// <param name="conn">Connexion recherchée</param> /// <returns></returns> public static Player FindPlayer(NetworkConnection conn) { Player[] players = FindObjectsOfType<Player>(); foreach (Player p in players) if (p.connectionToServer == conn) return p; return null; }
private void ClientConnectedToServer(NetworkConnection connection) { onlinePlayerList.Add(networkManager.networkAuthenticator.nicknames[connection.connectionId]); }
public override IEnumerator Process(NetworkConnection sentBy) { SentByPlayer = PlayerList.Instance.Get(sentBy); return(base.Process(sentBy)); }
private PlayerController PlayerForConnection(NetworkConnection connection) { return(connection.identity.GetComponent <PlayerController>()); }
public override void OnClientError(NetworkConnection conn, int errorCode) { Debug.Log("Client network error occurred: " + (NetworkError)errorCode); }
public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId, NetworkReader extraMessageReader) { Debug.Log("connexion établie"); }
public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId) { Debug.Log("on server add player: " + playerControllerId); base.OnServerAddPlayer(conn, playerControllerId); }
public override void OnClientSceneChanged(NetworkConnection conn) { base.OnClientSceneChanged(conn); Debug.Log("Server triggered scene change and we've done the same, do any extra work here for the client..."); }
public override void OnClientConnect(NetworkConnection conn) { IntegerMessage msg = new IntegerMessage(playerPrefabIndex); ClientScene.AddPlayer(conn, 0, msg); //Comunicamos al server con un mensaje de red el identificador de la opción elegida }
public void TargetStopMusic(NetworkConnection target) { MusicManager.SongTracker.Stop(); }
public override void OnServerReady(NetworkConnection conn) { NetworkServer.SetClientReady(conn); Debug.Log("Client is set to the ready state (ready to receive state updates): " + conn); }
public override void OnServerDisconnect(NetworkConnection conn) { Debug.Log("Connection to server terminated"); base.OnServerDisconnect(conn); }
// ----------------- Client callbacks ------------------ public override void OnLobbyClientConnect(NetworkConnection conn) { connectingCanvas.Hide(); }
public override void OnClientConnect(NetworkConnection conn) { Debug.Log(Time.timeSinceLevelLoad + " Client is connected to IP: " + conn.address); CancelInvoke(); }
/// <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()); 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); } return(newPlayer); }
public override void OnClientConnect(NetworkConnection conn) { base.OnClientConnect(conn); RegisterHandlerClient(MsgType.OtherTestMessage, OnTestMessage); }
void Disconnect() { m_Connection.Disconnect(m_Driver); m_Connection = default(NetworkConnection); }
public override void OnServerConnect(NetworkConnection conn) { base.OnServerConnect(conn); NetworkServer.RegisterHandler(MsgType.OtherTestMessage, OnTestMessage); }
public override void OnLobbyClientDisconnect(NetworkConnection conn) { lobbyCanvas.Hide(); offlineCanvas.Show(); }
public override void OnServerReady(NetworkConnection conn) { base.OnServerReady(conn); }
public IEnumerator DelayedDisconnect(NetworkConnection conn, float waitTime) { yield return(new WaitForSeconds(waitTime)); conn.Disconnect(); }
public override void OnClientNotReady(NetworkConnection conn) { Debug.Log("Server has set client to be not-ready (stop getting state updates)"); }
public override void OnServerAuthenticate(NetworkConnection conn) { // do nothing...wait for AuthRequestMessage from client }
public override void OnServerError(NetworkConnection conn, int errorCode) { Debug.Log("Server network error occurred: " + (NetworkError)errorCode); }
private void ActivateScene(NetworkConnection connection, ActivateSceneMessage message) { Debug.Log($"Activating {message.sceneNameOrPath}"); StartCoroutine(WaitForSceneActivationThenSetActive(message.sceneNameOrPath)); }
public static void ServerTransferPlayerToNewBody(NetworkConnection conn, GameObject newBody, GameObject oldBody, EVENT eventType, CharacterSettings characterSettings, bool willDestroyOldBody = false) { ServerTransferPlayer(conn, newBody, oldBody, eventType, characterSettings, willDestroyOldBody); }
void OnDisconnect() { Debug.Log("Client got disconnected from server"); m_Connection = default(NetworkConnection); }
/// <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 <ItemStorage>()?.ServerRemoveObserverPlayer(oldBody); } 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 newBody.GetComponent <ItemStorage>()?.ServerAddObserverPlayer(newBody); } 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) { FollowCameraMessage.Send(newBody, playerObjectBehavior.parentContainer.gameObject); } if (characterSettings != null) { playerScript.characterSettings = characterSettings; playerScript.playerName = characterSettings.Name; newBody.name = characterSettings.Name; var playerSprites = newBody.GetComponent <PlayerSprites>(); if (playerSprites) { playerSprites.OnCharacterSettingsChange(characterSettings); } } var healthStateMonitor = newBody.GetComponent <HealthStateMonitor>(); if (healthStateMonitor) { healthStateMonitor.ProcessClientUpdateRequest(newBody); } }
/// <summary> /// Called on the server when a client disconnects. /// <para>This is called on the Server when a Client disconnects from the Server. Use an override to decide what should happen when a disconnection is detected.</para> /// </summary> /// <param name="conn">Connection from client.</param> public override void OnServerDisconnect(NetworkConnection conn) { base.OnServerDisconnect(conn); ResetPlayerNumbers(); }
public override void OnServerDisconnect(NetworkConnection conn) { Debug.Log("Disconnection handle"); GameData.INSTANCE.CmdDeletePlayerInfoObsolete(conn.connectionId); base.OnServerDisconnect(conn); }
//////////////////// Partie Network /////////////////////////////////////// public override void OnServerConnect(NetworkConnection conn) { NetworkServer.RegisterHandler(MsgType.Connect, OnClientConnected); }