private void OnClientGameTick(float dt)
        {
            if (ownBlock == null || Api?.World == null || !canTeleport || !Activated)
            {
                return;
            }

            if (Api.World.ElapsedMilliseconds - somebodyIsTeleportingReceivedTotalMs > 6000)
            {
                somebodyIsTeleporting = false;
            }

            HandleSoundClient(dt);

            bool selfInside   = (Api.World.ElapsedMilliseconds > 100 && Api.World.ElapsedMilliseconds - lastCollideMsOwnPlayer < 100);
            bool playerInside = selfInside || somebodyIsTeleporting;
            bool active       = animUtil.activeAnimationsByAnimCode.ContainsKey("teleport");

            if (!selfInside && playerInside)
            {
                manager.lastTranslocateCollideMsOtherPlayer = Api.World.ElapsedMilliseconds;
            }

            SimpleParticleProperties currentParticles = active ?
                                                        ownBlock.insideParticles :
                                                        ownBlock.idleParticles
            ;

            if (playerInside)
            {
                var meta = new AnimationMetaData()
                {
                    Animation = "teleport", Code = "teleport", AnimationSpeed = 1, EaseInSpeed = 1, EaseOutSpeed = 2, Weight = 1, BlendMode = EnumAnimationBlendMode.Add
                };
                animUtil.StartAnimation(meta);
                animUtil.StartAnimation(new AnimationMetaData()
                {
                    Animation = "idle", Code = "idle", AnimationSpeed = 1, EaseInSpeed = 1, EaseOutSpeed = 1, Weight = 1, BlendMode = EnumAnimationBlendMode.Average
                });
            }
            else
            {
                animUtil.StopAnimation("teleport");
            }


            if (animUtil.activeAnimationsByAnimCode.Count > 0 && Api.World.ElapsedMilliseconds - lastCollideMsOwnPlayer > 10000 && Api.World.ElapsedMilliseconds - manager.lastTranslocateCollideMsOtherPlayer > 10000)
            {
                animUtil.StopAnimation("idle");
            }


            //int color = temporalGearStack.Collectible.GetRandomColor(api as ICoreClientAPI, temporalGearStack); - not working o.O

            int r = 53;
            int g = 221;
            int b = 172;

            currentParticles.Color = (r << 16) | (g << 8) | (b << 0) | (50 << 24);

            currentParticles.AddPos.Set(0, 0, 0);
            currentParticles.BlueEvolve    = null;
            currentParticles.RedEvolve     = null;
            currentParticles.GreenEvolve   = null;
            currentParticles.MinSize       = 0.1f;
            currentParticles.MaxSize       = 0.2f;
            currentParticles.SizeEvolve    = null;
            currentParticles.OpacityEvolve = EvolvingNatFloat.create(EnumTransformFunction.LINEAR, 100f);


            bool rot = Block.Variant["side"] == "east" || Block.Variant["side"] == "west";

            particleAngle = active ? particleAngle + 5 * dt : 0;


            double dx = GameMath.Cos(particleAngle + (rot ? GameMath.PIHALF : 0)) * 0.35f;
            double dy = 1.9 + Api.World.Rand.NextDouble() * 0.2;
            double dz = GameMath.Sin(particleAngle + (rot ? GameMath.PIHALF : 0)) * 0.35f;

            currentParticles.LifeLength = GameMath.Sqrt(dx * dx + dz * dz) / 10;
            currentParticles.MinPos.Set(posvec.X + dx, posvec.Y + dy, posvec.Z + dz);
            currentParticles.MinVelocity.Set(-(float)dx / 2, -1 - (float)Api.World.Rand.NextDouble() / 2, -(float)dz / 2);
            currentParticles.MinQuantity = active ? 3 : 0.25f;
            currentParticles.AddVelocity.Set(0, 0, 0);
            currentParticles.AddQuantity = 0.5f;

            Api.World.SpawnParticles(currentParticles);

            currentParticles.MinPos.Set(posvec.X - dx, posvec.Y + dy, posvec.Z - dz);
            currentParticles.MinVelocity.Set((float)dx / 2, -1 - (float)Api.World.Rand.NextDouble() / 2, (float)dz / 2);
            Api.World.SpawnParticles(currentParticles);
        }
示例#2
0
        private bool TryCircleTarget()
        {
            // Console.WriteLine("try circle target");

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

            attackPattern  = EnumAttackPattern.CircleTarget;
            lastPathfindOk = false;

            // 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);

            for (int i = 0; i < 3; i++)
            {
                // We need to avoid crossing the path of the target, so we do only small angle variation between us and the target
                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.Add(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.SelectionBox, new Vec3d(tmp.X + 0.5, tmp.Y - dy + 1, tmp.Z + 0.5), false))
                    {
                        ok           = true;
                        targetPos.Y -= dy;
                        targetPos.Y++;
                        break;
                    }

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

                    tries++;
                    dy++;
                }

                if (ok)
                {
                    pathTraverser.NavigateTo_Async(targetPos.Clone(), moveSpeed, MinDistanceToTarget(), OnGoalReached, OnStuck, OnCircleTargetUnable, searchDepth, 1);
                    return(true);
                }
            }

            return(false);
        }
示例#3
0
        /// <summary> Try to execute an allomantic effect from this entity </summary>
        public void TryExecuteActiveAllomanticEffect(string power, int strength, bool flare)
        {
            //Console.WriteLine(GetPower(power) + " " + GetMetalReserve(power));
            if (!Helper.GetPower(power))
            {
                return;
            }
            if (Helper.GetMetalReserve(power) <= 0)
            {
                return;
            }
            float consumption = ((float)strength / 100);

            if (flare)
            {
                consumption += 1 / 50;
            }
            Helper.IncrementMetalReserve(power, -consumption);
            if (power == "aluminium")
            {
                Helper.ClearAllReserves();
            }
            EntityBehaviorHealth health = (EntityBehaviorHealth)entity.GetBehavior("health");

            if (power == "pewter")
            {
                if (health.Health < health.MaxHealth)
                {
                    float divider   = 50;
                    float magnitude = strength / divider;
                    if (flare)
                    {
                        magnitude = 2;
                    }
                    entity.ReceiveDamage(new DamageSource()
                    {
                        Source = EnumDamageSource.Internal,
                        Type   = EnumDamageType.Heal
                    }, magnitude);
                    Helper.IncreasePewterFatigue(magnitude);
                    Helper.IncrementMetalReserve("pewter", -magnitude / 2);
                }
            }
            if (power == "steel" | power == "iron")
            {
                if (keyTick % 15 == 0 | flare)
                {
                    float divider   = 23;
                    float magnitude = strength / divider;
                    if (flare)
                    {
                        magnitude += 2 / 10;
                    }
                    float forwardpitch = GameMath.PI - entity.ServerPos.Pitch + GameMath.PI;
                    float forwardyaw   = entity.ServerPos.Yaw + GameMath.PIHALF;
                    float inversepitch = GameMath.PI - entity.ServerPos.Pitch + GameMath.PI;
                    float inverseyaw   = entity.ServerPos.Yaw + GameMath.PIHALF + GameMath.PI;
                    float playerpitch  = power == "steel" ? forwardpitch : inversepitch;
                    float playeryaw    = power == "steel" ? forwardyaw : inverseyaw;
                    float targetpitch  = power == "steel" ? inversepitch : forwardpitch;
                    float targetyaw    = power == "steel" ? inverseyaw : forwardyaw;
                    entity.ServerPos.Motion.Add(
                        (GameMath.Sin(playeryaw) * GameMath.Cos(playerpitch)) * magnitude,
                        (GameMath.Sin(playerpitch)) * magnitude,
                        (GameMath.Cos(playeryaw) * GameMath.Cos(playerpitch)) * magnitude);
                    ((IServerPlayer)entity.World.PlayerByUid(((EntityPlayer)entity).PlayerUID)).SendPositionToClient();
                }
            }
        }
示例#4
0
        // This method was contributed by Eliam (Avdudia#0696) on Discord <3
        public SolarSphericalCoords GetSolarSphericalCoords(double posX, double posZ, float yearRel, float dayRel)
        {
            // Tyron: For your understanding, this would be the simple most spherical coord calculator - this is how the sun rises and sets if you were standing at the equator and without earth axial tilt
            // return new SolarSphericalCoords(GameMath.TWOPI * GameMath.Mod(api.World.Calendar.HourOfDay / api.World.Calendar.HoursPerDay, 1f), 0);

            float latitude = (float)api.World.Calendar.OnGetLatitude(posZ);

            float hourAngle = GameMath.TWOPI * (dayRel - 0.5f);

            float dayOfYear   = api.World.Calendar.DayOfYearf;
            float daysPerYear = api.World.Calendar.DaysPerYear;

            // The Sun's declination at any given moment
            // The number 10 is the approximate number of days after the December solstice to January 1
            float declination = -EarthAxialTilt *GameMath.Cos(GameMath.TWOPI *(dayOfYear / daysPerYear + 10 / 365f));

            float zenithAngle = (float)Math.Acos(GameMath.Sin(latitude * GameMath.PIHALF) * GameMath.Sin(declination) + GameMath.Cos(latitude * GameMath.PIHALF) * GameMath.Cos(declination) * GameMath.Cos(hourAngle));

            // Added 1.e-10 to prevent division by 0
            float azimuthAngle = (float)Math.Acos(((GameMath.Sin(latitude * GameMath.PIHALF) * GameMath.Cos(zenithAngle)) - GameMath.Sin(declination)) / (GameMath.Cos(latitude * GameMath.PIHALF) * GameMath.Sin(zenithAngle) + 0.0000001f));

            // The sign function gives the correct azimuth angle sign depending on the hour without using IF statement (branchless)
            azimuthAngle = (GameMath.PI + Math.Sign(hourAngle) * azimuthAngle) % GameMath.TWOPI;

            return(new SolarSphericalCoords(GameMath.TWOPI - zenithAngle, GameMath.TWOPI - azimuthAngle));
        }
示例#5
0
        public override bool OnHeldInteractStep(float secondsUsed, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
        {
            string blockMaterialCode = GetBlockMaterialCode(slot.Itemstack);

            if (blockMaterialCode == null || !slot.Itemstack.TempAttributes.GetBool("canpan"))
            {
                return(false);
            }

            Vec3d pos = byEntity.Pos.AheadCopy(0.4f).XYZ;

            pos.Y += byEntity.EyeHeight - 0.4f;

            if (secondsUsed > 0.5f && (int)(30 * secondsUsed) % 7 == 1)
            {
                Block block = api.World.GetBlock(new AssetLocation(blockMaterialCode));
                byEntity.World.SpawnCubeParticles(pos, new ItemStack(block), 0.3f, 4, 0.35f, (byEntity as EntityPlayer)?.Player);
            }


            if (byEntity.World is IClientWorldAccessor)
            {
                ModelTransform tf = new ModelTransform();

                tf.EnsureDefaultValues();

                tf.Origin.Set(0f, 0, 0f);

                if (secondsUsed > 0.5f)
                {
                    tf.Translation.X = Math.Min(0.25f, GameMath.Cos(10 * secondsUsed) / 4f);
                    tf.Translation.Y = Math.Min(0.15f, GameMath.Sin(10 * secondsUsed) / 6.666f);

                    if (sound == null)
                    {
                        sound = (api as ICoreClientAPI).World.LoadSound(new SoundParams()
                        {
                            Location         = new AssetLocation("sounds/player/panning.ogg"),
                            ShouldLoop       = false,
                            RelativePosition = true,
                            Position         = new Vec3f(),
                            DisposeOnFinish  = true,
                            Volume           = 0.5f,
                            Range            = 8
                        });

                        sound.Start();
                    }
                }

                tf.Translation.X -= Math.Min(1.6f, secondsUsed * 4 * 1.57f);
                tf.Translation.Y -= Math.Min(0.1f, secondsUsed * 2);
                tf.Translation.Z -= Math.Min(1f, secondsUsed * 180);

                tf.Scale = 1 + Math.Min(0.6f, 2 * secondsUsed);


                byEntity.Controls.UsingHeldItemTransformAfter = tf;

                return(secondsUsed <= 4f);
            }

            // Let the client decide when he is done eating
            return(true);
        }
示例#6
0
        public override bool OnHeldInteractStep(float secondsUsed, ItemSlot slot, EntityAgent byEntity, BlockSelection blockSel, EntitySelection entitySel)
        {
            if ((byEntity.Controls.TriesToMove || byEntity.Controls.Jump) && !byEntity.Controls.Sneak)
            {
                return(false);                                                                                       // Cancel if the player begins walking
            }
            IPlayer byPlayer = (byEntity as EntityPlayer)?.Player;

            if (byPlayer == null)
            {
                return(false);
            }
            if (blockSel != null && !byEntity.World.Claims.TryAccess(byPlayer, blockSel.Position, EnumBlockAccessFlags.BuildOrBreak))
            {
                return(false);
            }


            string blockMaterialCode = GetBlockMaterialCode(slot.Itemstack);

            if (blockMaterialCode == null || !slot.Itemstack.TempAttributes.GetBool("canpan"))
            {
                return(false);
            }

            Vec3d pos = byEntity.Pos.AheadCopy(0.4f).XYZ;

            pos.Y += byEntity.LocalEyePos.Y - 0.4f;

            if (secondsUsed > 0.5f && api.World.Rand.NextDouble() > 0.5)
            {
                Block block       = api.World.GetBlock(new AssetLocation(blockMaterialCode));
                Vec3d particlePos = pos.Clone();

                particlePos.X += GameMath.Sin(-secondsUsed * 20) / 5f;
                particlePos.Z += GameMath.Cos(-secondsUsed * 20) / 5f;
                particlePos.Y -= 0.07f;

                byEntity.World.SpawnCubeParticles(particlePos, new ItemStack(block), 0.3f, (int)(1.5f + (float)api.World.Rand.NextDouble()), 0.3f + (float)api.World.Rand.NextDouble() / 6f, (byEntity as EntityPlayer)?.Player);
            }


            if (byEntity.World is IClientWorldAccessor)
            {
                ModelTransform tf = new ModelTransform();

                tf.EnsureDefaultValues();

                tf.Origin.Set(0f, 0, 0f);

                if (secondsUsed > 0.5f)
                {
                    tf.Translation.X = Math.Min(0.25f, GameMath.Cos(10 * secondsUsed) / 4f);
                    tf.Translation.Y = Math.Min(0.15f, GameMath.Sin(10 * secondsUsed) / 6.666f);

                    if (sound == null)
                    {
                        sound = (api as ICoreClientAPI).World.LoadSound(new SoundParams()
                        {
                            Location         = new AssetLocation("sounds/player/panning.ogg"),
                            ShouldLoop       = false,
                            RelativePosition = true,
                            Position         = new Vec3f(),
                            DisposeOnFinish  = true,
                            Volume           = 0.5f,
                            Range            = 8
                        });

                        sound.Start();
                    }
                }

                tf.Translation.X -= Math.Min(1.6f, secondsUsed * 4 * 1.57f);
                tf.Translation.Y -= Math.Min(0.1f, secondsUsed * 2);
                tf.Translation.Z -= Math.Min(1f, secondsUsed * 180);

                tf.Scale = 1 + Math.Min(0.6f, 2 * secondsUsed);


                byEntity.Controls.UsingHeldItemTransformAfter = tf;

                return(secondsUsed <= 4f);
            }

            // Let the client decide when he is done eating
            return(true);
        }
        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;
        }
        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);
        }
示例#9
0
        public void CullInvisibleChunks()
        {
            if (!ClientSettings.Occlusionculling || game.WorldMap.chunks.Count < 100)
            {
                return;
            }

            Vec3d camPos = game.player.Entity.CameraPos;

            centerpos.Set((int)(camPos.X / chunksize), (int)(camPos.Y / chunksize), (int)(camPos.Z / chunksize));

            isAboveHeightLimit = centerpos.Y >= game.WorldMap.ChunkMapSizeY;

            playerViewVec = EntityPos.GetViewVector(game.mousePitch, game.mouseYaw).Normalize();

            lock (game.WorldMap.chunksLock)
            {
                foreach (var val in game.WorldMap.chunks)
                {
                    val.Value.SetVisible(false);
                }

                // We sometimes have issues with chunks adjacent to the player getting culled, so lets make these always visible
                for (int dx = -1; dx <= 1; dx++)
                {
                    for (int dy = -1; dy <= 1; dy++)
                    {
                        for (int dz = -1; dz <= 1; dz++)
                        {
                            long        index3d = game.WorldMap.ChunkIndex3D(dx + centerpos.X, dy + centerpos.Y, dz + centerpos.Z);
                            ClientChunk chunk   = null;

                            if (game.WorldMap.chunks.TryGetValue(index3d, out chunk))
                            {
                                chunk.SetVisible(true);
                            }
                        }
                    }
                }
            }


            // Add some 15 extra degrees to the field of view angle for safety
            float fov = GameMath.Cos(game.MainCamera.Fov + 15 * GameMath.DEG2RAD);

            for (int i = 0; i < cubicShellPositions.Length; i++)
            {
                Vec3i vec = cubicShellPositions[i];

                float dotProd = playerViewVec.Dot(cubicShellPositionsNormalized[i]);
                if (dotProd <= fov / 2)
                {
                    // Outside view frustum
                    continue;
                }

                // It seems that one trace can cause issues where chunks are culled when they shouldn't
                // 2 traces with a y-offset seems to mitigate most of that issue
                TraverseRayAndMarkVisible(centerpos, vec, 0.25);
                TraverseRayAndMarkVisible(centerpos, vec, 0.75);
            }
        }
示例#10
0
        /// <summary>
        /// Returns the solar altitude from -1 to 1 for given latitude
        /// </summary>
        /// <param name="latitude">Must be between -1 and 1. -1 is the south pole, 0 is the equater, and 1 is the north pole</param>
        /// <returns></returns>
        public float GetSolarAltitude(double posX, double posZ, float yearRel, float dayRel)
        {
            float latitude = (float)onGetLatitude(posZ);

            // https://en.wikipedia.org/wiki/Solar_zenith_angle
            // theta = sin(phi) * sin(delta) + cos(phi) * cos(delta) * cos(h)
            // theta: the solar zenith angle

            // phi: the local latitude
            // h: the hour angle, in the local solar time.
            // delta: is the current declination of the Sun

            //  the solar hour angle is an expression of time, expressed in angular measurement, usually degrees, from solar noon
            float h = GameMath.TWOPI * (dayRel - 0.5f);

            float dayOfYear   = api.World.Calendar.DayOfYear;
            float daysPerYear = api.World.Calendar.DaysPerYear;

            // The Sun's declination at any given moment is calculated by:
            // delta = arcsin(sin(-23.44°) * sin(EL))
            // EL is the ecliptic longitude (essentially, the Earth's position in its orbit). Since the Earth's orbital eccentricity is small, its orbit can be approximated as a circle which causes up to 1° of error.
            // delta = -23.44° * cos(360° / 365 * (ye   arRel +10))
            // The number 10, in (N+10), is the approximate number of days after the December solstice to January 1
            float delta = -EarthAxialTilt *GameMath.Cos(GameMath.TWOPI *(dayOfYear + 10) / daysPerYear);

            // sample 1
            // latitude = 0.5 (equator)
            // day of year = 0.5 (summer)
            // sin(0.5) * sin(0.5 * -0.4) + cos(0.5) * cos(0.5 * -0.4) * cos((x / 24 - 0.5) * 3.14159 * 2)
            // http://fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJzaW4oMC41KSpzaW4oMC41Ki0wLjQpK2NvcygwLjUpKmNvcygwLjUqLTAuNCkqY29zKCh4LzI0LTAuNSkqMy4xNDE1OSoyKSIsImNvbG9yIjoiIzAwMDAwMCJ9LHsidHlwZSI6MTAwMCwid2luZG93IjpbIjAiLCIyNCIsIi0xIiwiMSJdfV0-

            // sample 2
            // latitude = 0.5 (~austria, europe)
            // day of year = 1 (winter)
            // sin(3.14159/2 * 0.5) * sin(1 * -0.4) + cos(3.14159/2 * 0.5) * cos(1 * -0.4) * cos((x / 24 - 0.5) * 3.14159 * 2)
            // http://fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJzaW4oMy4xNDE1OS80KSpzaW4oMSotMC40KStjb3MoMy4xNDE1OS80KSpjb3MoMSotMC40KSpjb3MoKHgvMjQtMC41KSozLjE0MTU5KjIpIiwiY29sb3IiOiIjMDAwMDAwIn0seyJ0eXBlIjoxMDAwLCJ3aW5kb3ciOlsiMCIsIjI0IiwiLTEiLCIxIl19XQ--

            // sample 3
            // latitude = -1 (south pole)
            // day of year = 1 (winter)
            // sin(3.14159/2 * -1) * sin(1 * -0.4) + cos(3.14159/2 * -1) * cos(1 * -0.4) * cos((x / 24 - 0.5) * 3.14159 * 2)
            // http://fooplot.com/#W3sidHlwZSI6MCwiZXEiOiJzaW4oMy4xNDE1OS8yKi0xKSpzaW4oMSotMC40KStjb3MoMy4xNDE1OS8yKi0xKSpjb3MoMSotMC40KSpjb3MoKHgvMjQtMC41KSozLjE0MTU5KjIpIiwiY29sb3IiOiIjMDAwMDAwIn0seyJ0eXBlIjoxMDAwLCJ3aW5kb3ciOlsiMCIsIjI0IiwiLTEiLCIxIl19XQ--


            // So this method is supposed to return the solar zenith or 90 - SolartAltitude, but apparently its inverted, dunno why
            return(GameMath.Sin(latitude * GameMath.PIHALF) * GameMath.Sin(delta) + GameMath.Cos(latitude * GameMath.PIHALF) * GameMath.Cos(delta) * GameMath.Cos(h));
        }
        public void OnRenderFrame(float deltaTime, EnumRenderStage stage)
        {
            IRenderAPI rpi    = capi.Render;
            Vec3d      camPos = capi.World.Player.Entity.CameraPos;

            rpi.GlDisableCullFace();
            rpi.GlToggleBlend(true);

            IStandardShaderProgram prog = rpi.PreparedStandardShader(pos.X, pos.Y, pos.Z);

            prog.Tex2D            = capi.BlockTextureAtlas.AtlasTextureIds[0];
            prog.DontWarpVertices = 0;
            prog.AddRenderFlags   = 0;
            prog.RgbaAmbientIn    = rpi.AmbientColor;
            prog.RgbaFogIn        = rpi.FogColor;
            prog.FogMinIn         = rpi.FogMin;
            prog.FogDensityIn     = rpi.FogDensity;
            prog.RgbaTint         = ColorUtil.WhiteArgbVec;
            prog.NormalShaded     = 1;
            prog.ExtraGodray      = 0;
            prog.SsaoAttn         = 0;
            prog.AlphaTest        = 0.05f;
            prog.OverlayOpacity   = 0;


            prog.ModelMatrix = ModelMat
                               .Identity()
                               .Translate(pos.X - camPos.X + 0.001f, pos.Y - camPos.Y, pos.Z - camPos.Z - 0.001f)
                               .Translate(0f, 1 / 16f, 0f)
                               .Values
            ;

            prog.ViewMatrix       = rpi.CameraMatrixOriginf;
            prog.ProjectionMatrix = rpi.CurrentProjectionMatrix;

            rpi.RenderMesh(potRef == null ? potWithFoodRef : potRef);

            if (!isInOutputSlot)
            {
                float origx = GameMath.Sin(capi.World.ElapsedMilliseconds / 300f) * 5 / 16f;
                float origz = GameMath.Cos(capi.World.ElapsedMilliseconds / 300f) * 5 / 16f;

                float cookIntensity = GameMath.Clamp((temp - 50) / 50, 0, 1);

                prog.ModelMatrix = ModelMat
                                   .Identity()
                                   .Translate(pos.X - camPos.X, pos.Y - camPos.Y, pos.Z - camPos.Z)
                                   .Translate(0, 6.5f / 16f, 0)
                                   .Translate(-origx, 0, -origz)
                                   .RotateX(cookIntensity * GameMath.Sin(capi.World.ElapsedMilliseconds / 50f) / 60)
                                   .RotateZ(cookIntensity * GameMath.Sin(capi.World.ElapsedMilliseconds / 50f) / 60)
                                   .Translate(origx, 0, origz)
                                   .Values
                ;
                prog.ViewMatrix       = rpi.CameraMatrixOriginf;
                prog.ProjectionMatrix = rpi.CurrentProjectionMatrix;


                rpi.RenderMesh(lidRef);
            }

            prog.Stop();
        }
 private double PolarHelperX(double angle, double distance)
 {
     return(GameMath.Cos(angle) * distance);
 }