MeshData GetMesh(NBTChunk chunk, Vector3Int pos) { byte eastType = chunk.GetBlockByte(pos + Vector3Int.right); bool eastConnect = !NBTGeneratorManager.IsTransparent(eastType) || NBTGeneratorManager.IsFence(eastType); byte southType = chunk.GetBlockByte(pos + Vector3Int.back); bool southConnect = !NBTGeneratorManager.IsTransparent(southType) || NBTGeneratorManager.IsFence(southType); byte westType = chunk.GetBlockByte(pos + Vector3Int.left); bool westConnect = !NBTGeneratorManager.IsTransparent(westType) || NBTGeneratorManager.IsFence(westType); byte northType = chunk.GetBlockByte(pos + Vector3Int.forward); bool northConnect = !NBTGeneratorManager.IsTransparent(northType) || NBTGeneratorManager.IsFence(northType); int index = 0; if (westConnect) { index += 8; } if (northConnect) { index += 4; } if (eastConnect) { index += 2; } if (southConnect) { index += 1; } return(meshes[index]); }
public override void AddCube(NBTChunk chunk, byte blockData, Vector3Int pos, NBTGameObject nbtGO) { ca.pos = pos; ca.blockData = blockData; InitBlockAttributes(chunk, ref ca); bool topIsSnow = chunk.GetBlockByte(pos.x, pos.y + 1, pos.z) == 78; if (!chunk.HasOpaqueBlock(pos.x, pos.y, pos.z - 1)) { FaceAttributes fa = GetFrontFaceAttributes(chunk, nbtGO.nbtMesh, ca); if (topIsSnow) { fa.faceIndex = TextureArrayManager.GetIndexByName("grass_side_snowed"); } AddFace(nbtGO.nbtMesh, fa, ca); } if (!chunk.HasOpaqueBlock(pos.x + 1, pos.y, pos.z)) { FaceAttributes fa = GetRightFaceAttributes(chunk, nbtGO.nbtMesh, ca); if (topIsSnow) { fa.faceIndex = TextureArrayManager.GetIndexByName("grass_side_snowed"); } AddFace(nbtGO.nbtMesh, fa, ca); } if (!chunk.HasOpaqueBlock(pos.x - 1, pos.y, pos.z)) { FaceAttributes fa = GetLeftFaceAttributes(chunk, nbtGO.nbtMesh, ca); if (topIsSnow) { fa.faceIndex = TextureArrayManager.GetIndexByName("grass_side_snowed"); } AddFace(nbtGO.nbtMesh, fa, ca); } if (!chunk.HasOpaqueBlock(pos.x, pos.y, pos.z + 1)) { FaceAttributes fa = GetBackFaceAttributes(chunk, nbtGO.nbtMesh, ca); if (topIsSnow) { fa.faceIndex = TextureArrayManager.GetIndexByName("grass_side_snowed"); } AddFace(nbtGO.nbtMesh, fa, ca); } if (!chunk.HasOpaqueBlock(pos.x, pos.y + 1, pos.z)) { FaceAttributes fa = GetTopFaceAttributes(chunk, nbtGO.nbtMesh, ca); if (topIsSnow) { fa.faceIndex = TextureArrayManager.GetIndexByName("snow"); } AddFace(nbtGO.nbtMesh, fa, ca); } if (!chunk.HasOpaqueBlock(pos.x, pos.y - 1, pos.z)) { FaceAttributes fa = GetBottomFaceAttributes(chunk, nbtGO.nbtMesh, ca); AddFace(nbtGO.nbtMesh, fa, ca); } }
public static void SetBlockByte(int x, int y, int z, byte type) { int chunkX = Mathf.FloorToInt(x / 16f); int chunkZ = Mathf.FloorToInt(z / 16f); int xInChunk = x - chunkX * 16; int zInChunk = z - chunkZ * 16; NBTChunk chunk = GetChunk(chunkX, chunkZ); NBTBlock oldGenerator = NBTGeneratorManager.GetMeshGenerator(chunk.GetBlockByte(xInChunk, y, zInChunk)); UpdateFlags updateFlag = GetUpdateFlags(oldGenerator); if (type == 0) { chunk.GetBlockData(xInChunk, y + 1, zInChunk, out byte topType, out byte topData); NBTBlock topGenerator = NBTGeneratorManager.GetMeshGenerator(topType); if (topGenerator != null && topGenerator is NBTPlant) { BreakBlockEffect.Create(topType, topData, new Vector3(x, y + 1, z)); chunk.SetBlockByte(xInChunk, y + 1, zInChunk, 0); updateFlag |= UpdateFlags.NotCollidable; } } chunk.SetBlockByte(xInChunk, y, zInChunk, type); if (updateFlag.HasFlag(UpdateFlags.Lighting)) { UpdateLighting(x, y, z); } chunk.RebuildMesh(updateFlag); NBTChunk leftChunk = GetChunk(chunkX - 1, chunkZ); if (xInChunk == 0) { leftChunk.RebuildMesh(); } NBTChunk rightChunk = GetChunk(chunkX + 1, chunkZ); if (xInChunk == 15) { rightChunk.RebuildMesh(); } NBTChunk backChunk = GetChunk(chunkX, chunkZ - 1); if (zInChunk == 0) { backChunk.RebuildMesh(); } NBTChunk frontChunk = GetChunk(chunkX, chunkZ + 1); if (zInChunk == 15) { frontChunk.RebuildMesh(); } }
public static byte GetBlockByte(int x, int y, int z) { int chunkX = Mathf.FloorToInt(x / 16f); int chunkY = Mathf.FloorToInt(y / 16f); int chunkZ = Mathf.FloorToInt(z / 16f); int xInChunk = x - chunkX * 16; int yInChunk = y - chunkY * 16; int zInChunk = z - chunkZ * 16; NBTChunk chunk = GetChunk(chunkX, chunkZ); if (chunk != null) { return(chunk.GetBlockByte(xInChunk, y, zInChunk)); } else { //TagNodeCompound Chunk = GetChunkNode(chunkX, chunkZ); //if (Chunk != null) //{ // TagNodeCompound Level = Chunk["Level"] as TagNodeCompound; // TagNodeList Sections = Level["Sections"] as TagNodeList; // if (chunkY < Sections.Count) // { // TagNodeCompound section = Sections[chunkY] as TagNodeCompound; // TagNodeByteArray Blocks = section["Blocks"] as TagNodeByteArray; // byte[] blocks = new byte[4096]; // Buffer.BlockCopy(Blocks, 0, blocks, 0, 4096); // int blockPos = yInChunk * 16 * 16 + zInChunk * 16 + xInChunk; // return blocks[blockPos]; // } //} } return(0); }
public static void UpdateLighting(int x, int y, int z) { //Debug.Log("update lighting"); //float start = Time.realtimeSinceStartup; Queue <Vector3Int> skyLightQueue = new Queue <Vector3Int>(); Vector3Int p = new Vector3Int(); // init for (int i = -15; i <= 15; i++) { for (int j = -15; j <= 15; j++) { p.Set(x + i, y, z + j); int chunkX = Mathf.FloorToInt(p.x / 16f); int chunkZ = Mathf.FloorToInt(p.z / 16f); int xInChunk = p.x - chunkX * 16; int zInChunk = p.z - chunkZ * 16; NBTChunk chunk = GetChunk(chunkX, chunkZ); for (int temp_y = chunk.Sections.Count * 16 - 1; temp_y >= 0; temp_y--) { chunk.SetSkyLightByte(xInChunk, temp_y, zInChunk, 0); } } } HashSet <Vector3Int> skyLightSet = new HashSet <Vector3Int>(); // light from sun (no vertical falloff) for (int i = -15; i <= 15; i++) { for (int j = -15; j <= 15; j++) { p.Set(x + i, y, z + j); int chunkX = Mathf.FloorToInt(p.x / 16f); int chunkZ = Mathf.FloorToInt(p.z / 16f); int xInChunk = p.x - chunkX * 16; int zInChunk = p.z - chunkZ * 16; NBTChunk chunk = GetChunk(chunkX, chunkZ); int temp_y = chunk.Sections.Count * 16 - 1; while (NBTGeneratorManager.LightCanTravel(chunk.GetBlockByte(xInChunk, temp_y, zInChunk))) { chunk.SetSkyLightByte(xInChunk, temp_y, zInChunk, 15); skyLightSet.Add(new Vector3Int(p.x, temp_y, p.z)); if (temp_y == 0) { break; } else { temp_y--; } } } } foreach (Vector3Int skyLightPos in skyLightSet) { if (skyLightSet.Contains(skyLightPos + Vector3Int.left) && skyLightSet.Contains(skyLightPos + Vector3Int.right) && skyLightSet.Contains(skyLightPos + Vector3Int.forward) && skyLightSet.Contains(skyLightPos + Vector3Int.back)) { continue; } skyLightQueue.Enqueue(new Vector3Int(skyLightPos.x, skyLightPos.y, skyLightPos.z)); } int count = 0; int setcount = 0; // light propagation (use flood fill) Vector3Int[] arr = new Vector3Int[6]; while (skyLightQueue.Count > 0) { count++; p = skyLightQueue.Dequeue(); byte skyLight = GetSkyLightByte(p.x, p.y, p.z); arr[0] = p + Vector3Int.left; arr[1] = p + Vector3Int.right; arr[2] = p + Vector3Int.up; arr[3] = p + Vector3Int.down; arr[4] = p + Vector3Int.forward; arr[5] = p + Vector3Int.back; for (int i = 0; i < 6; i++) { Vector3Int nextPos = arr[i]; if (NBTGeneratorManager.IsTransparent(GetBlockByte(nextPos.x, nextPos.y, nextPos.z))) { byte nextSkyLight = GetSkyLightByte(nextPos.x, nextPos.y, nextPos.z); if (nextSkyLight < skyLight - 1) { setcount++; //Debug.Log("SetSkyLightByte,nextPos=" + nextPos.x + "," + nextPos.y + "," + nextPos.z); SetSkyLightByte(nextPos.x, nextPos.y, nextPos.z, (byte)(skyLight - 1)); if (skyLight > 2) { skyLightQueue.Enqueue(nextPos); } } } } } //float end = Time.realtimeSinceStartup; //Debug.Log("time cost =" + (end - start) + ", actual propagation count=" + count + ",setcount=" + setcount); }