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); }
/// <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); } } } }
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); } } } } } } }
/// <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; } } } }
/// <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; } } } }