/// <summary> /// Despawn the object server side and sync the despawn to all clients. Despawning removes an /// object from the game, but may not necessarilly destroy it completely - it may end up back in the /// object pool to be later reused. /// </summary> /// <param name="info"></param> /// <param name="skipInventoryDespawn">If the indicated object is in inventory, it will /// be despawned via the inventory API instead. Set this to true to bypass this. This is only /// intended to be set to true for particular internal use cases in the lifecycle system, so should /// almost always be left at the default</param> /// <returns></returns> private static DespawnResult Server(DespawnInfo info, bool skipInventoryDespawn = false) { if (info == null) { Logger.LogError("Cannot despawn - info is null", Category.ItemSpawn); return(DespawnResult.Fail(info)); } if (!skipInventoryDespawn) { var pu = info.GameObject.GetComponent <Pickupable>(); if (pu != null && pu.ItemSlot != null) { if (Inventory.ServerDespawn(pu.ItemSlot)) { return(DespawnResult.Single(info)); } else { return(DespawnResult.Fail(info)); } } } //even if it has a pool prefab tracker, will still destroy it if it has no object behavior var poolPrefabTracker = info.GameObject.GetComponent <PoolPrefabTracker>(); var transform = info.GameObject.GetComponent <IPushable>(); var Electrical = info.GameObject.GetComponent <ElectricalOIinheritance>(); if (Electrical != null) { if (!Electrical.InData.DestroyAuthorised) { Electrical.DestroyThisPlease(); return(DespawnResult.Single(info)); } } _ServerFireDespawnHooks(DespawnResult.Single(info)); if (transform != null) { transform.VisibleState = false; } if (poolPrefabTracker != null) { //pooled Spawn._AddToPool(info.GameObject); } else { //not pooled NetworkServer.Destroy(info.GameObject); } return(DespawnResult.Single(info)); }
/// <summary> /// Despawn the object server side and sync the despawn to all clients. Should only be /// called on networked objects (i.e. ones which have NetworkIdentity component). Despawning removes an /// object from the game, but may not necessarilly destroy it completely - it may end up back in the /// object pool to be later reused. /// </summary> /// <param name="info"></param> /// <param name="skipInventoryDespawn">If the indicated object is in inventory, it will /// be despawned via the inventory API instead. Set this to true to bypass this. This is only /// intended to be set to true for particular internal use cases in the lifecycle system, so should /// almost always be left at the default</param> /// <returns></returns> private static async Task <DespawnResult> Server(DespawnInfo info, bool skipInventoryDespawn = false) { if (info == null) { Logger.LogError("Cannot despawn - info is null", Category.ItemSpawn); return(DespawnResult.Fail(info)); } if (!skipInventoryDespawn) { var pu = info.GameObject.GetComponent <Pickupable>(); if (pu != null && pu.ItemSlot != null) { if (Inventory.ServerDespawn(pu.ItemSlot)) { return(DespawnResult.Single(info)); } else { return(DespawnResult.Fail(info)); } } } var Electrical = info.GameObject.GetComponent <ElectricalOIinheritance>(); //TODO: What's the purpose of this? if (Electrical != null) { if (!Electrical.InData.DestroyAuthorised) { Electrical.DestroyThisPlease(); return(DespawnResult.Single(info)); } } _ServerFireDespawnHooks(DespawnResult.Single(info)); var cnt = info.GameObject.GetComponent <CustomNetTransform>(); if (cnt != null) { cnt.DisappearFromWorldServer(); } await Task.Delay(10); if (Spawn._ObjectPool.TryDespawnToPool(info.GameObject, false)) { return(DespawnResult.Single(info)); } else { return(DespawnResult.Fail(info)); } }
/// <summary> /// Despawn the object locally, on this client only. Should ONLY be called on non-networked objects /// (i.e. ones which don't have NetworkIdentity component). Despawning removes an /// object from the game, but may not necessarilly destroy it completely - it may end up back in the /// object pool to be later reused. /// </summary> /// <param name="info"></param> /// <returns></returns> public static DespawnResult Client(DespawnInfo info) { if (info == null) { Logger.LogError("Cannot despawn - info is null", Category.ItemSpawn); return(DespawnResult.Fail(info)); } if (Spawn._ObjectPool.TryDespawnToPool(info.GameObject, true)) { return(DespawnResult.Single(info)); } else { return(DespawnResult.Fail(info)); } }
/// <summary> /// Despawn the object locally, on this client only. Despawning removes an /// object from the game, but may not necessarilly destroy it completely - it may end up back in the /// object pool to be later reused. /// </summary> /// <param name="info"></param> /// <returns></returns> public static DespawnResult Client(DespawnInfo info) { if (info == null) { Logger.LogError("Cannot despawn - info is null", Category.ItemSpawn); return(DespawnResult.Fail(info)); } //fire despawn hooks var hooks = info.GameObject.GetComponents <IClientDespawn>(); if (hooks != null) { foreach (var hook in hooks) { hook.OnDespawnClient(ClientDespawnInfo.Default()); } } Spawn._AddToPool(info.GameObject); info.GameObject.SetActive(false); return(DespawnResult.Single(info)); }
/// <summary> /// FOR DEV / TESTING ONLY! Simulates destroying and recreating an item by putting it in the pool and taking it back /// out again. If item is not pooled, simply destroys and recreates it as if calling Despawn and then Spawn /// Can use this to validate that the object correctly re-initializes itself after spawning - /// no state should be left over from its previous incarnation. /// </summary> /// <returns>the re-created object</returns> public static GameObject ServerPoolTestRespawn(GameObject target) { var poolPrefabTracker = target.GetComponent <PoolPrefabTracker>(); if (poolPrefabTracker == null) { //destroy / create using normal approach with no pooling Logger.LogWarningFormat("Object {0} has no pool prefab tracker, thus cannot be pooled. It will be destroyed / created" + " without going through the pool.", Category.ItemSpawn, target.name); //determine prefab var position = target.TileWorldPosition(); var prefab = DeterminePrefab(target); if (prefab == null) { Logger.LogErrorFormat("Object {0} at {1} cannot be respawned because it has no PoolPrefabTracker and its name" + " does not match a prefab name, so we cannot" + " determine the prefab to instantiate. Please fix this object so that it" + " has an attached PoolPrefabTracker or so its name matches the prefab it was created from.", Category.ItemSpawn, target.name, position); return(null); } Despawn.ServerSingle(target); return(ServerPrefab(prefab, position.To3Int()).GameObject); } else { //destroy / create with pooling //save previous position var destination = SpawnDestination.At(target); var worldPos = target.TileWorldPosition(); var transform = target.GetComponent <IPushable>(); var prevParent = target.transform.parent; //this simulates going into the pool Despawn._ServerFireDespawnHooks(DespawnResult.Single(DespawnInfo.Single(target))); if (transform != null) { transform.VisibleState = false; } //this simulates coming back out of the pool target.SetActive(true); target.transform.parent = prevParent; target.transform.position = worldPos.To3Int(); var cnt = target.GetComponent <CustomNetTransform>(); if (cnt) { cnt.ReInitServerState(); cnt.NotifyPlayers(); //Sending out clientState for already spawned items } var prefab = DeterminePrefab(target); SpawnInfo spawnInfo = SpawnInfo.Spawnable( SpawnablePrefab.For(prefab), destination); _ServerFireClientServerSpawnHooks(SpawnResult.Single(spawnInfo, target)); return(target); } }