Exemplo n.º 1
0
        public override void Initialize(ICoreAPI api)
        {
            base.Initialize(api);

            ownBlock = Block as BlockCondenser;
            if (Api.Side == EnumAppSide.Client)
            {
                currentMesh = GenMesh();
                MarkDirty(true);
                RegisterGameTickListener(clientTick, 200, Api.World.Rand.Next(50));

                if (!inventory[1].Empty && bucketMesh == null)
                {
                    genBucketMesh();
                }
            }

            Matrixf mat = new Matrixf();

            mat
            .Translate(0.5f, 0, 0.5f)
            .RotateYDeg(Block.Shape.rotateY - 90)
            .Translate(-0.5f, 0, -0.5f)
            ;

            spoutPos = mat.TransformVector(new Vec4f(8f / 16f, 7.5f / 16f, 3.5f / 16f, 1)).XYZ;

            var steamposoffmin = mat.TransformVector(new Vec4f(6 / 16f, 13 / 16f, 9 / 16f, 1)).XYZ;
            var steamposoffmax = mat.TransformVector(new Vec4f(10 / 16f, 13 / 16f, 13 / 16f, 1)).XYZ;

            steamposmin = Pos.ToVec3d().Add(steamposoffmin);
            steamposmax = Pos.ToVec3d().Add(steamposoffmax);
        }
Exemplo n.º 2
0
        public void InitForUse(float rotateYDeg)
        {
            Matrixf mat = new Matrixf();

            mat.RotateYDeg(rotateYDeg);

            BlockCodes         = new Dictionary <int, AssetLocation>();
            TransformedOffsets = new List <BlockOffsetAndNumber>();

            foreach (var val in BlockNumbers)
            {
                BlockCodes[val.Value] = val.Key;
            }

            for (int i = 0; i < Offsets.Count; i++)
            {
                Vec4i offset     = Offsets[i];
                Vec4f offsetTf   = new Vec4f(offset.X, offset.Y, offset.Z, 0);
                Vec4f tfedOffset = mat.TransformVector(offsetTf);

                TransformedOffsets.Add(new BlockOffsetAndNumber()
                {
                    X = (int)Math.Round(tfedOffset.X), Y = (int)Math.Round(tfedOffset.Y), Z = (int)Math.Round(tfedOffset.Z), W = offset.W
                });
            }
        }
Exemplo n.º 3
0
        private void Crush(int slot, int capTier, double xOffset)
        {
            ItemStack inputStack  = inv[slot].TakeOut(1);
            ItemStack outputStack = inputStack.Collectible.CrushingProps?.CrushedStack?.ResolvedItemstack.Clone();

            Vec3d  position   = mat.TransformVector(new Vec4d(xOffset * 0.999, 0.1, 0.8, 0)).XYZ.Add(Pos).Add(0.5, 0, 0.5);
            double lengthways = Api.World.Rand.NextDouble() * 0.07 - 0.035;
            double sideways   = Api.World.Rand.NextDouble() * 0.03 - 0.005;
            Vec3d  velocity   = new Vec3d(Facing.IsAxisNS ? sideways : lengthways, Api.World.Rand.NextDouble() * 0.02 - 0.01, Facing.IsAxisNS ? lengthways : sideways);

            bool tierPassed = outputStack != null && inputStack.Collectible.CrushingProps.HardnessTier <= capTier;

            Api.World.SpawnItemEntity(tierPassed ? outputStack : inputStack, position, velocity);

            MarkDirty(true);
        }
Exemplo n.º 4
0
        public bool OnTesselation(ITerrainMeshPool mesher, ITesselatorAPI tessThreadTesselator)
        {
            ICoreClientAPI capi = api as ICoreClientAPI;

            Matrixf mat = new Matrixf();

            mat.RotateYDeg(block.Shape.rotateY);

            for (int i = 0; i < 8; i++)
            {
                if (inv[i].Empty)
                {
                    continue;
                }

                ItemStack  stack      = inv[i].Itemstack;
                BlockCrock crockblock = stack.Collectible as BlockCrock;
                Vec3f      rot        = new Vec3f(0, block.Shape.rotateY, 0);

                MeshData mesh = BlockEntityCrock.GetMesh(tessThreadTesselator, api, crockblock, crockblock.GetContents(api.World, stack), crockblock.GetRecipeCode(api.World, stack), rot);

                float y = i >= 4 ? 10 / 16f : 2 / 16f;
                float x = (i % 2 == 0) ? 4 / 16f : 12 / 16f;
                float z = ((i % 4) >= 2) ? 10 / 16f : 4 / 16f;

                Vec4f offset = mat.TransformVector(new Vec4f(x - 0.5f, y, z - 0.5f, 0));
                mesh.Translate(offset.XYZ);
                mesher.AddMeshData(mesh);
            }

            return(false);
        }
Exemplo n.º 5
0
        protected override MeshData genMesh(ItemStack stack, int index)
        {
            BlockCrock crockblock = stack.Collectible as BlockCrock;
            BlockMeal  mealblock  = stack.Collectible as BlockMeal;
            MeshData   mesh;

            if (crockblock != null)
            {
                Vec3f rot = new Vec3f(0, block.Shape.rotateY, 0);
                mesh = BlockEntityCrock.GetMesh(capi.Tesselator, Api, crockblock, crockblock.GetContents(Api.World, stack), crockblock.GetRecipeCode(Api.World, stack), rot).Clone();
            }
            else if (mealblock != null)
            {
                ICoreClientAPI capi      = Api as ICoreClientAPI;
                MealMeshCache  meshCache = capi.ModLoader.GetModSystem <MealMeshCache>();
                mesh = meshCache.GenMealInContainerMesh(mealblock, mealblock.GetCookingRecipe(capi.World, stack), mealblock.GetNonEmptyContents(capi.World, stack));
            }
            else
            {
                ICoreClientAPI capi = Api as ICoreClientAPI;
                if (stack.Class == EnumItemClass.Block)
                {
                    mesh = capi.TesselatorManager.GetDefaultBlockMesh(stack.Block).Clone();
                }
                else
                {
                    nowTesselatingItem  = stack.Item;
                    nowTesselatingShape = capi.TesselatorManager.GetCachedShape(stack.Item.Shape.Base);
                    capi.Tesselator.TesselateItem(stack.Item, out mesh, this);

                    mesh.RenderPasses.Fill((short)EnumChunkRenderPass.BlendNoCull);
                }
            }

            if (stack.Collectible.Attributes?["onDisplayTransform"].Exists == true)
            {
                ModelTransform transform = stack.Collectible.Attributes?["onDisplayTransform"].AsObject <ModelTransform>();
                transform.EnsureDefaultValues();
                mesh.ModelTransform(transform);
            }


            if (stack.Class == EnumItemClass.Item && (stack.Item.Shape == null || stack.Item.Shape.VoxelizeTexture))
            {
                mesh.Rotate(new Vec3f(0.5f, 0.5f, 0.5f), GameMath.PIHALF, 0, 0);
                mesh.Scale(new Vec3f(0.5f, 0.5f, 0.5f), 0.33f, 0.5f, 0.33f);
                mesh.Translate(0, -7.5f / 16f, 0f);
            }


            float x = ((index % 4) >= 2) ? 12 / 16f : 4 / 16f;
            float y = index >= 4 ? 10 / 16f : 2 / 16f;
            float z = (index % 2 == 0) ? 4 / 16f : 10 / 16f;

            Vec4f offset = mat.TransformVector(new Vec4f(x - 0.5f, y, z - 0.5f, 0));

            mesh.Translate(offset.XYZ);

            return(mesh);
        }
Exemplo n.º 6
0
        public override void TranslateMesh(MeshData mesh, int index)
        {
            float x = 3 / 16f + 3 / 16f * index - 1;
            float y = 0;
            float z = 0;

            Vec4f offset = mat.TransformVector(new Vec4f(x, y, z, 0));

            mesh.Translate(offset.XYZ);
        }
Exemplo n.º 7
0
        public override void TranslateMesh(MeshData mesh, int index)
        {
            float x = ((index % 4) >= 2) ? 12 / 16f : 4 / 16f;
            float y = index >= 4 ? 10 / 16f : 2 / 16f;
            float z = (index % 2 == 0) ? 4 / 16f : 10 / 16f;

            Vec4f offset = mat.TransformVector(new Vec4f(x - 0.5f, y, z - 0.5f, 0));

            mesh.Translate(offset.XYZ);
        }
        public override void OnRenderGUI(float deltaTime)
        {
            base.OnRenderGUI(deltaTime);

            capi.Render.GlPushMatrix();

            if (focused)
            {
                capi.Render.GlTranslate(0, 0, 150);
            }

            capi.Render.GlRotate(-14, 1, 0, 0);

            mat.Identity();
            mat.RotateXDeg(-14);
            Vec4f  lightRot = mat.TransformVector(lighPos);
            double pad      = GuiElement.scaled(GuiElementItemSlotGridBase.unscaledSlotPadding);

            capi.Render.CurrentActiveShader.Uniform("lightPosition", new Vec3f(lightRot.X, lightRot.Y, lightRot.Z));

            capi.Render.PushScissor(insetSlotBounds);

            if (curTab == 0)
            {
                capi.Render.RenderEntityToGui(
                    deltaTime,
                    capi.World.Player.Entity,
                    insetSlotBounds.renderX + pad - GuiElement.scaled(195) * charZoom + GuiElement.scaled(115 * (1 - charZoom)),
                    insetSlotBounds.renderY + pad - GuiElement.scaled(10 + 30 * (1 - charZoom)),
                    (float)GuiElement.scaled(230),
                    yaw,
                    (float)GuiElement.scaled(330 * charZoom),
                    ColorUtil.WhiteArgb);
            }
            else
            {
                capi.Render.RenderEntityToGui(
                    deltaTime,
                    capi.World.Player.Entity,
                    insetSlotBounds.renderX + pad - GuiElement.scaled(95),
                    insetSlotBounds.renderY + pad - GuiElement.scaled(35),
                    (float)GuiElement.scaled(230),
                    yaw,
                    (float)GuiElement.scaled(180),
                    ColorUtil.WhiteArgb);
            }

            capi.Render.PopScissor();

            capi.Render.CurrentActiveShader.Uniform("lightPosition", new Vec3f(1, -1, 0).Normalize());

            capi.Render.GlPopMatrix();
        }
Exemplo n.º 9
0
        public override void Initialize(ICoreAPI api, JsonObject properties)
        {
            base.Initialize(api, properties);

            bepu = Blockentity as BEPulverizer;


            Matrixf mat = bepu.mat;

            leftOffset  = mat.TransformVector(new Vec4f(4.5f / 16f - 0.5f, 4 / 16f, -4.5f / 16f, 0f));
            rightOffset = mat.TransformVector(new Vec4f(11.5f / 16f - 0.5f, 4 / 16f, -4.5f / 16f, 0f));


            slideDustParticles = new SimpleParticleProperties(1, 3, ColorUtil.ToRgba(40, 220, 220, 220), new Vec3d(), new Vec3d(), new Vec3f(-0.25f, -0.25f, -0.25f), new Vec3f(0.25f, 0.25f, 0.25f), 1, 1, 0.1f, 0.2f, EnumParticleModel.Quad);
            slideDustParticles.AddPos.Set(2 / 32f, 1 / 32f, 2 / 32f);
            slideDustParticles.WithTerrainCollision = false;
            slideDustParticles.ParticleModel        = EnumParticleModel.Quad;
            slideDustParticles.LifeLength           = 0.75f;
            slideDustParticles.SelfPropelled        = true;
            slideDustParticles.GravityEffect        = 0f;
            slideDustParticles.SizeEvolve           = EvolvingNatFloat.create(EnumTransformFunction.QUADRATIC, 0.4f);
            slideDustParticles.OpacityEvolve        = EvolvingNatFloat.create(EnumTransformFunction.QUADRATIC, -16f);
            slideDustParticles.MinQuantity          = 1;
            slideDustParticles.AddQuantity          = 3;

            Vec4f vec = mat.TransformVector(new Vec4f(-0.1f, -0.1f, 0.2f, 0f));

            slideDustParticles.MinVelocity.Set(vec.X, vec.Y, vec.Z);

            vec = mat.TransformVector(new Vec4f(0.2f, -0.05f, 0.2f, 0f));
            slideDustParticles.AddVelocity.Set(vec.X, vec.Y, vec.Z);

            leftSlidePos  = mat.TransformVector(new Vec4f(4.5f / 16f - 0.5f, 4 / 16f, -2.5f / 16f, 0f)).XYZ.ToVec3d().Add(Position).Add(0.5, 0, 0.5);
            rightSlidePos = mat.TransformVector(new Vec4f(11.5f / 16f - 0.5f, 4 / 16f, -2.5f / 16f, 0f)).XYZ.ToVec3d().Add(Position).Add(0.5, 0, 0.5);
        }
Exemplo n.º 10
0
        static void initRotations()
        {
            for (int i = 0; i < 4; i++)
            {
                Matrixf m = new Matrixf();
                m.Translate(0.5f, 0.5f, 0.5f);
                m.RotateYDeg(i * 90);
                m.Translate(-0.5f, -0.5f, -0.5f);

                Vec3f[] poses = candleWickPositionsByRot[i] = new Vec3f[candleWickPositions.Length];
                for (int j = 0; j < poses.Length; j++)
                {
                    Vec4f rotated = m.TransformVector(new Vec4f(candleWickPositions[j].X / 16f, candleWickPositions[j].Y / 16f, candleWickPositions[j].Z / 16f, 1));
                    poses[j] = new Vec3f(rotated.X, rotated.Y, rotated.Z);
                }
            }
        }
Exemplo n.º 11
0
        protected override MeshData genMesh(ItemStack stack, int index)
        {
            MeshData mesh;

            ICoreClientAPI capi = Api as ICoreClientAPI;

            if (stack.Class == EnumItemClass.Block)
            {
                mesh = capi.TesselatorManager.GetDefaultBlockMesh(stack.Block).Clone();
            }
            else
            {
                nowTesselatingItem  = stack.Item;
                nowTesselatingShape = capi.TesselatorManager.GetCachedShape(stack.Item.Shape.Base);
                capi.Tesselator.TesselateItem(stack.Item, out mesh, this);

                mesh.RenderPasses.Fill((short)EnumChunkRenderPass.BlendNoCull);
            }

            if (stack.Collectible.Attributes?["onmoldrackTransform"].Exists == true)
            {
                ModelTransform transform = stack.Collectible.Attributes?["onmoldrackTransform"].AsObject <ModelTransform>();
                transform.EnsureDefaultValues();

                transform.Rotation.X = 0;
                transform.Rotation.Y = block.Shape.rotateY;
                transform.Rotation.Z = 90;

                mesh.ModelTransform(transform);
            }

            //ModelTransform tf = new ModelTransform();
            //tf.EnsureDefaultValues();
            //mesh.ModelTransform(tf);

            float x = 3 / 16f + 3 / 16f * index - 1;
            float y = 0;
            float z = 0;

            Vec4f offset = mat.TransformVector(new Vec4f(x, y, z, 0));

            mesh.Translate(offset.XYZ);

            return(mesh);
        }
Exemplo n.º 12
0
        protected override MeshData genMesh(ItemStack stack, int index)
        {
            MeshData       mesh;
            ICoreClientAPI capi = Api as ICoreClientAPI;

            nowTesselatingItem  = stack.Item;
            nowTesselatingShape = capi.TesselatorManager.GetCachedShape(stack.Item.Shape.Base);
            capi.Tesselator.TesselateItem(stack.Item, out mesh, this);

            mesh.RenderPasses.Fill((short)EnumChunkRenderPass.BlendNoCull);

            Vec4f offset = mat.TransformVector(new Vec4f(
                                                   (rand.NextDouble() >= 0.33 ? rand.NextDouble() >= 0.66 ? 0 : -0.5f : 0.5f),
                                                   (index + 1) * 8,
                                                   (rand.NextDouble() >= 0.33 ? rand.NextDouble() >= 0.66 ? 0 : -0.5f : 0.5f),
                                                   0
                                                   ));

            mesh.Translate(offset.XYZ);

            return(mesh);
        }
Exemplo n.º 13
0
        protected void RenderHeldItem(float dt, bool isShadowPass, bool right)
        {
            IRenderAPI rapi  = capi.Render;
            ItemSlot   slot  = right ? eagent?.RightHandItemSlot : eagent?.LeftHandItemSlot;
            ItemStack  stack = slot?.Itemstack;

            AttachmentPointAndPose apap = entity.AnimManager.Animator.GetAttachmentPointPose(right ? "RightHand" : "LeftHand");

            if (apap == null || stack == null)
            {
                return;
            }

            AttachmentPoint        ap         = apap.AttachPoint;
            ItemRenderInfo         renderInfo = rapi.GetItemStackRenderInfo(slot, right ? EnumItemRenderTarget.HandTp : EnumItemRenderTarget.HandTpOff);
            IStandardShaderProgram prog       = null;

            if (renderInfo?.Transform == null)
            {
                return;                                // Happens with unknown items/blocks
            }
            ItemModelMat
            .Set(ModelMat)
            .Mul(apap.AnimModelMatrix)
            .Translate(renderInfo.Transform.Origin.X, renderInfo.Transform.Origin.Y, renderInfo.Transform.Origin.Z)
            .Scale(renderInfo.Transform.ScaleXYZ.X, renderInfo.Transform.ScaleXYZ.Y, renderInfo.Transform.ScaleXYZ.Z)
            .Translate(ap.PosX / 16f + renderInfo.Transform.Translation.X, ap.PosY / 16f + renderInfo.Transform.Translation.Y, ap.PosZ / 16f + renderInfo.Transform.Translation.Z)
            .RotateX((float)(ap.RotationX + renderInfo.Transform.Rotation.X) * GameMath.DEG2RAD)
            .RotateY((float)(ap.RotationY + renderInfo.Transform.Rotation.Y) * GameMath.DEG2RAD)
            .RotateZ((float)(ap.RotationZ + renderInfo.Transform.Rotation.Z) * GameMath.DEG2RAD)
            .Translate(-(renderInfo.Transform.Origin.X), -(renderInfo.Transform.Origin.Y), -(renderInfo.Transform.Origin.Z))
            ;


            if (isShadowPass)
            {
                rapi.CurrentActiveShader.BindTexture2D("tex2d", renderInfo.TextureId, 0);
                float[] mvpMat = Mat4f.Mul(ItemModelMat.Values, capi.Render.CurrentModelviewMatrix, ItemModelMat.Values);
                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.DontWarpVertices = 0;
                prog.AddRenderFlags   = 0;
                prog.NormalShaded     = 1;
                prog.Tex2D            = renderInfo.TextureId;
                prog.RgbaTint         = ColorUtil.WhiteArgbVec;
                prog.AlphaTest        = renderInfo.AlphaTest;
                prog.DamageEffect     = renderInfo.DamageEffect;

                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(stack);
                    prog.BaseUvOrigin = new Vec2f(texPos.x1, texPos.y1);
                }


                int     temp      = (int)stack.Collectible.GetTemperature(capi.World, stack);
                float[] glowColor = ColorUtil.GetIncandescenceColorAsColor4f(temp);

                /*lightrgbs[0] += glowColor[0];
                *  lightrgbs[1] += glowColor[1];
                *  lightrgbs[2] += glowColor[2];*/

                var gi = GameMath.Clamp((temp - 500) / 3, 0, 255);
                prog.ExtraGlow     = gi;
                prog.RgbaAmbientIn = rapi.AmbientColor;
                prog.RgbaLightIn   = lightrgbs;
                prog.RgbaGlowIn    = new Vec4f(glowColor[0], glowColor[1], glowColor[2], gi / 255f);
                prog.RgbaFogIn     = rapi.FogColor;
                prog.FogMinIn      = rapi.FogMin;
                prog.FogDensityIn  = rapi.FogDensity;
                prog.NormalShaded  = renderInfo.NormalShaded ? 1 : 0;

                prog.ProjectionMatrix = rapi.CurrentProjectionMatrix;
                prog.ViewMatrix       = rapi.CameraMatrixOriginf;
                prog.ModelMatrix      = ItemModelMat.Values;
            }


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

            rapi.RenderMesh(renderInfo.ModelRef);

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

            if (!isShadowPass)
            {
                prog.DamageEffect = 0;
            }

            if (!isShadowPass)
            {
                prog.Stop();

                AdvancedParticleProperties[] ParticleProperties = stack.Collectible?.ParticleProperties;

                if (stack.Collectible != null && !capi.IsGamePaused)
                {
                    Vec4f        pos          = ItemModelMat.TransformVector(new Vec4f(stack.Collectible.TopMiddlePos.X, stack.Collectible.TopMiddlePos.Y, stack.Collectible.TopMiddlePos.Z, 1));
                    EntityPlayer entityPlayer = capi.World.Player.Entity;
                    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 = pos.X + entity.Pos.X + -(entity.Pos.X - entityPlayer.CameraPos.X);
                            bps.basePos.Y = pos.Y + entity.Pos.Y + -(entity.Pos.Y - entityPlayer.CameraPos.Y);
                            bps.basePos.Z = pos.Z + entity.Pos.Z + -(entity.Pos.Z - entityPlayer.CameraPos.Z);

                            eagent.World.SpawnParticles(bps);
                        }
                    }
                }
            }
        }
Exemplo n.º 14
0
        public void update(float dt)
        {
            if (pinned)
            {
                if (pinnedTo != null)
                {
                    if (pinnedTo.ShouldDespawn && pinnedTo.DespawnReason?.reason != EnumDespawnReason.Unload)
                    {
                        UnPin();
                        return;
                    }

                    // New ideas:
                    // don't apply force onto the player/entity on compression
                    // apply huge forces onto the player on strong extension (to prevent massive stretching) (just set player motion to 0 or so. or we add a new countermotion field thats used in EntityControlledPhysics?)

                    float weight = pinnedTo.Properties.Weight;
                    float counterTensionStrength = GameMath.Clamp(50f / weight, 0.1f, 2f);

                    bool  extraResist           = (pinnedTo as EntityAgent)?.Controls.Sneak == true || pinnedTo.AnimManager?.IsAnimationActive("sit") == true || pinnedTo.AnimManager?.IsAnimationActive("sleep") == true;
                    float tensionResistStrength = weight / 10f * (extraResist ? 200 : 0);

                    pinOffsetTransform.Identity();
                    pinOffsetTransform.RotateY(pinnedTo.SidedPos.Yaw - pinnedToOffsetStartYaw);
                    tmpvec.Set(pinnedToOffset.X, pinnedToOffset.Y, pinnedToOffset.Z, 1);
                    Vec4f outvec = pinOffsetTransform.TransformVector(tmpvec);

                    EntityPos pos = pinnedTo.SidedPos;
                    Pos.Set(pos.X + outvec.X, pos.Y + outvec.Y, pos.Z + outvec.Z);

                    bool pushable = !(pinnedTo is EntityPlayer eplr && eplr.Player.WorldData.CurrentGameMode == EnumGameMode.Creative);

                    if (pushable && extension > 0) // Do not act on compressive force
                    {
                        float f = counterTensionStrength * dt * 0.003f;
                        pos.Motion.Add(
                            GameMath.Clamp(Math.Abs(TensionDirection.X) - tensionResistStrength, 0, 400) * f * Math.Sign(TensionDirection.X),
                            GameMath.Clamp(Math.Abs(TensionDirection.Y) - tensionResistStrength, 0, 400) * f * Math.Sign(TensionDirection.Y),
                            GameMath.Clamp(Math.Abs(TensionDirection.Z) - tensionResistStrength, 0, 400) * f * Math.Sign(TensionDirection.Z)
                            );
                    }

                    Velocity.Set(0, 0, 0);
                }
                else
                {
                    Velocity.Set(0, 0, 0);

                    accum1s += dt;

                    if (accum1s >= 1)
                    {
                        accum1s = 0;
                        Block block = cs.api.World.BlockAccessor.GetBlock(PinnedToBlockPos);
                        if (!block.HasBehavior <BlockBehaviorRopeTieable>())
                        {
                            UnPin();
                        }
                    }
                }

                return;
            }

            // Calculate the force on this ball
            Vec3f force = Tension.Clone();

            force.Y -= GravityStrength * 10;

            // Calculate the acceleration
            Vec3f acceleration = force * (float)InvMass;

            if (CollideFlags == 0)
            {
                acceleration.X += (float)cs.windSpeed.X * InvMass;
            }


            // Update velocity
            Vec3f nextVelocity = Velocity + (acceleration * dt);

            // Damp the velocity
            nextVelocity *= dampFactor;

            // Collision detection
            float size = 0.1f;

            cs.pp.HandleBoyancy(Pos, nextVelocity, cs.boyant, GravityStrength, dt, size);
            CollideFlags = cs.pp.UpdateMotion(Pos, nextVelocity, size);

            dt *= 0.99f;
            Pos.Add(nextVelocity.X * dt, nextVelocity.Y * dt, nextVelocity.Z * dt);


            Velocity.Set(nextVelocity);
            Tension.Set(0, 0, 0);
        }