예제 #1
0
        public void HandleBoyancy(Vec3d pos, Vec3f velocity, bool boyant, float gravityStrength, float deltatime, float height)
        {
            int xPrev = (int)pos.X;
            int yPrev = (int)pos.Y;
            int zPrev = (int)pos.Z;

            tmpPos.Set(xPrev, yPrev, zPrev);
            Block block     = BlockAccess.GetBlock(tmpPos);
            Block prevBlock = block;

            if (block == null)
            {
                return;
            }

            if (boyant)
            {
                if (block.IsLiquid())
                {
                    tmpPos.Set(xPrev, (int)(pos.Y + 1), zPrev);
                    block = BlockAccess.GetBlock(tmpPos);
                    if (block == null)
                    {
                        return;
                    }

                    float waterY = (int)pos.Y + prevBlock.LiquidLevel / 8f + (block.IsLiquid() ? 9 / 8f : 0);
                    float bottomSubmergedness = waterY - (float)pos.Y;

                    float swimlineSubmergedness = GameMath.Clamp(bottomSubmergedness + height, 0, 1);

                    float boyancyStrength = GameMath.Clamp(9 * swimlineSubmergedness, -1.25f, 1.25f); // was 3* before. Dunno why it has to be 9* now

                    velocity.Y += gravityStrength * deltatime * boyancyStrength;

                    float waterDrag = (float)GameMath.Clamp(30 * Math.Abs(velocity.Y) - 0.02f, 1, 1.25f);

                    velocity.Y /= waterDrag;
                    velocity.X *= 0.99f;
                    velocity.Z *= 0.99f;

                    if (prevBlock.PushVector != null && swimlineSubmergedness >= 0)
                    {
                        float factor = deltatime / (33f / 1000f);
                        velocity.Add(
                            (float)prevBlock.PushVector.X * 15 * factor,
                            (float)prevBlock.PushVector.Y * 15 * factor,
                            (float)prevBlock.PushVector.Z * 15 * factor
                            );
                    }
                }
            }
            else
            {
                if (block.PushVector != null)
                {
                    velocity.Add(
                        (float)block.PushVector.X * 30 * deltatime,
                        (float)block.PushVector.Y * 30 * deltatime,
                        (float)block.PushVector.Z * 30 * deltatime
                        );
                }
            }
        }
예제 #2
0
        /// <summary>
        /// For placement of ruins during worldgen, replaces the topsoil with the area specific soil (e.g. sand)
        /// </summary>
        /// <param name="blockAccessor"></param>
        /// <param name="blocks"></param>
        /// <param name="startPos"></param>
        /// <param name="climateUpLeft"></param>
        /// <param name="climateUpRight"></param>
        /// <param name="climateBotLeft"></param>
        /// <param name="climateBotRight"></param>
        /// <param name="replaceblockids"></param>
        /// <returns></returns>
        public int PlaceRespectingBlockLayers(IBlockAccessor blockAccessor, IWorldAccessor worldForCollectibleResolve, BlockPos startPos, int climateUpLeft, int climateUpRight, int climateBotLeft, int climateBotRight, ushort[] replaceblockids)
        {
            BlockPos curPos    = new BlockPos();
            int      placed    = 0;
            int      chunksize = blockAccessor.ChunkSize;


            for (int x = 0; x < SizeX; x++)
            {
                for (int z = 0; z < SizeZ; z++)
                {
                    curPos.Set(x + startPos.X, startPos.Y, z + startPos.Z);
                    ushort rockblockid = blockAccessor.GetMapChunkAtBlockPos(curPos).TopRockIdMap[(curPos.Z % chunksize) * chunksize + curPos.X % chunksize];
                    int    depth       = 0;

                    for (int y = SizeY - 1; y >= 0; y--)
                    {
                        curPos.Set(x + startPos.X, y + startPos.Y, z + startPos.Z);
                        Block newBlock = blocksByPos[x, y, z];
                        if (newBlock == null)
                        {
                            continue;
                        }

                        if (newBlock.Replaceable < 1000)
                        {
                            if (replaceblockids.Length > depth && newBlock.BlockId == replaceblockids[depth])
                            {
                                int climate = GameMath.BiLerpRgbColor((float)x / chunksize, (float)z / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);

                                newBlock = GetBlockLayerBlock((climate >> 8) & 0xff, (climate >> 16) & 0xff, startPos.Y, rockblockid, depth, newBlock, worldForCollectibleResolve.Blocks);
                            }
                            depth++;
                        }

                        Block oldBlock = blockAccessor.GetBlock(curPos);
                        placed += handler(blockAccessor, curPos, oldBlock, newBlock);

                        byte[] lightHsv = newBlock.GetLightHsv(blockAccessor, curPos);

                        if (lightHsv[2] > 0 && blockAccessor is IWorldGenBlockAccessor)
                        {
                            int chunkSize = blockAccessor.ChunkSize;
                            ((IWorldGenBlockAccessor)blockAccessor).ScheduleBlockLightUpdate(curPos.Copy(), oldBlock.BlockId, newBlock.BlockId);
                        }
                    }
                }
            }

            foreach (var val in BlockEntities)
            {
                uint index = val.Key;
                int  dx    = (int)(index & 0x1ff);
                int  dy    = (int)((index >> 20) & 0x1ff);
                int  dz    = (int)((index >> 10) & 0x1ff);

                curPos.Set(startPos.X + dx, startPos.Y + dy, startPos.Z + dz);

                BlockEntity be = blockAccessor.GetBlockEntity(curPos);
                if (be != null)
                {
                    be.FromTreeAtributes(DecodeBlockEntityData(val.Value), worldForCollectibleResolve);
                    be.OnLoadCollectibleMappings(worldForCollectibleResolve, BlockCodes, ItemCodes);
                    be.pos = curPos.Copy();
                }
            }

            return(placed);
        }
예제 #3
0
        /// <summary>
        /// Checks the Positive Spells.  Handles buffs, heals, etc.
        /// </summary>
        protected override bool CheckDefensiveSpells(Spell spell)
        {
            if (spell == null || spell.IsHarmful)
            {
                return(false);
            }

            // Make sure we're currently able to cast the spell
            if (spell.CastTime > 0 && (Body.IsCasting || (Body.IsBeingInterrupted && !spell.Uninterruptible)))
            {
                return(false);
            }

            // Make sure the spell isn't disabled
            if (spell.HasRecastDelay && Body.GetSkillDisabledDuration(spell) > 0)
            {
                return(false);
            }

            bool casted = false;

            // clear current target, set target based on spell type, cast spell, return target to original target
            GameObject lastTarget = Body.TargetObject;

            Body.TargetObject = null;
            GamePlayer player = null;
            GameLiving owner  = null;

            switch (spell.SpellType.ToUpper())
            {
                #region Buffs
            case "ACUITYBUFF":
            case "AFHITSBUFF":
            case "ALLMAGICRESISTSBUFF":
            case "ARMORABSORPTIONBUFF":
            case "ARMORFACTORBUFF":
            case "BODYRESISTBUFF":
            case "BODYSPIRITENERGYBUFF":
            case "BUFF":
            case "CELERITYBUFF":
            case "COLDRESISTBUFF":
            case "COMBATSPEEDBUFF":
            case "CONSTITUTIONBUFF":
            case "COURAGEBUFF":
            case "CRUSHSLASHTHRUSTBUFF":
            case "DEXTERITYBUFF":
            case "DEXTERITYQUICKNESSBUFF":
            case "EFFECTIVENESSBUFF":
            case "ENDURANCEREGENBUFF":
            case "ENERGYRESISTBUFF":
            case "FATIGUECONSUMPTIONBUFF":
            case "FELXIBLESKILLBUFF":
            case "HASTEBUFF":
            case "HEALTHREGENBUFF":
            case "HEATCOLDMATTERBUFF":
            case "HEATRESISTBUFF":
            case "HEROISMBUFF":
            case "KEEPDAMAGEBUFF":
            case "MAGICRESISTSBUFF":
            case "MATTERRESISTBUFF":
            case "MELEEDAMAGEBUFF":
            case "MESMERIZEDURATIONBUFF":
            case "MLABSBUFF":
            case "PALADINARMORFACTORBUFF":
            case "PARRYBUFF":
            case "POWERHEALTHENDURANCEREGENBUFF":
            case "POWERREGENBUFF":
            case "SAVAGECOMBATSPEEDBUFF":
            case "SAVAGECRUSHRESISTANCEBUFF":
            case "SAVAGEDPSBUFF":
            case "SAVAGEPARRYBUFF":
            case "SAVAGESLASHRESISTANCEBUFF":
            case "SAVAGETHRUSTRESISTANCEBUFF":
            case "SPIRITRESISTBUFF":
            case "STRENGTHBUFF":
            case "STRENGTHCONSTITUTIONBUFF":
            case "SUPERIORCOURAGEBUFF":
            case "TOHITBUFF":
            case "WEAPONSKILLBUFF":
            case "DAMAGEADD":
            case "OFFENSIVEPROC":
            case "DEFENSIVEPROC":
            case "DAMAGESHIELD":
            case "BLADETURN":
            {
                String target;

                //Buff self
                if (!LivingHasEffect(Body, spell))
                {
                    Body.TargetObject = Body;
                    break;
                }

                target = spell.Target.ToUpper();

                if (target == "SELF")
                {
                    break;
                }

                if (target == "REALM" || target == "GROUP")
                {
                    owner  = (this as IControlledBrain).Owner;
                    player = null;
                    //Buff owner
                    if (!LivingHasEffect(owner, spell) && GameMath.IsWithinRadius(Body, owner, spell.Range))
                    {
                        Body.TargetObject = owner;
                        break;
                    }

                    if (owner is GameNPC npc)
                    {
                        //Buff other minions
                        foreach (IControlledBrain icb in npc.ControlledNpcList)
                        {
                            if (icb != null && icb.Body != null && !LivingHasEffect(icb.Body, spell) &&
                                GameMath.IsWithinRadius(Body, icb.Body, spell.Range))
                            {
                                Body.TargetObject = icb.Body;
                                break;
                            }
                        }
                    }

                    player = GetPlayerOwner();

                    //Buff player
                    if (player != null)
                    {
                        if (!LivingHasEffect(player, spell))
                        {
                            Body.TargetObject = player;
                            break;
                        }

                        if (player.Group != null)
                        {
                            foreach (GamePlayer p in player.Group.GetPlayersInTheGroup())
                            {
                                if (!LivingHasEffect(p, spell) && GameMath.IsWithinRadius(Body, p, spell.Range))
                                {
                                    Body.TargetObject = p;
                                    break;
                                }
                            }
                        }
                    }
                }
            }
            break;
                #endregion Buffs

                #region Disease Cure/Poison Cure/Summon
            case "CUREDISEASE":
                //Cure owner
                owner = (this as IControlledBrain).Owner;
                if (owner.IsDiseased)
                {
                    Body.TargetObject = owner;
                    break;
                }

                //Cure self
                if (Body.IsDiseased)
                {
                    Body.TargetObject = Body;
                    break;
                }

                // Cure group members

                player = GetPlayerOwner();

                if (player.Group != null)
                {
                    foreach (GamePlayer p in player.Group.GetPlayersInTheGroup())
                    {
                        if (p.IsDiseased && GameMath.IsWithinRadius(Body, p, spell.Range))
                        {
                            Body.TargetObject = p;
                            break;
                        }
                    }
                }
                break;

            case "CUREPOISON":
                //Cure owner
                owner = (this as IControlledBrain).Owner;
                if (LivingIsPoisoned(owner))
                {
                    Body.TargetObject = owner;
                    break;
                }

                //Cure self
                if (LivingIsPoisoned(Body))
                {
                    Body.TargetObject = Body;
                    break;
                }

                // Cure group members

                player = GetPlayerOwner();

                if (player.Group != null)
                {
                    foreach (GamePlayer p in player.Group.GetPlayersInTheGroup())
                    {
                        if (LivingIsPoisoned(p) && GameMath.IsWithinRadius(Body, p, spell.Range))
                        {
                            Body.TargetObject = p;
                            break;
                        }
                    }
                }
                break;

            case "SUMMON":
                Body.TargetObject = Body;
                break;
                #endregion

                #region Heals
            case "COMBATHEAL":
            case "HEAL":
            case "HEALOVERTIME":
            case "MERCHEAL":
            case "OMNIHEAL":
            case "PBAEHEAL":
            case "SPREADHEAL":
                String spellTarget = spell.Target.ToUpper();
                int    bodyPercent = Body.HealthPercent;

                if (spellTarget == "SELF")
                {
                    if (bodyPercent < GS.ServerProperties.Properties.NPC_HEAL_THRESHOLD && !spell.TargetHasEffect(Body))
                    {
                        Body.TargetObject = Body;
                    }

                    break;
                }

                // Heal seriously injured targets first
                int emergencyThreshold = GS.ServerProperties.Properties.NPC_HEAL_THRESHOLD / 2;

                //Heal owner
                owner = (this as IControlledBrain).Owner;
                int ownerPercent = owner.HealthPercent;
                if (ownerPercent < emergencyThreshold && !spell.TargetHasEffect(owner) && GameMath.IsWithinRadius(Body, owner, spell.Range))
                {
                    Body.TargetObject = owner;
                    break;
                }

                //Heal self
                if (bodyPercent < emergencyThreshold &&
                    !spell.TargetHasEffect(Body))
                {
                    Body.TargetObject = Body;
                    break;
                }

                // Heal group
                player = GetPlayerOwner();
                ICollection <GamePlayer> playerGroup = null;
                if (player.Group != null && (spellTarget == "REALM" || spellTarget == "GROUP"))
                {
                    playerGroup = player.Group.GetPlayersInTheGroup();

                    foreach (GamePlayer p in playerGroup)
                    {
                        if (p.HealthPercent < emergencyThreshold && !spell.TargetHasEffect(p) &&
                            GameMath.IsWithinRadius(Body, p, spell.Range))
                        {
                            Body.TargetObject = p;
                            break;
                        }
                    }
                }

                // Now check for targets which aren't seriously injured

                if (spellTarget == "SELF")
                {
                    // if we have a self heal and health is less than 75% then heal, otherwise return false to try another spell or do nothing
                    if (bodyPercent < GS.ServerProperties.Properties.NPC_HEAL_THRESHOLD &&
                        !spell.TargetHasEffect(Body))
                    {
                        Body.TargetObject = Body;
                    }
                    break;
                }

                //Heal owner
                owner = (this as IControlledBrain).Owner;
                if (ownerPercent < GS.ServerProperties.Properties.NPC_HEAL_THRESHOLD &&
                    !spell.TargetHasEffect(owner) && GameMath.IsWithinRadius(Body, owner, spell.Range))
                {
                    Body.TargetObject = owner;
                    break;
                }

                //Heal self
                if (bodyPercent < GS.ServerProperties.Properties.NPC_HEAL_THRESHOLD &&
                    !spell.TargetHasEffect(Body))
                {
                    Body.TargetObject = Body;
                    break;
                }

                // Heal group
                if (playerGroup != null)
                {
                    foreach (GamePlayer p in playerGroup)
                    {
                        if (p.HealthPercent < GS.ServerProperties.Properties.NPC_HEAL_THRESHOLD &&
                            !spell.TargetHasEffect(p) && GameMath.IsWithinRadius(Body, p, spell.Range))
                        {
                            Body.TargetObject = p;
                            break;
                        }
                    }
                }
                break;
                #endregion

            default:
                log.Warn($"CheckDefensiveSpells() encountered an unknown spell type [{spell.SpellType}], calling base method");
                return(base.CheckDefensiveSpells(spell));
            }

            if (Body.TargetObject != null)
            {
                casted = Body.CastSpell(spell, m_mobSpellLine);

                if (casted && spell.CastTime > 0)
                {
                    if (Body.IsMoving)
                    {
                        Body.StopFollowing();
                    }

                    if (Body.TargetObject != Body)
                    {
                        Body.TurnTo(Body.TargetObject);
                    }
                }
            }

            Body.TargetObject = lastTarget;

            return(casted);
        }
예제 #4
0
        private void TrySpawnGroupAt(BlockPos origin, Vec3d posAsVec, EntityProperties entityType, EntityProperties[] grouptypes)
        {
            BlockPos pos = origin.Copy();

            float xRel = (float)(posAsVec.X % chunksize) / chunksize;
            float zRel = (float)(posAsVec.Z % chunksize) / chunksize;

            int   climate       = GameMath.BiLerpRgbColor(xRel, zRel, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);
            float temp          = TerraGenConfig.GetScaledAdjustedTemperatureFloat((climate >> 16) & 0xff, (int)posAsVec.Y - TerraGenConfig.seaLevel);
            float rain          = ((climate >> 8) & 0xff) / 255f;
            float forestDensity = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, xRel, zRel);
            float shrubDensity  = GameMath.BiLerp(shrubsUpLeft, shrubsUpRight, shrubsBotLeft, shrubsBotRight, xRel, zRel);

            int spawned = 0;

            WorldGenSpawnConditions sc = entityType.Server.SpawnConditions.Worldgen;
            bool hasCompanions         = sc.Companions != null && sc.Companions.Length > 0;

            spawnPositions.Clear();

            int nextGroupSize = 0;
            int tries         = 10;

            while (nextGroupSize <= 0 && tries-- > 0)
            {
                float val = sc.GroupSize.nextFloat();
                nextGroupSize = (int)val + ((val - (int)val) > rnd.NextDouble() ? 1 : 0);
            }


            for (int i = 0; i < nextGroupSize * 4 + 5; i++)
            {
                if (spawned >= nextGroupSize)
                {
                    break;
                }

                EntityProperties typeToSpawn = entityType;

                // First entity 80% chance to spawn the dominant creature, every subsequent only 20% chance for males (or even lower if more than 5 companion types)
                double dominantChance = i == 0 ? 0.8 : Math.Min(0.2, 1f / grouptypes.Length);

                if (grouptypes.Length > 1 && rnd.NextDouble() > dominantChance)
                {
                    typeToSpawn = grouptypes[1 + rnd.Next(grouptypes.Length - 1)];
                }

                posAsVec.Set(pos.X + 0.5, pos.Y + 0.005, pos.Z + 0.5);

                IBlockAccessor blockAccesssor = wgenBlockAccessor.GetChunkAtBlockPos(pos.X, pos.Y, pos.Z) == null ? api.World.BlockAccessor : wgenBlockAccessor;

                IMapChunk mapchunk = blockAccesssor.GetMapChunkAtBlockPos(pos);
                if (mapchunk != null)
                {
                    ushort[] heightMap = mapchunk.WorldGenTerrainHeightMap;

                    pos.Y =
                        sc.TryOnlySurface ?
                        heightMap[((int)pos.Z % chunksize) * chunksize + ((int)pos.X % chunksize)] + 1 :
                        pos.Y
                    ;

                    xRel = (float)(posAsVec.X % chunksize) / chunksize;
                    zRel = (float)(posAsVec.Z % chunksize) / chunksize;

                    climate       = GameMath.BiLerpRgbColor(xRel, zRel, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);
                    temp          = TerraGenConfig.GetScaledAdjustedTemperatureFloat((climate >> 16) & 0xff, (int)posAsVec.Y - TerraGenConfig.seaLevel);
                    rain          = ((climate >> 8) & 0xff) / 255f;
                    forestDensity = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, xRel, zRel) / 255f;
                    shrubDensity  = GameMath.BiLerp(shrubsUpLeft, shrubsUpRight, shrubsBotLeft, shrubsBotRight, xRel, zRel) / 255f;


                    if (CanSpawnAt(blockAccesssor, typeToSpawn, pos, posAsVec, sc, rain, temp, forestDensity, shrubDensity))
                    {
                        spawnPositions.Add(new SpawnOppurtunity()
                        {
                            ForType = typeToSpawn, Pos = posAsVec.Clone()
                        });
                        spawned++;
                    }
                }

                pos.X = origin.X + ((rnd.Next(11) - 5) + (rnd.Next(11) - 5)) / 2;
                pos.Z = origin.Z + ((rnd.Next(11) - 5) + (rnd.Next(11) - 5)) / 2;
            }


            // Only spawn if the group reached the minimum group size
            if (spawnPositions.Count >= nextGroupSize)
            {
                long herdId = api.WorldManager.GetNextHerdId();

                foreach (SpawnOppurtunity so in spawnPositions)
                {
                    Entity ent = CreateEntity(so.ForType, so.Pos);
                    if (ent is EntityAgent)
                    {
                        (ent as EntityAgent).HerdId = herdId;
                    }

                    if (wgenBlockAccessor.GetChunkAtBlockPos(pos.X, pos.Y, pos.Z) == null)
                    {
                        api.World.SpawnEntity(ent);
                    }
                    else
                    {
                        wgenBlockAccessor.AddEntity(ent);
                    }
                }

                //Console.WriteLine("Spawn a group of {0}x{1} at {2}", spawnPositions.Count, entityType.Code, origin);
            }
        }
예제 #5
0
        // Requirements:
        // - ✔ Try to not move a lot vertically
        // - ✔ If territorial: Stay close to the spawn point
        // - ✔ If air habitat: Don't go above maxHeight blocks above surface
        // - ✔ If land habitat: Don't walk into water, prefer surface
        // - ~~If cave habitat: Prefer caves~~
        // - ✔ If water habitat: Don't walk onto land
        // - ✔ Try not to fall from very large heights. Try not to fall from any large heights if entity has FallDamage
        // - ✔ Prefer preferredLightLevel
        // - ✔ If land habitat: Must be above a block the entity can stand on
        // - ✔ if failed searches is high, reduce wander range
        public Vec3d loadNextWanderTarget()
        {
            EnumHabitat habitat       = entity.Properties.Habitat;
            bool        canFallDamage = entity.Properties.FallDamage;
            bool        territorial   = StayCloseToSpawn;
            int         tries         = 9;
            Vec4d       bestTarget    = null;
            Vec4d       curTarget     = new Vec4d();
            BlockPos    tmpPos        = new BlockPos();

            if (FailedConsecutivePathfinds > 10)
            {
                WanderRangeMul = Math.Max(0.1f, WanderRangeMul * 0.9f);
            }
            else
            {
                WanderRangeMul = Math.Min(1, WanderRangeMul * 1.1f);
                if (rand.NextDouble() < 0.05)
                {
                    WanderRangeMul = Math.Min(1, WanderRangeMul * 1.5f);
                }
            }

            float  wRangeMul = WanderRangeMul;
            double dx, dy, dz;

            if (rand.NextDouble() < 0.05)
            {
                wRangeMul *= 3;
            }

            while (tries-- > 0)
            {
                dx = wanderRangeHorizontal.nextFloat() * (rand.Next(2) * 2 - 1) * wRangeMul;
                dy = wanderRangeVertical.nextFloat() * (rand.Next(2) * 2 - 1) * wRangeMul;
                dz = wanderRangeHorizontal.nextFloat() * (rand.Next(2) * 2 - 1) * wRangeMul;

                curTarget.X = entity.ServerPos.X + dx;
                curTarget.Y = entity.ServerPos.Y + dy;
                curTarget.Z = entity.ServerPos.Z + dz;
                curTarget.W = 1;

                if (StayCloseToSpawn)
                {
                    double distToEdge = curTarget.SquareDistanceTo(SpawnPosition) / (MaxDistanceToSpawn * MaxDistanceToSpawn);
                    // Prefer staying close to spawn
                    curTarget.W = 1 - distToEdge;
                }

                Block waterorIceBlock;


                switch (habitat)
                {
                case EnumHabitat.Air:
                    int rainMapY = world.BlockAccessor.GetRainMapHeightAt((int)curTarget.X, (int)curTarget.Z);
                    // Don't fly above max height
                    curTarget.Y = Math.Min(curTarget.Y, rainMapY + maxHeight);

                    // Cannot be in water
                    waterorIceBlock = entity.World.BlockAccessor.GetLiquidBlock((int)curTarget.X, (int)curTarget.Y, (int)curTarget.Z);
                    if (waterorIceBlock.IsLiquid())
                    {
                        curTarget.W = 0;
                    }
                    break;

                case EnumHabitat.Land:
                    curTarget.Y = moveDownToFloor((int)curTarget.X, curTarget.Y, (int)curTarget.Z);
                    // No floor found
                    if (curTarget.Y < 0)
                    {
                        curTarget.W = 0;
                    }
                    else
                    {
                        // Does not like water
                        waterorIceBlock = entity.World.BlockAccessor.GetLiquidBlock((int)curTarget.X, (int)curTarget.Y, (int)curTarget.Z);
                        if (waterorIceBlock.IsLiquid())
                        {
                            curTarget.W /= 2;
                        }

                        // Lets make a straight line plot to see if we would fall off a cliff
                        bool stop     = false;
                        bool willFall = false;

                        float angleHor          = (float)Math.Atan2(dx, dz) + GameMath.PIHALF;
                        Vec3d target1BlockAhead = curTarget.XYZ.Ahead(1, 0, angleHor);
                        Vec3d startAhead        = entity.ServerPos.XYZ.Ahead(1, 0, angleHor); // Otherwise they are forever stuck if they stand over the edge

                        int prevY = (int)startAhead.Y;

                        GameMath.BresenHamPlotLine2d((int)startAhead.X, (int)startAhead.Z, (int)target1BlockAhead.X, (int)target1BlockAhead.Z, (x, z) =>
                        {
                            if (stop)
                            {
                                return;
                            }

                            double nowY = moveDownToFloor(x, prevY, z);

                            // Not more than 4 blocks down
                            if (nowY < 0 || prevY - nowY > 4)
                            {
                                willFall = true;
                                stop     = true;
                            }

                            // Not more than 2 blocks up
                            if (nowY - prevY > 2)
                            {
                                stop = true;
                            }

                            prevY = (int)nowY;
                        });

                        if (willFall)
                        {
                            curTarget.W = 0;
                        }
                    }
                    break;

                case EnumHabitat.Sea:
                    waterorIceBlock = entity.World.BlockAccessor.GetLiquidBlock((int)curTarget.X, (int)curTarget.Y, (int)curTarget.Z);
                    if (!waterorIceBlock.IsLiquid())
                    {
                        curTarget.W = 0;
                    }
                    break;

                case EnumHabitat.Underwater:
                    waterorIceBlock = entity.World.BlockAccessor.GetLiquidBlock((int)curTarget.X, (int)curTarget.Y, (int)curTarget.Z);
                    if (!waterorIceBlock.IsLiquid())
                    {
                        curTarget.W = 0;
                    }
                    else
                    {
                        curTarget.W = 1 / (Math.Abs(dy) + 1);       //prefer not too much vertical change when underwater
                    }
                    //TODO: reject (or de-weight) targets not in direct line of sight (avoiding terrain)

                    break;
                }

                if (curTarget.W > 0)
                {
                    // Try to not hug the wall so much
                    for (int i = 0; i < BlockFacing.HORIZONTALS.Length; i++)
                    {
                        BlockFacing face = BlockFacing.HORIZONTALS[i];
                        if (entity.World.BlockAccessor.IsSideSolid((int)curTarget.X + face.Normali.X, (int)curTarget.Y, (int)curTarget.Z + face.Normali.Z, face.Opposite))
                        {
                            curTarget.W *= 0.5;
                        }
                    }
                }


                if (preferredLightLevel != null && curTarget.W != 0)
                {
                    tmpPos.Set((int)curTarget.X, (int)curTarget.Y, (int)curTarget.Z);
                    int lightdiff = Math.Abs((int)preferredLightLevel - entity.World.BlockAccessor.GetLightLevel(tmpPos, EnumLightLevelType.MaxLight));

                    curTarget.W /= Math.Max(1, lightdiff);
                }

                if (bestTarget == null || curTarget.W > bestTarget.W)
                {
                    bestTarget = new Vec4d(curTarget.X, curTarget.Y, curTarget.Z, curTarget.W);
                    if (curTarget.W >= 1.0)
                    {
                        break;                      //have a good enough target, no need for further tries
                    }
                }
            }


            if (bestTarget.W > 0)
            {
                //double bla = bestTarget.Y;
                //bestTarget.Y += 1;
                //dx = bestTarget.X - entity.ServerPos.X;
                //dz = bestTarget.Z - entity.ServerPos.Z;
                //Vec3d sadf = bestTarget.XYZ.Ahead(1, 0, (float)Math.Atan2(dx, dz) + GameMath.PIHALF);

                /*(entity.Api as ICoreServerAPI).World.HighlightBlocks(world.AllOnlinePlayers[0], 10, new List<BlockPos>() {
                 * new BlockPos((int)bestTarget.X, (int)bestTarget.Y, (int)bestTarget.Z) }, new List<int>() { ColorUtil.ColorFromRgba(0, 255, 0, 80) }, EnumHighlightBlocksMode.Absolute, EnumHighlightShape.Arbitrary);
                 * (entity.Api as ICoreServerAPI).World.HighlightBlocks(world.AllOnlinePlayers[0], 11, new List<BlockPos>() {
                 * new BlockPos((int)sadf.X, (int)sadf.Y, (int)sadf.Z) }, new List<int>() { ColorUtil.ColorFromRgba(0, 255, 255, 180) }, EnumHighlightBlocksMode.Absolute, EnumHighlightShape.Arbitrary);*/

                //bestTarget.Y = bla;


                FailedConsecutivePathfinds = Math.Max(FailedConsecutivePathfinds - 3, 0);
                return(bestTarget.XYZ);
            }

            FailedConsecutivePathfinds++;
            return(null);
        }
        public override void DoRender3DOpaque(float dt, bool isShadowPass)
        {
            IRenderAPI rapi = capi.Render;

            // the value 22 is just trial&error, should probably be something proportial to the
            // 13ms game ticks (which is the physics frame rate)
            lerpedPos.X += (entity.Pos.X - lerpedPos.X) * 22 * dt;
            lerpedPos.Y += (entity.Pos.Y - lerpedPos.Y) * 22 * dt;
            lerpedPos.Z += (entity.Pos.Z - lerpedPos.Z) * 22 * dt;

            ItemRenderInfo renderInfo = rapi.GetItemStackRenderInfo(inslot, EnumItemRenderTarget.Ground);

            if (renderInfo.ModelRef == null)
            {
                return;
            }
            inslot.Itemstack.Collectible.OnBeforeRender(capi, inslot.Itemstack, EnumItemRenderTarget.Ground, ref renderInfo);

            IStandardShaderProgram prog = null;

            LoadModelMatrix(renderInfo, isShadowPass, dt);

            if (isShadowPass)
            {
                rapi.CurrentActiveShader.BindTexture2D("tex2d", renderInfo.TextureId, 0);
                float[] mvpMat = Mat4f.Mul(ModelMat, capi.Render.CurrentModelviewMatrix, ModelMat);
                Mat4f.Mul(mvpMat, capi.Render.CurrentProjectionMatrix, mvpMat);
                capi.Render.CurrentActiveShader.UniformMatrix("mvpMatrix", mvpMat);
                capi.Render.CurrentActiveShader.Uniform("origin", new Vec3f());
            }
            else
            {
                prog = rapi.StandardShader;
                prog.Use();
                prog.Tex2D            = renderInfo.TextureId;
                prog.RgbaTint         = ColorUtil.WhiteArgbVec;
                prog.DontWarpVertices = 0;
                prog.NormalShaded     = 1;
                prog.AlphaTest        = renderInfo.AlphaTest;

                if (entity.Swimming)
                {
                    prog.AddRenderFlags   = (entityitem.Itemstack.Collectible.MaterialDensity > 1000 ? 0 : 1) << 12;
                    prog.WaterWaveCounter = capi.Render.ShaderUniforms.WaterWaveCounter;
                }
                else
                {
                    prog.AddRenderFlags = 0;
                }

                prog.OverlayOpacity = renderInfo.OverlayOpacity;
                if (renderInfo.OverlayTexture != null && renderInfo.OverlayOpacity > 0)
                {
                    prog.Tex2dOverlay2D     = renderInfo.OverlayTexture.TextureId;
                    prog.OverlayTextureSize = new Vec2f(renderInfo.OverlayTexture.Width, renderInfo.OverlayTexture.Height);
                    prog.BaseTextureSize    = new Vec2f(renderInfo.TextureSize.Width, renderInfo.TextureSize.Height);
                    TextureAtlasPosition texPos = rapi.GetTextureAtlasPosition(entityitem.Itemstack);
                    prog.BaseUvOrigin = new Vec2f(texPos.x1, texPos.y1);
                }


                BlockPos pos       = entityitem.Pos.AsBlockPos;
                Vec4f    lightrgbs = capi.World.BlockAccessor.GetLightRGBs(pos.X, pos.Y, pos.Z);
                int      temp      = (int)entityitem.Itemstack.Collectible.GetTemperature(capi.World, entityitem.Itemstack);
                float[]  glowColor = ColorUtil.GetIncandescenceColorAsColor4f(temp);
                int      extraGlow = GameMath.Clamp((temp - 550) / 2, 0, 255);
                glowRgb.R = glowColor[0];
                glowRgb.G = glowColor[1];
                glowRgb.B = glowColor[2];
                glowRgb.A = extraGlow / 255f;

                prog.ExtraGlow     = extraGlow;
                prog.RgbaAmbientIn = rapi.AmbientColor;
                prog.RgbaLightIn   = lightrgbs;
                prog.RgbaGlowIn    = glowRgb;
                prog.RgbaFogIn     = rapi.FogColor;
                prog.FogMinIn      = rapi.FogMin;
                prog.FogDensityIn  = rapi.FogDensity;
                prog.ExtraGodray   = 0;
                prog.NormalShaded  = renderInfo.NormalShaded ? 1 : 0;

                prog.ProjectionMatrix = rapi.CurrentProjectionMatrix;
                prog.ViewMatrix       = rapi.CameraMatrixOriginf;
                prog.ModelMatrix      = ModelMat;


                ItemStack stack = entityitem.Itemstack;
                AdvancedParticleProperties[] ParticleProperties = stack.Block?.ParticleProperties;

                if (stack.Block != null && !capi.IsGamePaused)
                {
                    Mat4f.MulWithVec4(ModelMat, new Vec4f(stack.Block.TopMiddlePos.X, stack.Block.TopMiddlePos.Y - 0.4f, stack.Block.TopMiddlePos.Z - 0.5f, 0), particleOutTransform); // No idea why the -0.5f and -0.4f

                    accum += dt;
                    if (ParticleProperties != null && ParticleProperties.Length > 0 && accum > 0.025f)
                    {
                        accum = accum % 0.025f;

                        for (int i = 0; i < ParticleProperties.Length; i++)
                        {
                            AdvancedParticleProperties bps = ParticleProperties[i];
                            bps.basePos.X = particleOutTransform.X + entity.Pos.X;
                            bps.basePos.Y = particleOutTransform.Y + entity.Pos.Y;
                            bps.basePos.Z = particleOutTransform.Z + entity.Pos.Z;

                            entityitem.World.SpawnParticles(bps);
                        }
                    }
                }
            }


            if (!renderInfo.CullFaces)
            {
                rapi.GlDisableCullFace();
            }

            rapi.RenderMesh(renderInfo.ModelRef);

            if (!renderInfo.CullFaces)
            {
                rapi.GlEnableCullFace();
            }


            if (!isShadowPass)
            {
                prog.Stop();
            }
        }
        void genShrubs(int chunkX, int chunkZ)
        {
            int triesShrubs = (int)treeSupplier.treeGenProps.shrubsPerChunk.nextFloat();

            int   dx, dz, x, z;
            Block block;

            while (triesShrubs > 0)
            {
                triesShrubs--;

                dx = rnd.NextInt(chunksize);
                dz = rnd.NextInt(chunksize);
                x  = dx + chunkX * chunksize;
                z  = dz + chunkZ * chunksize;

                int y = heightmap[dz * chunksize + dx];
                if (y <= 0 || y >= worldheight - 15)
                {
                    continue;
                }

                tmpPos.Set(x, y, z);
                block = blockAccessor.GetBlock(tmpPos);
                if (block.Fertility == 0)
                {
                    continue;
                }

                // Place according to forest value
                int   climate     = GameMath.BiLerpRgbColor((float)dx / chunksize, (float)dz / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);
                float shrubChance = GameMath.BiLerp(shrubUpLeft, shrubUpRight, shrubBotLeft, shrubBotRight, (float)dx / chunksize, (float)dz / chunksize);
                shrubChance = GameMath.Clamp(shrubChance + 255 * forestMod, 0, 255);

                if (rnd.NextDouble() > (shrubChance / 255f) * (shrubChance / 255f))
                {
                    continue;
                }
                TreeGenForClimate treegenParams = treeSupplier.GetRandomShrubGenForClimate(climate, (int)shrubChance, y);

                if (treegenParams != null)
                {
                    bool canGen = true;
                    for (int i = 0; i < structuresIntersectingChunk.Count; i++)
                    {
                        if (structuresIntersectingChunk[i].Contains(tmpPos))
                        {
                            canGen = false; break;
                        }
                    }
                    if (!canGen)
                    {
                        continue;
                    }

                    if (blockAccessor.GetBlock(tmpPos.X, tmpPos.Y, tmpPos.Z).Replaceable >= 6000)
                    {
                        tmpPos.Y--;
                    }

                    treegenParams.treeGen.GrowTree(
                        blockAccessor,
                        tmpPos,
                        true,
                        treegenParams.size,
                        treegenParams.vinesGrowthChance
                        );
                }
            }
        }
예제 #8
0
        public override void Initialize(EntityProperties properties, JsonObject attributes)
        {
            base.Initialize(properties, attributes);

            skintree = entity.WatchedAttributes.GetTreeAttribute("skinConfig");
            if (skintree == null)
            {
                entity.WatchedAttributes["skinConfig"] = skintree = new TreeAttribute();
            }

            entity.WatchedAttributes.RegisterModifiedListener("skinConfig", onSkinConfigChanged);
            entity.WatchedAttributes.RegisterModifiedListener("voicetype", onVoiceConfigChanged);
            entity.WatchedAttributes.RegisterModifiedListener("voicepitch", onVoiceConfigChanged);

            AvailableSkinParts = properties.Attributes["skinnableParts"].AsObject <SkinnablePart[]>();
            foreach (var val in AvailableSkinParts)
            {
                string partCode = val.Code;
                val.VariantsByCode = new Dictionary <string, SkinnablePartVariant>();

                AvailableSkinPartsByCode[val.Code] = val;

                if (val.Type == EnumSkinnableType.Texture && entity.Api.Side == EnumAppSide.Client)
                {
                    ICoreClientAPI capi = entity.Api as ICoreClientAPI;

                    LoadedTexture texture = new LoadedTexture(capi);
                    foreach (var variant in val.Variants)
                    {
                        AssetLocation textureLoc;

                        if (val.TextureTemplate != null)
                        {
                            textureLoc      = val.TextureTemplate.Clone();
                            textureLoc.Path = textureLoc.Path.Replace("{code}", variant.Code);
                        }
                        else
                        {
                            textureLoc = variant.Texture;
                        }

                        IAsset asset = capi.Assets.TryGet(textureLoc.Clone().WithPathAppendixOnce(".png").WithPathPrefixOnce("textures/"), true);

                        int   r = 0, g = 0, b = 0;
                        float c = 0;

                        BitmapRef bmp = asset.ToBitmap(capi);
                        for (int i = 0; i < 8; i++)
                        {
                            Vec2d vec  = GameMath.R2Sequence2D(i);
                            Color col2 = bmp.GetPixelRel((float)vec.X, (float)vec.Y);
                            if (col2.A > 0.5)
                            {
                                r += col2.R;
                                g += col2.G;
                                b += col2.B;
                                c++;
                            }
                        }

                        bmp.Dispose();

                        c             = Math.Max(1, c);
                        variant.Color = ColorUtil.ColorFromRgba((int)(r / c), (int)(g / c), (int)(b / c), 255);
                        val.VariantsByCode[variant.Code] = variant;
                    }
                }
                else
                {
                    foreach (var variant in val.Variants)
                    {
                        val.VariantsByCode[variant.Code] = variant;
                    }
                }
            }

            if (entity.Api.Side == EnumAppSide.Server && AppliedSkinParts.Count == 0)
            {
                foreach (var val in AvailableSkinParts)
                {
                    string partCode    = val.Code;
                    string variantCode = val.Variants[entity.World.Rand.Next(val.Variants.Length)].Code;
                    selectSkinPart(partCode, variantCode, false);
                }
            }

            onVoiceConfigChanged();
        }
예제 #9
0
        /// <summary>
        /// Do we continue playing this track?
        /// </summary>
        /// <param name="dt">Delta time or Change in time</param>
        /// <param name="props">The properties of the current track.</param>
        /// <returns>Are we still playing or do we stop?</returns>
        public bool ContinuePlay(float dt, TrackedPlayerProperties props)
        {
            if (props.sunSlight > 3 || !ShouldPlayCaveMusic)
            {
                FadeOut(3);
                return(false);
            }

            if (activeUntilMs > 0 && capi.World.ElapsedMilliseconds >= activeUntilMs)
            {
                // Ok, time to stop. We play the current tracks until the end and stop
                bool active = IsActive;
                if (!active)
                {
                    activeUntilMs = 0;
                    foreach (MusicTrackPart part in Parts)
                    {
                        part.Sound?.Dispose();
                    }
                }
                return(active);
            }

            int quantityActive = 0;

            for (int i = 0; i < Parts.Length; i++)
            {
                quantityActive += (Parts[i].IsPlaying || Parts[i].Loading) ? 1: 0;
            }

            int beforePlaying = quantityActive;

            GameMath.Shuffle(rand, PartsShuffled);

            for (int i = 0; i < PartsShuffled.Length; i++)
            {
                MusicTrackPart part = PartsShuffled[i];
                if (part.Files.Length == 0)
                {
                    continue;
                }

                bool isPlaying  = part.IsPlaying;
                bool shouldPlay = part.Applicable(capi.World, props);

                // Part has recently ended
                if (!isPlaying && part.Sound != null)
                {
                    part.Sound.Dispose();
                    part.Sound = null;
                    continue;
                }

                // Part should be stopped
                if (isPlaying && !shouldPlay)
                {
                    if (!part.Sound.IsFadingOut)
                    {
                        part.Sound.FadeOut(3, (sound) => { part.Sound.Dispose(); part.Sound = null; });
                    }
                    continue;
                }


                bool shouldStart =
                    !isPlaying &&
                    shouldPlay &&
                    !part.Loading &&
                    quantityActive < maxSimultaenousTracks &&
                    (quantityActive == 0 || rand.NextDouble() < simultaenousTrackChance)
                ;

                if (shouldStart)
                {
                    AssetLocation location = part.Files[rand.Next(part.Files.Length)];
                    part.NowPlayingFile = location;
                    part.Loading        = true;
                    musicEngine.LoadTrack(location, (sound) => {
                        if (sound != null)
                        {
                            sound.Start();
                            part.Sound = sound;
                        }
                        part.Loading = false;
                    });

                    part.StartedMs = capi.World.ElapsedMilliseconds;
                    quantityActive++;
                }
            }

            return(true);
        }
예제 #10
0
        private void OnScanComplete()
        {
            quantityNearbyFlowers = scanQuantityNearbyFlowers;
            quantityNearbyHives   = scanQuantityNearbyHives;
            emptySkeps            = new List <BlockPos>(scanEmptySkeps);

            if (emptySkeps.Count == 0)
            {
                skepToPop = null;
            }

            hivePopSize = (EnumHivePopSize)GameMath.Clamp(quantityNearbyFlowers - 3 * quantityNearbyHives, 0, 2);

            MarkDirty();


            if (3 * quantityNearbyHives + 3 > quantityNearbyFlowers)
            {
                skepToPop = null;
                MarkDirty(false);
                return;
            }

            if (skepToPop != null && api.World.Calendar.TotalHours > beginPopStartTotalHours + popHiveAfterHours)
            {
                TryPopCurrentSkep();
                cooldownUntilTotalHours = api.World.Calendar.TotalHours + 4 * 24;
                MarkDirty(false);
                return;
            }

            // Default Spread speed: Once every 4 in game days * factor
            // Don't spread at all if 3 * livinghives + 3 > flowers

            // factor = Clamped(livinghives / Math.Sqrt(flowers - 3 * livinghives - 3), 1, 1000)
            // After spreading: 4 extra days cooldown
            if (skepToPop != null)
            {
                float newPopHours = 4 * 24 * GameMath.Clamp(quantityNearbyHives / GameMath.Sqrt(quantityNearbyFlowers - 3 * quantityNearbyHives - 3), 1, 1000);
                this.popHiveAfterHours = (float)(0.75 * popHiveAfterHours + 0.25 * newPopHours);

                if (!emptySkeps.Contains(skepToPop))
                {
                    skepToPop = null;
                    MarkDirty(false);
                    return;
                }
            }
            else
            {
                popHiveAfterHours = 4 * 24 * GameMath.Clamp(quantityNearbyHives / GameMath.Sqrt(quantityNearbyFlowers - 3 * quantityNearbyHives - 3), 1, 1000);

                beginPopStartTotalHours = api.World.Calendar.TotalHours;

                float    mindistance = 999;
                BlockPos closestPos  = new BlockPos();
                foreach (BlockPos pos in emptySkeps)
                {
                    float dist = pos.DistanceTo(this.pos);
                    if (dist < mindistance)
                    {
                        mindistance = dist;
                        closestPos  = pos;
                    }
                }

                skepToPop = closestPos;
            }
        }
        public override void OnGameTick(float deltaTime)
        {
            if (!enabled)
            {
                return;
            }

            if (requireInitSounds)
            {
                initSoundsAndEffects();
                requireInitSounds = false;
            }

            if (entity.World.Side == EnumAppSide.Client)
            {
                if (!(entity.World.Api as ICoreClientAPI).PlayerReadyFired)
                {
                    return;
                }
            }
            else
            {
                IServerPlayer player = entity.World.PlayerByUid(((EntityPlayer)entity).PlayerUID) as IServerPlayer;
                if (player != null && player.ConnectionState != EnumClientState.Playing)
                {
                    return;
                }
            }


            deltaTime = GameMath.Min(0.5f, deltaTime);

            float changeSpeed = deltaTime / 3;


            double hereStability = stabilityOffset + tempStabilitySystem.GetTemporalStability(entity.SidedPos.X, entity.SidedPos.Y, entity.SidedPos.Z);

            entity.Attributes.SetDouble("tempStabChangeVelocity", TempStabChangeVelocity);

            double gain = TempStabChangeVelocity > 0 ? (TempStabChangeVelocity / 200.0) : (TempStabChangeVelocity / 800.0);

            OwnStability = GameMath.Clamp(OwnStability + gain, 0f, 1);
            double ownStability = OwnStability;

            TempStabChangeVelocity = (hereTempStabChangeVelocity - TempStabChangeVelocity) * deltaTime;

            float glitchEffectExtraStrength = tempStabilitySystem.GetGlitchEffectExtraStrength();

            double targetGlitchEffectStrength = Math.Max(0, Math.Max(0, (0.2f - ownStability) * 1 / 0.2f) + glitchEffectExtraStrength);

            glitchEffectStrength += (targetGlitchEffectStrength - glitchEffectStrength) * changeSpeed;
            glitchEffectStrength  = GameMath.Clamp(glitchEffectStrength, 0, 1.1f);

            double targetFogEffectStrength = Math.Max(0, Math.Max(0, (0.3f - ownStability) * 1 / 0.3f) + glitchEffectExtraStrength);

            fogEffectStrength += (targetFogEffectStrength - fogEffectStrength) * changeSpeed;
            fogEffectStrength  = GameMath.Clamp(fogEffectStrength, 0, 1.1f);

            double targetRustPrecipStrength = Math.Max(0, Math.Max(0, (0.3f - ownStability) * 1 / 0.3f) + glitchEffectExtraStrength);

            rustPrecipColorStrength += (targetRustPrecipStrength - rustPrecipColorStrength) * changeSpeed;
            rustPrecipColorStrength  = GameMath.Clamp(rustPrecipColorStrength, 0, 1f);

            if (precipParticleSys != null)
            {
                precipParticleSys.rainParticleColor = ColorUtil.ColorOverlay(WeatherSimulationParticles.waterColor, WeatherSimulationParticles.lowStabColor, (float)rustPrecipColorStrength);
            }


            hereTempStabChangeVelocity = hereStability - 1;

            oneSecAccum += deltaTime;
            if (oneSecAccum > 1)
            {
                oneSecAccum = 0;
                updateSoundsAndEffects(hereStability, Math.Max(0, ownStability - 1.5f * glitchEffectExtraStrength));
            }
            threeSecAccum += deltaTime;
            if (threeSecAccum > 4)
            {
                threeSecAccum = 0;
                if (entity.World.Side == EnumAppSide.Server && ownStability < 0.13)
                {
                    entity.ReceiveDamage(new DamageSource()
                    {
                        DamageTier = 0,
                        Source     = EnumDamageSource.Machine,
                        Type       = EnumDamageType.Poison
                    }, (float)(0.15 - ownStability));
                }
            }

            if (isSelf)
            {
                capi.Render.ShaderUniforms.GlitchStrength = 0;
            }

            if (isSelf && (fogEffectStrength > 0.05 || glitchEffectStrength > 0.05))
            {
                capi.Render.ShaderUniforms.GlitchStrength    = (float)glitchEffectStrength;
                capi.Render.ShaderUniforms.GlobalWorldWarp   = (float)(capi.World.Rand.NextDouble() < 0.015 ? (Math.Max(0, glitchEffectStrength - 0.05f) * capi.World.Rand.NextDouble() * capi.World.Rand.NextDouble()) : 0);
                capi.Render.ShaderUniforms.WindWaveCounter  += (float)(capi.World.Rand.NextDouble() < 0.015 ? 9 * capi.World.Rand.NextDouble() : 0);
                capi.Render.ShaderUniforms.WaterWaveCounter += (float)(capi.World.Rand.NextDouble() < 0.015 ? 9 * capi.World.Rand.NextDouble() : 0);

                if (capi.World.Rand.NextDouble() < 0.002)
                {
                    capi.Input.MouseYaw   += (float)capi.World.Rand.NextDouble() * 0.125f - 0.125f / 2;
                    capi.Input.MousePitch += (float)capi.World.Rand.NextDouble() * 0.125f - 0.125f / 2;
                }

                tmpPos.Set((int)entity.Pos.X, (int)entity.Pos.Y, (int)entity.Pos.Z);
                float sunb = capi.World.BlockAccessor.GetLightLevel(tmpPos, EnumLightLevelType.OnlySunLight) / 22f;

                float strength = Math.Min(1, (float)(glitchEffectStrength));

                double fognoise = fogEffectStrength * Math.Abs(fogNoise.Noise(0, capi.InWorldEllapsedMilliseconds / 1000f)) / 60f;

                rainfogAmbient.FogDensity.Value = 0.05f + (float)fognoise;

                rainfogAmbient.AmbientColor.Weight = strength;
                rainfogAmbient.FogColor.Weight     = strength;
                rainfogAmbient.FogDensity.Weight   = (float)Math.Pow(strength, 2);

                rainfogAmbient.FogColor.Value[0] = sunb * 116 / 255f;
                rainfogAmbient.FogColor.Value[1] = sunb * 77 / 255f;
                rainfogAmbient.FogColor.Value[2] = sunb * 49 / 255f;

                rainfogAmbient.AmbientColor.Value[0] = 0.5f * 116 / 255f;
                rainfogAmbient.AmbientColor.Value[1] = 0.5f * 77 / 255f;
                rainfogAmbient.AmbientColor.Value[2] = 0.5f * 49 / 255f;

                rustParticles.MinVelocity.Set(-0.1f, 0.1f, 0.1f);
                rustParticles.AddVelocity.Set(0.2f, 0.2f, 0.2f);
                rustParticles.Color   = ColorUtil.ToRgba((int)(strength * 150), 50, 25, 15);
                rustParticles.MaxSize = 0.25f;
                rustParticles.RandomVelocityChange = false;
                rustParticles.MinVelocity.Set(0, 0, 0);
                rustParticles.AddVelocity.Set(0, 1, 0);


                Vec3d     position = new Vec3d();
                EntityPos plrPos   = capi.World.Player.Entity.Pos;

                float tries = 20 * strength;

                while (tries-- > 0)
                {
                    float offX = (float)capi.World.Rand.NextDouble() * 24 - 12;
                    float offY = (float)capi.World.Rand.NextDouble() * 24 - 12;
                    float offZ = (float)capi.World.Rand.NextDouble() * 24 - 12;

                    position.Set(plrPos.X + offX, plrPos.Y + offY, plrPos.Z + offZ);
                    BlockPos pos = new BlockPos((int)position.X, (int)position.Y, (int)position.Z);

                    if (!capi.World.BlockAccessor.IsValidPos(pos))
                    {
                        continue;
                    }

                    rustParticles.MinPos = position;
                    capi.World.SpawnParticles(rustParticles);
                }
            }
        }
예제 #12
0
        public void tick()
        {
            while (enable)
            {
                bool intersect_x_r = false, intersect_x_l = false, intersect_y_t = false, intersect_y_b = false;

                for (int i = 0; i < list.Count - 1; i++)
                {
                    Car car1 = list[i];

                    PointF[] colliderBuffer = GameMath.copyPointArray(car1.collider);
                    for (int x = 0; x < colliderBuffer.Length; x++)
                    {
                        colliderBuffer[x].X = colliderBuffer[x].X * car1.scale.x;
                        colliderBuffer[x].Y = colliderBuffer[x].Y * car1.scale.y;
                    }

                    for (int j = i + 1; j < list.Count; j++)
                    {
                        Car      car2            = list[j];
                        PointF[] colliderBuffer2 = GameMath.rotate(car2.collider, car2.rotate - car1.rotate);
                        Vector2f r = GameMath.rotate(car2.position - car1.position, -car1.rotate);
                        for (int x = 0; x < colliderBuffer2.Length; x++)
                        {
                            colliderBuffer2[x].X = (colliderBuffer2[x].X) * car2.scale.x + r.x;
                            colliderBuffer2[x].Y = (colliderBuffer2[x].Y) * car2.scale.y + r.y;
                        }

                        intersect_x_r = false; intersect_x_l = false; intersect_y_t = false; intersect_y_b = false;

                        for (int c1 = 0; c1 < colliderBuffer.Length; c1++)
                        {
                            for (int c2 = 0; c2 < colliderBuffer2.Length; c2++)
                            {
                                if (colliderBuffer[c1].X >= colliderBuffer2[c2].X)
                                {
                                    intersect_x_l = true;
                                }
                                else if (colliderBuffer[c1].X <= colliderBuffer2[c2].X)
                                {
                                    intersect_x_r = true;
                                }

                                if (colliderBuffer[c1].Y >= colliderBuffer2[c2].Y)
                                {
                                    intersect_y_b = true;
                                }
                                else if (colliderBuffer[c1].Y <= colliderBuffer2[c2].Y)
                                {
                                    intersect_y_t = true;
                                }

                                if (intersect_x_r && intersect_x_l && intersect_y_b && intersect_y_t)
                                {
                                    c1 = colliderBuffer.Length;
                                    break;
                                }
                            }
                        }

                        if (intersect_x_r && intersect_x_l && intersect_y_b && intersect_y_t)
                        {
                            if (car1.acceleration.x > 0)
                            {
                                if (car1.position.x > car2.position.x)
                                {
                                    car2.collide(CAR_COLLIDE);
                                }
                                else
                                {
                                    car1.collide(CAR_COLLIDE);
                                }
                            }
                            else if (car1.acceleration.x < 0)
                            {
                                if (car1.position.x < car2.position.x)
                                {
                                    car2.collide(CAR_COLLIDE);
                                }
                                else
                                {
                                    car1.collide(CAR_COLLIDE);
                                }
                            }
                            else if (car1.acceleration.y > 0)
                            {
                                if (car1.position.y > car2.position.y)
                                {
                                    car2.collide(CAR_COLLIDE);
                                }
                                else
                                {
                                    car1.collide(CAR_COLLIDE);
                                }
                                //
                            }
                            else if (car1.acceleration.y < 0)
                            {
                                if (car1.position.y < car2.position.y)
                                {
                                    car2.collide(CAR_COLLIDE);
                                }
                                else
                                {
                                    car1.collide(CAR_COLLIDE);
                                }
                            }
                        }
                    }
                }

                for (int i = 0; i < list.Count; i++)
                {
                    Car      car            = list[i];
                    PointF[] colliderBuffer = GameMath.rotate(car.collider, car.rotate);
                    for (int x = 0; x < colliderBuffer.Length; x++)
                    {
                        colliderBuffer[x].X = colliderBuffer[x].X * car.scale.x + car.position.x;
                        colliderBuffer[x].Y = colliderBuffer[x].Y * car.scale.y + car.position.y;
                    }

                    intersect_x_r = false; intersect_x_l = false; intersect_y_t = false; intersect_y_b = false;

                    for (int c1 = 0; c1 < colliderBuffer.Length; c1++)
                    {
                        for (int c2 = 0; c2 < trafficLightZone.Length; c2++)
                        {
                            if (colliderBuffer[c1].X >= trafficLightZone[c2].X)
                            {
                                intersect_x_l = true;
                            }
                            else if (colliderBuffer[c1].X <= trafficLightZone[c2].X)
                            {
                                intersect_x_r = true;
                            }

                            if (colliderBuffer[c1].Y >= trafficLightZone[c2].Y)
                            {
                                intersect_y_b = true;
                            }
                            else if (colliderBuffer[c1].Y <= trafficLightZone[c2].Y)
                            {
                                intersect_y_t = true;
                            }

                            if (intersect_x_r && intersect_x_l && intersect_y_b && intersect_y_t)
                            {
                                c1 = colliderBuffer.Length;
                                break;
                            }
                        }
                    }

                    if (intersect_x_r && intersect_x_l && intersect_y_b && intersect_y_t)
                    {
                        if (car.maxSpeed.x != 0 && horizont == false && !car.collideTrafficZone)
                        {
                            car.collide(TRAFFIC_LIGHT_COLLIDE);
                        }
                        else if (car.maxSpeed.y != 0 && vertical == false && !car.collideTrafficZone)
                        {
                            car.collide(TRAFFIC_LIGHT_COLLIDE);
                        }
                        else
                        {
                            car.collideTrafficZone = true;
                        }
                    }
                    else if (car.collideTrafficZone)
                    {
                        car.collideTrafficZone = false;
                    }
                }
            }
        }
예제 #13
0
        protected BlockSchematicStructure GetGeneratableStructure(VillageSchematic schem, IBlockAccessor blockAccessor, IWorldAccessor worldForCollectibleResolve, BlockPos pos)
        {
            int chunksize = blockAccessor.ChunkSize;
            int climate   = GameMath.BiLerpRgbColor((float)(pos.X % chunksize) / chunksize, (float)(pos.Z % chunksize) / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);


            int num = rand.NextInt(schem.Structures.Length);
            BlockSchematicStructure schematic = schem.Structures[num];

            int widthHalf  = (int)Math.Ceiling(schematic.SizeX / 2f);
            int lengthHalf = (int)Math.Ceiling(schematic.SizeZ / 2f);

            pos.Y += schem.OffsetY;

            // Probe all 4 corners + center if they are on the same height

            int centerY = blockAccessor.GetTerrainMapheightAt(pos);

            tmpPos.Set(pos.X - widthHalf, 0, pos.Z - lengthHalf);
            int topLeftY = blockAccessor.GetTerrainMapheightAt(tmpPos);

            tmpPos.Set(pos.X + widthHalf, 0, pos.Z - lengthHalf);
            int topRightY = blockAccessor.GetTerrainMapheightAt(tmpPos);

            tmpPos.Set(pos.X - widthHalf, 0, pos.Z + lengthHalf);
            int botLeftY = blockAccessor.GetTerrainMapheightAt(tmpPos);

            tmpPos.Set(pos.X + widthHalf, 0, pos.Z + lengthHalf);
            int botRightY = blockAccessor.GetTerrainMapheightAt(tmpPos);


            int diff = GameMath.Max(centerY, topLeftY, topRightY, botLeftY, botRightY) - GameMath.Min(centerY, topLeftY, topRightY, botLeftY, botRightY);

            if (diff > 2)
            {
                return(null);
            }

            pos.Y += centerY - pos.Y + 1 + schem.OffsetY;
            if (pos.Y <= 0)
            {
                return(null);
            }

            // Ensure not floating on water
            tmpPos.Set(pos.X - widthHalf, pos.Y - 1, pos.Z - lengthHalf);
            if (blockAccessor.GetBlock(tmpPos).IsLiquid())
            {
                return(null);
            }

            tmpPos.Set(pos.X + widthHalf, pos.Y - 1, pos.Z - lengthHalf);
            if (blockAccessor.GetBlock(tmpPos).IsLiquid())
            {
                return(null);
            }

            tmpPos.Set(pos.X - widthHalf, pos.Y - 1, pos.Z + lengthHalf);
            if (blockAccessor.GetBlock(tmpPos).IsLiquid())
            {
                return(null);
            }

            tmpPos.Set(pos.X + widthHalf, pos.Y - 1, pos.Z + lengthHalf);
            if (blockAccessor.GetBlock(tmpPos).IsLiquid())
            {
                return(null);
            }

            // Ensure not submerged in water
            tmpPos.Set(pos.X - widthHalf, pos.Y, pos.Z - lengthHalf);
            if (blockAccessor.GetBlock(tmpPos).IsLiquid())
            {
                return(null);
            }

            tmpPos.Set(pos.X + widthHalf, pos.Y, pos.Z - lengthHalf);
            if (blockAccessor.GetBlock(tmpPos).IsLiquid())
            {
                return(null);
            }

            tmpPos.Set(pos.X - widthHalf, pos.Y, pos.Z + lengthHalf);
            if (blockAccessor.GetBlock(tmpPos).IsLiquid())
            {
                return(null);
            }

            tmpPos.Set(pos.X + widthHalf, pos.Y, pos.Z + lengthHalf);
            if (blockAccessor.GetBlock(tmpPos).IsLiquid())
            {
                return(null);
            }



            tmpPos.Set(pos.X - widthHalf, pos.Y + 1, pos.Z - lengthHalf);
            if (blockAccessor.GetBlock(tmpPos).IsLiquid())
            {
                return(null);
            }

            tmpPos.Set(pos.X + widthHalf, pos.Y + 1, pos.Z - lengthHalf);
            if (blockAccessor.GetBlock(tmpPos).IsLiquid())
            {
                return(null);
            }

            tmpPos.Set(pos.X - widthHalf, pos.Y + 1, pos.Z + lengthHalf);
            if (blockAccessor.GetBlock(tmpPos).IsLiquid())
            {
                return(null);
            }

            tmpPos.Set(pos.X + widthHalf, pos.Y + 1, pos.Z + lengthHalf);
            if (blockAccessor.GetBlock(tmpPos).IsLiquid())
            {
                return(null);
            }

            if (!TestUndergroundCheckPositions(blockAccessor, pos, schematic.UndergroundCheckPositions))
            {
                return(null);
            }

            if (isStructureAt(pos, worldForCollectibleResolve))
            {
                return(null);
            }

            return(schematic);
        }
예제 #14
0
        public void OnRenderFrame(float deltaTime, EnumRenderStage stage)
        {
            if (!renderAurora)
            {
                return;
            }

            if (capi.Render.FrameWidth == 0)
            {
                return;
            }



            quarterSecAccum += deltaTime;
            if (quarterSecAccum > 0.25f)
            {
                plrPos.X = (int)capi.World.Player.Entity.CameraPos.X;
                plrPos.Y = capi.World.SeaLevel;
                plrPos.Z = (int)capi.World.Player.Entity.CameraPos.Z;

                clientClimateCond = capi.World.BlockAccessor.GetClimateAt(plrPos);
                quarterSecAccum   = 0;
            }

            if (clientClimateCond == null)
            {
                return;
            }

            float tempfac = GameMath.Clamp((Math.Max(0, -clientClimateCond.Temperature) - 5) / 15f, 0, 1);

            col.W = GameMath.Clamp(1 - 1.5f * capi.World.Calendar.DayLightStrength, 0, 1) * tempfac;

            if (col.W <= 0)
            {
                return;
            }

            prog.Use();
            prog.Uniform("color", col);
            prog.Uniform("rgbaFogIn", capi.Ambient.BlendedFogColor);
            prog.Uniform("fogMinIn", capi.Ambient.BlendedFogMin);
            prog.Uniform("fogDensityIn", capi.Ambient.BlendedFogDensity);
            prog.UniformMatrix("projectionMatrix", capi.Render.CurrentProjectionMatrix);

            prog.Uniform("flatFogDensity", capi.Ambient.BlendedFlatFogDensity);
            prog.Uniform("flatFogStart", capi.Ambient.BlendedFlatFogYPosForShader);

            float speedmul = capi.World.Calendar.SpeedOfTime / 60f;

            prog.Uniform("auroraCounter", (float)(capi.InWorldEllapsedMilliseconds / 4000.0 * speedmul) % 579f);


            mvMat
            .Set(capi.Render.MvMatrix.Top)
            .FollowPlayer()
            .Translate(
                0, //    capi.World.BlockAccessor.MapSizeX/2,
                (1.1f * capi.World.BlockAccessor.MapSizeY + 0.5 - capi.World.Player.Entity.CameraPos.Y),
                0  //   capi.World.BlockAccessor.MapSizeZ/2
                )
            ;

            prog.UniformMatrix("modelViewMatrix", mvMat.Values);
            capi.Render.RenderMesh(quadTilesRef);

            prog.Stop();
        }
예제 #15
0
 public string GetKey(string holdingstack)
 {
     return(GameMath.Md5Hash(holdingstack + block.Code.ToString() + block.Id));
 }
예제 #16
0
        public static void Solve(List <Contact2D> contacts, int iterations, float dt)
        {
            float muD = 0.7f;

            bool  SpecSequential = true;
            float dtInv          = 1f / dt;

            for (int j = 0; j < iterations; j++)
            {
                for (int i = 0; i < contacts.Count; i++)
                {
                    Contact2D con = contacts[i];
                    Vector2   n   = con.Normal;

                    float relNv = Vector2.Dot(con.B.Vel - con.A.Vel, n);

                    //Do either speculative or speculative sequential
                    if (!SpecSequential)
                    {
                        float remove = relNv + con.Dist * dtInv;
                        //double remove = relNv + con.m_dist / Constants.kTimeStep(1/30);
                        if (remove < 0)
                        {
                            Vector2 aVel   = con.A.GetVelocityOfWorldPoint(con.pointA);
                            Vector2 bVel   = con.B.GetVelocityOfWorldPoint(con.pointB);
                            Vector2 relVel = bVel - aVel;

                            float mag = remove * con.InvDenom;

                            Vector2 imp = con.Normal * mag;

                            Vector2 t = relVel - (Vector2.Dot(relVel, n)) * n;
                            if (!(t.Length() <= float.Epsilon))
                            {
                                t = Vector2.Normalize(t);
                            }

                            Vector2 frictionJ = -(muD * Math.Abs(mag)) * t;

                            con.ApplyImpulses(imp - frictionJ);
                        }
                    }
                    else
                    {
                        Vector2 aVel   = con.A.GetVelocityOfWorldPoint(con.pointA);
                        Vector2 bVel   = con.B.GetVelocityOfWorldPoint(con.pointB);
                        Vector2 relVel = bVel - aVel;

                        float remove = relNv + con.Dist * dtInv;

                        float mag        = remove * con.InvDenom;
                        float newImpulse = Math.Min(mag + con.ImpulseN, 0);
                        float change     = newImpulse - con.ImpulseN;

                        Vector2 imp = con.Normal * change;

                        // apply impulse
                        con.ApplyImpulses(imp);
                        con.ImpulseN = newImpulse;

                        float absMag = Math.Abs(con.ImpulseN) * muD;

                        // friction
                        mag        = Vector2.Dot(relVel, GameMath.Perp2D(n)) * con.InvDenom;
                        newImpulse = MathHelper.Clamp(mag + con.ImpulseT, -absMag, absMag);
                        change     = newImpulse - con.ImpulseT;
                        imp        = GameMath.Perp2D(n) * change;

                        // apply impulse
                        con.ApplyImpulses(imp);
                        con.ImpulseT = newImpulse;
                    }
                }
            }
        }
        private void LoadModelMatrix(ItemRenderInfo renderInfo, bool isShadowPass, float dt)
        {
            IRenderAPI   rapi         = capi.Render;
            EntityPlayer entityPlayer = capi.World.Player.Entity;

            Mat4f.Identity(ModelMat);
            Mat4f.Translate(ModelMat, ModelMat,
                            (float)(lerpedPos.X - entityPlayer.CameraPos.X),
                            (float)(lerpedPos.Y - entityPlayer.CameraPos.Y),
                            (float)(lerpedPos.Z - entityPlayer.CameraPos.Z)
                            );

            float sizeX = 0.2f * renderInfo.Transform.ScaleXYZ.X;
            float sizeY = 0.2f * renderInfo.Transform.ScaleXYZ.Y;
            float sizeZ = 0.2f * renderInfo.Transform.ScaleXYZ.Z;

            float dx = 0, dz = 0;


            if (!isShadowPass)
            {
                long ellapseMs = capi.World.ElapsedMilliseconds;
                bool freefall  = !(entity.Collided || entity.Swimming || capi.IsGamePaused);
                if (!freefall)
                {
                    touchGroundMS = ellapseMs;
                }

                if (entity.Collided)
                {
                    xangle *= 0.55f;
                    yangle *= 0.55f;
                    zangle *= 0.55f;
                }
                else
                {
                    float easeIn    = Math.Min(1, (ellapseMs - touchGroundMS) / 200);
                    float angleGain = freefall ? 1000 * dt / 7 * easeIn : 0;

                    yangle += angleGain;
                    xangle += angleGain;
                    zangle += angleGain;
                }

                if (entity.Swimming)
                {
                    float diff = 1;

                    if (entityitem.Itemstack.Collectible.MaterialDensity > 1000)
                    {
                        dx   = GameMath.Sin((float)(ellapseMs / 1000.0)) / 50;
                        dz   = -GameMath.Sin((float)(ellapseMs / 3000.0)) / 50;
                        diff = 0.1f;
                    }

                    xangle = GameMath.Sin((float)(ellapseMs / 1000.0)) * 8 * diff;
                    yangle = GameMath.Cos((float)(ellapseMs / 2000.0)) * 3 * diff;
                    zangle = -GameMath.Sin((float)(ellapseMs / 3000.0)) * 8 * diff;
                }
            }


            Mat4f.Translate(ModelMat, ModelMat, dx + renderInfo.Transform.Translation.X, renderInfo.Transform.Translation.Y, dz + renderInfo.Transform.Translation.Z);
            Mat4f.Scale(ModelMat, ModelMat, new float[] { sizeX + scaleRand, sizeY + scaleRand, sizeZ + scaleRand });
            Mat4f.RotateY(ModelMat, ModelMat, GameMath.DEG2RAD * (renderInfo.Transform.Rotation.Y + yangle) + (renderInfo.Transform.Rotate ? yRotRand : 0));
            Mat4f.RotateZ(ModelMat, ModelMat, GameMath.DEG2RAD * (renderInfo.Transform.Rotation.Z + zangle));
            Mat4f.RotateX(ModelMat, ModelMat, GameMath.DEG2RAD * (renderInfo.Transform.Rotation.X + xangle));
            Mat4f.Translate(ModelMat, ModelMat, -renderInfo.Transform.Origin.X, -renderInfo.Transform.Origin.Y, -renderInfo.Transform.Origin.Z);
        }
        public virtual bool TryPutItem(IPlayer player)
        {
            if (OwnStackSize >= MaxStackSize)
            {
                return(false);
            }

            ItemSlot hotbarSlot = player.InventoryManager.ActiveHotbarSlot;

            if (hotbarSlot.Itemstack == null)
            {
                return(false);
            }

            ItemSlot invSlot = inventory[0];

            if (invSlot.Itemstack == null)
            {
                invSlot.Itemstack           = hotbarSlot.Itemstack.Clone();
                invSlot.Itemstack.StackSize = 0;
                Api.World.PlaySoundAt(SoundLocation, Pos.X, Pos.Y, Pos.Z, null, 0.88f + (float)Api.World.Rand.NextDouble() * 0.24f, 16);
            }

            if (invSlot.Itemstack.Equals(Api.World, hotbarSlot.Itemstack, GlobalConstants.IgnoredStackAttributes))
            {
                bool putBulk = player.Entity.Controls.Sprint;

                int q = GameMath.Min(hotbarSlot.StackSize, putBulk ? BulkTakeQuantity : DefaultTakeQuantity, MaxStackSize - OwnStackSize);

                // add to the pile and average item temperatures
                int oldSize = invSlot.Itemstack.StackSize;
                invSlot.Itemstack.StackSize += q;
                if (oldSize + q > 0)
                {
                    float tempPile  = invSlot.Itemstack.Collectible.GetTemperature(Api.World, invSlot.Itemstack);
                    float tempAdded = hotbarSlot.Itemstack.Collectible.GetTemperature(Api.World, hotbarSlot.Itemstack);
                    invSlot.Itemstack.Collectible.SetTemperature(Api.World, invSlot.Itemstack, (tempPile * oldSize + tempAdded * q) / (oldSize + q), false);
                }

                if (player.WorldData.CurrentGameMode != EnumGameMode.Creative)
                {
                    hotbarSlot.TakeOut(q);
                    hotbarSlot.OnItemSlotModified(null);
                }

                Api.World.PlaySoundAt(SoundLocation, Pos.X, Pos.Y, Pos.Z, player, 0.88f + (float)Api.World.Rand.NextDouble() * 0.24f, 16);

                MarkDirty();

                Cuboidf[] collBoxes = Api.World.BlockAccessor.GetBlock(Pos).GetCollisionBoxes(Api.World.BlockAccessor, Pos);
                if (collBoxes != null && collBoxes.Length > 0 && CollisionTester.AabbIntersect(collBoxes[0], Pos.X, Pos.Y, Pos.Z, player.Entity.SelectionBox, player.Entity.SidedPos.XYZ))
                {
                    player.Entity.SidedPos.Y += collBoxes[0].Y2 - (player.Entity.SidedPos.Y - (int)player.Entity.SidedPos.Y);
                }

                (player as IClientPlayer)?.TriggerFpAnimation(EnumHandInteract.HeldItemInteract);

                return(true);
            }

            return(false);
        }
        void genPatches(int chunkX, int chunkZ, bool postPass)
        {
            int   dx, dz, x, z;
            Block block;
            int   mapsizeY = blockAccessor.MapSizeY;

            var mapregion = sapi?.WorldManager.GetMapRegion((chunkX * chunksize) / regionSize, (chunkZ * chunksize) / regionSize);


            for (int i = 0; i < bpc.PatchesNonTree.Length; i++)
            {
                BlockPatch blockPatch = bpc.PatchesNonTree[i];
                if (blockPatch.PostPass != postPass)
                {
                    continue;
                }

                float chance = blockPatch.Chance * bpc.ChanceMultiplier.nextFloat();

                while (chance-- > rnd.NextDouble())
                {
                    dx = rnd.NextInt(chunksize);
                    dz = rnd.NextInt(chunksize);
                    x  = dx + chunkX * chunksize;
                    z  = dz + chunkZ * chunksize;

                    int y = heightmap[dz * chunksize + dx];
                    if (y <= 0 || y >= worldheight - 15)
                    {
                        continue;
                    }

                    tmpPos.Set(x, y, z);
                    block = blockAccessor.GetBlock(tmpPos);

                    // Place according to forest value
                    float forestRel = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, (float)dx / chunksize, (float)dz / chunksize) / 255f;
                    forestRel = GameMath.Clamp(forestRel + forestMod, 0, 1);

                    float shrubRel = GameMath.BiLerp(shrubUpLeft, shrubUpRight, shrubBotLeft, shrubBotRight, (float)dx / chunksize, (float)dz / chunksize) / 255f;
                    shrubRel = GameMath.Clamp(shrubRel + shrubMod, 0, 1);

                    int climate = GameMath.BiLerpRgbColor((float)dx / chunksize, (float)dz / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);

                    if (bpc.IsPatchSuitableAt(blockPatch, block, mapsizeY, climate, y, forestRel, shrubRel))
                    {
                        if (blockPatch.MapCode != null && rnd.NextInt(255) > GetPatchDensity(blockPatch.MapCode, x, z, mapregion))
                        {
                            continue;
                        }

                        int  firstBlockId = 0;
                        bool found        = true;

                        if (blockPatch.BlocksByRockType != null)
                        {
                            found = false;
                            int dy = 1;
                            while (dy < 5 && y - dy > 0)
                            {
                                string lastCodePart = blockAccessor.GetBlock(x, y - dy, z).LastCodePart();
                                if (RockBlockIdsByType.TryGetValue(lastCodePart, out firstBlockId))
                                {
                                    found = true; break;
                                }
                                dy++;
                            }
                        }

                        if (found)
                        {
                            blockPatch.Generate(blockAccessor, rnd, x, y, z, firstBlockId);
                        }
                    }
                }
            }
        }
예제 #20
0
 private static bool CanEquipItem(Item item, Skills skills)
 {
     return(item.Category != (int)ItemCategory.Resource &&
            item.RequiredDefenseLevel <= GameMath.ExperienceToLevel(skills.Defense) &&
            item.RequiredAttackLevel <= GameMath.ExperienceToLevel(skills.Attack));
 }
        void genTrees(int chunkX, int chunkZ)
        {
            int   climate = GameMath.BiLerpRgbColor((float)0.5f, (float)0.5f, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);
            float wetrel  = TerraGenConfig.GetRainFall((climate >> 8) & 0xff, heightmap[(chunksize / 2) * chunksize + chunksize / 2]) / 255f;
            float dryrel  = 1 - wetrel;

            float drypenalty = 1 - GameMath.Clamp(2f * (dryrel - 0.5f), 0, 0.8f); // Reduce tree generation by up to 70% in low rain places
            float wetboost   = 1 + 3 * Math.Max(0, wetrel - 0.75f);

            int   triesTrees = (int)(treeSupplier.treeGenProps.treesPerChunk.nextFloat() * drypenalty * wetboost);
            int   dx, dz, x, z;
            Block block;
            int   treesGenerated = 0;

            while (triesTrees > 0)
            {
                triesTrees--;

                dx = rnd.NextInt(chunksize);
                dz = rnd.NextInt(chunksize);
                x  = dx + chunkX * chunksize;
                z  = dz + chunkZ * chunksize;

                int y = heightmap[dz * chunksize + dx];
                if (y <= 0 || y >= worldheight - 15)
                {
                    continue;
                }

                bool underwater = false;

                tmpPos.Set(x, y, z);
                block = blockAccessor.GetBlock(tmpPos);

                if (block.IsLiquid())
                {
                    underwater = true; tmpPos.Y--; block = blockAccessor.GetBlock(tmpPos);
                }
                if (block.IsLiquid())
                {
                    underwater = true; tmpPos.Y--; block = blockAccessor.GetBlock(tmpPos);
                }

                if (block.Fertility == 0)
                {
                    continue;
                }

                // Place according to forest value
                float treeDensity = GameMath.BiLerp(forestUpLeft, forestUpRight, forestBotLeft, forestBotRight, (float)dx / chunksize, (float)dz / chunksize);
                climate = GameMath.BiLerpRgbColor((float)dx / chunksize, (float)dz / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);

                treeDensity = GameMath.Clamp(treeDensity + forestMod * 255, 0, 255);

                float treeDensityNormalized = treeDensity / 255f;



                // 1 in 400 chance to always spawn a tree
                // otherwise go by tree density using a quadratic drop off to create clearer forest edges
                if (rnd.NextDouble() > Math.Max(0.0025, treeDensityNormalized * treeDensityNormalized) || forestMod <= -1)
                {
                    continue;
                }
                TreeGenForClimate treegenParams = treeSupplier.GetRandomTreeGenForClimate(climate, (int)treeDensity, y, underwater);

                if (treegenParams != null)
                {
                    bool canGen = true;
                    for (int i = 0; i < structuresIntersectingChunk.Count; i++)
                    {
                        if (structuresIntersectingChunk[i].Contains(tmpPos))
                        {
                            canGen = false; break;
                        }
                    }
                    if (!canGen)
                    {
                        continue;
                    }

                    if (blockAccessor.GetBlock(tmpPos.X, tmpPos.Y, tmpPos.Z).Replaceable >= 6000)
                    {
                        tmpPos.Y--;
                    }

                    treegenParams.treeGen.GrowTree(
                        blockAccessor,
                        tmpPos,
                        false,
                        treegenParams.size,
                        treegenParams.vinesGrowthChance,
                        1,
                        treesGenerated
                        );

                    treesGenerated++;
                }
            }
        }
예제 #22
0
        public AddItemResult CraftItem(SessionToken token, string userId, Guid itemId)
        {
            var item = gameData.GetItem(itemId);

            if (item == null)
            {
                return(AddItemResult.Failed);
            }

            var character = GetCharacter(token, userId);

            if (character == null)
            {
                return(AddItemResult.Failed);
            }

            if (!integrityChecker.VerifyPlayer(token.SessionId, character.Id, 0))
            {
                return(AddItemResult.Failed);
            }

            var resources = gameData.GetResources(character.ResourcesId);

            if (resources == null)
            {
                return(AddItemResult.Failed);
            }

            var skills = gameData.GetSkills(character.SkillsId);

            if (skills == null)
            {
                return(AddItemResult.Failed);
            }

            var craftingLevel = GameMath.ExperienceToLevel(skills.Crafting);

            if (item.WoodCost > resources.Wood || item.OreCost > resources.Ore || item.RequiredCraftingLevel > craftingLevel)
            {
                return(AddItemResult.Failed);
            }

            var craftingRequirements = gameData.GetCraftingRequirements(itemId);

            foreach (var req in craftingRequirements)
            {
                var invItem = gameData.GetInventoryItem(character.Id, req.ResourceItemId);
                if (invItem == null || invItem.Amount < req.Amount)
                {
                    return(AddItemResult.Failed);
                }
            }

            foreach (var req in craftingRequirements)
            {
                var invItem = gameData.GetInventoryItem(character.Id, req.ResourceItemId);
                invItem.Amount -= req.Amount;
                if (invItem.Amount == 0)
                {
                    gameData.Remove(invItem);
                }
            }

            resources.Wood -= item.WoodCost;
            resources.Ore  -= item.OreCost;

            return(AddItem(token, userId, itemId));
        }
예제 #23
0
        public void TickEntityPhysics(EntityPos pos, EntityControls controls, float dt)
        {
            // This seems to make creatures clip into the terrain. Le sigh.
            // Since we currently only really need it for when the creature is dead, let's just use it only there

            // Also running animations for all nearby living entities is pretty CPU intensive so
            // the AnimationManager also just ticks if the entity is in view or dead
            if (!entity.Alive)
            {
                AdjustCollisionBoxToAnimation();
            }


            foreach (EntityLocomotion locomotor in Locomotors)
            {
                if (locomotor.Applicable(entity, pos, controls))
                {
                    locomotor.Apply(dt, entity, pos, controls);
                }
            }

            EntityAgent agent = entity as EntityAgent;

            if (agent?.MountedOn != null)
            {
                pos.SetFrom(agent.MountedOn.MountPosition);
                pos.Motion.X = 0;
                pos.Motion.Y = 0;
                pos.Motion.Z = 0;
                return;
            }

            pos.Motion.X = GameMath.Clamp(pos.Motion.X, -10, 10);
            pos.Motion.Y = GameMath.Clamp(pos.Motion.Y, -10, 10);
            pos.Motion.Z = GameMath.Clamp(pos.Motion.Z, -10, 10);

            if (!controls.NoClip)
            {
                DisplaceWithBlockCollision(pos, controls, dt);
            }
            else
            {
                pos.X += pos.Motion.X;
                pos.Y += pos.Motion.Y;
                pos.Z += pos.Motion.Z;

                entity.Swimming     = false;
                entity.FeetInLiquid = false;
                entity.OnGround     = false;
            }



            // Shake the player violently when falling at high speeds

            /*if (movedy < -50)
             * {
             *  pos.X += (rand.NextDouble() - 0.5) / 5 * (-movedy / 50f);
             *  pos.Z += (rand.NextDouble() - 0.5) / 5 * (-movedy / 50f);
             * }
             */

            //return result;
        }
예제 #24
0
        public override void StartExecute()
        {
            base.StartExecute();

            stopNow   = false;
            siegeMode = false;

            bool giveUpWhenNoPath = targetPos.SquareDistanceTo(entity.Pos.XYZ) < 12 * 12;
            int  searchDepth      = 3500;

            // 1 in 20 times we do an expensive search
            if (world.Rand.NextDouble() < 0.05)
            {
                searchDepth = 10000;
            }

            if (!pathTraverser.NavigateTo(targetPos.Clone(), moveSpeed, MinDistanceToTarget(), OnGoalReached, OnStuck, giveUpWhenNoPath, searchDepth, true))
            {
                // If we cannot find a path to the target, let's circle it!
                float angle = (float)Math.Atan2(entity.ServerPos.X - targetPos.X, entity.ServerPos.Z - targetPos.Z);

                double randAngle = angle + 0.5 + world.Rand.NextDouble() / 2;

                double distance = 4 + world.Rand.NextDouble() * 6;

                double dx = GameMath.Sin(randAngle) * distance;
                double dz = GameMath.Cos(randAngle) * distance;
                targetPos = targetPos.AddCopy(dx, 0, dz);

                int      tries = 0;
                bool     ok    = false;
                BlockPos tmp   = new BlockPos((int)targetPos.X, (int)targetPos.Y, (int)targetPos.Z);

                int dy = 0;
                while (tries < 5)
                {
                    // Down ok?
                    if (world.BlockAccessor.GetBlock(tmp.X, tmp.Y - dy, tmp.Z).SideSolid[BlockFacing.UP.Index] && !world.CollisionTester.IsColliding(world.BlockAccessor, entity.CollisionBox, new Vec3d(tmp.X + 0.5, tmp.Y - dy + 1, tmp.Z + 0.5), false))
                    {
                        ok           = true;
                        targetPos.Y -= dy;
                        targetPos.Y++;
                        siegeMode = true;
                        break;
                    }

                    // Down ok?
                    if (world.BlockAccessor.GetBlock(tmp.X, tmp.Y + dy, tmp.Z).SideSolid[BlockFacing.UP.Index] && !world.CollisionTester.IsColliding(world.BlockAccessor, entity.CollisionBox, new Vec3d(tmp.X + 0.5, tmp.Y + dy + 1, tmp.Z + 0.5), false))
                    {
                        ok           = true;
                        targetPos.Y += dy;
                        targetPos.Y++;
                        siegeMode = true;
                        break;
                    }

                    tries++;
                    dy++;
                }



                ok = ok && pathTraverser.NavigateTo(targetPos.Clone(), moveSpeed, MinDistanceToTarget(), OnGoalReached, OnStuck, giveUpWhenNoPath, searchDepth, true);

                stopNow = !ok;
            }

            currentFollowTime = 0;
        }
예제 #25
0
 public override void InGuiIdle(IWorldAccessor world, ItemStack stack)
 {
     GuiTransform.Rotation.Y = GameMath.Mod(world.ElapsedMilliseconds / 50f, 360);
 }
예제 #26
0
        public override bool ContinueExecute(float dt)
        {
            currentFollowTime     += dt;
            lastPathUpdateSeconds += dt;

            if (!siegeMode && lastPathUpdateSeconds >= 1 && targetPos.SquareDistanceTo(targetEntity.ServerPos.X, targetEntity.ServerPos.Y, targetEntity.ServerPos.Z) >= 3 * 3)
            {
                pathTraverser.NavigateTo(targetPos.Clone(), moveSpeed, MinDistanceToTarget(), OnGoalReached, OnStuck, false, 2000, true);
                lastPathUpdateSeconds = 0;
                targetPos.Set(targetEntity.ServerPos.X, targetEntity.ServerPos.Y, targetEntity.ServerPos.Z);
            }

            if (jumpAnimOn && entity.World.ElapsedMilliseconds - finishedMs > 2000)
            {
                entity.AnimManager.StopAnimation(leapAnimationCode);
            }

            if (!siegeMode)
            {
                pathTraverser.CurrentTarget.X = targetEntity.ServerPos.X;
                pathTraverser.CurrentTarget.Y = targetEntity.ServerPos.Y;
                pathTraverser.CurrentTarget.Z = targetEntity.ServerPos.Z;
            }

            Cuboidd targetBox = targetEntity.CollisionBox.ToDouble().Translate(targetEntity.ServerPos.X, targetEntity.ServerPos.Y, targetEntity.ServerPos.Z);
            Vec3d   pos       = entity.ServerPos.XYZ.Add(0, entity.CollisionBox.Y2 / 2, 0).Ahead(entity.CollisionBox.XSize / 2, 0, entity.ServerPos.Yaw);
            double  distance  = targetBox.ShortestDistanceFrom(pos);


            bool inCreativeMode = (targetEntity as EntityPlayer)?.Player?.WorldData.CurrentGameMode == EnumGameMode.Creative;

            if (!inCreativeMode && leapAtTarget && rand.NextDouble() < leapChance)
            {
                bool recentlyJumped = entity.World.ElapsedMilliseconds - jumpedMS < 3000;

                if (distance > 0.5 && distance < 4 && !recentlyJumped && targetEntity.ServerPos.Y + 0.1 >= entity.ServerPos.Y)
                {
                    double dx = (targetEntity.ServerPos.X + targetEntity.ServerPos.Motion.X * 80 - entity.ServerPos.X) / 30;
                    double dz = (targetEntity.ServerPos.Z + targetEntity.ServerPos.Motion.Z * 80 - entity.ServerPos.Z) / 30;
                    entity.ServerPos.Motion.Add(
                        dx,
                        leapHeightMul * GameMath.Max(0.13, (targetEntity.ServerPos.Y - entity.ServerPos.Y) / 30),
                        dz
                        );

                    float yaw = (float)Math.Atan2(dx, dz);
                    entity.ServerPos.Yaw = yaw;


                    jumpedMS   = entity.World.ElapsedMilliseconds;
                    finishedMs = entity.World.ElapsedMilliseconds;
                    if (leapAnimationCode != null)
                    {
                        entity.AnimManager.StopAnimation("walk");
                        entity.AnimManager.StopAnimation("run");
                        entity.AnimManager.StartAnimation(new AnimationMetaData()
                        {
                            Animation = leapAnimationCode, Code = leapAnimationCode
                        }.Init());
                        jumpAnimOn = true;
                    }
                }

                if (recentlyJumped && !entity.Collided && distance < 0.5)
                {
                    entity.ServerPos.Motion /= 2;
                }
            }


            float minDist = MinDistanceToTarget();
            float range   = lowTempMode ? belowTempSeekingRange : seekingRange;

            return
                (currentFollowTime < maxFollowTime &&
                 distance < range * range &&
                 (distance > minDist || targetEntity.ServerControls.TriesToMove) &&
                 targetEntity.Alive &&
                 !inCreativeMode &&
                 !stopNow
                );
        }
예제 #27
0
        /// <summary>
        /// Do the mob AI
        /// </summary>
        public override void Think()
        {
            GamePlayer playerowner = GetPlayerOwner();

            long lastUpdate = 0;

            if (playerowner != null && !playerowner.Client.GameObjectUpdateArray.TryGetValue(new Tuple <ushort, ushort>(Body.CurrentRegionID, (ushort)Body.ObjectID), out lastUpdate))
            {
                lastUpdate = 0;
            }

            // Load abilities on first Think cycle.
            if (!checkAbility)
            {
                CheckAbilities();
                checkAbility = true;
            }

            if (playerowner != null && (GameTimer.GetTickCount() - lastUpdate) > ThinkInterval)
            {
                playerowner.Out.SendObjectUpdate(Body);
            }

            //See if the pet is too far away, if so release it!
            if (Owner is GamePlayer && IsMainPet && !GameMath.IsWithinRadius(Body, Owner, MAX_OWNER_FOLLOW_DIST))
            {
                (Owner as GamePlayer).CommandNpcRelease();
            }

            // if pet is in agressive mode then check aggressive spells and attacks first
            if (!Body.AttackState && AggressionState == eAggressionState.Aggressive)
            {
                CheckPlayerAggro();
                CheckNPCAggro();
                AttackMostWanted();
            }

            // Check for buffs, heals, etc, interrupting melee if not being interrupted
            // Only prevent casting if we are ordering pet to come to us or go to target
            if (Owner is GameNPC || (Owner is GamePlayer && WalkState != eWalkState.ComeHere && WalkState != eWalkState.GoTarget))
            {
                CheckSpells(eCheckSpellType.Defensive);
            }

            // Stop hunting player entering in steath
            if (Body.TargetObject != null && Body.TargetObject is GamePlayer)
            {
                GamePlayer player = Body.TargetObject as GamePlayer;
                if (Body.IsAttacking && player.IsStealthed && !previousIsStealthed)
                {
                    Body.StopAttack();
                    Body.StopCurrentSpellcast();
                    RemoveFromAggroList(player);
                    Body.TargetObject = null;
                    FollowOwner();
                }
                previousIsStealthed = player.IsStealthed;
            }

            // Always check offensive spells, or pets in melee will keep blindly melee attacking,
            //	when they should be stopping to cast offensive spells.
            if (IsActive && m_aggressionState != eAggressionState.Passive)
            {
                CheckSpells(eCheckSpellType.Offensive);
            }

            if (!Body.AttackState && WalkState == eWalkState.Follow && Owner != null)
            {
                Follow(Owner);
            }
        }
예제 #28
0
        void genPatches(int chunkX, int chunkZ)
        {
            int   dx, dz, x, z;
            Block block;

            for (int i = 0; i < bpc.Patches.Length; i++)
            {
                BlockPatch blockPatch = bpc.Patches[i];
                if (!blockPatch.PrePass)
                {
                    continue;
                }

                float chance = blockPatch.Chance * bpc.ChanceMultiplier.nextFloat();

                while (chance-- > rnd.NextDouble())
                {
                    dx = rnd.NextInt(chunksize);
                    dz = rnd.NextInt(chunksize);
                    x  = dx + chunkX * chunksize;
                    z  = dz + chunkZ * chunksize;

                    int y = heightmap[dz * chunksize + dx];
                    if (y <= 0 || y >= worldheight - 15)
                    {
                        continue;
                    }

                    tmpPos.Set(x, y, z);
                    block = blockAccessor.GetBlock(tmpPos);

                    // Place according to forest value
                    int climate = GameMath.BiLerpRgbColor((float)dx / chunksize, (float)dz / chunksize, climateUpLeft, climateUpRight, climateBotLeft, climateBotRight);

                    if (bpc.IsPatchSuitableAt(blockPatch, block, api.WorldManager.MapSizeY, climate, y, 0, 0))
                    {
                        int  firstBlockId = 0;
                        bool found        = true;

                        if (blockPatch.BlocksByRockType != null)
                        {
                            found = false;
                            int dy = 1;
                            while (dy < 5 && y - dy > 0)
                            {
                                string lastCodePart = blockAccessor.GetBlock(x, y - dy, z).LastCodePart();
                                if (RockBlockIdsByType.TryGetValue(lastCodePart, out firstBlockId))
                                {
                                    found = true; break;
                                }
                                dy++;
                            }
                        }

                        if (found)
                        {
                            blockPatch.Generate(blockAccessor, rnd, x, y, z, firstBlockId);
                        }
                    }
                }
            }
        }
예제 #29
0
        override internal void OnDeserialized()
        {
            base.OnDeserialized();

            // Only one collision/selectionbox
            if (CollisionBoxR != null)
            {
                CollisionBoxes = ToCuboidf(CollisionBoxR);
            }
            if (SelectionBoxR != null)
            {
                SelectionBoxes = ToCuboidf(SelectionBoxR);
            }

            // Multiple collision/selectionboxes
            if (CollisionBoxesR != null)
            {
                CollisionBoxes = ToCuboidf(CollisionBoxesR);
            }
            if (SelectionBoxesR != null)
            {
                SelectionBoxes = ToCuboidf(SelectionBoxesR);
            }

            // Merged collision+selectioboxes
            if (CollisionSelectionBoxR != null)
            {
                CollisionBoxes = ToCuboidf(CollisionSelectionBoxR);
                SelectionBoxes = ToCuboidf(CollisionSelectionBoxR);
            }

            if (CollisionSelectionBoxesR != null)
            {
                CollisionBoxes = ToCuboidf(CollisionSelectionBoxesR);
                SelectionBoxes = ToCuboidf(CollisionSelectionBoxesR);
            }

            ResolveStringBoolDictFaces(SideSolidOpaqueAo);
            ResolveStringBoolDictFaces(SideSolid);
            ResolveStringBoolDictFaces(SideOpaque);
            ResolveStringBoolDictFaces(SideAo);
            ResolveStringBoolDictFaces(EmitSideAo);

            if (SideSolidOpaqueAo != null && SideSolidOpaqueAo.Count > 0)
            {
                ResolveDict(SideSolidOpaqueAo, ref SideSolid);
                ResolveDict(SideSolidOpaqueAo, ref SideOpaque);
                ResolveDict(SideSolidOpaqueAo, ref SideAo);
                ResolveDict(SideSolidOpaqueAo, ref EmitSideAo);
            }

            if (EmitSideAo == null)
            {
                EmitSideAo = new Dictionary <string, bool>()
                {
                    { "all", LightAbsorption > 0 }
                };
                ResolveStringBoolDictFaces(EmitSideAo);
            }


            if (LightHsv == null)
            {
                LightHsv = new byte[3];
            }

            // Boundary check light values, if they go beyond allowed values the lighting system will crash
            LightHsv[0] = (byte)GameMath.Clamp(LightHsv[0], 0, ColorUtil.HueQuantities - 1);
            LightHsv[1] = (byte)GameMath.Clamp(LightHsv[1], 0, ColorUtil.SatQuantities - 1);
            LightHsv[2] = (byte)GameMath.Clamp(LightHsv[2], 0, ColorUtil.BrightQuantities - 1);
        }
예제 #30
0
        public override bool OnHeldInteractStep(float secondsUsed, IItemSlot slot, IEntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
        {
            if (blockSel == null)
            {
                return(false);
            }
            if (slot.Itemstack.TempAttributes.GetInt("refilled") > 0)
            {
                return(false);
            }

            float prevsecondsused = slot.Itemstack.TempAttributes.GetFloat("secondsUsed");

            slot.Itemstack.TempAttributes.SetFloat("secondsUsed", secondsUsed);

            float remainingwater = GetRemainingWateringSeconds(slot.Itemstack);

            SetRemainingWateringSeconds(slot.Itemstack, remainingwater -= secondsUsed - prevsecondsused);


            if (remainingwater <= 0)
            {
                return(false);
            }

            IWorldAccessor world = byEntity.World;

            BlockPos targetPos = blockSel.Position;

            Block facingBlock = world.BlockAccessor.GetBlock(blockSel.Position.AddCopy(blockSel.Face));

            if (facingBlock.Code.Path == "fire")
            {
                world.BlockAccessor.SetBlock(0, blockSel.Position.AddCopy(blockSel.Face));
            }

            Block block           = world.BlockAccessor.GetBlock(blockSel.Position);
            bool  notOnSolidblock = false;

            if ((block.CollisionBoxes == null || block.CollisionBoxes.Length == 0) && !block.IsLiquid())
            {
                notOnSolidblock = true;
                targetPos       = targetPos.DownCopy();
            }

            BlockEntityFarmland be = world.BlockAccessor.GetBlockEntity(targetPos) as BlockEntityFarmland;

            if (be != null)
            {
                be.WaterFarmland(secondsUsed - prevsecondsused);
            }

            float speed = 4f;

            if (world.Side == EnumAppSide.Client)
            {
                ModelTransform tf = new ModelTransform();
                tf.EnsureDefaultValues();

                tf.Origin.Set(0.5f, 0.2f, 0.5f);
                tf.Translation.Set(-Math.Min(0.25f, speed * secondsUsed / 4), 0, 0);

                tf.Rotation.Z = GameMath.Min(60, secondsUsed * 90 * speed, 80 - remainingwater * 5);
                byEntity.Controls.UsingHeldItemTransformBefore = tf;
            }

            IPlayer byPlayer = null;

            if (byEntity is IEntityPlayer)
            {
                byPlayer = byEntity.World.PlayerByUid(((IEntityPlayer)byEntity).PlayerUID);
            }


            if (secondsUsed > 1 / speed)
            {
                Vec3d pos = blockSel.Position.ToVec3d().Add(blockSel.HitPosition);
                if (notOnSolidblock)
                {
                    pos.Y = (int)pos.Y + 0.05;
                }
                WaterParticles.minPos = pos.Add(-0.125 / 2, 1 / 16f, -0.125 / 2);
                byEntity.World.SpawnParticles(WaterParticles, byPlayer);
            }

            return(true);
        }