protected void CreateRotorGrid(out MyCubeGrid rotorGrid, out MyAttachableTopBlockBase rotorBlock, long builtBy, MyCubeBlockDefinitionGroup rotorGroup) { Debug.Assert(Sync.IsServer, "Rotor grid can be created only on server"); if (rotorGroup == null) { rotorGrid = null; rotorBlock = null; return; } var gridSize = CubeGrid.GridSizeEnum; float size = MyDefinitionManager.Static.GetCubeSize(gridSize); var matrix = MatrixD.CreateWorld(Vector3D.Transform(DummyPosition, CubeGrid.WorldMatrix), WorldMatrix.Forward, WorldMatrix.Up); var definition = rotorGroup[gridSize]; Debug.Assert(definition != null); var block = MyCubeGrid.CreateBlockObjectBuilder(definition, Vector3I.Zero, MyBlockOrientation.Identity, MyEntityIdentifier.AllocateId(), OwnerId, fullyBuilt: MySession.Static.CreativeMode); var gridBuilder = MyObjectBuilderSerializer.CreateNewObject <MyObjectBuilder_CubeGrid>(); gridBuilder.GridSizeEnum = gridSize; gridBuilder.IsStatic = false; gridBuilder.PositionAndOrientation = new MyPositionAndOrientation(matrix); gridBuilder.CubeBlocks.Add(block); var grid = MyEntityFactory.CreateEntity <MyCubeGrid>(gridBuilder); grid.Init(gridBuilder); rotorGrid = grid; MyMotorRotor rotor = (MyMotorRotor)rotorGrid.GetCubeBlock(Vector3I.Zero).FatBlock; rotorBlock = rotor; rotorGrid.PositionComp.SetPosition(rotorGrid.WorldMatrix.Translation - (Vector3D.Transform(rotor.DummyPosLoc, rotorGrid.WorldMatrix) - rotorGrid.WorldMatrix.Translation)); if (!CanPlaceRotor(rotorBlock, builtBy)) { rotorGrid = null; rotorBlock = null; grid.Close(); return; } MyEntities.Add(grid); if (MyFakes.ENABLE_SENT_GROUP_AT_ONCE) { MyMultiplayer.ReplicateImmediatelly(MyExternalReplicable.FindByObject(grid), MyExternalReplicable.FindByObject(CubeGrid)); } MatrixD masterToSlave = rotorBlock.CubeGrid.WorldMatrix * MatrixD.Invert(WorldMatrix); m_connectionState.Value = new State() { TopBlockId = rotorBlock.EntityId, MasterToSlave = masterToSlave }; }
private static bool OnAttach(MyMechanicalConnectionBlockBase __instance, MyAttachableTopBlockBase top) { if (!BlockLimiterConfig.Instance.MergerBlocking || !BlockLimiterConfig.Instance.EnableLimits || !MySession.Static.Ready) { return(true); } var topGrid = top.CubeGrid; var baseGrid = __instance.CubeGrid; var remoteUserId = MyEventContext.Current.Sender.Value; DateTime topDateTime = default; if (_lastChecked.TryGetValue(__instance.EntityId, out var inDateTime) || _lastChecked.TryGetValue(top.EntityId, out topDateTime)) { if (Math.Abs((DateTime.Now - inDateTime).Seconds) > 10) { _lastChecked.Remove(__instance.EntityId); } if (Math.Abs((DateTime.Now - topDateTime).Seconds) > 10) { _lastChecked.Remove(top.EntityId); } if (remoteUserId <= 0) { return(false); } Utilities.SendFailSound(remoteUserId); Utilities.ValidationFailed(remoteUserId); return(false); } var result = Grid.CanMerge(topGrid, baseGrid, out var blocks, out var count, out var limitName); if (result) { return(true); } _lastChecked[__instance.EntityId] = DateTime.Now; _lastChecked[top.EntityId] = DateTime.Now; BlockLimiter.Instance.Log.Info($"Blocked attachement between {baseGrid.DisplayName} and {topGrid.DisplayName}"); if (remoteUserId <= 0) { return(false); } Utilities.SendFailSound(remoteUserId); Utilities.ValidationFailed(remoteUserId); var msg = Utilities.GetMessage(BlockLimiterConfig.Instance.DenyMessage, blocks, limitName, count); BlockLimiter.Instance.Torch.CurrentSession.Managers.GetManager <ChatManagerServer>()? .SendMessageAsOther(BlockLimiterConfig.Instance.ServerName, msg, Color.Red, remoteUserId); topGrid.RemoveBlock(top.SlimBlock); baseGrid.RemoveBlock(__instance.SlimBlock); return(false); }
protected override bool Attach(MyAttachableTopBlockBase rotor, bool updateGroup = true) { if (rotor is MyMotorRotor && base.Attach(rotor, updateGroup)) { CreateConstraint(rotor); UpdateText(); return(true); } return(false); }
private void SetConstraintPosition(MyAttachableTopBlockBase rotor, HkLimitedHingeConstraintData data) { var posA = DummyPosition; var posB = rotor.Position * rotor.CubeGrid.GridSize; var axisA = PositionComp.LocalMatrix.Up; var axisAPerp = PositionComp.LocalMatrix.Forward; var axisB = rotor.PositionComp.LocalMatrix.Up; var axisBPerp = rotor.PositionComp.LocalMatrix.Forward; data.SetInBodySpace(posA, posB, axisA, axisB, axisAPerp, axisBPerp, CubeGrid.Physics, TopGrid.Physics); }
protected override void Detach(MyCubeGrid topGrid, bool updateGroup = true) { if ((base.TopBlock != null) & updateGroup) { MyAttachableTopBlockBase topBlock = base.TopBlock; if (topBlock is MyMotorAdvancedRotor) { base.m_conveyorEndpoint.Detach((topBlock as MyMotorAdvancedRotor).ConveyorEndpoint as MyAttachableConveyorEndpoint); } } base.Detach(topGrid, updateGroup); }
protected override bool CanPlaceRotor(MyAttachableTopBlockBase rotorBlock, long builtBy) { // Compute the rough actual position for the wheel, this improves the detection if it can be placed float wheelDistance = BlockDefinition.Size.Y * CubeGrid.GridSize - 0.2f * CubeGrid.GridSize; Vector3D wheelPosition = this.WorldMatrix.Translation + this.WorldMatrix.Up * wheelDistance; float wheelRadius = rotorBlock.ModelCollision.HavokCollisionShapes[0].ConvexRadius * 0.9f; // First test if we intersect any blocks of our own grid BoundingSphereD sphere = rotorBlock.Model.BoundingSphere; sphere.Center = wheelPosition; sphere.Radius = wheelRadius; CubeGrid.GetBlocksInsideSphere(ref sphere, m_tmpSet); // If we intersect more than 1 block (because wheel sometimes intersects suspension), don't add wheel if (m_tmpSet.Count > 1) { m_tmpSet.Clear(); if (builtBy == MySession.Static.LocalPlayerId) { MyHud.Notifications.Add(MyNotificationSingletons.WheelNotPlaced); } return(false); } m_tmpSet.Clear(); // Next test if we intersect any physics objects HkSphereShape spShape = new HkSphereShape(wheelRadius); Quaternion q = Quaternion.Identity; MyPhysics.GetPenetrationsShape(rotorBlock.ModelCollision.HavokCollisionShapes[0], ref wheelPosition, ref q, m_tmpList, MyPhysics.CollisionLayers.DefaultCollisionLayer); // If we have any collisions with anything other than our own grid, don't add the wheel // We already checked for inner-grid collisions in the previous case for (int i = 0; i < m_tmpList.Count; i++) { MyCubeGrid grid = m_tmpList[i].GetCollisionEntity() as MyCubeGrid; if (grid == null || grid != CubeGrid) { m_tmpList.Clear(); if (builtBy == MySession.Static.LocalPlayerId) { MyHud.Notifications.Add(MyNotificationSingletons.WheelNotPlaced); } return(false); } } m_tmpList.Clear(); return(true); }
protected override bool CreateConstraint(MyAttachableTopBlockBase rotor) { if (!base.CreateConstraint(rotor)) { return(false); } var rotorBody = TopGrid.Physics.RigidBody; rotorBody.MaxAngularVelocity = float.MaxValue; rotorBody.Restitution = 0.5f; CubeGrid.GetPhysicsBody().HavokWorld.BreakOffPartsUtil.UnmarkEntityBreakable(rotorBody); if (MyFakes.WHEEL_SOFTNESS) { HkUtils.SetSoftContact(rotorBody, null, MyPhysicsConfig.WheelSoftnessRatio, MyPhysicsConfig.WheelSoftnessVelocity); } var info = HkGroupFilter.CalcFilterInfo(rotorBody.Layer, CubeGrid.GetPhysicsBody().HavokCollisionSystemID, 1, 1); rotorBody.SetCollisionFilterInfo(info); CubeGrid.GetPhysicsBody().HavokWorld.RefreshCollisionFilterOnEntity(rotorBody); HkWheelConstraintData data = new HkWheelConstraintData(); var suspensionAx = PositionComp.LocalMatrix.Forward; var posA = DummyPosition + (suspensionAx * m_height); var posB = (rotor as MyMotorRotor).DummyPosLoc; var axisA = PositionComp.LocalMatrix.Up; var axisAPerp = PositionComp.LocalMatrix.Forward; var axisB = rotor.PositionComp.LocalMatrix.Up; data.SetInBodySpace(posB, posA, axisB, axisA, suspensionAx, suspensionAx, RotorGrid.Physics, CubeGrid.Physics); //empirical values because who knows what havoc sees behind this //docs say one value should mean same effect for 2 ton or 200 ton vehicle //but we have virtual mass blocks so real mass doesnt corespond to actual "weight" in game and varying gravity data.SetSuspensionDamping(m_damping); data.SetSuspensionStrength(m_strenth); //Min/MaxHeight also define the limits of the suspension and SuspensionTravel lowers this limit data.SetSuspensionMinLimit((BlockDefinition.MinHeight - m_height) * SuspensionTravel); data.SetSuspensionMaxLimit((BlockDefinition.MaxHeight - m_height) * SuspensionTravel); m_constraint = new HkConstraint(rotorBody, CubeGrid.Physics.RigidBody, data); m_constraint.WantRuntime = true; CubeGrid.Physics.AddConstraint(m_constraint); if (!m_constraint.InWorld) { Debug.Fail("Constraint not added!"); CubeGrid.Physics.RemoveConstraint(m_constraint); m_constraint = null; return(false); } m_constraint.Enabled = true; return(true); }
protected override bool Attach(MyAttachableTopBlockBase rotor, bool updateGroup = true) { if (!(rotor is MyMotorRotor)) { return(false); } bool flag1 = base.Attach(rotor, updateGroup); if ((flag1 & updateGroup) && (base.TopBlock is MyMotorAdvancedRotor)) { base.m_conveyorEndpoint.Attach((base.TopBlock as MyMotorAdvancedRotor).ConveyorEndpoint as MyAttachableConveyorEndpoint); } return(flag1); }
protected override bool Attach(MyAttachableTopBlockBase rotor, bool updateGroup = true) { if (rotor is MyMotorRotor && base.Attach(rotor, updateGroup)) { Debug.Assert(rotor != null, "Rotor cannot be null!"); Debug.Assert(m_constraint == null, "Already attached, call detach first!"); Debug.Assert(m_connectionState.Value.TopBlockId == 0 || m_connectionState.Value.TopBlockId == rotor.EntityId, "m_rotorBlockId must be set prior calling Attach"); var rotorBody = m_topGrid.Physics.RigidBody; var data = new HkLimitedHingeConstraintData(); m_motor = new HkVelocityConstraintMotor(1.0f, 1000000f); data.SetSolvingMethod(HkSolvingMethod.MethodStabilized); data.Motor = m_motor; data.DisableLimits(); var posA = DummyPosition; var posB = rotor.Position * rotor.CubeGrid.GridSize; var axisA = PositionComp.LocalMatrix.Up; var axisAPerp = PositionComp.LocalMatrix.Forward; var axisB = rotor.PositionComp.LocalMatrix.Up; var axisBPerp = rotor.PositionComp.LocalMatrix.Forward; data.SetInBodySpace(posA, posB, axisA, axisB, axisAPerp, axisBPerp, CubeGrid.Physics, m_topGrid.Physics); m_constraint = new HkConstraint(CubeGrid.Physics.RigidBody, rotorBody, data); m_constraint.WantRuntime = true; CubeGrid.Physics.AddConstraint(m_constraint); if (!m_constraint.InWorld) { CubeGrid.Physics.RemoveConstraint(m_constraint); m_constraint.Dispose(); m_constraint = null; return(false); } m_constraint.Enabled = true; SetAngleToPhysics(); m_topBlock.Attach(this); m_isAttached = true; UpdateText(); return(true); } return(false); }
protected override bool Attach(MyAttachableTopBlockBase rotor, bool updateGroup = true) { if (rotor is MyMotorRotor) { var ret = base.Attach(rotor, updateGroup); if (ret && updateGroup) { if (m_topBlock is MyMotorAdvancedRotor) { m_conveyorEndpoint.Attach((m_topBlock as MyMotorAdvancedRotor).ConveyorEndpoint as MyAttachableConveyorEndpoint); } } return(ret); } return(false); }
protected override bool Attach(MyAttachableTopBlockBase rotor, bool updateGroup = true) { Debug.Assert(rotor != null, "Rotor cannot be null!"); Debug.Assert(m_constraint == null, "Already attached, call detach first!"); if (rotor is MyMotorRotor && base.Attach(rotor, updateGroup)) { CreateConstraint(rotor); PropagateFriction(m_friction); UpdateIsWorking(); if (m_updateBrakeNeeded) { UpdateBrake(); } return(true); } return(false); }
protected override bool CreateConstraint(MyAttachableTopBlockBase rotor) { if (!base.CreateConstraint(rotor)) { return(false); } Debug.Assert(rotor != null, "Rotor cannot be null!"); Debug.Assert(m_constraint == null, "Already attached, call detach first!"); Debug.Assert( m_connectionState.Value.TopBlockId == 0 || m_connectionState.Value.TopBlockId == rotor.EntityId, "m_rotorBlockId must be set prior calling Attach"); var rotorBody = TopGrid.Physics.RigidBody; var data = new HkLimitedHingeConstraintData(); m_motor = new HkVelocityConstraintMotor(1.0f, 1000000f); data.SetSolvingMethod(HkSolvingMethod.MethodStabilized); data.Motor = m_motor; data.DisableLimits(); SetConstraintPosition(rotor, data); m_constraint = new HkConstraint(CubeGrid.Physics.RigidBody, rotorBody, data); m_constraint.WantRuntime = true; CubeGrid.Physics.AddConstraint(m_constraint); if (!m_constraint.InWorld) { CubeGrid.Physics.RemoveConstraint(m_constraint); m_constraint.Dispose(); m_constraint = null; return(false); } m_constraint.Enabled = true; SetAngleToPhysics(); return(true); }
protected override bool Attach(MyAttachableTopBlockBase rotor, bool updateGroup = true) { Debug.Assert(rotor != null, "Rotor cannot be null!"); Debug.Assert(m_constraint == null, "Already attached, call detach first!"); if (rotor is MyMotorRotor) { if (CubeGrid.Physics != null && CubeGrid.Physics.Enabled) { m_topBlock = rotor; m_topGrid = m_topBlock.CubeGrid; var rotorBody = m_topGrid.Physics.RigidBody; rotorBody.MaxAngularVelocity = float.MaxValue; rotorBody.Restitution = 0.5f; CubeGrid.GetPhysicsBody().HavokWorld.BreakOffPartsUtil.UnmarkEntityBreakable(rotorBody); if (MyFakes.WHEEL_SOFTNESS) { HkUtils.SetSoftContact(rotorBody, null, MyPhysicsConfig.WheelSoftnessRatio, MyPhysicsConfig.WheelSoftnessVelocity); } var info = HkGroupFilter.CalcFilterInfo(rotorBody.Layer, CubeGrid.GetPhysicsBody().HavokCollisionSystemID, 1, 1); rotorBody.SetCollisionFilterInfo(info); HkWheelConstraintData data = new HkWheelConstraintData(); var suspensionAx = PositionComp.LocalMatrix.Forward; var posA = DummyPosition + (suspensionAx * m_height); var posB = (rotor as MyMotorRotor).DummyPosLoc; var axisA = PositionComp.LocalMatrix.Up; var axisAPerp = PositionComp.LocalMatrix.Forward; var axisB = rotor.PositionComp.LocalMatrix.Up; //empirical values because who knows what havoc sees behind this //docs say one value should mean same effect for 2 ton or 200 ton vehicle //but we have virtual mass blocks so real mass doesnt corespond to actual "weight" in game and varying gravity data.SetSuspensionDamping(m_damping); data.SetSuspensionStrength(m_strenth); //Min/MaxHeight also define the limits of the suspension and SuspensionTravel lowers this limit data.SetSuspensionMinLimit((BlockDefinition.MinHeight - m_height) * SuspensionTravel); data.SetSuspensionMaxLimit((BlockDefinition.MaxHeight - m_height) * SuspensionTravel); data.SetInBodySpace(posB, posA, axisB, axisA, suspensionAx, suspensionAx, RotorGrid.Physics, CubeGrid.Physics); m_constraint = new HkConstraint(rotorBody, CubeGrid.Physics.RigidBody, data); m_constraint.WantRuntime = true; CubeGrid.Physics.AddConstraint(m_constraint); if (!m_constraint.InWorld) { Debug.Fail("Constraint not added!"); CubeGrid.Physics.RemoveConstraint(m_constraint); m_constraint = null; return(false); } m_constraint.Enabled = true; m_topBlock.Attach(this); m_isAttached = true; PropagateFriction(m_friction); UpdateIsWorking(); if (m_updateBrakeNeeded) { UpdateBrake(); } if (m_updateFrictionNeeded) { FrictionChanged(); } if (updateGroup) { OnConstraintAdded(GridLinkTypeEnum.Physical, m_topGrid); OnConstraintAdded(GridLinkTypeEnum.Logical, m_topGrid); } return(true); } } return(false); }
protected override bool CanPlaceRotor(MyAttachableTopBlockBase rotorBlock, long builtBy) { return(true); }
protected override void CreateTopGrid(out MyCubeGrid rotorGrid, out MyAttachableTopBlockBase rotorBlock, long builtBy) { CreateRotorGrid(out rotorGrid, out rotorBlock, builtBy, MyDefinitionManager.Static.TryGetDefinitionGroup(MotorDefinition.RotorPart)); }