예제 #1
0
        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));
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
                    }
                }
            }
        }
예제 #4
0
        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;
        }
예제 #5
0
        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);
        }