Esempio n. 1
0
        private void garbageCollect()
        {
            ThreadingUtils.assertMainThread();

            var partsUnloaded = 0;
            var stopwatch     = new Stopwatch();

            stopwatch.Start();

            foreach (var part in loadedParts)
            {
                var key          = part.Key;
                var shouldRemove = shouldRemoveDuringGarbageCollection(part.Key, part.Value);

                if (shouldRemove)
                {
                    if (UnloadChunk(key))
                    {
                        partsUnloaded++;
                    }
                }
            }

            stopwatch.Stop();

            if (partsUnloaded > 0)
            {
                GameConsole.WriteLine("ChunkLoading", "Garbage Collector unloaded " + partsUnloaded + " " + GetType().Name + " parts took " + stopwatch.ElapsedMilliseconds + "ms");
            }
        }
Esempio n. 2
0
        public static bool IsHitableBlockHitted(Rect hitboxBounds, string interiorID = null)
        {
            ThreadingUtils.assertMainThread();

            if (interiorID == Interior.Outside)
            {
                // Check if blocks are of type blocking
                Point topLeft     = GeometryUtils.GetChunkPosition(hitboxBounds.Left, hitboxBounds.Top, WorldGrid.BlockSize.X, WorldGrid.BlockSize.Y);
                Point bottomRight = GeometryUtils.GetChunkPosition(hitboxBounds.Right, hitboxBounds.Bottom, WorldGrid.BlockSize.X, WorldGrid.BlockSize.Y);

                for (int blockX = topLeft.X; blockX <= bottomRight.X; blockX++)
                {
                    for (int blockY = topLeft.Y; blockY <= bottomRight.Y; blockY++)
                    {
                        Point          chunkPos       = GeometryUtils.GetChunkPosition(blockX, blockY, WorldGrid.WorldChunkBlockSize.X, WorldGrid.WorldChunkBlockSize.Y);
                        WorldGridChunk worldGridChunk = SimulationGame.World.GetFromChunkPoint(chunkPos.X, chunkPos.Y);

                        int blockType = worldGridChunk.GetBlockType(blockX, blockY);

                        if (IsBlockHitable(blockType))
                        {
                            return(true);
                        }
                    }
                }
            }
            else
            {
                Interior interior = SimulationGame.World.InteriorManager.Get(interiorID);

                // Check if blocks are of type blocking
                Point topLeft     = GeometryUtils.GetChunkPosition(hitboxBounds.Left, hitboxBounds.Top, WorldGrid.BlockSize.X, WorldGrid.BlockSize.Y);
                Point bottomRight = GeometryUtils.GetChunkPosition(hitboxBounds.Right, hitboxBounds.Bottom, WorldGrid.BlockSize.X, WorldGrid.BlockSize.Y);

                for (int blockX = topLeft.X; blockX <= bottomRight.X; blockX++)
                {
                    for (int blockY = topLeft.Y; blockY <= bottomRight.Y; blockY++)
                    {
                        int blockType = interior.GetBlockType(blockX, blockY);

                        if (IsBlockHitable(blockType))
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
Esempio n. 3
0
        public bool LoadAsync(KEY key)
        {
            ThreadingUtils.assertMainThread();

            if (!partsCurrentlyLoading.ContainsKey(key))
            {
                partsCurrentlyLoading[key] = true;

                Task.Run(() =>
                {
                    loadedParts.GetOrAdd(key, this.loadUnguarded);
                });

                return(true);
            }

            return(false);
        }
Esempio n. 4
0
        public bool RemoveChunk(KEY key)
        {
            ThreadingUtils.assertMainThread();

            PART removedPart;
            bool couldRemove = loadedParts.TryRemove(key, out removedPart);

            if (couldRemove)
            {
                unloadPart(key, removedPart);

                if (partsCurrentlyLoading.ContainsKey(key))
                {
                    partsCurrentlyLoading.Remove(key);
                }
            }

            return(couldRemove);
        }
Esempio n. 5
0
        private void connectWorldGridChunk(ulong key, WorldGridChunk part)
        {
            ThreadingUtils.assertMainThread();
            Point chunkPos = GeometryUtils.GetPointFromLong(key);
            Point blockPos = GeometryUtils.GetBlockFromReal(part.RealChunkBounds.X, part.RealChunkBounds.Y);

            // Set walkable grid blocking for contained objects
            if (part.ContainedObjects != null)
            {
                foreach (var hitableObject in part.ContainedObjects)
                {
                    hitableObject.ConnectToOverlappingChunks();
                }
            }

            // Set walkable grid blocking for blocks
            for (int i = 0; i < WorldChunkBlockSize.X; i++)
            {
                for (int j = 0; j < WorldChunkBlockSize.Y; j++)
                {
                    if (CollisionUtils.IsBlockBlocking(part.GetBlockType(blockPos.X + i, blockPos.Y + j)))
                    {
                        SimulationGame.World.WalkableGrid.SetBlockNotWalkable(blockPos.X + i, blockPos.Y + j, true);
                    }
                }
            }

            for (int i = -1; i <= 1; i++)
            {
                for (int j = -1; j < 1; j++)
                {
                    if (i == 0 && j == 0)
                    {
                        continue;
                    }

                    var neighborX     = chunkPos.X + i;
                    var neighborY     = chunkPos.Y + j;
                    var neighborChunk = Get(GeometryUtils.ConvertPointToLong(neighborX, neighborY), false);

                    if (neighborChunk != null)
                    {
                        // Add neighbor contained objects to self
                        if (neighborChunk.ContainedObjects != null)
                        {
                            foreach (var overlappingObject in neighborChunk.ContainedObjects)
                            {
                                if (overlappingObject.UnionBounds.Intersects(part.RealChunkBounds))
                                {
                                    part.AddOverlappingObject(overlappingObject);

                                    // Update walkable grid
                                    if (overlappingObject.IsBlocking())
                                    {
                                        SimulationGame.World.WalkableGrid.BlockRect(overlappingObject.BlockingBounds);
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Esempio n. 6
0
        public static bool IsRectBlockedAccurate(HitableObject origin, Rect rect)
        {
            ThreadingUtils.assertMainThread();

            if (origin.InteriorID == Interior.Outside)
            {
                // Check if blocks are of type blocking
                Point topLeft     = GeometryUtils.GetChunkPosition(rect.Left, rect.Top, WorldGrid.BlockSize.X, WorldGrid.BlockSize.Y);
                Point bottomRight = GeometryUtils.GetChunkPosition(rect.Right, rect.Bottom, WorldGrid.BlockSize.X, WorldGrid.BlockSize.Y);

                for (int blockX = topLeft.X; blockX <= bottomRight.X; blockX++)
                {
                    for (int blockY = topLeft.Y; blockY <= bottomRight.Y; blockY++)
                    {
                        Point          chunkPos       = GeometryUtils.GetChunkPosition(blockX, blockY, WorldGrid.WorldChunkBlockSize.X, WorldGrid.WorldChunkBlockSize.Y);
                        WorldGridChunk worldGridChunk = SimulationGame.World.GetFromChunkPoint(chunkPos.X, chunkPos.Y);

                        int blockType = worldGridChunk.GetBlockType(blockX, blockY);

                        if (IsBlockBlocking(blockType))
                        {
                            return(true);
                        }
                    }
                }

                // Check collision with interactive && contained objects
                Point chunkTopLeft     = GeometryUtils.GetChunkPosition(rect.Left, rect.Top, WorldGrid.WorldChunkPixelSize.X, WorldGrid.WorldChunkPixelSize.Y);
                Point chunkBottomRight = GeometryUtils.GetChunkPosition(rect.Right, rect.Bottom, WorldGrid.WorldChunkPixelSize.X, WorldGrid.WorldChunkPixelSize.Y);

                for (int chunkX = chunkTopLeft.X; chunkX <= chunkBottomRight.X; chunkX++)
                {
                    for (int chunkY = chunkTopLeft.Y; chunkY <= chunkBottomRight.Y; chunkY++)
                    {
                        WorldGridChunk worldGridChunk = SimulationGame.World.GetFromChunkPoint(chunkX, chunkY);

                        if (worldGridChunk.OverlappingObjects != null)
                        {
                            foreach (HitableObject hitableObject in worldGridChunk.OverlappingObjects)
                            {
                                if (hitableObject.IsBlocking() && hitableObject != origin && hitableObject.BlockingBounds.Intersects(rect))
                                {
                                    return(true);
                                }
                            }
                        }

                        if (worldGridChunk.ContainedObjects != null)
                        {
                            foreach (var hitableObject in worldGridChunk.ContainedObjects)
                            {
                                if (hitableObject.IsBlocking() && hitableObject != origin && hitableObject.BlockingBounds.Intersects(rect))
                                {
                                    return(true);
                                }
                            }
                        }
                    }
                }

                return(false);
            }
            else
            {
                Interior interior = SimulationGame.World.InteriorManager.Get(origin.InteriorID);

                // Check if blocks are of type blocking
                Point topLeft     = GeometryUtils.GetChunkPosition(rect.Left, rect.Top, WorldGrid.BlockSize.X, WorldGrid.BlockSize.Y);
                Point bottomRight = GeometryUtils.GetChunkPosition(rect.Right, rect.Bottom, WorldGrid.BlockSize.X, WorldGrid.BlockSize.Y);

                for (int blockX = topLeft.X; blockX <= bottomRight.X; blockX++)
                {
                    for (int blockY = topLeft.Y; blockY <= bottomRight.Y; blockY++)
                    {
                        if (blockX < 0 || blockX >= interior.Dimensions.X)
                        {
                            return(true);
                        }
                        if (blockY < 0 || blockY >= interior.Dimensions.Y)
                        {
                            return(true);
                        }

                        int blockType = interior.GetBlockType(blockX, blockY);

                        if (IsBlockBlocking(blockType))
                        {
                            return(true);
                        }
                    }
                }

                foreach (var hitableObject in interior.ContainedObjects)
                {
                    if (hitableObject.IsBlocking() && hitableObject != origin && hitableObject.BlockingBounds.Intersects(rect))
                    {
                        return(true);
                    }
                }

                return(false);
            }
        }
Esempio n. 7
0
        public static bool IsRectBlockedFast(HitableObject origin, Rect rect)
        {
            ThreadingUtils.assertMainThread();

            if (origin.InteriorID == Interior.Outside)
            {
                // Check if blocks are of type blocking
                Point topLeft     = GeometryUtils.GetChunkPosition(rect.Left, rect.Top, WorldGrid.BlockSize.X, WorldGrid.BlockSize.Y);
                Point bottomRight = GeometryUtils.GetChunkPosition(rect.Right, rect.Bottom, WorldGrid.BlockSize.X, WorldGrid.BlockSize.Y);

                for (int blockX = topLeft.X; blockX <= bottomRight.X; blockX++)
                {
                    for (int blockY = topLeft.Y; blockY <= bottomRight.Y; blockY++)
                    {
                        if (!SimulationGame.World.WalkableGrid.IsBlockWalkable(blockX, blockY))
                        {
                            return(true);
                        }
                    }
                }

                return(false);
            }
            else
            {
                Interior interior = SimulationGame.World.InteriorManager.Get(origin.InteriorID);

                // Check if blocks are of type blocking
                Point topLeft     = GeometryUtils.GetChunkPosition(rect.Left, rect.Top, WorldGrid.BlockSize.X, WorldGrid.BlockSize.Y);
                Point bottomRight = GeometryUtils.GetChunkPosition(rect.Right, rect.Bottom, WorldGrid.BlockSize.X, WorldGrid.BlockSize.Y);

                for (int blockX = topLeft.X; blockX <= bottomRight.X; blockX++)
                {
                    for (int blockY = topLeft.Y; blockY <= bottomRight.Y; blockY++)
                    {
                        if (blockX < 0 || blockX >= interior.Dimensions.X)
                        {
                            return(true);
                        }
                        if (blockY < 0 || blockY >= interior.Dimensions.Y)
                        {
                            return(true);
                        }

                        int blockType = interior.GetBlockType(blockX, blockY);

                        if (IsBlockBlocking(blockType))
                        {
                            return(true);
                        }
                    }
                }

                foreach (var hitableObject in interior.ContainedObjects)
                {
                    if (hitableObject.IsBlocking() && hitableObject != origin && hitableObject.BlockingBounds.Intersects(rect))
                    {
                        return(true);
                    }
                }

                return(false);
            }
        }
Esempio n. 8
0
        public static List <HitableObject> GetHittedObjects(Rect hitboxBounds, string interiorId, HitableObject origin)
        {
            ThreadingUtils.assertMainThread();
            List <HitableObject> hittedObjecs = new List <HitableObject>();

            if (interiorId == Interior.Outside)
            {
                // Check collision with interactive && contained objects
                Point chunkTopLeft     = GeometryUtils.GetChunkPosition(hitboxBounds.Left, hitboxBounds.Top, WorldGrid.WorldChunkPixelSize.X, WorldGrid.WorldChunkPixelSize.Y);
                Point chunkBottomRight = GeometryUtils.GetChunkPosition(hitboxBounds.Right, hitboxBounds.Bottom, WorldGrid.WorldChunkPixelSize.X, WorldGrid.WorldChunkPixelSize.Y);

                for (int chunkX = chunkTopLeft.X; chunkX <= chunkBottomRight.X; chunkX++)
                {
                    for (int chunkY = chunkTopLeft.Y; chunkY <= chunkBottomRight.Y; chunkY++)
                    {
                        WorldGridChunk worldGridChunk = SimulationGame.World.GetFromChunkPoint(chunkX, chunkY);

                        if (worldGridChunk.OverlappingObjects != null)
                        {
                            foreach (HitableObject hitableObject in worldGridChunk.OverlappingObjects)
                            {
                                if (hitableObject != origin && hitableObject.IsHitable() && hitableObject.HitBoxBounds.Intersects(hitboxBounds))
                                {
                                    if (hittedObjecs.Contains(hitableObject) == false && (hitableObject is LivingEntity == false || ((LivingEntity)hitableObject).IsDead() == false))
                                    {
                                        hittedObjecs.Add(hitableObject);
                                    }
                                }
                            }
                        }

                        if (worldGridChunk.ContainedObjects != null)
                        {
                            foreach (var hitableObject in worldGridChunk.ContainedObjects)
                            {
                                if (hitableObject != origin && hitableObject.IsHitable() && hitableObject.HitBoxBounds.Intersects(hitboxBounds))
                                {
                                    if (hittedObjecs.Contains(hitableObject) == false && (hitableObject is LivingEntity == false || ((LivingEntity)hitableObject).IsDead() == false))
                                    {
                                        hittedObjecs.Add(hitableObject);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                Interior interior = SimulationGame.World.InteriorManager.Get(interiorId);

                foreach (var hitableObject in interior.ContainedObjects)
                {
                    if (hitableObject != origin && hitableObject.IsHitable() && hitableObject.HitBoxBounds.Intersects(hitboxBounds))
                    {
                        if (hittedObjecs.Contains(hitableObject) == false && (hitableObject is LivingEntity == false || ((LivingEntity)hitableObject).IsDead() == false))
                        {
                            hittedObjecs.Add(hitableObject);
                        }
                    }
                }
            }

            return(hittedObjecs);
        }
Esempio n. 9
0
        public static LivingEntity GetClosestLivingTarget(Rect hitboxBounds, string interiorId, HitableObject origin, int maxAggro)
        {
            ThreadingUtils.assertMainThread();

            HitableObject closestTarget   = null;
            float         closestDistance = float.PositiveInfinity;

            if (interiorId == Interior.Outside)
            {
                // Check collision with interactive && contained objects
                Point chunkTopLeft     = GeometryUtils.GetChunkPosition(hitboxBounds.Left, hitboxBounds.Top, WorldGrid.WorldChunkPixelSize.X, WorldGrid.WorldChunkPixelSize.Y);
                Point chunkBottomRight = GeometryUtils.GetChunkPosition(hitboxBounds.Right, hitboxBounds.Bottom, WorldGrid.WorldChunkPixelSize.X, WorldGrid.WorldChunkPixelSize.Y);

                for (int chunkX = chunkTopLeft.X; chunkX <= chunkBottomRight.X; chunkX++)
                {
                    for (int chunkY = chunkTopLeft.Y; chunkY <= chunkBottomRight.Y; chunkY++)
                    {
                        WorldGridChunk worldGridChunk = SimulationGame.World.GetFromChunkPoint(chunkX, chunkY);

                        if (worldGridChunk.OverlappingObjects != null)
                        {
                            foreach (HitableObject hitableObject in worldGridChunk.OverlappingObjects)
                            {
                                if (hitableObject is LivingEntity &&
                                    hitableObject != origin &&
                                    hitableObject.IsHitable() &&
                                    ((LivingEntity)origin).GetAggroTowardsEntity((LivingEntity)hitableObject) <= maxAggro &&
                                    hitableObject.HitBoxBounds.Intersects(hitboxBounds))
                                {
                                    var distance = GeometryUtils.GetDiagonalDistance(hitableObject.Position.X, hitableObject.Position.Y, origin.Position.X, origin.Position.Y);

                                    if (distance < closestDistance)
                                    {
                                        closestDistance = distance;
                                        closestTarget   = hitableObject;
                                    }
                                }
                            }
                        }


                        if (worldGridChunk.ContainedObjects != null)
                        {
                            foreach (var hitableObject in worldGridChunk.ContainedObjects)
                            {
                                if (hitableObject is LivingEntity &&
                                    hitableObject != origin &&
                                    hitableObject.IsHitable() &&
                                    ((LivingEntity)origin).GetAggroTowardsEntity((LivingEntity)hitableObject) <= maxAggro &&
                                    hitableObject.HitBoxBounds.Intersects(hitboxBounds))
                                {
                                    var distance = GeometryUtils.GetDiagonalDistance(hitableObject.Position.X, hitableObject.Position.Y, origin.Position.X, origin.Position.Y);

                                    if (distance < closestDistance)
                                    {
                                        closestDistance = distance;
                                        closestTarget   = hitableObject;
                                    }
                                }
                            }
                        }
                    }
                }
            }
            else
            {
                Interior interior = SimulationGame.World.InteriorManager.Get(interiorId);

                foreach (var hitableObject in interior.ContainedObjects)
                {
                    if (hitableObject is LivingEntity &&
                        hitableObject != origin &&
                        hitableObject.IsHitable() &&
                        ((LivingEntity)origin).GetAggroTowardsEntity((LivingEntity)hitableObject) <= maxAggro &&
                        hitableObject.HitBoxBounds.Intersects(hitboxBounds))
                    {
                        var distance = GeometryUtils.GetDiagonalDistance(hitableObject.Position.X, hitableObject.Position.Y, origin.Position.X, origin.Position.Y);

                        if (distance < closestDistance)
                        {
                            closestDistance = distance;
                            closestTarget   = hitableObject;
                        }
                    }
                }
            }

            return((LivingEntity)closestTarget);
        }