private List <LandscapeEntity> PopulateChunksWithTree(Vector3I chunkPosition, Biome biome, byte[] chunkBytes, ChunkColumnInfo[] columndInfo, FastRandom rnd) { if (biome.BiomeTrees.Trees.Count <= 0) { return(null); } //Get Rnd chunk Location. int x = rnd.Next(0, 16); int z = rnd.Next(0, 16); int y = columndInfo[x * AbstractChunk.ChunkSize.Z + z].MaxGroundHeight + 1; //Validate position = Must be Air block (not water) ! if (chunkBytes[((z * AbstractChunk.ChunkSize.X) + x) * AbstractChunk.ChunkSize.Y + y] != WorldConfiguration.CubeId.Air) { return(null); } x += (chunkPosition.X * AbstractChunk.ChunkSize.X); z += (chunkPosition.Z * AbstractChunk.ChunkSize.Z); Vector3I worldPosition = new Vector3I(x, y, z); //Generate Tree mesh ! //Get tree type following distribution chances inside the biome TreeBluePrint treeType = biome.BiomeTrees.GetTreeTemplate(rnd, _worldParameters.Configuration.TreeBluePrintsDico); int generationSeed = rnd.Next(); return(LandscapeEntityParser.GlobalMesh2ChunkMesh(_treeGenerator.Generate(generationSeed, worldPosition, treeType), worldPosition, treeType.Id, generationSeed)); }
public IToolImpact Use(IDynamicEntity owner) { IToolImpact checkImpact; if (!CanDoBlockAction(owner, out checkImpact)) { return(checkImpact); } var impact = new BlockToolImpact { SrcBlueprintId = BluePrintId }; var cursor = LandscapeManager.GetCursor(owner.EntityState.PickedBlockPosition); if (cursor == null) { impact.Dropped = true; return(impact); } cursor.OwnerDynamicId = owner.DynamicId; var selectedCube = cursor.Read(); var treeSystem = new TreeLSystem(); bool removed = false; foreach (var soul in EntityFactory.LandscapeManager.AroundChunks(owner.Position, 16).SelectMany(c => c.Entities.Enumerate <TreeSoul>())) { var treeBlueprint = EntityFactory.Config.TreeBluePrintsDico[soul.TreeTypeId]; if (selectedCube != treeBlueprint.TrunkBlock && selectedCube != treeBlueprint.FoliageBlock) { continue; } var blocks = treeSystem.Generate(soul.TreeRndSeed, BlockHelper.EntityToBlock(soul.Position), treeBlueprint); if (blocks.Any(b => b.WorldPosition == owner.EntityState.PickedBlockPosition)) { cursor.RemoveEntity(soul.GetLink()); removed = true; break; } } if (!removed) { impact.Message = "This is not an alive tree"; return(impact); } TakeFromPlayer(owner); return(impact); }
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); } } } }
private void RefreshBuffers(TreeBluePrint treeTemplate) { FastRandom rnd = new FastRandom(); FastRandom rndColor = new FastRandom(); //Generate the list of Tree points. List <BlockWithPosition> result = _treeSystem.Generate(rnd.Next(), new S33M3Resources.Structs.Vector3I(), treeTemplate); _letreeVertexCollection = new List <VertexHLSLLTree>(); _letreeIndexCollection = new List <ushort>(); MaxtreeSize.X = int.MinValue; MaxtreeSize.Y = int.MinValue; MaxtreeSize.Z = int.MinValue; MintreeSize.X = int.MaxValue; MintreeSize.Y = int.MaxValue; MintreeSize.Z = int.MaxValue; //For each block foreach (BlockWithPosition block in result) { float blockShade = rnd.NextFloat(0.8f, 1.0f); int vertexOffset = _letreeVertexCollection.Count; //Create the 24 vertex + 36 Index data per cube ! for (int i = 0; i < vertexCube.Length; i++) { ByteColor c; if (block.BlockId == treeTemplate.TrunkBlock) { c = Color.Brown; } else { c = Color.Green; } //int blue = c.B + rndColor.Next(-10, 10); if (blue < 0 || blue > 255) blue = c.B; c.B += (byte)blue; //int red = c.R + rndColor.Next(-10, 10); if (red < 0 || red > 255) red = c.R; c.R += (byte)red; //int green = c.G + rndColor.Next(-10, 10); if (green < 0 || green > 255) blue = c.G; c.G += (byte)green; if (block.WorldPosition.X > MaxtreeSize.X) { MaxtreeSize.X = block.WorldPosition.X; } if (block.WorldPosition.Y > MaxtreeSize.Y) { MaxtreeSize.Y = block.WorldPosition.Y; } if (block.WorldPosition.Z > MaxtreeSize.Z) { MaxtreeSize.Z = block.WorldPosition.Z; } if (block.WorldPosition.X < MintreeSize.X) { MintreeSize.X = block.WorldPosition.X; } if (block.WorldPosition.Y < MintreeSize.Y) { MintreeSize.Y = block.WorldPosition.Y; } if (block.WorldPosition.Z < MintreeSize.Z) { MintreeSize.Z = block.WorldPosition.Z; } _letreeVertexCollection.Add(new VertexHLSLLTree(vertexCube[i] + block.WorldPosition, blockShade, c)); } foreach (var index in indicesCube) { _letreeIndexCollection.Add((ushort)(index + vertexOffset)); } } _bufferDirty = true; }
private IToolImpact BlockHit(IDynamicEntity owner) { var impact = new BlockToolImpact { SrcBlueprintId = BluePrintId, Position = owner.EntityState.PickedBlockPosition }; var cursor = LandscapeManager.GetCursor(owner.EntityState.PickedBlockPosition); if (cursor == null) { //Impossible to find chunk, chunk not existing, event dropped impact.Message = "Block not existing, event dropped"; impact.Dropped = true; return(impact); } cursor.OwnerDynamicId = owner.DynamicId; if (cursor.PeekProfile().Indestructible) { impact.Message = "Indestrutible cube, cannot be removed !"; return(impact); } DamageTag damage; var cube = cursor.Read(out damage); if (cube != WorldConfiguration.CubeId.Air) { impact.CubeId = cube; var profile = cursor.PeekProfile(); var hardness = profile.Hardness; if (damage == null) { damage = new DamageTag { Strength = (int)hardness, TotalStrength = (int)hardness }; } var toolBlockDamage = Damage; if (SpecialDamages != null) { var index = SpecialDamages.FindIndex(cd => cd.CubeId == cube); if (index != -1) { toolBlockDamage = SpecialDamages[index].Damage; } } damage.Strength -= toolBlockDamage; if (toolBlockDamage > 0 && SoundEngine != null) { if (profile.HitSounds.Count > 0) { var random = new Random(); var sound = profile.HitSounds[random.Next(0, profile.HitSounds.Count)]; SoundEngine.StartPlay3D(sound, owner.EntityState.PickedBlockPosition + new Vector3(0.5f)); } } if (damage.Strength <= 0) { var chunk = LandscapeManager.GetChunkFromBlock(owner.EntityState.PickedBlockPosition); if (chunk == null) { //Impossible to find chunk, chunk not existing, event dropped impact.Message = "Chunk is not existing, event dropped"; impact.Dropped = true; return(impact); } chunk.Entities.RemoveAll <BlockLinkedItem>(e => e.Linked && e.LinkedCube == owner.EntityState.PickedBlockPosition, owner.DynamicId); cursor.Write(WorldConfiguration.CubeId.Air); #region TreeSoul remove logic foreach (var treeSoul in EntityFactory.LandscapeManager.AroundEntities(owner.EntityState.PickedBlockPosition, 16).OfType <TreeSoul>()) { var treeBp = EntityFactory.Config.TreeBluePrintsDico[treeSoul.TreeTypeId]; if (cube != treeBp.FoliageBlock && cube != treeBp.TrunkBlock) { continue; } var treeLSystem = new TreeLSystem(); var treeBlocks = treeLSystem.Generate(treeSoul.TreeRndSeed, (Vector3I)treeSoul.Position, treeBp); // did we remove the block of the tree? if (treeBlocks.Exists(b => b.WorldPosition == owner.EntityState.PickedBlockPosition)) { treeSoul.IsDamaged = true; // count removed trunk blocks var totalTrunks = treeBlocks.Count(b => b.BlockId == treeBp.TrunkBlock); var existsTrunks = treeBlocks.Count(b => { if (b.BlockId == treeBp.TrunkBlock) { cursor.GlobalPosition = b.WorldPosition; return(cursor.Read() == treeBp.TrunkBlock); } return(false); }); if (existsTrunks < totalTrunks / 2) { treeSoul.IsDying = true; } } } #endregion if (SoundEngine != null && EntityFactory.Config.ResourceTake != null) { SoundEngine.StartPlay3D(EntityFactory.Config.ResourceTake, owner.EntityState.PickedBlockPosition + new Vector3(0.5f)); } var charEntity = owner as CharacterEntity; if (charEntity == null) { impact.Message = "Charater entity is expected"; return(impact); } var putItems = new List <KeyValuePair <IItem, int> >(); putItems.Add(new KeyValuePair <IItem, int>((IItem)EntityFactory.CreateFromBluePrint(cube), 1)); if (profile.Transformations != null) { var random = new FastRandom(owner.EntityState.PickedEntityPosition.GetHashCode() ^ owner.EntityState.Entropy); foreach (var itemTransformation in profile.Transformations) { if (random.NextDouble() < itemTransformation.TransformChance) { // don't give the block putItems.Clear(); foreach (var slot in itemTransformation.GeneratedItems) { putItems.Add(new KeyValuePair <IItem, int>((Item)EntityFactory.CreateFromBluePrint(slot.BlueprintId), slot.Count)); } break; } } } // in case of infinite resources we will not add more than 1 block entity var existingSlot = charEntity.FindSlot(s => s.Item.BluePrintId == cube); if (!EntityFactory.Config.IsInfiniteResources || existingSlot == null) { if (!charEntity.Inventory.PutMany(putItems)) { impact.Message = "Can't put the item(s) to inventory"; } } impact.CubeId = WorldConfiguration.CubeId.Air; } else if (damage.Strength >= hardness) { cursor.Write(cube); } else { cursor.Write(cube, damage); } impact.Success = true; return(impact); } impact.Message = "Cannot hit air block"; return(impact); }