private void StopThrow(EntityUid uid, ThrownItemComponent thrownItemComponent) { if (EntityManager.TryGetComponent(uid, out PhysicsComponent? physicsComponent)) { var fixture = _fixtures.GetFixtureOrNull(physicsComponent, ThrowingFixture); if (fixture != null) { _fixtures.DestroyFixture(physicsComponent, fixture); } } EntityManager.EventBus.RaiseLocalEvent(uid, new StopThrowEvent { User = thrownItemComponent.Thrower }, true); EntityManager.RemoveComponent <ThrownItemComponent>(uid); }
private void DisableDocking(EntityUid uid, DockingComponent component) { if (!component.Enabled) { return; } component.Enabled = false; if (component.DockedWith != null) { Undock(component); } if (!TryComp(uid, out PhysicsComponent? physicsComponent)) { return; } _fixtureSystem.DestroyFixture(physicsComponent, DockingFixture); }
/// <summary> /// Called where you want the user to stop blocking. /// </summary> /// <param name="item"> The entity with the blocking component</param> /// <param name="component"> The <see cref="BlockingComponent"/></param> /// <param name="user"> The entity who's using the item to block</param> /// <returns></returns> public bool StopBlocking(EntityUid item, BlockingComponent component, EntityUid user) { if (!component.IsBlocking) { return(false); } var xform = Transform(user); var shieldName = Name(item); var blockerName = Identity.Entity(user, EntityManager); var msgUser = Loc.GetString("action-popup-blocking-disabling-user", ("shield", shieldName)); var msgOther = Loc.GetString("action-popup-blocking-disabling-other", ("blockerName", blockerName), ("shield", shieldName)); //If the component blocking toggle isn't null, grab the users SharedBlockingUserComponent and PhysicsComponent //then toggle the action to false, unanchor the user, remove the hard fixture //and set the users bodytype back to their original type if (component.BlockingToggleAction != null && TryComp <BlockingUserComponent>(user, out var blockingUserComponent) && TryComp <PhysicsComponent>(user, out var physicsComponent)) { if (xform.Anchored) { _transformSystem.Unanchor(xform); } _actionsSystem.SetToggled(component.BlockingToggleAction, false); _fixtureSystem.DestroyFixture(physicsComponent, BlockingComponent.BlockFixtureID); physicsComponent.BodyType = blockingUserComponent.OriginalBodyType; _popupSystem.PopupEntity(msgUser, user, Filter.Entities(user)); _popupSystem.PopupEntity(msgOther, user, Filter.Pvs(user).RemoveWhereAttachedEntity(e => e == user)); } component.IsBlocking = false; return(true); }
internal void RegenerateCollision(EntityUid gridEuid, MapChunk chunk, List <Box2i> rectangles) { if (!_enabled) { return; } DebugTools.Assert(chunk.FilledTiles > 0); if (!EntityManager.TryGetComponent(gridEuid, out PhysicsComponent? physicsComponent)) { Logger.ErrorS("physics", $"Trying to regenerate collision for {gridEuid} that doesn't have {nameof(physicsComponent)}"); return; } if (!EntityManager.TryGetComponent(gridEuid, out FixturesComponent? fixturesComponent)) { Logger.ErrorS("physics", $"Trying to regenerate collision for {gridEuid} that doesn't have {nameof(fixturesComponent)}"); return; } var origin = chunk.Indices * chunk.ChunkSize; // So we store a reference to the fixture on the chunk because it's easier to cross-reference it. // This is because when we get multiple fixtures per chunk there's no easy way to tell which the old one // corresponds with. // We also ideally want to avoid re-creating the fixture every time a tile changes and pushing that data // to the client hence we diff it. // Additionally, we need to handle map deserialization where content may have stored its own data // on the grid (e.g. mass) which we want to preserve. var newFixtures = new List <Fixture>(); Span <Vector2> vertices = stackalloc Vector2[4]; foreach (var rectangle in rectangles) { var bounds = ((Box2)rectangle.Translated(origin)).Enlarged(_fixtureEnlargement); var poly = new PolygonShape(); vertices[0] = bounds.BottomLeft; vertices[1] = bounds.BottomRight; vertices[2] = bounds.TopRight; vertices[3] = bounds.TopLeft; poly.SetVertices(vertices); var newFixture = new Fixture( poly, MapGridHelpers.CollisionGroup, MapGridHelpers.CollisionGroup, true) { ID = $"grid_chunk-{bounds.Left}-{bounds.Bottom}", Body = physicsComponent }; newFixtures.Add(newFixture); } var toRemove = new RemQueue <Fixture>(); // Check if we even need to issue an eventbus event var updated = false; foreach (var oldFixture in chunk.Fixtures) { var existing = false; // Handle deleted / updated fixtures // (TODO: Check IDs and cross-reference for updates?) for (var i = newFixtures.Count - 1; i >= 0; i--) { var fixture = newFixtures[i]; if (!oldFixture.Equals(fixture)) { continue; } existing = true; newFixtures.RemoveSwap(i); break; } // Doesn't align with any new fixtures so delete if (existing) { continue; } toRemove.Add(oldFixture); } foreach (var fixture in toRemove) { chunk.Fixtures.Remove(fixture); _fixtures.DestroyFixture(fixture, false, fixturesComponent); } if (newFixtures.Count > 0 || toRemove.List?.Count > 0) { updated = true; } // Anything remaining is a new fixture (or at least, may have not serialized onto the chunk yet). foreach (var fixture in newFixtures) { var existingFixture = _fixtures.GetFixtureOrNull(physicsComponent, fixture.ID); // Check if it's the same (otherwise remove anyway). if (existingFixture?.Shape is PolygonShape poly && poly.EqualsApprox((PolygonShape)fixture.Shape)) { chunk.Fixtures.Add(existingFixture); continue; } chunk.Fixtures.Add(fixture); _fixtures.CreateFixture(physicsComponent, fixture, false, fixturesComponent); } if (updated) { _fixtures.FixtureUpdate(fixturesComponent, physicsComponent); EntityManager.EventBus.RaiseLocalEvent(gridEuid, new GridFixtureChangeEvent { NewFixtures = chunk.Fixtures }); } }