private void SpawnSeeds(ServerChunk chunk, TreeSoul soul) { // TODO: check other constraints (season, maxseeds etc) var seeds = chunk.Entities.OfType <TreeGrowingEntity>().Count(e => e.TreeTypeId == soul.TreeTypeId); if (seeds == 0) { var pos = new Vector2I(_fastRandom.Next(chunk.BlockData.ChunkSize.X), _fastRandom.Next(chunk.BlockData.ChunkSize.Z)); var metaData = chunk.BlockData.GetColumnInfo(pos); var cursor = _server.LandscapeManager.GetCursor(BlockHelper.ConvertToGlobal(chunk.Position, new Vector3I(pos.X, metaData.MaxGroundHeight + 1, pos.Y))); while (cursor.GlobalPosition.Y > 0) { var val = cursor.PeekValue(Vector3I.Down); if (val != WorldConfiguration.CubeId.Air) { break; } cursor.Move(Vector3I.Down); } if (cursor.Read() != WorldConfiguration.CubeId.Air) { return; } if (cursor.GlobalPosition.Y == 0) { return; } var config = _server.EntityFactory.Config; var treeBp = config.TreeBluePrintsDico[soul.TreeTypeId]; var treeSeed = _server.EntityFactory.CreateEntity <TreeGrowingEntity>(); treeSeed.TreeTypeId = soul.TreeTypeId; treeSeed.TreeRndSeed = _fastRandom.Next(); treeSeed.ModelName = treeBp.SeedModel; treeSeed.Name = "Seed of " + treeBp.Name; treeSeed.IsPickable = true; treeSeed.IsPlayerCollidable = true; treeSeed.CollisionType = Entity.EntityCollisionType.Model; treeSeed.MountPoint = BlockFace.Top; treeSeed.Position = cursor.GlobalPosition + new Vector3D(0.5, 0, 0.5); treeSeed.LinkedCube = cursor.GlobalPosition - Vector3I.Up; treeSeed.BlockFaceCentered = true; treeSeed.GrowingSeasons = config.TreeBluePrintsDico[soul.TreeTypeId].GrowingSeasons; treeSeed.GrowingBlocks = config.TreeBluePrintsDico[soul.TreeTypeId].GrowingBlocks; cursor.AddEntity(treeSeed); } }
private void TreeIntegrity(ServerChunk chunk, TreeSoul soul) { if (!soul.IsDamaged) { return; } // the tree will regenerate or die after one day if ((_server.Clock.Now - soul.LastUpdate) < UtopiaTimeSpan.FromDays(1)) { return; } var config = _server.EntityFactory.Config; var treeBp = config.TreeBluePrintsDico[soul.TreeTypeId]; var treeBlocks = _treeLSystem.Generate(soul.TreeRndSeed, new Vector3I(), treeBp); var cursor = _server.LandscapeManager.GetCursor(soul.Position); if (soul.IsDying) { // remove the tree using (cursor.TransactionScope()) { foreach (var blockWithPosition in treeBlocks) { cursor.GlobalPosition = (Vector3I)soul.Position + blockWithPosition.WorldPosition; if (cursor.Read() == blockWithPosition.BlockId) { cursor.Write(WorldConfiguration.CubeId.Air); } } } chunk.Entities.Remove(soul); } else { // restore the tree using (cursor.TransactionScope()) { foreach (var blockWithPosition in treeBlocks) { cursor.GlobalPosition = (Vector3I)soul.Position + blockWithPosition.WorldPosition; if (cursor.Read() == WorldConfiguration.CubeId.Air) { cursor.Write(blockWithPosition.BlockId); } } } soul.IsDamaged = false; } }
private void SpawnTreeEntities(ServerChunk chunk, TreeSoul soul) { var config = _server.EntityFactory.Config; var treeBp = config.TreeBluePrintsDico[soul.TreeTypeId]; if (_server.Clock.Now - soul.LastItemsRegeneration < treeBp.ItemsRegenerationTime) { return; } List <BlockWithPosition> treeBlocks = null; soul.LastItemsRegeneration = _server.Clock.Now; foreach (var item in treeBp.StaticItems) { // check quantity limit var maxItems = _fastRandom.Next(item.Quantity.Min, item.Quantity.Max + 1); if (_server.LandscapeManager.AroundEntities(soul.Position, item.SpawningRange).Count(e => e.BluePrintId == item.ItemblueprintId) >= maxItems) { continue; } var point = _fastRandom.NextVector2IInRadius(item.SpawningRange) + new Vector2I((int)soul.Position.X, (int)soul.Position.Z); var groundSpawning = item.SpawningType == SpawningType.Ground || (item.SpawningType == SpawningType.Both && _fastRandom.NextDouble() < 0.5f); if (groundSpawning) { var cursor = _server.LandscapeManager.GetCursor(new Vector3I(point.X, AbstractChunk.ChunkSize.Y - 1, point.Y)); while (true) { var block = cursor.Read(); if (block != WorldConfiguration.CubeId.Air && block != treeBp.FoliageBlock) { break; } cursor.Move(Vector3I.Down); } cursor.Move(Vector3I.Up); if (cursor.Read() == WorldConfiguration.CubeId.Air) { if (Vector3I.Distance(cursor.GlobalPosition, (Vector3I)soul.Position) <= item.SpawningRange) { var entity = (IStaticEntity)_server.EntityFactory.CreateFromBluePrint(item.ItemblueprintId); entity.Position = cursor.GlobalPosition; var blockLinkedItem = entity as IBlockLinkedEntity; if (blockLinkedItem != null) { blockLinkedItem.LinkedCube = cursor.GlobalPosition + Vector3I.Down; } cursor.AddEntity(entity); } } } else { // lazy initialization of tree treeBlocks = treeBlocks ?? _treeLSystem.Generate(soul.TreeRndSeed, (Vector3I)soul.Position, treeBp); // find the lowest Y in our point var minY = treeBlocks.Where(b => b.WorldPosition.X == point.X && b.WorldPosition.Z == point.Y).Select(b => b.WorldPosition.Y).DefaultIfEmpty().Min(); if (minY == 0 || minY <= soul.Position.Y) { // the point is outside of tree continue; } var cursor = _server.LandscapeManager.GetCursor(new Vector3I(point.X, minY - 1, point.Y)); if (cursor.Read() == WorldConfiguration.CubeId.Air) { var entity = (IStaticEntity)_server.EntityFactory.CreateFromBluePrint(item.ItemblueprintId); entity.Position = cursor.GlobalPosition; var blockLinkedItem = entity as IBlockLinkedEntity; if (blockLinkedItem != null) { blockLinkedItem.LinkedCube = cursor.GlobalPosition + Vector3I.Down; } cursor.AddEntity(entity); } } } }