private Color GetBiomeColor(byte biomeId) { var biome = _biomeUtils.GetBiome(biomeId); var c = biome.Grass; //if (Mode == DisplayMode.BiomeFoilage) { // c = biome.Foliage; } int r = (int)((c >> 16) & 0xff); int g = (int)((c >> 8) & 0xff); int b = (int)c & 0xff; //Debug.WriteLine("Biome {0}: {1} {2}", biomeId, biome.Grass, biome.Foliage); return(Color.FromArgb(r, g, b)); }
private Biome GetBiome(float x, float z) { x /= CoordinateScale; z /= CoordinateScale; var mX = x + BiomeModifierX.GetValue(x, z); var mZ = z + BiomeModifierZ.GetValue(x, z); var temp = TempNoise.GetValue(mX, mZ) * 3.024F; var rain = RainNoise.GetValue(mX, mZ); if (temp < -1f) { temp = -(temp % 1); } if (rain < 0) { rain = -rain; } return(BiomeUtils.GetBiome(temp, rain)); }
public virtual void AttemptMobSpawn(BlockCoordinates packCoord, Random random, bool canSpawnPassive, bool canSpawnHostile) { if (Level.Dimension != Dimension.Overworld) { return; } if (Level.Players.Count(player => player.Value.IsSpawned && Vector3.Distance(packCoord, player.Value.KnownPosition) < 24) != 0) { //if (Log.IsDebugEnabled) // Log.Debug($"Can't spawn entity because players within 24 blocks distance: {blockCoordinates}"); return; } if (!canSpawnHostile && !canSpawnPassive) { // Mob cap reached on all creatures return; } for (int c = 0; c < 2; c++) { int maxPackSize = int.MaxValue; int numberOfSpawnedMobs = 0; EntityType entityType = EntityType.None; bool doSpawnHostile = false; bool doSpawnPassive = false; if (c == 0) { if (!canSpawnHostile) { continue; } doSpawnHostile = true; } else if (c == 1) { if (!canSpawnPassive) { continue; } doSpawnPassive = true; } for (int j = 0; j < 3; j++) { int x = packCoord.X; int y = packCoord.Y; int z = packCoord.Z; // The next 3 (k, x and z) random construct heavily weigh the coordinates toward center of pack-origin int k = random.Next(1, 5); for (int i = 0; i < k && numberOfSpawnedMobs < maxPackSize; i++) { x += random.Next(6) - random.Next(6); z += random.Next(6) - random.Next(6); var spawnBlock = Level.GetBlock(x, y - 1, z); //FIXME: The following is wrong. It shouldn't be the same for all mobs and need to be moved into some sort of // entity-based "CanSpawn()" method. But performance need to be handled too, and this is way faster right now. if (spawnBlock is Grass || spawnBlock is Sand || spawnBlock is Gravel || (doSpawnHostile && spawnBlock.IsSolid && !spawnBlock.IsTransparent)) { if (entityType == EntityType.None) { entityType = SelectEntityType(spawnBlock, random, doSpawnHostile, doSpawnPassive); if (entityType == EntityType.None) { if (Log.IsDebugEnabled && doSpawnHostile) { Log.Debug($"Failed to spawn because found no proper entity types for biome {BiomeUtils.GetBiome(spawnBlock.BiomeId).Name}"); } break; } maxPackSize = entityType == EntityType.Wolf ? 8 : entityType == EntityType.Rabbit ? 2 + random.Next(1) : entityType == EntityType.Horse ? 2 + random.Next(5) : entityType == EntityType.Enderman ? 1 + random.Next(4) : 4; } var firstBlock = Level.GetBlock(x, y, z); if (!firstBlock.IsSolid && !(firstBlock is Stationary) && !(firstBlock is Flowing)) { if (doSpawnPassive && PassiveMobs.Contains(entityType) && Level.GetSubtractedLight(firstBlock.Coordinates, 0) >= 9) { var secondBlock = Level.GetBlock(x, y + 2, z); if ((spawnBlock is Grass || (entityType == EntityType.Rabbit && spawnBlock is Sand)) && !secondBlock.IsSolid) { var yaw = random.Next(360); if (Spawn(new PlayerLocation(x + 0.5, y, z + 0.5, yaw + 15, yaw), entityType, random)) { if (Log.IsDebugEnabled) { Log.Warn($"Spawned {entityType}"); } //Level.StrikeLightning(new PlayerLocation(x + 0.5, y, z + 0.5, yaw + 15, yaw)); //Level.SetBlock(new StainedGlass() { Metadata = (byte)firstBlock.SkyLight, Coordinates = firstBlock.Coordinates + BlockCoordinates.Down }); ++numberOfSpawnedMobs; } else { if (Log.IsDebugEnabled) { Log.Debug($"Failed to spawn {entityType} because area not clear"); } } } } else if (doSpawnHostile && HostileMobs.Contains(entityType) && Level.GetSubtractedLight(firstBlock.Coordinates) < random.Next(8)) { var secondBlock = Level.GetBlock(x, y + 1, z); if (!secondBlock.IsSolid) { var yaw = random.Next(360); if (Spawn(new PlayerLocation(x + 0.5, y, z + 0.5, yaw + 15, yaw), entityType, random)) { //Level.SetBlock(new StainedGlass() { Metadata = (byte) firstBlock.SkyLight, Coordinates = firstBlock.Coordinates + BlockCoordinates.Down }); //Log.Warn($"Spawned {entityType} at {firstBlock.Coordinates} at light level on bottom={firstBlock.SkyLight} amd top={secondBlock.SkyLight}, world time={Level.CurrentWorldTime}"); ++numberOfSpawnedMobs; } else { if (Log.IsDebugEnabled) { Log.Debug($"Failed to spawn {entityType} because area not clear"); } } } } } } } } } }
public void UpdateLevel() { Invoke(new MethodInvoker(delegate() { var chunks = _level.GetLoadedChunks(); if (chunks.Length == 0) { return; } if (!Monitor.TryEnter(_busy)) { return; } var showProgress = _lastUpdateDuration > ShowUpdateProgressThreshold; try { Busy(); var sw = Stopwatch.StartNew(); var minChunkX = chunks.Min(c => c.x); var minChunkZ = chunks.Min(c => c.z); var maxChunkX = chunks.Max(c => c.x); var maxChunkZ = chunks.Max(c => c.z); var imageWidth = (maxChunkX - minChunkX + 1) * 16; var imageHeight = (maxChunkZ - minChunkZ + 1) * 16; var offsetX = Math.Abs(minChunkX * 16); var offsetZ = Math.Abs(minChunkZ * 16); var tot = chunks.Length; Bitmap image; bool usingBase = false; if (_baseImage != null && imageWidth == _baseImage.Width && imageHeight == _baseImage.Height && minChunkX == _minChunk.X && minChunkZ == _minChunk.Z && maxChunkX == _maxChunk.X && maxChunkZ == _maxChunk.Z ) { image = (Bitmap)_baseImage.Clone(); usingBase = true; if (tot == _lastChunkCount) { return; } } else { image = new Bitmap(imageWidth, imageHeight); } _lastChunkCount = tot; if (showProgress) { ShowProgress(tot); } var i = 0; foreach (var chunk in chunks) { lock (_chunkSync) { var coords = new ChunkCoordinates(chunk.x, chunk.z); if (_validChunks.Contains(coords)) { if (!chunk.isDirty && usingBase) { continue; } } else { _validChunks.Add(coords); } } if (showProgress) { UpdateProgress(i, "Drawing Bitmap"); } i++; //Debug.WriteLine("Processing Chunk {0}/{1}", i, tot); for (int x = 0; x < 16; x++) { for (int z = 0; z < 16; z++) { var iX = offsetX + chunk.x * 16 + x; var iZ = offsetZ + chunk.z * 16 + z; //Debug.WriteLine(string.Format("{0} {1} {2} {3} {4} {5} {6} {7}", iX, iZ, imageWidth, imageHeight, offsetX, offsetZ, chunk.x, chunk.z, x, z)); var biomeId = chunk.GetBiome(x, z); var color = GetBiomeColor(biomeId); if (Mode == DisplayMode.Rainfall) { color = HeatMap.GetColor(0.33M, 0.66M, 1M, (decimal)(_biomeUtils.GetBiome(biomeId).Downfall / BiomeMapUtil.MaxBiomeDownfall)); } else if (Mode == DisplayMode.Temperature) { color = HeatMap.GetColor(0.33M, 0.66M, 1M, (decimal)(_biomeUtils.GetBiome(biomeId).Temperature / BiomeMapUtil.MaxBiomeTemperature)); } image.SetPixel(iX, iZ, color); } } } _baseImage = (Bitmap)image.Clone(); foreach (var player in _level.Players.Values.ToArray()) { var pX = offsetX + (int)player.KnownPosition.X; var pZ = offsetX + (int)player.KnownPosition.Z; //Debug.WriteLine("Player at " + pX + "," + pZ); var r = 2; for (int x = -r; x <= r; x++) { for (int z = -r; z <= r; z++) { image.SetPixel(pX + x, pZ + z, Color.Black); } } } sw.Stop(); _lastUpdateDuration = sw.Elapsed; _minChunk = new ChunkCoordinates(minChunkX, minChunkZ); _maxChunk = new ChunkCoordinates(maxChunkX, maxChunkZ); UpdateImage(); //Debug.WriteLine("Drawing Image"); statusChunks.Text = tot + " Chunks"; } catch (Exception ex) { Log.Error("Exception during bitmap update", ex); } finally { Monitor.Exit(_busy); Busy(false); if (showProgress) { HideProgress(); } } })); }