示例#1
0
    /// <summary>
    /// Performs the specified spawn locally, for this client only. Must not be called on
    /// networked objects (objects with NetworkIdentity), or you will get unpredictable behavior.
    /// </summary>
    /// <returns></returns>
    public static SpawnResult Client(SpawnInfo info)
    {
        if (info == null)
        {
            Logger.LogError("Cannot spawn, info is null", Category.ItemSpawn);
            return(SpawnResult.Fail(info));
        }

        if (info.SpawnableToSpawn is IClientSpawnable clientSpawnable)
        {
            List <GameObject> spawnedObjects = new List <GameObject>();
            for (var i = 0; i < info.Count; i++)
            {
                var result = clientSpawnable.ClientSpawnAt(info.SpawnDestination);
                if (result.Successful)
                {
                    spawnedObjects.Add(result.GameObject);
                }
            }

            if (spawnedObjects.Count == 1)
            {
                return(SpawnResult.Single(info, spawnedObjects[0]));
            }

            return(SpawnResult.Multiple(info, spawnedObjects));
        }
        else
        {
            Logger.LogErrorFormat("Cannot spawn {0} client side, spawnable does not" +
                                  " implement IClientSpawnable", Category.ItemSpawn, info);
            return(SpawnResult.Fail(info));
        }
    }
示例#2
0
    /// <summary>
    /// Server-side only. Performs the spawn and syncs it to all clients.
    /// </summary>
    /// <returns></returns>
    private static SpawnResult Server(SpawnInfo info, bool AutoOnSpawnServerHook = true)
    {
        if (info == null)
        {
            Logger.LogError("Cannot spawn, info is null", Category.ItemSpawn);
            return(SpawnResult.Fail(info));
        }

        EnsureInit();
        Logger.LogTraceFormat("Server spawning {0}", Category.ItemSpawn, info);

        List <GameObject> spawnedObjects = new List <GameObject>();

        for (int i = 0; i < info.Count; i++)
        {
            var result = info.SpawnableToSpawn.SpawnAt(info.SpawnDestination);

            if (result.Successful)
            {
                spawnedObjects.Add(result.GameObject);
                //apply scattering if it was specified
                if (info.ScatterRadius != null)
                {
                    foreach (var spawned in spawnedObjects)
                    {
                        var cnt           = spawned.GetComponent <CustomNetTransform>();
                        var scatterRadius = info.ScatterRadius.GetValueOrDefault(0);
                        if (cnt != null)
                        {
                            cnt.SetPosition(info.SpawnDestination.WorldPosition + new Vector3(Random.Range(-scatterRadius, scatterRadius), Random.Range(-scatterRadius, scatterRadius)));
                        }
                    }
                }
            }
            else
            {
                return(SpawnResult.Fail(info));
            }
        }

        //fire hooks for all spawned objects
        SpawnResult spawnResult = null;

        if (spawnedObjects.Count == 1)
        {
            spawnResult = SpawnResult.Single(info, spawnedObjects[0]);
        }
        else
        {
            spawnResult = SpawnResult.Multiple(info, spawnedObjects);
        }

        if (AutoOnSpawnServerHook)
        {
            _ServerFireClientServerSpawnHooks(spawnResult);
        }


        return(spawnResult);
    }
示例#3
0
    /// <summary>
    /// Performs the specified spawn locally, for this client only.
    /// </summary>
    /// <returns></returns>
    public static SpawnResult Client(SpawnInfo info)
    {
        if (info == null)
        {
            Logger.LogError("Cannot spawn, info is null", Category.ItemSpawn);
            return(SpawnResult.Fail(info));
        }

        if (info.SpawnableToSpawn is IClientSpawnable clientSpawnable)
        {
            List <GameObject> spawnedObjects = new List <GameObject>();
            for (var i = 0; i < info.Count; i++)
            {
                var result = clientSpawnable.ClientSpawnAt(info.SpawnDestination);
                if (result.Successful)
                {
                    spawnedObjects.Add(result.GameObject);
                }
            }

            //fire client side lifecycle hooks
            foreach (var spawnedObject in spawnedObjects)
            {
                var hooks = spawnedObject.GetComponents <IClientSpawn>();
                if (hooks != null)
                {
                    foreach (var hook in hooks)
                    {
                        hook.OnSpawnClient(ClientSpawnInfo.Default());
                    }
                }
            }

            if (spawnedObjects.Count == 1)
            {
                return(SpawnResult.Single(info, spawnedObjects[0]));
            }

            return(SpawnResult.Multiple(info, spawnedObjects));
        }
        else
        {
            Logger.LogErrorFormat("Cannot spawn {0} client side, spawnable does not" +
                                  " implement IClientSpawnable", Category.ItemSpawn, info);
            return(SpawnResult.Fail(info));
        }
    }
示例#4
0
    /// <summary>
    /// Performs the specified spawn locally, for this client only.
    /// </summary>
    /// <returns></returns>
    public static SpawnResult Client(SpawnInfo info)
    {
        if (info == null)
        {
            Logger.LogError("Cannot spawn, info is null", Category.ItemSpawn);
            return(SpawnResult.Fail(info));
        }
        List <GameObject> spawnedObjects = new List <GameObject>();

        for (var i = 0; i < info.Count; i++)
        {
            if (info.SpawnableType == SpawnableType.Cloth)
            {
                Logger.LogErrorFormat("Spawning cloths on client side is not currently supported. {0}", Category.ItemSpawn, info);
                return(SpawnResult.Fail(info));
            }

            bool isPooled;             // not used for Client-only instantiation
            var  go = PoolInstantiate(info.PrefabUsed, info.WorldPosition, info.Rotation, info.Parent, out isPooled);

            spawnedObjects.Add(go);
        }

        //fire client side lifecycle hooks
        foreach (var spawnedObject in spawnedObjects)
        {
            var hooks = spawnedObject.GetComponents <IClientSpawn>();
            if (hooks != null)
            {
                foreach (var hook in hooks)
                {
                    hook.OnSpawnClient(ClientSpawnInfo.Default());
                }
            }
        }

        if (spawnedObjects.Count == 1)
        {
            return(SpawnResult.Single(info, spawnedObjects[0]));
        }

        return(SpawnResult.Multiple(info, spawnedObjects));
    }
示例#5
0
    /// <summary>
    /// Server-side only. Performs the spawn and syncs it to all clients.
    /// </summary>
    /// <returns></returns>
    private static SpawnResult Server(SpawnInfo info)
    {
        if (info == null)
        {
            Logger.LogError("Cannot spawn, info is null", Category.ItemSpawn);
            return(SpawnResult.Fail(info));
        }
        EnsureInit();
        Logger.LogTraceFormat("Server spawning {0}", Category.ItemSpawn, info);

        List <GameObject> spawnedObjects = new List <GameObject>();

        for (int i = 0; i < info.Count; i++)
        {
            if (info.SpawnableType == SpawnableType.Prefab)
            {
                if (info.PrefabUsed == null)
                {
                    Logger.LogError("Cannot spawn, prefab to use is null", Category.ItemSpawn);
                    return(SpawnResult.Fail(info));
                }

                if (info.CancelIfImpassable)
                {
                    if (IsTotallyImpassable(info.WorldPosition.CutToInt()))
                    {
                        Logger.LogTraceFormat("Cancelling spawn of {0} because" +
                                              " the position being spawned to {1} is impassable",
                                              Category.ItemSpawn, info.PrefabUsed, info.WorldPosition.CutToInt());
                        return(SpawnResult.Fail(info));
                    }
                }

                bool isPooled;

                GameObject tempObject = PoolInstantiate(info.PrefabUsed, info.WorldPosition, info.Rotation,
                                                        info.Parent,
                                                        out isPooled);

                if (!isPooled)
                {
                    Logger.LogTrace("Prefab to spawn was not pooled, spawning new instance.", Category.ItemSpawn);
                    NetworkServer.Spawn(tempObject);
                    tempObject.GetComponent <CustomNetTransform>()
                    ?.NotifyPlayers();                             //Sending clientState for newly spawned items
                }
                else
                {
                    Logger.LogTrace("Prefab to spawn was pooled, reusing it...", Category.ItemSpawn);
                }

                spawnedObjects.Add(tempObject);
            }
            else if (info.SpawnableType == SpawnableType.Cloth)
            {
                var result = ServerCloth(info);
                if (result == null)
                {
                    return(SpawnResult.Fail(info));
                }

                spawnedObjects.Add(result);
            }
            else if (info.SpawnableType == SpawnableType.Clone)
            {
                var prefab = DeterminePrefab(info.ClonedFrom);
                if (prefab == null)
                {
                    Logger.LogErrorFormat(
                        "Object {0} cannot be cloned 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, info.ClonedFrom);
                }

                GameObject tempObject = PoolInstantiate(prefab, info.WorldPosition, info.Rotation, info.Parent,
                                                        out var isPooled);

                if (!isPooled)
                {
                    NetworkServer.Spawn(tempObject);
                    tempObject.GetComponent <CustomNetTransform>()
                    ?.NotifyPlayers();                             //Sending clientState for newly spawned items
                }

                spawnedObjects.Add(tempObject);
            }

            //apply scattering if it was specified
            if (info.ScatterRadius != null)
            {
                foreach (var spawned in spawnedObjects)
                {
                    var cnt           = spawned.GetComponent <CustomNetTransform>();
                    var scatterRadius = info.ScatterRadius.GetValueOrDefault(0);
                    if (cnt != null)
                    {
                        cnt.SetPosition(info.WorldPosition + new Vector3(Random.Range(-scatterRadius, scatterRadius), Random.Range(-scatterRadius, scatterRadius)));
                    }
                }
            }

            //fire hooks for all spawned objects
            if (spawnedObjects.Count == 1)
            {
                _ServerFireClientServerSpawnHooks(SpawnResult.Single(info, spawnedObjects[0]));
            }
            else
            {
                _ServerFireClientServerSpawnHooks(SpawnResult.Multiple(info, spawnedObjects));
            }
        }

        return(SpawnResult.Multiple(info, spawnedObjects));
    }