public static UniversalCoords[] GetDoubleChestCoords(WorldManager world, UniversalCoords coords) { Chunk chunk = world.GetChunk(coords); if (chunk == null || !IsDoubleChest(chunk, coords)) return null; // Is this chest the "North or East", or the "South or West" BlockData.Blocks[] nsewBlocks = new BlockData.Blocks[4]; UniversalCoords[] nsewBlockPositions = new UniversalCoords[4]; int nsewCount = 0; byte? blockId; chunk.ForNSEW(coords, uc => { blockId = world.GetBlockId(uc) ?? 0; nsewBlocks[nsewCount] = (BlockData.Blocks)blockId; nsewBlockPositions[nsewCount] = uc; nsewCount++; }); UniversalCoords firstCoords; UniversalCoords secondCoords; if ((byte)nsewBlocks[0] == (byte)BlockData.Blocks.Chest) // North { firstCoords = nsewBlockPositions[0]; secondCoords = coords; } else if ((byte)nsewBlocks[2] == (byte)BlockData.Blocks.Chest) // East { firstCoords = nsewBlockPositions[2]; secondCoords = coords; } else if ((byte)nsewBlocks[1] == (byte)BlockData.Blocks.Chest) // South { firstCoords = coords; secondCoords = nsewBlockPositions[1]; } else// if ((byte)nsewBlocks[3] == (byte)BlockData.Blocks.Chest) // West { firstCoords = coords; secondCoords = nsewBlockPositions[3]; } return new UniversalCoords[] { firstCoords, secondCoords }; }
private static void DoSpawn(WorldManager world, HashSet<int> chunksToSpawnIn, Mob[] mobEntities, List<WeightedValue<MobType>> mobGroup, int maximumMobs, bool inWater = false) { // Based on original server spawn logic and minecraft wiki (http://www.minecraftwiki.net/wiki/Spawn) // Check that we haven't already reached the maximum number of this type of mob if (mobGroup.Count > 0 && (mobEntities.Where(e => mobGroup.Where(mob => mob.Value == e.Type).Any()).Count() <= maximumMobs * chunksToSpawnIn.Count / 256)) { foreach (var packedChunk in chunksToSpawnIn) { MobType mobType = mobGroup.SelectRandom(world.Server.Rand); UniversalCoords packSpawnPosition = GetRandomPointInChunk(world, UniversalCoords.FromPackedChunkToX(packedChunk), UniversalCoords.FromPackedChunkToZ(packedChunk)); byte? blockId = world.GetBlockId(packSpawnPosition); if (blockId == null) continue; BlockBase blockClass = BlockHelper.Instance.CreateBlockInstance((byte)blockId); if (!blockClass.IsOpaque && ((!inWater && blockClass.Type == BlockData.Blocks.Air) || (inWater && blockClass.IsLiquid))) // Lava is Opaque, so IsLiquid is safe to use here for water & still water { int spawnedCount = 0; int x = packSpawnPosition.WorldX; int y = packSpawnPosition.WorldY; int z = packSpawnPosition.WorldZ; for (int i = 0; i < 21; i++) { // Every 4th attempt reset the coordinates to the centre of the pack spawn if (i % 4 == 0) { x = packSpawnPosition.WorldX; y = packSpawnPosition.WorldY; z = packSpawnPosition.WorldZ; } const int distance = 6; x += world.Server.Rand.Next(distance) - world.Server.Rand.Next(distance); y += world.Server.Rand.Next(1) - world.Server.Rand.Next(1); z += world.Server.Rand.Next(distance) - world.Server.Rand.Next(distance); if (CanMobTypeSpawnAtLocation(mobType, world, x, y, z)) { AbsWorldCoords spawnPosition = new AbsWorldCoords(x + 0.5, y, z + 0.5); // Check that no player is within a radius of 24 blocks of the spawnPosition if (world.GetClosestPlayer(spawnPosition, 24.0) == null) { // Check that the squared distance is more than 576 from spawn (24 blocks) if (spawnPosition.ToVector().DistanceSquared(new AbsWorldCoords(world.Spawn).ToVector()) > 576.0) { Mob newMob = MobFactory.Instance.CreateMob(world, world.Server, mobType) as Mob; if (newMob == null) break; newMob.Position = spawnPosition; newMob.Yaw = world.Server.Rand.NextDouble()*360.0; // Finally apply any mob specific rules about spawning here if (newMob.CanSpawnHere()) { //Event EntitySpawnEventArgs e = new EntitySpawnEventArgs(newMob, newMob.Position); world.Server.PluginManager.CallEvent(Event.EntitySpawn, e); if (e.EventCanceled) continue; newMob.Position = e.Location; //End Event ++spawnedCount; MobSpecificInitialisation(newMob, world, spawnPosition); world.Server.AddEntity(newMob); if (spawnedCount >= newMob.MaxSpawnedPerGroup) { // This chunk is full - move to the next break; } } } } } } } } } }