public override void OnRemovedFromScene(object source) { base.OnRemovedFromScene(source); m_topBlockToReattach = m_topBlock; Detach(true); CubeGrid.OnPhysicsChanged -= cubeGrid_OnPhysicsChanged; }
protected override void Closing() { CubeGrid.OnPhysicsChanged -= cubeGrid_OnPhysicsChanged; Detach(); m_topBlockToReattach = null; base.Closing(); }
bool CanAttach(MyAttachableTopBlockBase top) { bool closed = MarkedForClose || Closed || CubeGrid.MarkedForClose || CubeGrid.Closed; if (closed) { return(false); } bool topClosed = top.MarkedForClose || top.Closed || top.CubeGrid.MarkedForClose || top.CubeGrid.Closed; if (topClosed) { return(false); } bool notInWorld = CubeGrid.Physics == null || CubeGrid.Physics.RigidBody == null || CubeGrid.Physics.RigidBody.InWorld == false; if (notInWorld) { return(false); } bool topNotInWorld = top.CubeGrid.Physics == null || top.CubeGrid.Physics.RigidBody == null || CubeGrid.Physics.RigidBody.InWorld == false; if (topNotInWorld) { return(false); } return(true); }
protected override bool Attach(MyAttachableTopBlockBase topBlock, bool updateGroup = true) { Debug.Assert(topBlock != null, "Top block cannot be null!"); MyPistonTop pistonTop = topBlock as MyPistonTop; if (pistonTop != null && base.Attach(topBlock, updateGroup)) { Debug.Assert(m_constraint == null, "Contraint already attached, call detach first!"); Debug.Assert(m_connectionState.Value.TopBlockId.HasValue && (m_connectionState.Value.TopBlockId.Value == 0 || m_connectionState.Value.TopBlockId.Value == topBlock.EntityId), "m_topBlockId must be set prior calling Attach!"); UpdateAnimation(); CreateConstraint(topBlock); if (updateGroup) { m_conveyorEndpoint.Attach(pistonTop.ConveyorEndpoint as MyAttachableConveyorEndpoint); } UpdateText(); return(true); } return(false); }
private void FindTopServer(MyEntityUpdateEnum updateFlags) { MyAttachableTopBlockBase top = null; if (m_topBlockToReattach != null) { top = m_topBlockToReattach; } else { top = FindMatchingTop(); } if (top != null) { if (CanDetach()) { Detach(); } if (TryAttach(top)) { m_topBlockToReattach = null; } else { updateFlags |= MyEntityUpdateEnum.EACH_10TH_FRAME; } } else { updateFlags |= MyEntityUpdateEnum.EACH_10TH_FRAME; } }
private void TryForceWeldServer() { if (m_topBlockToReattach != null && m_forceWeld) { m_topBlock = m_topBlockToReattach; m_topGrid = m_topBlock.CubeGrid; m_topBlockToReattach = null; } if (m_topBlock == null && (m_connectionState.Value.TopBlockId.HasValue)) { TryGetTop(); NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME; return; } if (m_topBlock != null) { if (m_forceWeld || m_speedWeld) { if (m_welded == false) { WeldGroup(false); UpdateText(); } } else if (m_welded) { UnweldGroup(); m_forceApply = true; TryAttach(); UpdateText(); } } }
private void CreateTopPart(out MyAttachableTopBlockBase topBlock, long builtBy, MyCubeBlockDefinitionGroup topGroup, bool smallToLarge) { Debug.Assert(Sync.IsServer, "Server only method."); if (topGroup == null) { topBlock = null; return; } var gridSize = CubeGrid.GridSizeEnum; if (smallToLarge && gridSize == MyCubeSize.Large) //If we have pressed the Attach Small Rotor Head button on large grid take the small grid definition from pair { gridSize = MyCubeSize.Small; } var matrix = GetTopGridMatrix(); var definition = topGroup[gridSize]; Debug.Assert(definition != null); var block = MyCubeGrid.CreateBlockObjectBuilder(definition, Vector3I.Zero, MyBlockOrientation.Identity, MyEntityIdentifier.AllocateId(), OwnerId, fullyBuilt: MySession.Static.CreativeMode); matrix.Translation = Vector3D.Transform(-definition.Center * CubeGrid.GridSize, matrix); 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); topBlock = (MyAttachableTopBlockBase)grid.GetCubeBlock(Vector3I.Zero).FatBlock; if (!CanPlaceTop(topBlock, builtBy)) { topBlock = null; grid.Close(); return; } grid.PositionComp.SetPosition(grid.WorldMatrix.Translation - (Vector3D.Transform(topBlock.DummyPosLoc, grid.WorldMatrix) - grid.WorldMatrix.Translation)); MyEntities.Add(grid); if (MyFakes.ENABLE_SENT_GROUP_AT_ONCE) { MyMultiplayer.ReplicateImmediatelly(MyExternalReplicable.FindByObject(grid), MyExternalReplicable.FindByObject(CubeGrid)); } MatrixD masterToSlave = topBlock.CubeGrid.WorldMatrix * MatrixD.Invert(WorldMatrix); m_connectionState.Value = new State() { TopBlockId = topBlock.EntityId, MasterToSlave = masterToSlave }; }
protected override bool Attach(MyAttachableTopBlockBase topBlock, bool updateGroup = true) { Debug.Assert(topBlock != null, "Top block cannot be null!"); if (CubeGrid == topBlock.CubeGrid) { return(false); } MyPistonTop pistonTop = topBlock as MyPistonTop; if (pistonTop != null && base.Attach(topBlock, updateGroup)) { Debug.Assert(m_constraint == null, "Contraint already attached, call detach first!"); Debug.Assert(m_connectionState.Value.TopBlockId.HasValue && (m_connectionState.Value.TopBlockId.Value == 0 || m_connectionState.Value.TopBlockId.Value == topBlock.EntityId), "m_topBlockId must be set prior calling Attach!"); UpdateAnimation(); var matAD = MatrixD.CreateWorld(Vector3D.Transform(Vector3D.Transform(m_constraintBasePos, Subpart3.WorldMatrix), CubeGrid.PositionComp.WorldMatrixNormalizedInv), PositionComp.LocalMatrix.Forward, PositionComp.LocalMatrix.Up); var matBD = MatrixD.CreateWorld(m_topBlock.Position * m_topBlock.CubeGrid.GridSize, m_topBlock.PositionComp.LocalMatrix.Forward, m_topBlock.PositionComp.LocalMatrix.Up); var matA = (Matrix)matAD; var matB = (Matrix)matBD; m_fixedData = new HkFixedConstraintData(); m_fixedData.SetInertiaStabilizationFactor(10); m_fixedData.SetSolvingMethod(HkSolvingMethod.MethodStabilized); m_fixedData.SetInBodySpace(matA, matB, CubeGrid.Physics, m_topGrid.Physics); //Dont dispose the fixed data or we wont have access to them m_constraint = new HkConstraint(CubeGrid.Physics.RigidBody, topBlock.CubeGrid.Physics.RigidBody, m_fixedData); m_constraint.WantRuntime = true; CubeGrid.Physics.AddConstraint(m_constraint); if (!m_constraint.InWorld) { Debug.Fail("Constraint was not added to world"); CubeGrid.Physics.RemoveConstraint(m_constraint); m_constraint.Dispose(); m_constraint = null; m_fixedData = null; return(false); } m_constraint.Enabled = true; m_topBlock = topBlock; m_topGrid = topBlock.CubeGrid; topBlock.Attach(this); m_isAttached = true; if (updateGroup) { m_conveyorEndpoint.Attach(pistonTop.ConveyorEndpoint as MyAttachableConveyorEndpoint); } UpdateText(); return(true); } return(false); }
public void Reattach(bool force = false) { if (m_isWelding || m_welded || m_topBlock == null || m_topBlock.Closed) { return; } var top = m_topBlock; bool detached = Detach(force); if (Sync.IsServer) { m_connectionState.Value = new State() { TopBlockId = 0, MasterToSlave = null }; } if (CanAttach(top)) { m_topBlock = top; m_topGrid = top.CubeGrid; bool attached = Attach(top, force); if (attached && Sync.IsServer) { MatrixD masterToSlave = top.CubeGrid.WorldMatrix * MatrixD.Invert(WorldMatrix); m_connectionState.Value = new State() { TopBlockId = top.EntityId, MasterToSlave = masterToSlave, Force = force }; } //Debug.Assert(detached && attached); if (!top.MarkedForClose && top.CubeGrid.Physics != null) { top.CubeGrid.Physics.ForceActivate(); } } else { if (MyCubeGridGroups.Static.GetGroups(GridLinkTypeEnum.Physical).LinkExists(EntityId, CubeGrid, top.CubeGrid)) { OnConstraintRemoved(GridLinkTypeEnum.Physical, top.CubeGrid); } if (MyCubeGridGroups.Static.GetGroups(GridLinkTypeEnum.Logical).LinkExists(EntityId, CubeGrid, top.CubeGrid)) { OnConstraintRemoved(GridLinkTypeEnum.Logical, top.CubeGrid); } if (Sync.IsServer && top != null) { top.Attach(this); } } }
private void CreateTopGrid(out MyCubeGrid topGrid, out MyAttachableTopBlockBase topBlock, long builtBy, MyCubeBlockDefinitionGroup topGroup) { if (topGroup == null) { topGrid = null; topBlock = null; return; } var gridSize = CubeGrid.GridSizeEnum; float size = MyDefinitionManager.Static.GetCubeSize(gridSize); var matrix = GetTopGridMatrix(); var definition = topGroup[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); topGrid = grid; topBlock = (MyAttachableTopBlockBase)topGrid.GetCubeBlock(Vector3I.Zero).FatBlock; if (!CanPlaceTop(topBlock, builtBy)) { topGrid = null; topBlock = null; grid.Close(); return; } //topGrid.SetPosition(topGrid.WorldMatrix.Translation - (topBlock.WorldMatrix.Translation/*Vector3.Transform(topBlock.DummyPosLoc, topGrid.WorldMatrix) - topGrid.WorldMatrix.Translation*/)); MyEntities.Add(grid); if (MyFakes.ENABLE_SENT_GROUP_AT_ONCE) { MyMultiplayer.ReplicateImmediatelly(MyExternalReplicable.FindByObject(grid), MyExternalReplicable.FindByObject(CubeGrid)); } MatrixD masterToSlave = topBlock.CubeGrid.WorldMatrix * MatrixD.Invert(WorldMatrix); m_connectionState.Value = new State() { TopBlockId = topBlock.EntityId, MasterToSlave = masterToSlave }; }
private void FindAndAttachTopServer() { Debug.Assert(Sync.IsServer, "Server only method"); MyAttachableTopBlockBase top = FindMatchingTop(); if (top != null) { TryAttach(top); } }
//Only overriden, not called from elsewhere protected virtual bool Attach(MyAttachableTopBlockBase topBlock, bool updateGroup = true) { Debug.Assert(TopBlock == null, "Inconsistency"); Debug.Assert(!m_welded, "Inconsistency"); if (topBlock.CubeGrid.Physics == null) { return(false); } if (CubeGrid.Physics == null || !CubeGrid.Physics.Enabled) { return(false); } m_topBlock = topBlock; m_topGrid = TopBlock.CubeGrid; TopBlock.Attach(this); if (updateGroup) { CubeGrid.OnPhysicsChanged += cubeGrid_OnPhysicsChanged; TopGrid.OnGridSplit += CubeGrid_OnGridSplit; TopGrid.OnPhysicsChanged += cubeGrid_OnPhysicsChanged; TopBlock.OnClosing += TopBlock_OnClosing; OnConstraintAdded(GridLinkTypeEnum.Physical, TopGrid); OnConstraintAdded(GridLinkTypeEnum.Logical, TopGrid); RaiseAttachedEntityChanged(); //top is already set we can call here } if (Sync.IsServer) { MatrixD masterToSlave = TopBlock.CubeGrid.WorldMatrix * MatrixD.Invert(WorldMatrix); m_connectionState.Value = new State() { TopBlockId = TopBlock.EntityId, MasterToSlave = masterToSlave, Welded = m_welded }; } else if (m_connectionState.Value.MasterToSlave.HasValue) { TopBlock.CubeGrid.WorldMatrix = MatrixD.Multiply(m_connectionState.Value.MasterToSlave.Value, this.WorldMatrix); } m_isAttached = true; //Welding only allowed when attached if (m_forceWeld) { WeldGroup(true); } CheckVelocities(); return(true); }
public void ReattachTop(MyAttachableTopBlockBase top) { if (m_topBlock != null || m_welded) { Detach(); } m_topBlockToReattach = top; // Rotor not found by EntityId or not in scene, try again in 10 frames NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME; }
protected virtual bool CreateConstraint(MyAttachableTopBlockBase top) { if (CanAttach(top)) { return(!m_welded && CubeGrid.Physics.RigidBody != top.CubeGrid.Physics.RigidBody); } else { return(false); } }
protected override bool CanPlaceTop(MyAttachableTopBlockBase topBlock, long builtBy) { // Compute the rough actual position for the head, this improves the detection if it can be placed float topDistance = (Subpart3.Model.BoundingBoxSize.Y); Vector3D topPosition = this.Subpart3.WorldMatrix.Translation + this.WorldMatrix.Up * topDistance; float topRadius = topBlock.ModelCollision.HavokCollisionShapes[0].ConvexRadius * 0.9f; // First test if we intersect any blocks of our own grid BoundingSphereD sphere = topBlock.Model.BoundingSphere; sphere.Center = topPosition; sphere.Radius = topRadius; CubeGrid.GetBlocksInsideSphere(ref sphere, m_tmpSet); // If we intersect more than 1 block (because top sometimes intersects piston), don't add top if (m_tmpSet.Count > 1) { m_tmpSet.Clear(); if (builtBy == MySession.Static.LocalPlayerId) { MyHud.Notifications.Add(MyNotificationSingletons.HeadNotPlaced); } return(false); } m_tmpSet.Clear(); // Next test if we intersect any physics objects HkSphereShape spShape = new HkSphereShape(topRadius); Quaternion q = Quaternion.Identity; MyPhysics.GetPenetrationsShape(topBlock.ModelCollision.HavokCollisionShapes[0], ref topPosition, ref q, m_penetrations, MyPhysics.CollisionLayers.DefaultCollisionLayer); // If we have any collisions with anything other than our own grid, don't add the head // We already checked for inner-grid collisions in the previous case for (int i = 0; i < m_penetrations.Count; i++) { MyCubeGrid grid = m_penetrations[i].GetCollisionEntity().GetTopMostParent() as MyCubeGrid; if (grid == null || grid != CubeGrid) { m_penetrations.Clear(); if (builtBy == MySession.Static.LocalPlayerId) { MyHud.Notifications.Add(MyNotificationSingletons.HeadNotPlaced); } return(false); } } m_penetrations.Clear(); return(true); }
private MyAttachableTopBlockBase FindMatchingTop() { Debug.Assert(CubeGrid != null, "\"Impossible\""); Debug.Assert(m_penetrations != null, "\"Impossible\""); Debug.Assert(CubeGrid.Physics != null, "\"Impossible\""); Quaternion orientation; Vector3D pos; Vector3 halfExtents; ComputeTopQueryBox(out pos, out halfExtents, out orientation); try { MyPhysics.GetPenetrationsBox(ref halfExtents, ref pos, ref orientation, m_penetrations, MyPhysics.CollisionLayers.DefaultCollisionLayer); foreach (var obj in m_penetrations) { var entity = obj.GetCollisionEntity(); if (entity == null || entity == CubeGrid) { continue; } MyAttachableTopBlockBase top = FindTopInGrid(entity, pos); if (top != null) { return(top); } MyPhysicsBody body = entity.Physics as MyPhysicsBody; if (body != null) { foreach (var child in body.WeldInfo.Children) { top = FindTopInGrid(child.Entity, pos); if (top != null) { return(top); } } } } } catch (Exception ex) { } finally { m_penetrations.Clear(); } return(null); }
public override void OnUnregisteredFromGridSystems() { base.OnUnregisteredFromGridSystems(); if (Sync.IsServer) { if (m_topBlock != null) { m_topBlockToReattach = m_topBlock; Detach(true); } CubeGrid.OnGridSplit -= CubeGrid_OnGridSplit; } }
protected virtual bool Attach(MyAttachableTopBlockBase topBlock, bool updateGroup = true) { if (topBlock.CubeGrid.Physics == null) { return(false); } if (CubeGrid.Physics != null && CubeGrid.Physics.Enabled) { m_topBlock = topBlock; m_topGrid = m_topBlock.CubeGrid; if (updateGroup) { OnConstraintAdded(GridLinkTypeEnum.Physical, m_topGrid); OnConstraintAdded(GridLinkTypeEnum.Logical, m_topGrid); m_topGrid.OnPhysicsChanged += cubeGrid_OnPhysicsChanged; } if (CubeGrid.Physics.RigidBody == m_topGrid.Physics.RigidBody) { if (m_welded) { m_isAttached = true; return(true); } else { m_topAndBottomSamePhysicsBody.Value = true; m_isAttached = false; return(false); } } else { m_topAndBottomSamePhysicsBody.Value = false; } if (m_connectionState.Value.MasterToSlave.HasValue) { m_topBlock.CubeGrid.WorldMatrix = MatrixD.Multiply(m_connectionState.Value.MasterToSlave.Value, this.WorldMatrix); } return(true); } return(m_welded); }
public virtual bool Detach(bool updateGroup = true) { var tmptopGrid = m_topBlock == null ? null: m_topBlock.CubeGrid; if (m_connectionState.Value.Welded || m_welded) { UnweldGroup(); } else { if (updateGroup && tmptopGrid != null && (m_connectionState.Value.Welded == false || m_isWelding == false)) { OnConstraintRemoved(GridLinkTypeEnum.Physical, tmptopGrid); OnConstraintRemoved(GridLinkTypeEnum.Logical, tmptopGrid); } } //Debug.Assert(m_topGrid != null); DisposeConstraint(); if (m_topBlock != null) { m_topBlock.Detach(m_connectionState.Value.Welded || m_isWelding); if (updateGroup) { tmptopGrid.OnPhysicsChanged -= cubeGrid_OnPhysicsChanged; if (Sync.IsServer) { m_connectionState.Value = new State() { TopBlockId = 0, Welded = false }; } } } m_topGrid = null; m_topBlock = null; m_isAttached = false; UpdateText(); return(true); }
protected override bool Attach(MyAttachableTopBlockBase rotor, bool updateGroup = true) { if (rotor is MyMotorRotor) { var ret = base.Attach(rotor, updateGroup); if (ret) { if (m_topBlock is MyMotorAdvancedRotor) { m_conveyorEndpoint.Attach((m_topBlock as MyMotorAdvancedRotor).ConveyorEndpoint as MyAttachableConveyorEndpoint); } } return ret; } return false; }
private bool TryAttach(MyAttachableTopBlockBase top) { bool attached = false; if (CanAttach(top)) { attached = Attach(top); if ((attached || m_topAndBottomSamePhysicsBody) && Sync.IsServer) { MatrixD masterToSlave = top.CubeGrid.WorldMatrix * MatrixD.Invert(WorldMatrix); m_connectionState.Value = new State() { TopBlockId = top.EntityId, MasterToSlave = masterToSlave, Welded = m_welded }; } } return(attached); }
private void WeldGroup(bool force) { var topBlock = m_topBlock; MyCubeGrid topGrid = m_topBlock.CubeGrid; m_isWelding = true; if (m_isAttached) { Detach(false); } MyWeldingGroups.Static.CreateLink(EntityId, CubeGrid, topGrid); if (MyCubeGridGroups.Static.GetGroups(GridLinkTypeEnum.Physical).LinkExists(EntityId, CubeGrid, topGrid) == false) { OnConstraintAdded(GridLinkTypeEnum.Physical, topGrid); } if (MyCubeGridGroups.Static.GetGroups(GridLinkTypeEnum.Logical).LinkExists(EntityId, CubeGrid, topGrid) == false) { OnConstraintAdded(GridLinkTypeEnum.Logical, topGrid); } if (Sync.IsServer) { MatrixD masterToSlave = topBlock.CubeGrid.WorldMatrix * MatrixD.Invert(WorldMatrix); m_connectionState.Value = new State() { TopBlockId = topBlock.EntityId, MasterToSlave = masterToSlave, Welded = true, Force = force }; } topBlock.Attach(this); topBlock.CubeGrid.OnPhysicsChanged += cubeGrid_OnPhysicsChanged; m_welded = true; m_topGrid = topGrid; m_topBlock = topBlock; m_isWelding = false; RaisePropertiesChanged(); }
//Only overriden, not called from elsewhere protected virtual void Detach(bool updateGroups = true) { Debug.Assert(m_isAttached && TopBlock != null, "Inconsistency! critical!"); if (m_welded) { UnweldGroup(); } if (updateGroups) { m_needReattach = false; //i.e. block could be destroyed after the flag was rised BreakLinks(TopGrid, TopBlock); if (Sync.IsServer) { m_connectionState.Value = new State() { TopBlockId = null, Welded = false }; } } DisposeConstraint(); if (TopBlock != null) { TopBlock.Detach(false); } m_topGrid = null; m_topBlock = null; m_isAttached = false; UpdateText(); if (updateGroups) { RaiseAttachedEntityChanged(); } }
/// <summary> /// Breaks links and unregisters all events /// </summary> private void BreakLinks(MyCubeGrid topGrid, MyAttachableTopBlockBase topBlock) { OnConstraintRemoved(GridLinkTypeEnum.Physical, topGrid); OnConstraintRemoved(GridLinkTypeEnum.Logical, topGrid); if (CubeGrid != null) { CubeGrid.OnPhysicsChanged -= cubeGrid_OnPhysicsChanged; } if (topGrid != null) { topGrid.OnGridSplit -= CubeGrid_OnGridSplit; topGrid.OnPhysicsChanged -= cubeGrid_OnPhysicsChanged; } if (topBlock != null) { topBlock.OnClosing -= TopBlock_OnClosing; } }
private void WeldGroup() { var topGrid = m_topGrid; var topBlock = m_topBlock; m_isWelding = true; m_weldedTopBlockId = m_topBlock.EntityId; Detach(false); MyWeldingGroups.Static.CreateLink(EntityId, CubeGrid, topGrid); if (MyCubeGridGroups.Static.GetGroups(GridLinkTypeEnum.Physical).LinkExists(EntityId, CubeGrid, topGrid) == false) { OnConstraintAdded(GridLinkTypeEnum.Physical, topGrid); } if (MyCubeGridGroups.Static.GetGroups(GridLinkTypeEnum.Logical).LinkExists(EntityId, CubeGrid, topGrid) == false) { OnConstraintAdded(GridLinkTypeEnum.Logical, topGrid); } if (Sync.IsServer) { MatrixD masterToSlave = topBlock.CubeGrid.WorldMatrix * MatrixD.Invert(WorldMatrix); m_connectionState.Value = new State() { TopBlockId = m_weldedTopBlockId, MasterToSlave = masterToSlave }; m_weldedEntityId.Value = m_weldedTopBlockId; } m_topGrid = topGrid; m_topBlock = topBlock; m_welded = true; m_isWelding = false; RaisePropertiesChanged(); }
protected override bool CreateConstraint(MyAttachableTopBlockBase topBlock) { if (!base.CreateConstraint(topBlock)) { return(false); } var matAD = MatrixD.CreateWorld( Vector3D.Transform(Vector3D.Transform(m_constraintBasePos, Subpart3.WorldMatrix), CubeGrid.PositionComp.WorldMatrixNormalizedInv), PositionComp.LocalMatrix.Forward, PositionComp.LocalMatrix.Up); var matBD = MatrixD.CreateWorld(TopBlock.Position * TopBlock.CubeGrid.GridSize, TopBlock.PositionComp.LocalMatrix.Forward, TopBlock.PositionComp.LocalMatrix.Up); var matA = (Matrix)matAD; var matB = (Matrix)matBD; m_fixedData = new HkFixedConstraintData(); m_fixedData.SetInertiaStabilizationFactor(10); m_fixedData.SetSolvingMethod(HkSolvingMethod.MethodStabilized); m_fixedData.SetInBodySpace(matA, matB, CubeGrid.Physics, TopGrid.Physics); //Dont dispose the fixed data or we wont have access to them m_constraint = new HkConstraint(CubeGrid.Physics.RigidBody, topBlock.CubeGrid.Physics.RigidBody, m_fixedData); m_constraint.WantRuntime = true; CubeGrid.Physics.AddConstraint(m_constraint); if (!m_constraint.InWorld) { Debug.Fail("Constraint was not added to world"); CubeGrid.Physics.RemoveConstraint(m_constraint); m_constraint.Dispose(); m_constraint = null; m_fixedData = null; return(false); } m_constraint.Enabled = true; return(true); }
private bool TryAttach(MyAttachableTopBlockBase top, bool updateGroup = true) { return(CanAttach(top) && Attach(top, updateGroup)); }
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; }
public virtual bool Detach(bool updateGroup = true) { var tmptopGrid = m_topBlock == null ? null: m_topBlock.CubeGrid; if (m_connectionState.Value.Welded || m_welded) { UnweldGroup(); } else { if (updateGroup && tmptopGrid != null && (m_connectionState.Value.Welded == false || m_isWelding == false)) { OnConstraintRemoved(GridLinkTypeEnum.Physical, tmptopGrid); OnConstraintRemoved(GridLinkTypeEnum.Logical, tmptopGrid); } } //Debug.Assert(m_topGrid != null); DisposeConstraint(); if (m_topBlock != null) { m_topBlock.Detach(m_connectionState.Value.Welded || m_isWelding); if(updateGroup) { tmptopGrid.OnPhysicsChanged -= cubeGrid_OnPhysicsChanged; if (Sync.IsServer) { m_connectionState.Value = new State() { TopBlockId = 0, Welded = false }; } } } m_topGrid = null; m_topBlock = null; m_isAttached = false; UpdateText(); return true; }
protected override void CreateTopGrid(out MyCubeGrid topGrid, out MyAttachableTopBlockBase topBlock, long ownerId) { CreateTopGrid(out topGrid, out topBlock, ownerId, MyDefinitionManager.Static.TryGetDefinitionGroup(BlockDefinition.TopPart)); }
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 void TryForceWeldServer() { if (m_topBlock == null && (m_connectionState.Value.TopBlockId.HasValue)) { TryGetTop(); NeedsUpdate |= MyEntityUpdateEnum.BEFORE_NEXT_FRAME; return; } if(m_topBlockToReattach != null && m_forceWeld) { m_topBlock = m_topBlockToReattach; m_topGrid = m_topBlock.CubeGrid; m_topBlockToReattach = null; } if (m_topBlock != null) { if (m_forceWeld || m_speedWeld) { if (m_welded == false) { WeldGroup(false); } } else if (m_welded) { UnweldGroup(); m_forceApply = true; TryAttach(); } } }
protected virtual bool CanPlaceRotor(MyAttachableTopBlockBase rotorBlock, long builtBy) { return(true); }
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); }
bool CanAttach(MyAttachableTopBlockBase top) { bool closed = MarkedForClose || Closed || CubeGrid.MarkedForClose || CubeGrid.Closed; if(closed) { return false; } bool topClosed = top.MarkedForClose || top.Closed || top.CubeGrid.MarkedForClose || top.CubeGrid.Closed; if(topClosed) { return false; } bool notInWorld = CubeGrid.Physics == null || CubeGrid.Physics.RigidBody == null || CubeGrid.Physics.RigidBody.InWorld == false || CubeGrid.Physics.RigidBody.IsAddedToWorld == false; if(notInWorld) { return false; } bool topNotInWorld = top.CubeGrid.Physics == null || top.CubeGrid.Physics.RigidBody == null || top.CubeGrid.Physics.RigidBody.InWorld == false || top.CubeGrid.Physics.RigidBody.IsAddedToWorld == false; if(topNotInWorld) { return false; } if(top.CubeGrid.Physics.HavokWorld != CubeGrid.Physics.HavokWorld) { return false; } return true; }
private void CreateTopGrid(out MyCubeGrid topGrid, out MyAttachableTopBlockBase topBlock, long ownerId) { CreateTopGrid(out topGrid, out topBlock, ownerId, MyDefinitionManager.Static.TryGetDefinitionGroup(((MyMechanicalConnectionBlockBaseDefinition)BlockDefinition).TopPart)); }
protected virtual bool CanPlaceRotor(MyAttachableTopBlockBase rotorBlock, long builtBy) { return true; }
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}; }
protected override bool CreateConstraint(MyAttachableTopBlockBase topBlock) { if (!base.CreateConstraint(topBlock)) return false; var matAD = MatrixD.CreateWorld( Vector3D.Transform(Vector3D.Transform(m_constraintBasePos, Subpart3.WorldMatrix), CubeGrid.PositionComp.WorldMatrixNormalizedInv), PositionComp.LocalMatrix.Forward, PositionComp.LocalMatrix.Up); var matBD = MatrixD.CreateWorld(TopBlock.Position*TopBlock.CubeGrid.GridSize, TopBlock.PositionComp.LocalMatrix.Forward, TopBlock.PositionComp.LocalMatrix.Up); var matA = (Matrix) matAD; var matB = (Matrix) matBD; m_fixedData = new HkFixedConstraintData(); m_fixedData.SetInertiaStabilizationFactor(10); m_fixedData.SetSolvingMethod(HkSolvingMethod.MethodStabilized); m_fixedData.SetInBodySpace(matA, matB, CubeGrid.Physics, TopGrid.Physics); //Dont dispose the fixed data or we wont have access to them m_constraint = new HkConstraint(CubeGrid.Physics.RigidBody, topBlock.CubeGrid.Physics.RigidBody, m_fixedData); m_constraint.WantRuntime = true; CubeGrid.Physics.AddConstraint(m_constraint); if (!m_constraint.InWorld) { Debug.Fail("Constraint was not added to world"); CubeGrid.Physics.RemoveConstraint(m_constraint); m_constraint.Dispose(); m_constraint = null; m_fixedData = null; return false; } m_constraint.Enabled = true; 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)); }
protected override bool Attach(MyAttachableTopBlockBase topBlock, bool updateGroup = true) { Debug.Assert(topBlock != null, "Top block cannot be null!"); MyPistonTop pistonTop = topBlock as MyPistonTop; if (pistonTop != null && base.Attach(topBlock, updateGroup)) { Debug.Assert(m_constraint == null, "Contraint already attached, call detach first!"); Debug.Assert(m_connectionState.Value.TopBlockId.HasValue && (m_connectionState.Value.TopBlockId.Value == 0 || m_connectionState.Value.TopBlockId.Value == topBlock.EntityId), "m_topBlockId must be set prior calling Attach!"); UpdateAnimation(); CreateConstraint(topBlock); if (updateGroup) { m_conveyorEndpoint.Attach(pistonTop.ConveyorEndpoint as MyAttachableConveyorEndpoint); } UpdateText(); return true; } return false; }
protected abstract void CreateTopGrid(out MyCubeGrid topGrid, out MyAttachableTopBlockBase topBlock, long ownerId);
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 Attach(MyAttachableTopBlockBase rotor, bool updateGroup = true) { if (rotor is MyMotorRotor && base.Attach(rotor, updateGroup)) { CreateConstraint(rotor); UpdateText(); return true; } return false; }
private void WeldGroup(bool force) { var topBlock = m_topBlock; MyCubeGrid topGrid = m_topBlock.CubeGrid; m_isWelding = true; if (m_isAttached) { Detach(false); } MyWeldingGroups.Static.CreateLink(EntityId, CubeGrid, topGrid); if (MyCubeGridGroups.Static.GetGroups(GridLinkTypeEnum.Physical).LinkExists(EntityId, CubeGrid, topGrid) == false) { OnConstraintAdded(GridLinkTypeEnum.Physical, topGrid); } if (MyCubeGridGroups.Static.GetGroups(GridLinkTypeEnum.Logical).LinkExists(EntityId, CubeGrid, topGrid) == false) { OnConstraintAdded(GridLinkTypeEnum.Logical, topGrid); } if (Sync.IsServer) { MatrixD masterToSlave = topBlock.CubeGrid.WorldMatrix * MatrixD.Invert(WorldMatrix); m_connectionState.Value = new State() { TopBlockId = topBlock.EntityId, MasterToSlave = masterToSlave, Welded = true,Force = force}; } topBlock.Attach(this); topBlock.CubeGrid.OnPhysicsChanged += cubeGrid_OnPhysicsChanged; m_welded = true; m_topGrid = topGrid; m_topBlock = topBlock; m_isWelding = false; RaisePropertiesChanged(); }
protected void TryForceWeldServer() { if (m_topBlock == null && (m_connectionState.Value.TopBlockId.HasValue)) { TryGetTop(); } if(m_topBlockToReattach != null && m_forceWeld) { m_topBlock = m_topBlockToReattach; m_topGrid = m_topBlock.CubeGrid; m_topBlockToReattach = null; } if (m_topBlock != null) { if (m_forceWeld) { if (m_welded == false) { WeldGroup(false); } } else if (m_welded) { UnweldGroup(); m_forceApply = true; TryAttach(); } } }
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 virtual bool Attach(MyAttachableTopBlockBase topBlock, bool updateGroup = true) { if (topBlock.CubeGrid.Physics == null) return false; if (CubeGrid.Physics != null && CubeGrid.Physics.Enabled) { m_topBlock = topBlock; m_topGrid = m_topBlock.CubeGrid; if (updateGroup) { OnConstraintAdded(GridLinkTypeEnum.Physical, m_topGrid); OnConstraintAdded(GridLinkTypeEnum.Logical, m_topGrid); m_topGrid.OnPhysicsChanged += cubeGrid_OnPhysicsChanged; } if (CubeGrid.Physics.RigidBody == m_topGrid.Physics.RigidBody) { if (m_welded) { m_isAttached = true; return true; } else { m_topAndBottomSamePhysicsBody.Value = true; m_isAttached = false; return false; } } else { m_topAndBottomSamePhysicsBody.Value = false; } if (m_connectionState.Value.MasterToSlave.HasValue) { m_topBlock.CubeGrid.WorldMatrix = MatrixD.Multiply(m_connectionState.Value.MasterToSlave.Value, this.WorldMatrix); } return true; } return m_welded; }
private bool TryAttach(MyAttachableTopBlockBase top) { bool attached = false; if (CanAttach(top)) { attached = Attach(top); if ((attached || m_topAndBottomSamePhysicsBody) && Sync.IsServer) { MatrixD masterToSlave = top.CubeGrid.WorldMatrix * MatrixD.Invert(WorldMatrix); m_connectionState.Value = new State() { TopBlockId = top.EntityId, MasterToSlave = masterToSlave, Welded = m_welded}; } } return attached; }
protected override bool Attach(MyAttachableTopBlockBase topBlock, bool updateGroup = true) { Debug.Assert(topBlock != null, "Top block cannot be null!"); if (CubeGrid == topBlock.CubeGrid) return false; MyPistonTop pistonTop = topBlock as MyPistonTop; if (pistonTop != null && base.Attach(topBlock, updateGroup)) { Debug.Assert(m_constraint == null, "Contraint already attached, call detach first!"); Debug.Assert(m_connectionState.Value.TopBlockId.HasValue && (m_connectionState.Value.TopBlockId.Value == 0 || m_connectionState.Value.TopBlockId.Value == topBlock.EntityId), "m_topBlockId must be set prior calling Attach!"); UpdateAnimation(); var matAD = MatrixD.CreateWorld(Vector3D.Transform(Vector3D.Transform(m_constraintBasePos, Subpart3.WorldMatrix), CubeGrid.PositionComp.WorldMatrixNormalizedInv), PositionComp.LocalMatrix.Forward, PositionComp.LocalMatrix.Up); var matBD = MatrixD.CreateWorld(m_topBlock.Position * m_topBlock.CubeGrid.GridSize, m_topBlock.PositionComp.LocalMatrix.Forward, m_topBlock.PositionComp.LocalMatrix.Up); var matA = (Matrix)matAD; var matB = (Matrix)matBD; m_fixedData = new HkFixedConstraintData(); m_fixedData.SetInertiaStabilizationFactor(10); m_fixedData.SetSolvingMethod(HkSolvingMethod.MethodStabilized); m_fixedData.SetInBodySpace(matA, matB, CubeGrid.Physics, m_topGrid.Physics); //Dont dispose the fixed data or we wont have access to them m_constraint = new HkConstraint(CubeGrid.Physics.RigidBody, topBlock.CubeGrid.Physics.RigidBody, m_fixedData); m_constraint.WantRuntime = true; CubeGrid.Physics.AddConstraint(m_constraint); if (!m_constraint.InWorld) { Debug.Fail("Constraint was not added to world"); CubeGrid.Physics.RemoveConstraint(m_constraint); m_constraint.Dispose(); m_constraint = null; m_fixedData = null; return false; } m_constraint.Enabled = true; m_topBlock = topBlock; m_topGrid = topBlock.CubeGrid; topBlock.Attach(this); m_isAttached = true; if (updateGroup) { m_conveyorEndpoint.Attach(pistonTop.ConveyorEndpoint as MyAttachableConveyorEndpoint); } UpdateText(); return true; } return false; }
private void CreateTopGrid(out MyCubeGrid topGrid, out MyAttachableTopBlockBase topBlock, long builtBy, MyCubeBlockDefinitionGroup topGroup) { if (topGroup == null) { topGrid = null; topBlock = null; return; } var gridSize = CubeGrid.GridSizeEnum; float size = MyDefinitionManager.Static.GetCubeSize(gridSize); var matrix = MatrixD.CreateWorld(Vector3D.Transform(m_constraintBasePos, Subpart3.WorldMatrix), WorldMatrix.Forward, WorldMatrix.Up); var definition = topGroup[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); topGrid = grid; topBlock = (MyPistonTop)topGrid.GetCubeBlock(Vector3I.Zero).FatBlock; if (!CanPlaceTop(topBlock, builtBy)) { topGrid = null; topBlock = null; grid.Close(); return; } //topGrid.SetPosition(topGrid.WorldMatrix.Translation - (topBlock.WorldMatrix.Translation/*Vector3.Transform(topBlock.DummyPosLoc, topGrid.WorldMatrix) - topGrid.WorldMatrix.Translation*/)); MyEntities.Add(grid); if (MyFakes.ENABLE_SENT_GROUP_AT_ONCE) { MyMultiplayer.ReplicateImmediatelly(MyExternalReplicable.FindByObject(grid), MyExternalReplicable.FindByObject(CubeGrid)); } }
protected virtual bool CanPlaceTop(MyAttachableTopBlockBase topBlock, long builtBy) { // Compute the rough actual position for the head, this improves the detection if it can be placed float topDistance = (Subpart3.Model.BoundingBoxSize.Y); Vector3D topPosition = this.Subpart3.WorldMatrix.Translation + this.WorldMatrix.Up * topDistance; float topRadius = topBlock.ModelCollision.HavokCollisionShapes[0].ConvexRadius * 0.9f; // First test if we intersect any blocks of our own grid BoundingSphereD sphere = topBlock.Model.BoundingSphere; sphere.Center = topPosition; sphere.Radius = topRadius; CubeGrid.GetBlocksInsideSphere(ref sphere, m_tmpSet); // If we intersect more than 1 block (because top sometimes intersects piston), don't add top if (m_tmpSet.Count > 1) { m_tmpSet.Clear(); if (builtBy == MySession.Static.LocalPlayerId) MyHud.Notifications.Add(MyNotificationSingletons.HeadNotPlaced); return false; } m_tmpSet.Clear(); // Next test if we intersect any physics objects HkSphereShape spShape = new HkSphereShape(topRadius); Quaternion q = Quaternion.Identity; MyPhysics.GetPenetrationsShape(topBlock.ModelCollision.HavokCollisionShapes[0], ref topPosition, ref q, m_penetrations, MyPhysics.CollisionLayers.DefaultCollisionLayer); // If we have any collisions with anything other than our own grid, don't add the head // We already checked for inner-grid collisions in the previous case for (int i = 0; i < m_penetrations.Count; i++) { MyCubeGrid grid = m_penetrations[i].GetCollisionEntity().GetTopMostParent() as MyCubeGrid; if (grid == null || grid != CubeGrid) { m_penetrations.Clear(); if (builtBy == MySession.Static.LocalPlayerId) MyHud.Notifications.Add(MyNotificationSingletons.HeadNotPlaced); return false; } } m_penetrations.Clear(); return true; }