コード例 #1
0
        /// <summary>
        /// Server spawn callback for static object.
        /// </summary>
        /// <param name="trigger">Trigger leading to this spawn.</param>
        /// <param name="zone">Server zone instance.</param>
        /// <param name="protoStaticWorldObject">Prototype of static object to spawn.</param>
        /// <param name="tilePosition">Position to try spawn at.</param>
        protected IGameObjectWithProto ServerSpawnStaticObject(
            IProtoTrigger trigger,
            IServerZone zone,
            IProtoStaticWorldObject protoStaticWorldObject,
            Vector2Ushort tilePosition)
        {
            foreach (var tileOffset in protoStaticWorldObject.Layout.TileOffsets)
            {
                // ensure that each tile in object layout is inside the zone
                if (tileOffset != Vector2Int.Zero &&
                    !zone.IsContainsPosition(tilePosition.AddAndClamp(tileOffset)))
                {
                    // some tile is outside the zone
                    return(null);
                }
            }

            if (!protoStaticWorldObject.CheckTileRequirements(
                    tilePosition,
                    character: null,
                    logErrors: false))
            {
                // cannot spawn static object there
                return(null);
            }

            var spawnedObject = ServerWorldService.CreateStaticWorldObject(protoStaticWorldObject, tilePosition);

            if (spawnedObject == null)
            {
                // cannot spawn static object there
                return(null);
            }

            // if spawned a vegetation - set random growth progress
            if (protoStaticWorldObject is IProtoObjectVegetation protoVegetation)
            {
                double growProgress;
                if (trigger == null ||
                    trigger is TriggerWorldInit)
                {
                    // world initialization spawn
                    growProgress = RandomHelper.RollWithProbability(0.6)
                                       ? 1                          // 60% are spawned in full grown state
                                       : Random.Next(0, 11) / 10.0; // other are spawned with random growth progress
                }
                else
                {
                    // spawn saplings
                    growProgress = 0;
                }

                protoVegetation.ServerSetGrowthProgress(spawnedObject, growProgress);
            }

            ServerDecalsDestroyHelper.DestroyAllDecals(tilePosition, protoStaticWorldObject.Layout);
            return(spawnedObject);
        }
コード例 #2
0
        protected static bool ServerCheckNoEventsInZone(IServerZone zoneInstance, List <ILogicObject> events)
        {
            foreach (var activeEvent in events)
            {
                var publicState = activeEvent.GetPublicState <EventWithAreaPublicState>();
                if (zoneInstance.IsContainsPosition(publicState.AreaEventOriginalPosition))
                {
                    // this event is in the same biome
                    return(false);
                }
            }

            return(true);
        }
コード例 #3
0
            public Vector2Ushort GetRandomPositionInside(IServerZone zone, Random random)
            {
                var           start = this.StartPosition;
                Vector2Ushort result;

                do
                {
                    result = new Vector2Ushort(
                        (ushort)random.Next(start.X, start.X + SpawnZoneAreaSize),
                        (ushort)random.Next(start.Y, start.Y + SpawnZoneAreaSize));
                }while (!zone.IsContainsPosition(result));

                return(result);
            }
コード例 #4
0
        /// <summary>
        /// Get all (already populated) areas with their objects inside the zone
        /// </summary>
        private async Task ServerFillSpawnAreasInZoneAsync(
            IServerZone zone,
            IReadOnlyDictionary <Vector2Ushort, SpawnZoneArea> areas,
            Func <Task> callbackYieldIfOutOfTime)
        {
            // this is a heavy method so we will try to yield every 100 objects to reduce the load
            const int defaultCounterToYieldValue = 100;
            var       counterToYield             = defaultCounterToYieldValue;

            // this check has a problem - it returns only objects strictly inside the zone,
            // but we also need to consider objects nearby the zone for restriction presets
            //await zone.PopulateStaticObjectsInZone(tempList, callbackYieldIfOutOfTime);

            TempListAllStaticWorldObjects.Clear();
            await Api.Server.World.GetStaticWorldObjectsAsync(TempListAllStaticWorldObjects);

            foreach (var staticObject in TempListAllStaticWorldObjects)
            {
                await YieldIfOutOfTime();

                if (staticObject.IsDestroyed)
                {
                    continue;
                }

                var position = staticObject.TilePosition;
                var area     = GetArea(position, isMobTrackingEnumeration: false);
                if (area is null)
                {
                    continue;
                }

                var protoStaticWorldObject = staticObject.ProtoStaticWorldObject;
                if (!(protoStaticWorldObject is ObjectGroundItemsContainer))
                {
                    if (protoStaticWorldObject.IsIgnoredBySpawnScripts)
                    {
                        // we don't consider padding to certain objects such as ground decals
                        // (though they still might affect spawn during the tiles check)
                        continue;
                    }

                    // create entry for regular static object
                    var preset = this.FindPreset(protoStaticWorldObject);
                    if (preset != null &&
                        preset.Density > 0 &&
                        !zone.IsContainsPosition(staticObject.TilePosition))
                    {
                        // this object is a part of the preset spawn list but it's not present in the zone
                        // don't consider this object
                        // TODO: this might cause a problem if there is a padding to this object check
                        continue;
                    }

                    area.Add(preset, position);
                    continue;
                }

                // ground container object
                var itemsContainer = ObjectGroundItemsContainer.GetPublicState(staticObject).ItemsContainer;
                foreach (var item in itemsContainer.Items)
                {
                    // create entry for each item in the ground container
                    var preset = this.FindPreset(item.ProtoItem);
                    if (preset != null &&
                        preset.Density > 0 &&
                        !zone.IsContainsPosition(staticObject.TilePosition))
                    {
                        // this object is a part of the preset spawn list but it's not present in the zone
                        // don't consider this object
                        continue;
                    }

                    area.Add(preset, position);
                }
            }

            var mobsTrackingManager = SpawnedMobsTrackingManagersStore.Get(this, zone);

            foreach (var mob in mobsTrackingManager.EnumerateAll())
            {
                await YieldIfOutOfTime();

                var position = mob.TilePosition;
                var area     = GetArea(position, isMobTrackingEnumeration: true);
                area?.Add(this.FindPreset(mob.ProtoCharacter), position);
            }

            return;

            SpawnZoneArea GetArea(Vector2Ushort tilePosition, bool isMobTrackingEnumeration)
            {
                var zoneChunkStartPosition = SpawnZoneArea.CalculateStartPosition(tilePosition);

                if (areas.TryGetValue(zoneChunkStartPosition, out var area))
                {
                    return(area);
                }

                if (isMobTrackingEnumeration)
                {
                    return(null);
                }

                return(null);
//                throw new Exception("No zone area found for " + tilePosition);

                //var newArea = new SpawnZoneArea(zoneChunkStartPosition, zoneChunk);
                //areas.Add(newArea);
                //return newArea;
            }

            Task YieldIfOutOfTime()
            {
                if (--counterToYield > 0)
                {
                    return(Task.CompletedTask);
                }

                counterToYield = defaultCounterToYieldValue;
                return(callbackYieldIfOutOfTime());
            }
        }