public override bool TryPlaceBlockForWorldGen(IBlockAccessor blockAccessor, BlockPos pos, BlockFacing onBlockFace, Random worldgenRand) { //blockAccessor.SetBlock(blockAccessor.GetBlock(new AssetLocation("creativeblock-60")).BlockId, pos); for (int i = 1; i < 4; i++) { Block aboveBlock = blockAccessor.GetBlock(pos.X, pos.Y - i, pos.Z); if ( (aboveBlock.BlockMaterial == EnumBlockMaterial.Wood || aboveBlock.BlockMaterial == EnumBlockMaterial.Plant) && aboveBlock.SideSolid[BlockFacing.DOWN.Index] ) { BlockPos atpos = new BlockPos(pos.X, pos.Y - i - 1, pos.Z); Block block = blockAccessor.GetBlock(atpos); if ( block.BlockMaterial == EnumBlockMaterial.Wood && aboveBlock.BlockMaterial == EnumBlockMaterial.Wood && blockAccessor.GetBlock(pos.X, pos.Y - i - 2, pos.Z).BlockMaterial == EnumBlockMaterial.Wood && aboveBlock.LastCodePart() == "ud" ) { blockAccessor.SetBlock(blockAccessor.GetBlock(new AssetLocation("wildbeehive-inlog-" + aboveBlock.FirstCodePart(2))).BlockId, atpos); if (EntityClass != null) { blockAccessor.SpawnBlockEntity(EntityClass, atpos); } return(true); } if (block.BlockMaterial != EnumBlockMaterial.Plant && block.BlockMaterial != EnumBlockMaterial.Air) { continue; } int dx = pos.X % blockAccessor.ChunkSize; int dz = pos.Z % blockAccessor.ChunkSize; int surfacey = blockAccessor.GetMapChunkAtBlockPos(atpos).WorldGenTerrainHeightMap[dz * blockAccessor.ChunkSize + dx]; if (pos.Y - surfacey < 4) { return(false); } blockAccessor.SetBlock(BlockId, atpos); if (EntityClass != null) { blockAccessor.SpawnBlockEntity(EntityClass, atpos); } return(true); } } return(false); }
//mostly copied from BlockBeehive public override bool TryPlaceBlockForWorldGen(IBlockAccessor blockAccessor, BlockPos pos, BlockFacing onBlockFace, LCGRandom worldgenRand) { Block cinnamon = blockAccessor.GetBlock(new AssetLocation("harvestcraftloader:fruits-cinnamon-ripe")); for (int i = 1; i < 4; i++) { Block aboveBlock = blockAccessor.GetBlock(pos.X, pos.Y - i, pos.Z); if ((aboveBlock.BlockMaterial == EnumBlockMaterial.Wood || aboveBlock.BlockMaterial == EnumBlockMaterial.Leaves) && aboveBlock.SideSolid[BlockFacing.DOWN.Index]) { BlockPos atpos = new BlockPos(pos.X, pos.Y - i - 1, pos.Z); Block block = blockAccessor.GetBlock(atpos); if (block.BlockMaterial == EnumBlockMaterial.Wood && aboveBlock.BlockMaterial == EnumBlockMaterial.Wood && blockAccessor.GetBlock(pos.X, pos.Y - i - 2, pos.Z).BlockMaterial == EnumBlockMaterial.Wood && aboveBlock.LastCodePart() == "ud") { blockAccessor.SetBlock(cinnamon.BlockId, atpos); if (EntityClass != null) { blockAccessor.SpawnBlockEntity(EntityClass, atpos); } return(true); } if (aboveBlock.BlockMaterial == EnumBlockMaterial.Wood || Id == cinnamon.Id || (block.BlockMaterial != EnumBlockMaterial.Leaves && block.BlockMaterial != EnumBlockMaterial.Air)) { continue; } int dx = pos.X % blockAccessor.ChunkSize; int dz = pos.Z % blockAccessor.ChunkSize; int surfacey = blockAccessor.GetMapChunkAtBlockPos(atpos).WorldGenTerrainHeightMap[dz * blockAccessor.ChunkSize + dx]; if (pos.Y - surfacey < 4) { return(false); } blockAccessor.SetBlock(BlockId, atpos); if (EntityClass != null) { blockAccessor.SpawnBlockEntity(EntityClass, atpos); } return(true); } } return(false); }
private void generateUpGrowingMushrooms(IBlockAccessor blockAccessor, IRandom rnd) { int cnt = 2 + rnd.NextInt(11); BlockPos pos = new BlockPos(); int chunkSize = blockAccessor.ChunkSize; List <Vec3i> offsets = new List <Vec3i>(); if (!isChunkAreaLoaded(blockAccessor, growRange)) { return; } while (cnt-- > 0) { int dx = growRange - rnd.NextInt(2 * growRange + 1); int dz = growRange - rnd.NextInt(2 * growRange + 1); pos.Set(Pos.X + dx, 0, Pos.Z + dz); var mapChunk = blockAccessor.GetMapChunkAtBlockPos(pos); int lx = GameMath.Mod(pos.X, chunkSize); int lz = GameMath.Mod(pos.Z, chunkSize); pos.Y = mapChunk.WorldGenTerrainHeightMap[lz * blockAccessor.ChunkSize + lx] + 1; Block hereBlock = blockAccessor.GetBlock(pos); Block belowBlock = blockAccessor.GetBlock(pos.X, pos.Y - 1, pos.Z); if (belowBlock.Fertility < 10 || hereBlock.LiquidCode != null) { continue; } if ((mushroomsGrownTotalDays == 0 && hereBlock.Replaceable >= 6000) || hereBlock.Id == 0) { blockAccessor.SetBlock(mushroomBlock.Id, pos); offsets.Add(new Vec3i(dx, pos.Y - Pos.Y, dz)); } } this.grownMushroomOffsets = offsets.ToArray(); }
/// <summary> /// For placement of ruins during worldgen, replaces the topsoil with the area specific soil (e.g. sand) /// </summary> /// <param name="blockAccessor"></param> /// <param name="blocks"></param> /// <param name="startPos"></param> /// <param name="climateUpLeft"></param> /// <param name="climateUpRight"></param> /// <param name="climateBotLeft"></param> /// <param name="climateBotRight"></param> /// <param name="replaceblockids"></param> /// <returns></returns> public int PlaceRespectingBlockLayers(IBlockAccessor blockAccessor, IWorldAccessor worldForCollectibleResolve, BlockPos startPos, int climateUpLeft, int climateUpRight, int climateBotLeft, int climateBotRight, int[] replaceblockids, bool replaceMetaBlocks = true) { BlockPos curPos = new BlockPos(); int placed = 0; int chunksize = blockAccessor.ChunkSize; for (int x = 0; x < SizeX; x++) { for (int z = 0; z < SizeZ; z++) { curPos.Set(x + startPos.X, startPos.Y, z + startPos.Z); IMapChunk mapchunk = blockAccessor.GetMapChunkAtBlockPos(curPos); int rockblockid = mapchunk.TopRockIdMap[(curPos.Z % chunksize) * chunksize + curPos.X % chunksize]; int depth = 0; int maxY = -1; for (int y = SizeY - 1; y >= 0; y--) { curPos.Set(x + startPos.X, y + startPos.Y, z + startPos.Z); Block newBlock = blocksByPos[x, y, z]; if (newBlock == null) { continue; } if (replaceMetaBlocks && newBlock == undergroundBlock) { continue; } if (newBlock.Replaceable < 1000) { if (replaceblockids.Length > depth && newBlock.BlockId == replaceblockids[depth]) { int climate = GameMath.BiLerpRgbColor((float)x / chunksize, (float)z / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight); newBlock = GetBlockLayerBlock((climate >> 8) & 0xff, (climate >> 16) & 0xff, startPos.Y, rockblockid, depth, newBlock, worldForCollectibleResolve.Blocks); } depth++; } Block oldBlock = blockAccessor.GetBlock(curPos); int p = handler(blockAccessor, curPos, oldBlock, newBlock); placed += p; if (p > 0 && !newBlock.RainPermeable) { if (newBlock == fillerBlock || newBlock == pathwayBlock) { int lx = curPos.X % chunksize; int lz = curPos.Z % chunksize; if (mapchunk.RainHeightMap[lz * chunksize + lx] == curPos.Y) { mapchunk.RainHeightMap[lz * chunksize + lx]--; } } else { maxY = Math.Max(curPos.Y, maxY); } } byte[] lightHsv = newBlock.GetLightHsv(blockAccessor, curPos); if (lightHsv[2] > 0 && blockAccessor is IWorldGenBlockAccessor) { ((IWorldGenBlockAccessor)blockAccessor).ScheduleBlockLightUpdate(curPos.Copy(), oldBlock.BlockId, newBlock.BlockId); } } // In the post pass the rain map does not update, so let's set it ourselves if (maxY >= 0) { int lx = curPos.X % chunksize; int lz = curPos.Z % chunksize; int y = mapchunk.RainHeightMap[lz * chunksize + lx]; mapchunk.RainHeightMap[lz * chunksize + lx] = (ushort)Math.Max(y, maxY); } } } PlaceEntitiesAndBlockEntities(blockAccessor, worldForCollectibleResolve, startPos); return(placed); }
public override bool TryPlaceBlockForWorldGen(IBlockAccessor blockAccessor, BlockPos pos, BlockFacing onBlockFace, LCGRandom worldgenRand) { //blockAccessor.SetBlock(blockAccessor.GetBlock(new AssetLocation("creativeblock-60")).BlockId, pos); for (int i = 1; i < 4; i++) { atPos.Set(pos.X, pos.Y - i, pos.Z); Block aboveBlock = blockAccessor.GetBlock(atPos); var abovemat = aboveBlock.GetBlockMaterial(blockAccessor, atPos); if ((abovemat == EnumBlockMaterial.Wood || abovemat == EnumBlockMaterial.Leaves) && aboveBlock.SideSolid[BlockFacing.DOWN.Index]) { atPos.Set(pos.X, pos.Y - i - 1, pos.Z); Block block = blockAccessor.GetBlock(atPos); var mat = block.GetBlockMaterial(blockAccessor, atPos); BlockPos belowPos = new BlockPos(pos.X, pos.Y - i - 2, pos.Z); if ( mat == EnumBlockMaterial.Wood && abovemat == EnumBlockMaterial.Wood && blockAccessor.GetBlock(belowPos).GetBlockMaterial(blockAccessor, belowPos) == EnumBlockMaterial.Wood && aboveBlock.LastCodePart() == "ud" ) { Block inlogblock = blockAccessor.GetBlock(new AssetLocation("wildbeehive-inlog-" + aboveBlock.Variant["wood"])); blockAccessor.SetBlock(inlogblock.BlockId, atPos); if (EntityClass != null) { blockAccessor.SpawnBlockEntity(EntityClass, atPos); } return(true); } if (mat != EnumBlockMaterial.Leaves && mat != EnumBlockMaterial.Air) { continue; } int dx = pos.X % blockAccessor.ChunkSize; int dz = pos.Z % blockAccessor.ChunkSize; int surfacey = blockAccessor.GetMapChunkAtBlockPos(atPos).WorldGenTerrainHeightMap[dz * blockAccessor.ChunkSize + dx]; if (pos.Y - surfacey < 4) { return(false); } blockAccessor.SetBlock(BlockId, atPos); if (EntityClass != null) { blockAccessor.SpawnBlockEntity(EntityClass, atPos); } //BlockPos test = pos.Copy(); //test.Y = 160; //blockAccessor.SetBlock(blockAccessor.GetBlock(new AssetLocation("creativeblock-60")).BlockId, test); return(true); } } return(false); }
/// <summary> /// For placement of ruins during worldgen, replaces the topsoil with the area specific soil (e.g. sand) /// </summary> /// <param name="blockAccessor"></param> /// <param name="blocks"></param> /// <param name="startPos"></param> /// <param name="climateUpLeft"></param> /// <param name="climateUpRight"></param> /// <param name="climateBotLeft"></param> /// <param name="climateBotRight"></param> /// <param name="replaceblockids"></param> /// <returns></returns> public int PlaceRespectingBlockLayers(IBlockAccessor blockAccessor, IWorldAccessor worldForCollectibleResolve, BlockPos startPos, int climateUpLeft, int climateUpRight, int climateBotLeft, int climateBotRight, ushort[] replaceblockids) { BlockPos curPos = new BlockPos(); int placed = 0; int chunksize = blockAccessor.ChunkSize; for (int x = 0; x < SizeX; x++) { for (int z = 0; z < SizeZ; z++) { curPos.Set(x + startPos.X, startPos.Y, z + startPos.Z); ushort rockblockid = blockAccessor.GetMapChunkAtBlockPos(curPos).TopRockIdMap[(curPos.Z % chunksize) * chunksize + curPos.X % chunksize]; int depth = 0; for (int y = SizeY - 1; y >= 0; y--) { curPos.Set(x + startPos.X, y + startPos.Y, z + startPos.Z); Block newBlock = blocksByPos[x, y, z]; if (newBlock == null) { continue; } if (newBlock.Replaceable < 1000) { if (replaceblockids.Length > depth && newBlock.BlockId == replaceblockids[depth]) { int climate = GameMath.BiLerpRgbColor((float)x / chunksize, (float)z / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight); newBlock = GetBlockLayerBlock((climate >> 8) & 0xff, (climate >> 16) & 0xff, startPos.Y, rockblockid, depth, newBlock, worldForCollectibleResolve.Blocks); } depth++; } Block oldBlock = blockAccessor.GetBlock(curPos); placed += handler(blockAccessor, curPos, oldBlock, newBlock); byte[] lightHsv = newBlock.GetLightHsv(blockAccessor, curPos); if (lightHsv[2] > 0 && blockAccessor is IWorldGenBlockAccessor) { int chunkSize = blockAccessor.ChunkSize; ((IWorldGenBlockAccessor)blockAccessor).ScheduleBlockLightUpdate(curPos.Copy(), oldBlock.BlockId, newBlock.BlockId); } } } } foreach (var val in BlockEntities) { uint index = val.Key; int dx = (int)(index & 0x1ff); int dy = (int)((index >> 20) & 0x1ff); int dz = (int)((index >> 10) & 0x1ff); curPos.Set(startPos.X + dx, startPos.Y + dy, startPos.Z + dz); BlockEntity be = blockAccessor.GetBlockEntity(curPos); if (be != null) { be.FromTreeAtributes(DecodeBlockEntityData(val.Value), worldForCollectibleResolve); be.OnLoadCollectibleMappings(worldForCollectibleResolve, BlockCodes, ItemCodes); be.pos = curPos.Copy(); } } return(placed); }
private void TrySpawnGroupAt(BlockPos origin, Vec3d posAsVec, EntityProperties entityType, EntityProperties[] grouptypes) { BlockPos pos = origin.Copy(); float xRel = (float)(posAsVec.X % chunksize) / chunksize; float zRel = (float)(posAsVec.Z % chunksize) / chunksize; int climate = GameMath.BiLerpRgbColor(xRel, zRel, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight); float temp = TerraGenConfig.GetScaledAdjustedTemperatureFloat((climate >> 16) & 0xff, (int)posAsVec.Y - TerraGenConfig.seaLevel); float rain = ((climate >> 8) & 0xff) / 255f; float forestDensity = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, xRel, zRel); float shrubDensity = GameMath.BiLerp(shrubsUpLeft, shrubsUpRight, shrubsBotLeft, shrubsBotRight, xRel, zRel); int spawned = 0; WorldGenSpawnConditions sc = entityType.Server.SpawnConditions.Worldgen; bool hasCompanions = sc.Companions != null && sc.Companions.Length > 0; spawnPositions.Clear(); int nextGroupSize = 0; int tries = 10; while (nextGroupSize <= 0 && tries-- > 0) { float val = sc.GroupSize.nextFloat(); nextGroupSize = (int)val + ((val - (int)val) > rnd.NextDouble() ? 1 : 0); } for (int i = 0; i < nextGroupSize * 4 + 5; i++) { if (spawned >= nextGroupSize) { break; } EntityProperties typeToSpawn = entityType; // First entity 80% chance to spawn the dominant creature, every subsequent only 20% chance for males (or even lower if more than 5 companion types) double dominantChance = i == 0 ? 0.8 : Math.Min(0.2, 1f / grouptypes.Length); if (grouptypes.Length > 1 && rnd.NextDouble() > dominantChance) { typeToSpawn = grouptypes[1 + rnd.Next(grouptypes.Length - 1)]; } posAsVec.Set(pos.X + 0.5, pos.Y + 0.005, pos.Z + 0.5); IBlockAccessor blockAccesssor = wgenBlockAccessor.GetChunkAtBlockPos(pos.X, pos.Y, pos.Z) == null ? api.World.BlockAccessor : wgenBlockAccessor; IMapChunk mapchunk = blockAccesssor.GetMapChunkAtBlockPos(pos); if (mapchunk != null) { ushort[] heightMap = mapchunk.WorldGenTerrainHeightMap; pos.Y = sc.TryOnlySurface ? heightMap[((int)pos.Z % chunksize) * chunksize + ((int)pos.X % chunksize)] + 1 : pos.Y ; xRel = (float)(posAsVec.X % chunksize) / chunksize; zRel = (float)(posAsVec.Z % chunksize) / chunksize; climate = GameMath.BiLerpRgbColor(xRel, zRel, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight); temp = TerraGenConfig.GetScaledAdjustedTemperatureFloat((climate >> 16) & 0xff, (int)posAsVec.Y - TerraGenConfig.seaLevel); rain = ((climate >> 8) & 0xff) / 255f; forestDensity = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, xRel, zRel) / 255f; shrubDensity = GameMath.BiLerp(shrubsUpLeft, shrubsUpRight, shrubsBotLeft, shrubsBotRight, xRel, zRel) / 255f; if (CanSpawnAt(blockAccesssor, typeToSpawn, pos, posAsVec, sc, rain, temp, forestDensity, shrubDensity)) { spawnPositions.Add(new SpawnOppurtunity() { ForType = typeToSpawn, Pos = posAsVec.Clone() }); spawned++; } } pos.X = origin.X + ((rnd.Next(11) - 5) + (rnd.Next(11) - 5)) / 2; pos.Z = origin.Z + ((rnd.Next(11) - 5) + (rnd.Next(11) - 5)) / 2; } // Only spawn if the group reached the minimum group size if (spawnPositions.Count >= nextGroupSize) { long herdId = api.WorldManager.GetNextHerdId(); foreach (SpawnOppurtunity so in spawnPositions) { Entity ent = CreateEntity(so.ForType, so.Pos); if (ent is EntityAgent) { (ent as EntityAgent).HerdId = herdId; } if (wgenBlockAccessor.GetChunkAtBlockPos(pos.X, pos.Y, pos.Z) == null) { api.World.SpawnEntity(ent); } else { wgenBlockAccessor.AddEntity(ent); } } //Console.WriteLine("Spawn a group of {0}x{1} at {2}", spawnPositions.Count, entityType.Code, origin); } }