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