/// <summary> /// If a new chunk was loaded (and the chunk contains acutal data) this chunk /// will be embedded into a new dynamic chunk. After this, for all relevant layers, /// there tiles and items will be loaded and set to be displayed. For all elements /// zDepth will be calculated relative to the current reference layer. /// </summary> /// <param name="sender">the object that informed about the event</param> /// <param name="chunk">the new chunk that was loaded</param> private void OnChunkLoaded(object sender, Chunk chunk) { if (chunk == null) { return; } var dynamicChunk = new DynamicChunk(spritePool); loadedChunks.Add(chunk, dynamicChunk); var applicableLayerIndices = GetApplicableLayerIndices(chunk.Layers); for (int xy = 0; xy < chunk.Map.Length; xy++) { int x = xy / Constants.Map.Chunksize + chunk.Origin[0]; int y = xy % Constants.Map.Chunksize + chunk.Origin[1]; foreach (int layerIndex in applicableLayerIndices) { UncompressTileId(chunk.Map[xy][layerIndex], out var tileId, out var overlayId); int layer = chunk.Layers[layerIndex]; int xPos = x + layer * 3; int yPos = -y + layer * 3; int zDepth = (referenceLayer - layer) * 2; if (tileId > 0) { tilemap.SetTile(new Vector3Int( xPos, yPos, zDepth), tiles[tileId]); } zDepth--; if (overlayId > 0) { tilemap.SetTile(new Vector3Int( xPos, yPos, zDepth), tiles[overlayId]); } var tilePosition = new Vector3i(x, y, layer); if (!chunk.Items.TryGetValue(tilePosition, out var items)) { continue; } LoadItemStack(items, new Vector3((xPos - yPos) * (38f / 76f) - (1f / 76f), (xPos + yPos) * (19f / 76f) + 0.25f, zDepth - ((y - x) / 20000f) - 0.3f), tilePosition, dynamicChunk); } } }
//Keep track of chunks that need their meshes rebuilt void AddChunkToUpdate(DynamicChunk chunk) { if (chunk != null) { if (!chunksToUpdate.Contains(chunk)) { chunksToUpdate.Add(chunk); } } }
DynamicChunk GenerateNewChunk(float chunkX, float chunkY, float chunkZ) { float[,,] chunkData = new float[chunkSize, chunkHeight, chunkSize]; FillData(ref chunkData, (int)chunkX, (int)chunkY, (int)chunkZ); GameObject chunk = new GameObject("Chunk" + chunkX + "," + chunkY + "," + chunkZ, typeof(DynamicChunk), typeof(MeshFilter), typeof(MeshRenderer), typeof(MeshCollider)); chunk.transform.position = new Vector3(chunkX, chunkY, chunkZ); chunk.transform.parent = this.transform; DynamicChunk dc = chunk.GetComponent <DynamicChunk>(); dc.Initialize(chunkData, chunkSize, chunkHeight, defaultMaterial, this); return(dc); }
//Used to change the density value at a specific data point void ModDensityAt(int x, int y, int z, float value) { int relativeX = (int)(x - worldStartPosition.x); int relativeZ = (int)(z - worldStartPosition.z); DynamicChunk chunk = GetChunkContaining(x, z); if (chunk != null) { int chunkOffsetX = (int)(x - worldStartPosition.x) % chunkSize; int chunkOffsetZ = (int)(z - worldStartPosition.z) % chunkSize; if (chunkOffsetX >= 0 && chunkOffsetX < chunkSize && y >= 0 && y < chunkHeight && chunkOffsetZ >= 0 && chunkOffsetZ < chunkSize) { float currentValue = chunk.GetValue(chunkOffsetX, y, chunkOffsetZ); chunk.SetValue(chunkOffsetX, y, chunkOffsetZ, Mathf.Max(-1, Mathf.Min(currentValue + value, 1))); AddChunkToUpdate(chunk); //Check surrounding chunks for data changes. DynamicChunk neighborChunk; if (chunkOffsetX == 0) { neighborChunk = GetChunkContaining(x - chunkSize, z); AddChunkToUpdate(neighborChunk); } if (chunkOffsetZ == 0) { neighborChunk = GetChunkContaining(x, z - chunkSize); AddChunkToUpdate(neighborChunk); } if (chunkOffsetX == chunkSize) { neighborChunk = GetChunkContaining(x + chunkSize, z); AddChunkToUpdate(neighborChunk); } if (chunkOffsetZ == chunkSize) { neighborChunk = GetChunkContaining(x, z + chunkSize); AddChunkToUpdate(neighborChunk); } } } }
/// <summary> /// Loads an array of items to be displayed. /// Will apply offset, initialize animated or variant items, /// scale and height-level. Loaded items will be in the order of the array. /// </summary> /// <param name="items">The array of items</param> /// <param name="screenPosition">The origin screenposition to display the items</param> /// <param name="tilePosition">The corresponding tileposition to the screenpostion</param> /// <param name="chunk">The dynamic chunk in charge of the item sprites</param> private void LoadItemStack(MapObject[] items, Vector3 screenPosition, Vector3i tilePosition, DynamicChunk chunk) { foreach (var item in items) { var unitySprite = spritePool.Get(); var itemBase = itemBases[item.BaseId]; Sprite sprite; float[] offset; if (itemBase is SimpleObjectBase simpleBase) { sprite = sprites[simpleBase.SpriteId]; offset = simpleBase.Offset; } else { var variantBase = (VariantObjectBase)itemBase; var spriteId = SetupMultiFrameItem(variantBase, tilePosition.x, tilePosition.y, unitySprite); sprite = sprites[spriteId]; offset = variantBase.GetOffset(spriteId); } unitySprite.sprite = sprite; unitySprite.transform.position = new Vector3( screenPosition.x - sprite.bounds.extents.x + offset[0], screenPosition.y + offset[1] + chunk.GetHeightLevel(tilePosition), screenPosition.z ); SetupItemScale(tilePosition.x, tilePosition.y, itemBase.SizeVariance, unitySprite); unitySprite.gameObject.SetActive(true); if (itemBase.Height > 0f) { chunk.IncreaseHeightLevel(tilePosition, itemBase.Height); } chunk.RegisterItem(unitySprite); screenPosition.z -= 0.000001f; } }