/* * public int GetMetadata(BlockPos pos) * { * Chunk chunk = GetChunk(ChunkPos.FromWorldSpace(pos)); * if (chunk == null || !chunk.HasData) * return -1; * * return chunk.GetMetadata(ChunkPos.ToChunkLocal(pos)); * }*/ /* * public void SetMetadata(BlockPos pos, int meta) * { * Chunk chunk = GetChunk(ChunkPos.FromWorldSpace(pos)); * if (chunk == null || !chunk.HasData) * return; * * chunk.SetMetadata(ChunkPos.ToChunkLocal(pos), meta); * }*/ public int GetHeightAtPos(float x, float z) { BlockPos pos = new BlockPos(x, 0, z); Chunk chunk = GetChunk(pos.ChunkPos()); if (chunk == null || !chunk.HasData) { return(0); } return(chunk.GetHeightAtPos(MathUtil.ToLocal(pos.X, Chunk.ChunkSize), MathUtil.ToLocal(pos.Z, Chunk.ChunkSize))); }
public static Chunk loadChunk(BlockPos pos) { var chunkPos = pos.ChunkPos(); var regionPos = new BlockPos(chunkPos.x / (4 * 16), 0, chunkPos.z / (4 * 16)); var fileName = $"r.{regionPos.x}.{regionPos.z}.region"; var bf = new BinaryFormatter(); try { locker.AcquireReaderLock(1000); if (!Directory.Exists(dir) || !File.Exists($"{dir}/{fileName}")) { return(null); } //read, if exists using (var fs = File.Open($"{dir}/{fileName}", FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { fs.SetLength(_regionInfoSize); var regionInfo = (RegionInfo)bf.Deserialize(fs); var chunkFilePos = regionInfo.getChunkPos(chunkPos); fs.Position = chunkFilePos; fs.SetLength(_chunkSize); var cc = (ChunkCache)bf.Deserialize(fs); return(Chunk.CreateFromCache(cc)); } } catch { return(null); } finally { locker.ReleaseLock(); } }
public override void RemoveTileEntity(BlockPos pos) { GetChunk(pos.ChunkPos())?.RemoveTileEntity(ChunkPos.ToChunkLocal(pos)); }
//TODO move this to some chunk generator public short[,,] GenerateChunk(ChunkPos chunkPos, bool updateContainingEntities) { Chunk chunk = null; lock (Chunks) { chunk = PutChunk(chunkPos, null); } if (chunk == null) { return(null); } var air = BlockRegistry.GetBlock <BlockAir>().GetState(); var leavesGreen = BlockRegistry.GetBlock <BlockLeaves>().GetState(); var leavesYellow = BlockRegistry.GetBlock <BlockLeaves>().GetState(1); var leavesOrange = BlockRegistry.GetBlock <BlockLeaves>().GetState(2); var leavesRed = BlockRegistry.GetBlock <BlockLeaves>().GetState(3); var log = BlockRegistry.GetBlock <BlockLog>().GetState(); var grass = BlockRegistry.GetBlock <BlockGrass>().GetState(); var dirt = BlockRegistry.GetBlock <BlockDirt>().GetState(); var stone = BlockRegistry.GetBlock <BlockStone>().GetState(); var rare = BlockRegistry.GetBlock <BlockRare>().GetState(); var bedrock = BlockRegistry.GetBlock <BlockBedrock>().GetState(); var tallgrass = BlockRegistry.GetBlock <BlockTallGrass>().GetState(); var tulipRed = BlockRegistry.GetBlock <BlockTulipRed>().GetState(); var tulipOrange = BlockRegistry.GetBlock <BlockTulipOrange>().GetState(); short airId = GetLocalBlockId(air.Block.UnlocalizedName); short[,,] chunkData = new short[Chunk.ChunkSize, Chunk.ChunkHeight, Chunk.ChunkSize]; void SetBlock(int x, int y, int z, BlockState s) { short id = GetLocalBlockId(s.Block.UnlocalizedName); short meta = s.Block.GetMetaFromState(s); #pragma warning disable CS0675 // Bitwise-or operator used on a sign-extended operand short value = (short)(id << 4 | meta); #pragma warning restore CS0675 // Bitwise-or operator used on a sign-extended operand chunkData[x, y, z] = value; } bool IsAir(int x, int y, int z) { return(chunkData[x, y, z] >> 4 == airId); } for (int z = 0; z < Chunk.ChunkSize; z++) { for (int x = 0; x < Chunk.ChunkSize; x++) { float wsX = chunk.Pos.WorldSpaceX(); float wsZ = chunk.Pos.WorldSpaceZ(); float xCh = x + wsX; float zCh = z + wsZ; int peakY = 32 + (int)Math.Abs( MathHelper.Clamp(0.35f + _noiseUtil.GetPerlinFractal(xCh, zCh), 0, 1) * 32); float grassSeed = _noiseUtil.GetPerlinFractal(-xCh * 32 + 8, -zCh * 32 + x * 8); for (int y = peakY; y >= 0; y--) { if (y == peakY) { SetBlock(x, y, z, grass); //set tallgrass above if (IsAir(x, y + 1, z) && grassSeed >= 0.3f) { var random = MathUtil.NextFloat(); if (random >= 0 && random <= 0.6666) { SetBlock(x, y + 1, z, tallgrass); } else { SetBlock(x, y + 1, z, random <= 0.83325D ? tulipRed : tulipOrange); } } } else if (y > 0 && peakY - y > 0 && peakY - y < 3) { SetBlock(x, y, z, dirt); } else if (y == 0) { SetBlock(x, y, z, bedrock); } else { float f = _noiseUtil.GetNoise(xCh * 32 - y * 16, zCh * 32 + x * 16); SetBlock(x, y, z, f >= 0.75f ? rare : stone); } } //trees float treeSeed = Math.Abs(MathHelper.Clamp(_noiseUtil.GetWhiteNoise(xCh, zCh), 0, 1)); //var treeSeed2 = Math.Abs(MathHelper.Clamp(0.35f + _noiseUtil.GetPerlinFractal(zCh, xCh), 0, 1)); if (treeSeed >= 0.85f && x >= 3 && z >= 3 && x <= 13 && z <= 13 && x % 4 == 0 && z % 4 == 0) { int treeTop = 0; int height = (int)MathHelper.Clamp(peakY * treeSeed / 64f * 7.5f, 3, 4); for (int treeY = 0; treeY < height; treeY++) { treeTop = peakY + 1 + treeY; SetBlock(x, treeTop, z, log); } //leaves for (int i = -3; i <= 3; i++) { for (int j = 0; j <= 3; j++) { for (int k = -3; k <= 3; k++) { if (i == 0 && k == 0 && j <= 0) { continue; } int pX = x + i; int pY = treeTop + j - 1; int pZ = z + k; if (!IsAir(pX, pY, pZ)) { continue; } Vector3 vec = new Vector3(i, j, k); float leavesSeed = (peakY - 32) / 32f; BlockState leaves = leavesGreen; if (leavesSeed > 0.2f && leavesSeed <= 0.4f) { leaves = leavesYellow; } else if (leavesSeed > 0.4f && leavesSeed <= 0.55f) { leaves = leavesOrange; } else if (leavesSeed > 0.65f) { leaves = leavesRed; } if (Vector3.Distance(vec, Vector3.Zero) <= 2.5f) { SetBlock(pX, pY, pZ, leaves); } } } } } } } return(chunkData); chunk.GeneratedData(chunkData); if (updateContainingEntities) { foreach (Entity entity in Entities) { BlockPos pos = new BlockPos(entity.Pos); if (chunk.Pos == pos.ChunkPos()) { int height = chunk.GetHeightAtPos(MathUtil.ToLocal(pos.X, Chunk.ChunkSize), MathUtil.ToLocal(pos.Z, Chunk.ChunkSize)); if (entity.Pos.Y < height) { entity.TeleportTo(new Vector3(entity.Pos.X, entity.LastPos.Y = height, entity.Pos.Z)); } } } } }
public void SaveTileEntity(BlockPos pos) { GetChunk(pos.ChunkPos())?.SaveTileEntity(ChunkPos.ToChunkLocal(pos)); }
public TileEntity GetTileEntity(BlockPos pos) { return(GetChunk(pos.ChunkPos())?.GetTileEntity(ChunkPos.ToChunkLocal(pos))); }
public void GenerateChunk(ChunkPos chunkPos, bool updateContainingEntities) //TODO - something is causing this to be extremely slow and ran many times simultaneously for one chunk { Chunk chunk = CreateChunk(chunkPos, null); if (chunk == null) { return; } var air = BlockRegistry.GetBlock <BlockAir>().GetState(); var leaves = BlockRegistry.GetBlock <BlockLeaves>().GetState(); var log = BlockRegistry.GetBlock <BlockLog>().GetState(); var grass = BlockRegistry.GetBlock <BlockGrass>().GetState(); var dirt = BlockRegistry.GetBlock <BlockDirt>().GetState(); var stone = BlockRegistry.GetBlock <BlockStone>().GetState(); var rare = BlockRegistry.GetBlock <BlockRare>().GetState(); var bedrock = BlockRegistry.GetBlock <BlockBedrock>().GetState(); var tallgrass = BlockRegistry.GetBlock <BlockTallGrass>().GetState(); short airId = GetLocalBlockId(air.Block.UnlocalizedName); short[,,] chunkData = new short[Chunk.ChunkSize, Chunk.ChunkHeight, Chunk.ChunkSize]; void SetBlock(int x, int y, int z, BlockState s) { short id = GetLocalBlockId(s.Block.UnlocalizedName); short meta = s.Block.GetMetaFromState(s); short value = (short)(id << 4 | meta); chunkData[x, y, z] = value; } bool IsAir(int x, int y, int z) { return(chunkData[x, y, z] >> 4 == airId); } for (int z = 0; z < Chunk.ChunkSize; z++) { for (int x = 0; x < Chunk.ChunkSize; x++) { float wsX = chunk.Pos.WorldSpaceX(); float wsZ = chunk.Pos.WorldSpaceZ(); float xCh = x + wsX; float zCh = z + wsZ; int peakY = 32 + (int)Math.Abs( MathHelper.Clamp(0.35f + _noiseUtil.GetPerlinFractal(xCh, zCh), 0, 1) * 32); float grassSeed = _noiseUtil.GetPerlinFractal(-xCh * 32 + 8, -zCh * 32 + x * 8); for (int y = peakY; y >= 0; y--) { if (y == peakY) { SetBlock(x, y, z, grass); //set tallgrass above if (IsAir(x, y + 1, z) && grassSeed >= 0.3f) { SetBlock(x, y + 1, z, tallgrass); } } else if (y > 0 && peakY - y > 0 && peakY - y < 3) { SetBlock(x, y, z, dirt); } else if (y == 0) { SetBlock(x, y, z, bedrock); } else { float f = _noiseUtil.GetNoise(xCh * 32 - y * 16, zCh * 32 + x * 16); SetBlock(x, y, z, f >= 0.75f ? rare : stone); } } //trees float treeSeed = Math.Abs(MathHelper.Clamp(_noiseUtil.GetWhiteNoise(xCh, zCh), 0, 1)); //var treeSeed2 = Math.Abs(MathHelper.Clamp(0.35f + _noiseUtil.GetPerlinFractal(zCh, xCh), 0, 1)); if (treeSeed >= 0.85f && x >= 3 && z >= 3 && x <= 13 && z <= 13 && x % 4 == 0 && z % 4 == 0) { int treeTop = 0; int height = (int)Math.Clamp(peakY * treeSeed / 64f * 7.5f, 3, 4); for (int treeY = 0; treeY < height; treeY++) { treeTop = peakY + 1 + treeY; SetBlock(x, treeTop, z, log); } //leaves for (int i = -3; i <= 3; i++) { for (int j = 0; j <= 3; j++) { for (int k = -3; k <= 3; k++) { if (i == 0 && k == 0 && j <= 0) { continue; } int pX = x + i; int pY = treeTop + j - 1; int pZ = z + k; if (!IsAir(pX, pY, pZ)) { continue; } Vector3 vec = new Vector3(i, j, k); if (MathUtil.Distance(vec, Vector3.Zero) <= 2.5f) { SetBlock(pX, pY, pZ, leaves); } } } } } } } chunk.GeneratedData(chunkData); if (updateContainingEntities) { foreach (Entity entity in Entities) { BlockPos pos = new BlockPos(entity.Pos); if (chunk.Pos == pos.ChunkPos()) { int height = chunk.GetHeightAtPos(MathUtil.ToLocal(pos.X, Chunk.ChunkSize), MathUtil.ToLocal(pos.Z, Chunk.ChunkSize)); if (entity.Pos.Y < height) { entity.TeleportTo(new Vector3(entity.Pos.X, entity.LastPos.Y = height, entity.Pos.Z)); } } } } }