예제 #1
0
        void BuildChunk()
        {
            cd = cRender.mm.map.chunks[position.x, position.y];
            int        hei = cRender.mm.chunkHeight;
            MapManager mm  = MapManager.instance;

            for (int i = 0; i < cRender.mm.chunkWidth; i++)
            {
                for (int j = 0; j < hei; j++)
                {
                    TileString tl = cd.GetTile(i, j, layer);
                    if (!ReferenceEquals(tl, null))
                    {
                        TileBase tb = mm.GetTileFromCollection(tl);
                        AddTile(i, j, tb);
                        if (tb.gameObject)
                        {
                            if (gameObjects[i, j] == null)
                            {
                                gameObjects[i, j] = GameObject.Instantiate(tb.gameObject, transform, false);
                                gameObjects[i, j].transform.localPosition = new Vector3(i, j) * scale;
                            }
                        }
                    }
                    else
                    {
                        if (gameObjects[i, j] != null)
                        {
                            Destroy(gameObjects[i, j]);
                        }
                    }
                }
            }
        }
    public void CreateChunk(int id, Vector2 position, ChunkDefinition definition)
    {
        var e = _contexts.game.CreateEntity();

        e.isChunk = true;
        e.AddChunkWidth(definition.Width);
        e.AddId(id);
        e.AddAsset(definition.Asset);
        e.AddPosition(position);
    }
예제 #3
0
        /// <inheritdoc />
        protected override void ConnectionLost(NodeDefinition node, NodeType type)
        {
            if (type == NodeType.Controller)
            {
                if (Equals(Primary, node))
                {
                    Logger.Log("Primary controller unreachable, searching for new primary.", LogLevel.Info);
                    Primary = null;
                }

                // start at 1 because GetConnectedNodes doesn't include the current node.
                var connectedNodes        = GetConnectedNodes();
                int controllerActiveCount = 1 + _controllerNodes.Count(def => connectedNodes.Any(e => Equals(e.Item1, def)));

                if (controllerActiveCount <= _controllerNodes.Count / 2)
                {
                    Logger.Log("Not enough connected nodes to remain primary.", LogLevel.Info);
                    Primary = null;
                }
            }
            else if (type == NodeType.Storage)
            {
                lock (_storageNodes)
                {
                    _storageNodes.RemoveAll(e => e.Item1.Equals(node));
                }

                lock (_chunkList)
                {
                    _chunkList.RemoveAll(e => Equals(e.Node, node));
                }

                lock (_balancingLockObject)
                {
                    if (Equals(node, _nodeManagingChunk))
                    {
                        _balancing         = BalancingState.None;
                        _nodeManagingChunk = null;
                    }

                    if (Equals(node, _nodeTransferingChunk))
                    {
                        _balancing            = BalancingState.None;
                        _nodeTransferingChunk = null;
                        _chunkBeingTransfered = null;
                        Logger.Log("Chunk transfer failed.", LogLevel.Info);
                    }
                }
            }
        }
예제 #4
0
        void UpdateCollision()
        {
            RecycleColls();
            chd = cRender.mm.map.chunks[position.x, position.y];
            chu = chd.tileLayers[layer];
            ignorePoints.Clear();
            recalcPoints.Clear();
            for (int y = 0; y < cRender.mm.chunkHeight; y++)
            {
                for (int x = 0; x < cRender.mm.chunkWidth; x++)
                {
                    Vector2 vt = new Vector2(x, y);
                    if (!ignorePoints.Contains(vt) || recalcPoints.Contains(vt))
                    {
                        if (chu[x, y].tile != 0)
                        {
                            if (x == 0)
                            {
                                //Debug.Log("Outline.");
                                GenerateOutline(x, y);
                            }
                            else
                            {
                                if (x - 1 >= 0 && y - 1 >= 0)
                                {
                                    if (chu[x - 1, y].tile == 0 && chu[x, y - 1].tile == 0)
                                    {
                                        GenerateOutline(x, y);
                                    }
                                }
                                else if (x - 1 >= 0)
                                {
                                    if (chu[x - 1, y].tile == 0)
                                    {
                                        //Debug.Log("Outline (2).");
                                        GenerateOutline(x, y);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            for (int y = 0; y < cRender.mm.chunkHeight; y++)
            {
                for (int x = 0; x < cRender.mm.chunkWidth; x++)
                {
                    Vector2 vt = new Vector2(x, y);
                    if (!ignorePoints.Contains(vt) || recalcPoints.Contains(vt))
                    {
                        if (chu[x, y].tile != 0)
                        {
                            if (x > 0)
                            {
                                if (chu[x - 1, y].tile == 0)
                                {
                                    //Debug.Log($"Inline. ({x},{y})");
                                    GenerateInline(x, y);
                                }
                            }
                        }
                    }
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Balances the chunks on the storage nodes.
        /// </summary>
        private void BalanceChunks()
        {
            SortedList <NodeDefinition, float> chunksPerNode = new SortedList <NodeDefinition, float>();

            lock (_chunkList)
            {
                if (_chunkList.Count == 0)
                {
                    lock (_balancingLockObject)
                    {
                        _nodeTransferingChunk = null;
                        _chunkBeingTransfered = null;
                        _balancing            = BalancingState.None;
                        return;
                    }
                }

                foreach (var item in _chunkList)
                {
                    if (!chunksPerNode.ContainsKey(item.Node))
                    {
                        chunksPerNode.Add(item.Node, 1);
                    }
                    else
                    {
                        chunksPerNode[item.Node] += 1;
                    }
                }

                lock (_storageNodes)
                {
                    foreach (var item in _storageNodes)
                    {
                        if (!chunksPerNode.ContainsKey(item.Item1))
                        {
                            chunksPerNode.Add(item.Item1, 0);
                        }

                        chunksPerNode[item.Item1] /= item.Item2;
                    }
                }

                var sortedChunks = chunksPerNode.OrderBy(e => e.Value).ToList();
                if (sortedChunks[sortedChunks.Count - 1].Value - sortedChunks[0].Value > 2)
                {
                    var    minNode        = sortedChunks[0].Key;
                    var    maxNode        = sortedChunks[sortedChunks.Count - 1].Key;
                    Random rand           = new Random();
                    var    possibleChunks = _chunkList.Where(e => Equals(e.Node, maxNode)).ToList();
                    var    chunk          = possibleChunks[rand.Next(possibleChunks.Count)];
                    _nodeTransferingChunk = minNode;
                    _chunkBeingTransfered = chunk;
                    Logger.Log("Starting chunk transfer.", LogLevel.Info);
                    SendMessage(new Message(minNode, new ChunkTransfer(maxNode, chunk.Start, chunk.End), false));
                }
                else
                {
                    lock (_balancingLockObject)
                    {
                        _nodeTransferingChunk = null;
                        _chunkBeingTransfered = null;
                        _balancing            = BalancingState.None;
                    }
                }
            }
        }
예제 #6
0
        /// <inheritdoc />
        protected override void MessageReceived(Message message)
        {
            if (Equals(message.Address, Primary))
            {
                _lastPrimaryMessageId = Math.Max(_lastPrimaryMessageId, message.ID);
            }

            if (message.Data is JoinAttempt)
            {
                HandleJoinAttemptMessage(message, (JoinAttempt)message.Data);
            }
            else if (message.Data is VotingRequest)
            {
                if (Primary != null)
                {
                    SendMessage(new Message(message, new VotingResponse(false), false));
                }
                else
                {
                    uint max = 0;
                    List <Tuple <NodeDefinition, uint> > votingIds = new List <Tuple <NodeDefinition, uint> >();
                    foreach (var def in _controllerNodes)
                    {
                        if (Equals(def, Self))
                        {
                            continue;
                        }

                        Message idRequest = new Message(def, new LastPrimaryMessageIdRequest(), true);
                        SendMessage(idRequest);
                        idRequest.BlockUntilDone();

                        if (idRequest.Success)
                        {
                            uint votingId = ((LastPrimaryMessageIdResponse)idRequest.Response.Data).LastMessageId;
                            max = Math.Max(max, votingId);
                            votingIds.Add(new Tuple <NodeDefinition, uint>(def, votingId));
                        }
                    }

                    bool votingResponse = false;
                    if (votingIds.Count > 0)
                    {
                        var top = votingIds.Where(e => e.Item2 == max).OrderBy(e => e.Item1.ConnectionName);

                        if (Equals(top.First().Item1, message.Address))
                        {
                            votingResponse = true;
                        }
                    }

                    SendMessage(new Message(message, new VotingResponse(votingResponse), false));
                }
            }
            else if (message.Data is LastPrimaryMessageIdRequest)
            {
                SendMessage(new Message(message, new LastPrimaryMessageIdResponse(_lastPrimaryMessageId), false));
            }
            else if (message.Data is PrimaryAnnouncement)
            {
                Logger.Log("Setting the primary controller to " + message.Address.ConnectionName, LogLevel.Info);
                Primary = message.Address;
            }
            else if (message.Data is ChunkListUpdate)
            {
                lock (_chunkList)
                {
                    _chunkList.Clear();
                    _chunkList.AddRange(((ChunkListUpdate)message.Data).ChunkList);
                }

                SendMessage(new Message(message, new Acknowledgement(), false));
            }
            else if (message.Data is ChunkSplit)
            {
                ChunkSplit splitData = (ChunkSplit)message.Data;
                lock (_chunkList)
                {
                    _chunkList.Remove(_chunkList.Find(e => Equals(e.Start, splitData.Start1)));
                    _chunkList.Add(new ChunkDefinition(splitData.Start1, splitData.End1, message.Address));
                    _chunkList.Add(new ChunkDefinition(splitData.Start2, splitData.End2, message.Address));
                }

                SendMessage(new Message(message, new Acknowledgement(), false));

                lock (_balancingLockObject)
                {
                    _balancing         = BalancingState.None;
                    _nodeManagingChunk = null;

                    Logger.Log("Committing chunk split.", LogLevel.Debug);
                }

                SendChunkList();
            }
            else if (message.Data is ChunkMerge)
            {
                ChunkMerge mergeData = (ChunkMerge)message.Data;
                lock (_chunkList)
                {
                    _chunkList.Remove(_chunkList.Find(e => Equals(e.Start, mergeData.Start)));
                    _chunkList.Remove(_chunkList.Find(e => Equals(e.End, mergeData.End)));
                    _chunkList.Add(new ChunkDefinition(mergeData.Start, mergeData.End, message.Address));
                }

                SendMessage(new Message(message, new Acknowledgement(), false));

                lock (_balancingLockObject)
                {
                    _balancing         = BalancingState.None;
                    _nodeManagingChunk = null;

                    Logger.Log("Committing chunk merge.", LogLevel.Debug);
                }

                SendChunkList();
            }
            else if (message.Data is ChunkManagementRequest)
            {
                bool success = false;
                lock (_balancingLockObject)
                {
                    if (_balancing == BalancingState.None)
                    {
                        _balancing         = BalancingState.ChunkManagement;
                        success            = true;
                        _nodeManagingChunk = message.Address;

                        Logger.Log("Granting chunk management request.", LogLevel.Debug);
                    }
                }

                SendMessage(new Message(message, new ChunkManagementResponse(success), false));
            }
            else if (message.Data is ChunkTransferComplete)
            {
                if (((ChunkTransferComplete)message.Data).Success)
                {
                    lock (_chunkList)
                    {
                        int index = _chunkList.IndexOf(_chunkBeingTransfered);
                        _chunkList[index] = new ChunkDefinition(_chunkBeingTransfered.Start, _chunkBeingTransfered.End, message.Address);
                    }

                    Logger.Log("Chunk transfer completed successfully.", LogLevel.Info);
                    SendChunkList();
                    BalanceChunks();
                }
                else
                {
                    Logger.Log("Chunk transfer failed.", LogLevel.Info);

                    lock (_balancingLockObject)
                    {
                        _nodeTransferingChunk = null;
                        _chunkBeingTransfered = null;
                        _balancing            = BalancingState.None;
                    }
                }
            }
        }