public void Update(float dt)
        {
            double totalElapsedGameTime = m_subsystemGameInfo.TotalElapsedGameTime;

            foreach (Projectile projectile in m_projectiles)
            {
                if (projectile.ToRemove)
                {
                    m_projectilesToRemove.Add(projectile);
                }
                else
                {
                    Block block = BlocksManager.Blocks[Terrain.ExtractContents(projectile.Value)];
                    if (totalElapsedGameTime - projectile.CreationTime > 40.0)
                    {
                        projectile.ToRemove = true;
                    }
                    TerrainChunk chunkAtCell = m_subsystemTerrain.Terrain.GetChunkAtCell(Terrain.ToCell(projectile.Position.X), Terrain.ToCell(projectile.Position.Z));
                    if (chunkAtCell == null || chunkAtCell.State <= TerrainChunkState.InvalidContents4)
                    {
                        projectile.NoChunk = true;
                        if (projectile.TrailParticleSystem != null)
                        {
                            projectile.TrailParticleSystem.IsStopped = true;
                        }
                    }
                    else
                    {
                        projectile.NoChunk = false;
                        Vector3              position             = projectile.Position;
                        Vector3              vector               = position + projectile.Velocity * dt;
                        Vector3              v                    = block.ProjectileTipOffset * Vector3.Normalize(projectile.Velocity);
                        BodyRaycastResult?   bodyRaycastResult    = m_subsystemBodies.Raycast(position + v, vector + v, 0.2f, (ComponentBody body, float distance) => true);
                        TerrainRaycastResult?terrainRaycastResult = m_subsystemTerrain.Raycast(position + v, vector + v, useInteractionBoxes: false, skipAirBlocks: true, (int value, float distance) => BlocksManager.Blocks[Terrain.ExtractContents(value)].IsCollidable);
                        bool flag = block.DisintegratesOnHit;
                        if (terrainRaycastResult.HasValue || bodyRaycastResult.HasValue)
                        {
                            CellFace?                cellFace       = terrainRaycastResult.HasValue ? new CellFace?(terrainRaycastResult.Value.CellFace) : null;
                            ComponentBody            componentBody  = bodyRaycastResult.HasValue ? bodyRaycastResult.Value.ComponentBody : null;
                            SubsystemBlockBehavior[] blockBehaviors = m_subsystemBlockBehaviors.GetBlockBehaviors(Terrain.ExtractContents(projectile.Value));
                            for (int i = 0; i < blockBehaviors.Length; i++)
                            {
                                flag |= blockBehaviors[i].OnHitAsProjectile(cellFace, componentBody, projectile);
                            }
                            projectile.ToRemove |= flag;
                        }
                        Vector3?vector2 = null;
                        if (bodyRaycastResult.HasValue && (!terrainRaycastResult.HasValue || bodyRaycastResult.Value.Distance < terrainRaycastResult.Value.Distance))
                        {
                            if (projectile.Velocity.Length() > 10f)
                            {
                                ComponentMiner.AttackBody(bodyRaycastResult.Value.ComponentBody, projectile.Owner, bodyRaycastResult.Value.HitPoint(), Vector3.Normalize(projectile.Velocity), block.GetProjectilePower(projectile.Value), isMeleeAttack: false);
                                if (projectile.Owner != null && projectile.Owner.PlayerStats != null)
                                {
                                    projectile.Owner.PlayerStats.RangedHits++;
                                }
                            }
                            if (projectile.IsIncendiary)
                            {
                                bodyRaycastResult.Value.ComponentBody.Entity.FindComponent <ComponentOnFire>()?.SetOnFire(projectile?.Owner, m_random.Float(6f, 8f));
                            }
                            vector = position;
                            projectile.Velocity        *= -0.05f;
                            projectile.Velocity        += m_random.Vector3(0.33f * projectile.Velocity.Length());
                            projectile.AngularVelocity *= -0.05f;
                        }
                        else if (terrainRaycastResult.HasValue)
                        {
                            CellFace cellFace2 = terrainRaycastResult.Value.CellFace;
                            int      cellValue = m_subsystemTerrain.Terrain.GetCellValue(cellFace2.X, cellFace2.Y, cellFace2.Z);
                            int      num       = Terrain.ExtractContents(cellValue);
                            Block    block2    = BlocksManager.Blocks[num];
                            float    num2      = projectile.Velocity.Length();
                            SubsystemBlockBehavior[] blockBehaviors2 = m_subsystemBlockBehaviors.GetBlockBehaviors(num);
                            for (int j = 0; j < blockBehaviors2.Length; j++)
                            {
                                blockBehaviors2[j].OnHitByProjectile(cellFace2, projectile);
                            }
                            if (num2 > 10f && m_random.Float(0f, 1f) > block2.ProjectileResilience)
                            {
                                m_subsystemTerrain.DestroyCell(0, cellFace2.X, cellFace2.Y, cellFace2.Z, 0, noDrop: true, noParticleSystem: false);
                                m_subsystemSoundMaterials.PlayImpactSound(cellValue, position, 1f);
                            }
                            if (projectile.IsIncendiary)
                            {
                                m_subsystemFireBlockBehavior.SetCellOnFire(terrainRaycastResult.Value.CellFace.X, terrainRaycastResult.Value.CellFace.Y, terrainRaycastResult.Value.CellFace.Z, 1f);
                                Vector3 vector3 = projectile.Position - 0.75f * Vector3.Normalize(projectile.Velocity);
                                for (int k = 0; k < 8; k++)
                                {
                                    Vector3 v2 = (k == 0) ? Vector3.Normalize(projectile.Velocity) : m_random.Vector3(1.5f);
                                    TerrainRaycastResult?terrainRaycastResult2 = m_subsystemTerrain.Raycast(vector3, vector3 + v2, useInteractionBoxes: false, skipAirBlocks: true, (int value, float distance) => true);
                                    if (terrainRaycastResult2.HasValue)
                                    {
                                        m_subsystemFireBlockBehavior.SetCellOnFire(terrainRaycastResult2.Value.CellFace.X, terrainRaycastResult2.Value.CellFace.Y, terrainRaycastResult2.Value.CellFace.Z, 1f);
                                    }
                                }
                            }
                            if (num2 > 5f)
                            {
                                m_subsystemSoundMaterials.PlayImpactSound(cellValue, position, 1f);
                            }
                            if (block.IsStickable && num2 > 10f && m_random.Bool(block2.ProjectileStickProbability))
                            {
                                Vector3 v3 = Vector3.Normalize(projectile.Velocity);
                                float   s  = MathUtils.Lerp(0.1f, 0.2f, MathUtils.Saturate((num2 - 15f) / 20f));
                                vector2 = position + terrainRaycastResult.Value.Distance * Vector3.Normalize(projectile.Velocity) + v3 * s;
                            }
                            else
                            {
                                Plane plane = cellFace2.CalculatePlane();
                                vector = position;
                                if (plane.Normal.X != 0f)
                                {
                                    projectile.Velocity *= new Vector3(-0.3f, 0.3f, 0.3f);
                                }
                                if (plane.Normal.Y != 0f)
                                {
                                    projectile.Velocity *= new Vector3(0.3f, -0.3f, 0.3f);
                                }
                                if (plane.Normal.Z != 0f)
                                {
                                    projectile.Velocity *= new Vector3(0.3f, 0.3f, -0.3f);
                                }
                                float num3 = projectile.Velocity.Length();
                                projectile.Velocity         = num3 * Vector3.Normalize(projectile.Velocity + m_random.Vector3(num3 / 6f, num3 / 3f));
                                projectile.AngularVelocity *= -0.3f;
                            }
                            MakeProjectileNoise(projectile);
                        }
                        if (terrainRaycastResult.HasValue || bodyRaycastResult.HasValue)
                        {
                            if (flag)
                            {
                                m_subsystemParticles.AddParticleSystem(block.CreateDebrisParticleSystem(m_subsystemTerrain, projectile.Position, projectile.Value, 1f));
                            }
                            else if (!projectile.ToRemove && (vector2.HasValue || projectile.Velocity.Length() < 1f))
                            {
                                if (projectile.ProjectileStoppedAction == ProjectileStoppedAction.TurnIntoPickable)
                                {
                                    int num4 = BlocksManager.DamageItem(projectile.Value, 1);
                                    if (num4 != 0)
                                    {
                                        if (vector2.HasValue)
                                        {
                                            CalculateVelocityAlignMatrix(block, vector2.Value, projectile.Velocity, out Matrix matrix);
                                            m_subsystemPickables.AddPickable(num4, 1, projectile.Position, Vector3.Zero, matrix);
                                        }
                                        else
                                        {
                                            m_subsystemPickables.AddPickable(num4, 1, position, Vector3.Zero, null);
                                        }
                                    }
                                    projectile.ToRemove = true;
                                }
                                else if (projectile.ProjectileStoppedAction == ProjectileStoppedAction.Disappear)
                                {
                                    projectile.ToRemove = true;
                                }
                            }
                        }
                        float num5 = projectile.IsInWater ? MathUtils.Pow(0.001f, dt) : MathUtils.Pow(block.ProjectileDamping, dt);
                        projectile.Velocity.Y      += -10f * dt;
                        projectile.Velocity        *= num5;
                        projectile.AngularVelocity *= num5;
                        projectile.Position         = vector;
                        projectile.Rotation        += projectile.AngularVelocity * dt;
                        if (projectile.TrailParticleSystem != null)
                        {
                            if (!m_subsystemParticles.ContainsParticleSystem((ParticleSystemBase)projectile.TrailParticleSystem))
                            {
                                m_subsystemParticles.AddParticleSystem((ParticleSystemBase)projectile.TrailParticleSystem);
                            }
                            Vector3 v4 = (projectile.TrailOffset != Vector3.Zero) ? Vector3.TransformNormal(projectile.TrailOffset, Matrix.CreateFromAxisAngle(Vector3.Normalize(projectile.Rotation), projectile.Rotation.Length())) : Vector3.Zero;
                            projectile.TrailParticleSystem.Position = projectile.Position + v4;
                            if (projectile.IsInWater)
                            {
                                projectile.TrailParticleSystem.IsStopped = true;
                            }
                        }
                        bool flag2 = IsWater(projectile.Position);
                        if (projectile.IsInWater != flag2)
                        {
                            if (flag2)
                            {
                                float num6 = new Vector2(projectile.Velocity.X + projectile.Velocity.Z).Length();
                                if (num6 > 6f && num6 > 4f * MathUtils.Abs(projectile.Velocity.Y))
                                {
                                    projectile.Velocity   *= 0.5f;
                                    projectile.Velocity.Y *= -1f;
                                    flag2 = false;
                                }
                                else
                                {
                                    projectile.Velocity *= 0.2f;
                                }
                                float?surfaceHeight = m_subsystemFluidBlockBehavior.GetSurfaceHeight(Terrain.ToCell(projectile.Position.X), Terrain.ToCell(projectile.Position.Y), Terrain.ToCell(projectile.Position.Z));
                                if (surfaceHeight.HasValue)
                                {
                                    m_subsystemParticles.AddParticleSystem(new WaterSplashParticleSystem(m_subsystemTerrain, new Vector3(projectile.Position.X, surfaceHeight.Value, projectile.Position.Z), large: false));
                                    m_subsystemAudio.PlayRandomSound("Audio/Splashes", 1f, m_random.Float(-0.2f, 0.2f), projectile.Position, 6f, autoDelay: true);
                                    MakeProjectileNoise(projectile);
                                }
                            }
                            projectile.IsInWater = flag2;
                        }
                        if (IsMagma(projectile.Position))
                        {
                            m_subsystemParticles.AddParticleSystem(new MagmaSplashParticleSystem(m_subsystemTerrain, projectile.Position, large: false));
                            m_subsystemAudio.PlayRandomSound("Audio/Sizzles", 1f, m_random.Float(-0.2f, 0.2f), projectile.Position, 3f, autoDelay: true);
                            projectile.ToRemove = true;
                            m_subsystemExplosions.TryExplodeBlock(Terrain.ToCell(projectile.Position.X), Terrain.ToCell(projectile.Position.Y), Terrain.ToCell(projectile.Position.Z), projectile.Value);
                        }
                        if (m_subsystemTime.PeriodicGameTimeEvent(1.0, (double)(projectile.GetHashCode() % 100) / 100.0) && (m_subsystemFireBlockBehavior.IsCellOnFire(Terrain.ToCell(projectile.Position.X), Terrain.ToCell(projectile.Position.Y + 0.1f), Terrain.ToCell(projectile.Position.Z)) || m_subsystemFireBlockBehavior.IsCellOnFire(Terrain.ToCell(projectile.Position.X), Terrain.ToCell(projectile.Position.Y + 0.1f) - 1, Terrain.ToCell(projectile.Position.Z))))
                        {
                            m_subsystemAudio.PlayRandomSound("Audio/Sizzles", 1f, m_random.Float(-0.2f, 0.2f), projectile.Position, 3f, autoDelay: true);
                            projectile.ToRemove = true;
                            m_subsystemExplosions.TryExplodeBlock(Terrain.ToCell(projectile.Position.X), Terrain.ToCell(projectile.Position.Y), Terrain.ToCell(projectile.Position.Z), projectile.Value);
                        }
                    }
                }
            }
            foreach (Projectile item in m_projectilesToRemove)
            {
                if (item.TrailParticleSystem != null)
                {
                    item.TrailParticleSystem.IsStopped = true;
                }
                m_projectiles.Remove(item);
                if (this.ProjectileRemoved != null)
                {
                    this.ProjectileRemoved(item);
                }
            }
            m_projectilesToRemove.Clear();
        }
示例#2
0
        public void TryAddPoint(int x, int y, int z, int axis, float currentPressure, bool isIncendiary, List <ProcessPoint> toProcess, SparseSpatialArray <bool> processed)
        {
            if (processed.Get(x, y, z))
            {
                return;
            }
            int cellValue = m_subsystemTerrain.Terrain.GetCellValue(x, y, z);
            int num       = Terrain.ExtractContents(cellValue);

            if (num != 0)
            {
                int   num2 = (int)(MathUtils.Hash((uint)(x + 913 * y + 217546 * z)) % 100u);
                float num3 = MathUtils.Lerp(1f, 2f, (float)num2 / 100f);
                if (num2 % 8 == 0)
                {
                    num3 *= 3f;
                }
                Block block = BlocksManager.Blocks[num];
                float num4  = m_pressureByPoint.Get(x - 1, y, z) + m_pressureByPoint.Get(x + 1, y, z) + m_pressureByPoint.Get(x, y - 1, z) + m_pressureByPoint.Get(x, y + 1, z) + m_pressureByPoint.Get(x, y, z - 1) + m_pressureByPoint.Get(x, y, z + 1);
                float num5  = MathUtils.Max(block.ExplosionResilience * num3, 1f);
                float num6  = num4 / num5;
                if (num6 > 1f)
                {
                    int newValue = Terrain.MakeBlockValue(0);
                    m_subsystemTerrain.DestroyCell(0, x, y, z, newValue, noDrop: true, noParticleSystem: true);
                    bool  flag        = false;
                    float probability = (num6 > 5f) ? 0.95f : 0.75f;
                    if (m_random.Bool(probability))
                    {
                        flag = TryExplodeBlock(x, y, z, cellValue);
                    }
                    if (!flag)
                    {
                        CalculateImpulseAndDamage(new Vector3((float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f), 60f, 2f * num4, out Vector3 impulse, out float _);
                        bool flag2 = false;
                        List <BlockDropValue> list = new List <BlockDropValue>();
                        block.GetDropValues(m_subsystemTerrain, cellValue, newValue, 0, list, out bool _);
                        if (list.Count == 0)
                        {
                            list.Add(new BlockDropValue
                            {
                                Value = cellValue,
                                Count = 1
                            });
                            flag2 = true;
                        }
                        foreach (BlockDropValue item in list)
                        {
                            int num7 = Terrain.ExtractContents(item.Value);
                            if (!(BlocksManager.Blocks[num7] is FluidBlock))
                            {
                                float num8 = (m_projectilesCount < 40) ? 1f : ((m_projectilesCount < 60) ? 0.5f : ((m_projectilesCount >= 80) ? 0.125f : 0.25f));
                                if (m_random.Float(0f, 1f) < num8)
                                {
                                    Vector3 velocity = impulse + m_random.Vector3(0.05f * impulse.Length());
                                    if (m_projectilesCount >= 1)
                                    {
                                        velocity *= m_random.Float(0.5f, 1f);
                                        velocity += m_random.Vector3(0.2f * velocity.Length());
                                    }
                                    float      num9       = flag2 ? 0f : MathUtils.Lerp(1f, 0f, (float)m_projectilesCount / 20f);
                                    Projectile projectile = m_subsystemProjectiles.AddProjectile(item.Value, new Vector3((float)x + 0.5f, (float)y + 0.5f, (float)z + 0.5f), velocity, m_random.Vector3(0f, 20f), null);
                                    projectile.ProjectileStoppedAction = ((!(m_random.Float(0f, 1f) < num9)) ? ProjectileStoppedAction.Disappear : ProjectileStoppedAction.TurnIntoPickable);
                                    if (m_random.Float(0f, 1f) < 0.5f && m_projectilesCount < 35)
                                    {
                                        float num10 = (num4 > 60f) ? m_random.Float(3f, 7f) : m_random.Float(1f, 3f);
                                        if (isIncendiary)
                                        {
                                            num10 += 10f;
                                        }
                                        m_subsystemProjectiles.AddTrail(projectile, Vector3.Zero, new SmokeTrailParticleSystem(15, m_random.Float(0.75f, 1.5f), num10, isIncendiary ? new Color(255, 140, 192) : Color.White));
                                        projectile.IsIncendiary = isIncendiary;
                                    }
                                    m_generatedProjectiles.Add(projectile, value: true);
                                    m_projectilesCount++;
                                }
                            }
                        }
                    }
                }
                else
                {
                    m_surroundingPressureByPoint.Set(x, y, z, new SurroundingPressurePoint
                    {
                        Pressure     = num4,
                        IsIncendiary = isIncendiary
                    });
                    if (block.IsCollidable)
                    {
                        return;
                    }
                }
            }
            toProcess.Add(new ProcessPoint
            {
                X    = x,
                Y    = y,
                Z    = z,
                Axis = axis
            });
            processed.Set(x, y, z, value: true);
        }
        void InitCommands()
        {
            commands["msg"] = new CommandDefination
            {
                Usage        = "msg @a/r/p/e <string> [bool=true] [bool=true]",
                AutoComplete = (obj) => obj.Enum(enumCreatureType).String().Bool().Bool(),
                Operation    = (obj) =>
                {
                    string type = obj.NextString();
                    string msg  = obj.NextString();
                    bool   b1   = obj.NextBool(true);
                    bool   b2   = obj.NextBool(true);
                    FindPlayer(type, obj, (a) =>
                    {
                        a.ComponentGui.DisplaySmallMessage(msg, b1, b2);
                    });
                }
            };

            commands["msgl"] = new CommandDefination
            {
                Usage        = "msgl @a/r/p/e <string> <string> <string> [float=5] [float=0]",
                AutoComplete = (obj) => obj.Enum(enumCreatureType).String().String().Float().Float(),
                Operation    = (obj) =>
                {
                    string type = obj.NextString();
                    string m1   = obj.NextString();
                    string m2   = obj.NextString();
                    float  f1   = obj.NextFloat(5);
                    float  f2   = obj.NextFloat(0);
                    FindPlayer(type, obj, (a) =>
                    {
                        a.ComponentGui.DisplayLargeMessage(m1, m2, f1, f2);
                    });
                }
            };

            commands["kill"] = new CommandDefination
            {
                Usage        = "kill @a/r/p/e [string=magic]",
                AutoComplete = (obj) => obj.Enum(enumCreatureType).String(),
                Operation    = (obj) =>
                {
                    string type   = obj.NextString();
                    string reason = obj.NextString("magic");
                    EnumCreatures(type, obj, (c) =>
                    {
                        c.ComponentHealth.Injure(1, null, true, reason);
                    });
                }
            };

            commands["health"] = new CommandDefination
            {
                Usage        = "health heal/injure [float=1] [string=magic]",
                AutoComplete = (obj) => obj.Enum(new string[] { "heal", "injure" }).Float().String(),
                Operation    = (obj) =>
                {
                    string type = obj.NextString();
                    switch (type)
                    {
                    case "heal":
                        float amount1 = obj.NextFloat(1);
                        obj.Creature.ComponentHealth.Heal(amount1);
                        break;

                    case "injure":
                        float  amount = obj.NextFloat(1);
                        string reason = obj.NextString("magic");
                        obj.Creature.ComponentHealth.Injure(amount, null, true, reason);
                        break;

                    default:
                        throw new Exception("usage: health heal/injure [float=1] [string=magic]");
                    }
                }
            };

            commands["strike"] = new CommandDefination
            {
                Usage        = "strike <vector3>",
                AutoComplete = (obj) => obj.Vector3(),
                Operation    = (obj) =>
                {
                    subsystemSky.MakeLightningStrike(obj.NextVector3());
                }
            };

            commands["setblock"] = new CommandDefination
            {
                Usage        = "setblock <point3> <int>",
                AutoComplete = (obj) => obj.Point3().Int(),
                Operation    = (s) =>
                {
                    var p = s.NextPoint3();
                    subsystemTerrain.ChangeCell(p.X, p.Y, p.Z, s.NextInt());
                }
            };

            commands["place"] = new CommandDefination
            {
                Usage        = "place <point3> <int> [bool=false] [bool=false]",
                AutoComplete = (obj) => obj.Point3().Int().Bool().Bool(),
                Operation    = (obj) =>
                {
                    var p = obj.NextPoint3();
                    subsystemTerrain.DestroyCell(2, p.X, p.Y, p.Z, obj.NextInt(), obj.NextBool(false), obj.NextBool(false));
                }
            };

            commands["fill"] = new CommandDefination
            {
                Usage        = "fill <point3> <point3>",
                AutoComplete = (obj) => obj.Point3().Point3().Int(),
                Operation    = (obj) =>
                {
                    var p1     = obj.NextPoint3();
                    var p2     = obj.NextPoint3();
                    var startx = Math.Min(p1.X, p2.X);
                    var endx   = Math.Max(p1.X, p2.X);
                    var starty = Math.Min(p1.Y, p2.Y);
                    var endy   = Math.Max(p1.Y, p2.Y);
                    var startz = Math.Min(p1.Z, p2.Z);
                    var endz   = Math.Max(p1.Z, p2.Z);

                    var val = obj.NextInt();

                    for (int x = startx; x <= endx; x++)
                    {
                        for (int y = starty; y <= endy; y++)
                        {
                            for (int z = startz; z <= endz; z++)
                            {
                                subsystemTerrain.Terrain.SetCellValueFast(x, y, z, val);
                            }
                        }
                    }

                    var startChunk = Terrain.ToChunk(startx, startz);
                    var endChunk   = Terrain.ToChunk(endx, endz);

                    for (int x = startChunk.X; x <= endChunk.X; x++)
                    {
                        for (int y = startChunk.Y; y <= endChunk.Y; y++)
                        {
                            var c = subsystemTerrain.Terrain.GetChunkAtCoords(x, y);
                            if (c != null)
                            {
                                subsystemTerrain.TerrainUpdater.DowngradeChunkNeighborhoodState(c.Coords, 1, TerrainChunkState.InvalidLight, false);
                            }
                        }
                    }
                }
            };

            commands["time"] = new CommandDefination
            {
                Usage        = "time add/set <float>",
                AutoComplete = (obj) => obj.Enum(new string[] { "add", "set" }).Float(),
                Operation    = (obj) =>
                {
                    switch (obj.NextString())
                    {
                    case "add":
                        subsystemTime.TimeOfDayOffset += obj.NextFloat();
                        break;

                    case "set":
                        subsystemTime.TimeOfDayOffset = obj.NextFloat();
                        break;

                    default:
                        throw new Exception("usage: time add/set <float>");
                    }
                }
            };

            commands["execute"] = new CommandDefination
            {
                Usage        = "execute @a/r/p/e <another command>",
                AutoComplete = (obj) =>
                {
                    obj.Enum(enumCreatureType);
                    AutoCompleteCommand(obj.CommandStream.GetAllLeft(), obj.Reciver);
                },
                Operation = (obj) =>
                {
                    var type    = obj.NextString();
                    var command = obj.GetAllLeft();

                    EnumCreatures(type, obj, (a) =>
                    {
                        RunCommand(a, command);
                    });
                }
            };

            commands["setdata"] = new CommandDefination
            {
                Usage        = "setdata <creature data> <data type>",
                AutoComplete = (obj) =>
                {
                    obj.Enum(creatureDatas.Keys);
                    string component = obj.CommandStream.Last;
                    int    i         = creatureDatas[component];
                    switch (i)
                    {
                    case 0:
                        obj.Any(typeof(ComponentLocomotion).GetProperty(component).PropertyType);
                        break;

                    case 1:
                        obj.Any(typeof(ComponentHealth).GetProperty(component).PropertyType);
                        break;

                    case 2:
                        obj.Any(typeof(ComponentBody).GetProperty(component).PropertyType);
                        break;
                    }
                },
                Operation = (s) =>
                {
                    while (s.HasNext)
                    {
                        var          component = s.NextString();
                        PropertyInfo p;
                        if (creatureDatas.TryGetValue(component, out int i))
                        {
                            switch (i)
                            {
                            case 0:
                                p = typeof(ComponentLocomotion).GetProperty(component);
                                p.SetValue(s.Creature.ComponentLocomotion, s.Next(p.PropertyType), null);
                                break;

                            case 1:
                                p = typeof(ComponentHealth).GetProperty(component);
                                p.SetValue(s.Creature.ComponentHealth, s.Next(p.PropertyType), null);
                                break;

                            case 2:
                                p = typeof(ComponentBody).GetProperty(component);
                                p.SetValue(s.Creature.ComponentBody, s.Next(p.PropertyType), null);
                                break;
                            }
                        }
                        else
                        {
                            throw new Exception(component + " is not a creature data");
                        }
                    }
                }
            };

            commands["gameinfo"] = new CommandDefination
            {
                Usage        = "gameinfo <info name> <info value>",
                AutoComplete = (obj) =>
                {
                    Type settings = typeof(WorldSettings);
                    obj.Enum(settings.GetFields().Select(f => f.Name));
                    obj.Any(settings.GetField(obj.CommandStream.Last).FieldType);
                },
                Operation = (s) =>
                {
                    var setting = s.NextString();
                    var val     = s.NextString();
                    var f       = typeof(WorldSettings).GetField(setting);
                    if (f != null)
                    {
                        f.SetValue(GameManager.WorldInfo.WorldSettings, ChangeType(val, f.FieldType));
                    }
                }
            };

            commands["summon"] = new CommandDefination
            {
                Usage        = "summon <animal name> <vector3> [float=0]",
                AutoComplete = (obj) => obj.String().Vector3().Float(),
                Operation    = (s) =>
                {
                    var    name     = s.NextString();
                    var    position = s.NextVector3();
                    var    rotation = s.NextFloat(0);
                    Entity entity   = DatabaseManager.CreateEntity(Project, creatureTemplateNames[name], true);
                    entity.FindComponent <ComponentBody>(true).Position       = position;
                    entity.FindComponent <ComponentBody>(true).Rotation       = Quaternion.CreateFromAxisAngle(Vector3.UnitY, rotation);
                    entity.FindComponent <ComponentSpawn>(true).SpawnDuration = 0.25f;
                    Project.AddEntity(entity);
                }
            };

            commands["tp"] = new CommandDefination
            {
                Usage        = "tp <vector3>",
                AutoComplete = (obj) => obj.Vector3(),
                Operation    = s => s.Creature.ComponentBody.Position = s.NextVector3()
            };

            commands["additem"] = new CommandDefination
            {
                Usage        = "additem <vector3> <int> [int=1] [vector=0,0,0]",
                AutoComplete = (obj) => obj.Vector3().Int().Int().Vector3(),
                Operation    = s =>
                {
                    var     position = s.NextVector3();
                    var     val      = s.NextInt();
                    var     count    = s.NextInt(1);
                    Vector3?speed    = null;
                    if (s.HasNext)
                    {
                        speed = s.NextVector3();
                    }
                    Project.FindSubsystem <SubsystemPickables>(true).AddPickable(s.NextInt(), s.NextInt(1), position, speed, null);
                }
            };

            commands["give"] = new CommandDefination
            {
                Usage        = "give @a/r/p/e <int> [int=1]",
                AutoComplete = (obj) => obj.Enum(enumCreatureType).Int().Int(),
                Operation    = s =>
                {
                    var enumType = s.NextString();
                    var val      = s.NextInt();
                    var count    = s.NextInt(1);

                    FindPlayer(enumType, s, (p) => ComponentInventoryBase.AcquireItems(p.ComponentMiner.Inventory, val, count));
                }
            };

            foreach (string name in commands.Keys)
            {
                commandUsage[commands[name].Usage] = name;
            }
        }

        void LoadBlockIds()
        {
            foreach (Block b in BlocksManager.Blocks)
            {
                foreach (int id in b.GetCreativeValues())
                {
                    var name = b.GetDisplayName(subsystemTerrain, id).Replace(' ', '_').ToLower();
                    blockIds[name] = id;
                }
                blockIds[b.DefaultDisplayName.Replace(' ', '_').ToLower()] = b.BlockIndex;
            }
        }

        void FindPlayer(string type, CommandStream s, Action <ComponentPlayer> a)
        {
            if (type[0] == '@')
            {
                EnumCreatures(type, s, c =>
                {
                    if (c is ComponentPlayer)
                    {
                        a(c as ComponentPlayer);
                    }
                });
            }
            else
            {
                FindPlayerByName(type, a);
            }
        }

        void FindPlayerByName(string name, Action <ComponentPlayer> a)
        {
            foreach (ComponentPlayer p in subsystemPlayers.ComponentPlayers)
            {
                if (p.PlayerData.Name == name)
                {
                    a(p);
                }
                else
                {
                    throw new WrongArgTypeException(name, "player");
                }
            }
        }

        void LoadCreatureTemplateNames()
        {
            var paramterType = DatabaseManager.GameDatabase.ParameterType;
            var entities     = DatabaseManager.GameDatabase.Database.Root.GetExplicitNestingChildren(paramterType, false);
            var displayName  = new Guid("715ff548-ef2b-430e-8e6b-51b934e5da1d");

            foreach (TemplatesDatabase.DatabaseObject o in entities)
            {
                if (o.EffectiveInheritanceRoot.Guid == displayName && o.Value.ToString() != string.Empty)
                {
                    creatureTemplateNames[o.NestingParent.NestingParent.Name.ToLower()] = o.Value.ToString();
                    //Log.Information("{0}, {1}", o.NestingParent.NestingParent.Name, o.Value);
                }
            }
        }

        void LoadCreatureDatas()
        {
            foreach (PropertyInfo p in typeof(ComponentLocomotion).GetRuntimeProperties())
            {
                if (CommandStream.IsTypeSupported(p.PropertyType))
                {
                    creatureDatas[p.Name] = 0;
                }
            }
            foreach (PropertyInfo p in typeof(ComponentHealth).GetRuntimeProperties())
            {
                if (CommandStream.IsTypeSupported(p.PropertyType))
                {
                    creatureDatas[p.Name] = 1;
                }
            }
            foreach (PropertyInfo p in typeof(ComponentBody).GetRuntimeProperties())
            {
                if (CommandStream.IsTypeSupported(p.PropertyType))
                {
                    creatureDatas[p.Name] = 2;
                }
            }
        }

        void EnumCreatures(string type, CommandStream s, Action <ComponentCreature> a)
        {
            var data = new EnumData(type, subsystemCreature.Creatures.Count, s.ExePosition);

            if (data.name == "player")
            {
                data.name = string.Empty;
                SearchCreature(data, SortCreatures(data, subsystemPlayers.ComponentPlayers), a);
            }
            else
            {
                SearchCreature(data, SortCreatures(data, subsystemCreature.Creatures), a);
            }
        }

        List <ComponentCreature> SortCreatures <T>(EnumData data, IEnumerable <T> collection) where T : ComponentCreature
        {
            var l = new List <ComponentCreature>();

            if (data.mode1 == SearchingMode1.Regular)
            {
                foreach (ComponentCreature c in collection)
                {
                    if (CheckCreatureWithData(data, c))
                    {
                        l.Add(c);
                    }
                }
            }
            else if (data.mode1 == SearchingMode1.Nearest)
            {
                var v    = new Vector3(data.x, data.y, data.z);
                var dict = new Dictionary <float, ComponentCreature>();
                foreach (ComponentCreature c in collection)
                {
                    if (CheckCreatureWithData(data, c))
                    {
                        dict.Add(Vector3.DistanceSquared(v, c.ComponentBody.Position), c);
                    }
                }
                var l2 = new List <float>();
                foreach (float i in dict.Keys)
                {
                    l2.Add(i);
                }
                l2.Sort(delegate(float i1, float i2)
                {
                    if (i1 > i2)
                    {
                        return(1);
                    }
                    return(-1);
                });

                foreach (float i in l2)
                {
                    l.Add(dict[i]);
                }
            }
            else
            {
                foreach (ComponentCreature c in collection)
                {
                    if (CheckCreatureWithData(data, c))
                    {
                        l.Add(c);
                    }
                }
                var r     = new Random();
                var count = l.Count;

                int n = l.Count;
                while (n > 1)
                {
                    n--;
                    int k     = r.UniformInt(0, n);
                    var value = l[k];
                    l[k] = l[n];
                    l[n] = value;
                }
            }

            return(l);
        }

        void SearchCreature(EnumData data, List <ComponentCreature> sorted, Action <ComponentCreature> a)
        {
            for (int i = 0; i < data.count; i++)
            {
                if (i >= sorted.Count)
                {
                    return;
                }
                a.Invoke(sorted[i]);
            }
        }

        bool CheckCreatureWithData(EnumData data, ComponentCreature c)
        {
            if (data.name != string.Empty)
            {
                string dataname;
                if (data.name[0] == '!')
                {
                    Log.Information(c.DisplayName);
                    if (creatureTemplateNames.TryGetValue(data.name.Substring(1), out dataname))
                    {
                        if (dataname == c.DisplayName)
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        return(false);
                    }
                }
                else
                {
                    if (creatureTemplateNames.TryGetValue(data.name, out dataname))
                    {
                        if (dataname != c.DisplayName)
                        {
                            return(false);
                        }
                    }
                    else
                    {
                        return(false);
                    }
                }
            }
            switch (data.SearchingMode)
            {
            case SearchingMode.Radius:
                if (data.r > 0)
                {
                    if (Vector3.DistanceSquared(new Vector3(data.x, data.y, data.z), c.ComponentBody.Position) >= data.r2)
                    {
                        return(false);
                    }
                }
                else
                {
                    if (Vector3.DistanceSquared(new Vector3(data.x, data.y, data.z), c.ComponentBody.Position) <= data.r2)
                    {
                        return(false);
                    }
                }
                break;

            case SearchingMode.Volume:
                var p = c.ComponentBody.Position;
                var x = p.X - data.x;
                var y = p.Y - data.y;
                var z = p.Z - data.z;
                if (x < 0 && x > data.dx && y < 0 && y > data.dy && z < 0 && z > data.dz)
                {
                    return(false);
                }
                break;
            }
            return(true);
        }