/// <summary> /// Updates all of the cached physics information on the body derived from fixtures. /// </summary> public void FixtureUpdate(FixturesComponent component, PhysicsComponent?body = null) { if (!Resolve(component.Owner, ref body)) { return; } var mask = 0; var layer = 0; var hard = false; foreach (var(_, fixture) in component.Fixtures) { mask |= fixture.CollisionMask; layer |= fixture.CollisionLayer; hard |= fixture.Hard; } body.ResetMassData(); // Normally this method is called when fixtures need to be dirtied anyway so no point in returning early I think body.CollisionMask = mask; body.CollisionLayer = layer; body.Hard = hard; component.Dirty(); }
private void OnGetState(EntityUid uid, FixturesComponent component, ref ComponentGetState args) { args.State = new FixtureManagerComponentState { Fixtures = component.Fixtures.Values.ToList(), }; }
private void OnShutdown(EntityUid uid, FixturesComponent component, ComponentShutdown args) { // TODO: Need a better solution to this because the only reason I don't throw is that allcomponents test // Yes it is actively making the game buggier but I would essentially double the size of this PR trying to fix it // my best solution rn is move the broadphase property onto FixturesComponent and then refactor // SharedBroadphaseSystem a LOT. if (!EntityManager.TryGetComponent(uid, out PhysicsComponent? body)) { return; } // Can't just get physicscomp on shutdown as it may be touched completely independently. body.DestroyContacts(); _broadphaseSystem.RemoveBody(body, component); body.CanCollide = false; }
private void OnInit(EntityUid uid, FixturesComponent component, ComponentInit args) { // Convert the serialized list to the dictionary format as it may not necessarily have an ID in YAML // (probably change this someday for perf reasons?) foreach (var fixture in component.SerializedFixtures) { fixture.ID = GetFixtureName(component, fixture); if (component.Fixtures.TryAdd(fixture.ID, fixture)) { continue; } // This can happen on stuff like grids that save their fixtures to the map file. // Logger.DebugS("physics", $"Tried to deserialize fixture {fixture.ID} on {uid} which already exists."); } component.SerializedFixtures.Clear(); // Can't ACTUALLY add it to the broadphase here because transform is still in a transient dimension on the 5th plane // hence we'll just make sure its body is set and SharedBroadphaseSystem will deal with it later. if (EntityManager.TryGetComponent(uid, out PhysicsComponent? body)) { foreach (var(_, fixture) in component.Fixtures) { fixture.Body = body; } // Make sure all the right stuff is set on the body FixtureUpdate(component); if (body.CanCollide) { DebugTools.Assert(!Get <SharedContainerSystem>().IsEntityInContainer(uid)); _broadphaseSystem.AddBody(body, component); } } /* TODO: Literally only AllComponentsOneToOneDeleteTest fails on this so f**k it this is what we get. * else * { * Logger.ErrorS("physics", $"Didn't find a {nameof(PhysicsComponuid)}" * } */ }
private string GetFixtureName(FixturesComponent component, Fixture fixture) { if (!string.IsNullOrEmpty(fixture.ID)) { return(fixture.ID); } var i = 0; while (true) { ++i; var name = $"fixture_{i}"; var found = component.Fixtures.ContainsKey(name); if (!found) { return(name); } } }
private void OnHandleState(EntityUid uid, FixturesComponent component, ref ComponentHandleState args) { if (args.Current is not FixtureManagerComponentState state) { return; } if (!EntityManager.TryGetComponent(uid, out PhysicsComponent? physics)) { DebugTools.Assert(false); Logger.ErrorS("physics", $"Tried to apply fixture state for {uid} which has name {nameof(PhysicsComponent)}"); return; } var toAddFixtures = new List <Fixture>(); var toRemoveFixtures = new List <Fixture>(); var computeProperties = false; // Given a bunch of data isn't serialized need to sort of re-initialise it var newFixtures = new List <Fixture>(state.Fixtures.Count); foreach (var fixture in state.Fixtures) { var newFixture = new Fixture(); fixture.CopyTo(newFixture); newFixture.Body = physics; newFixtures.Add(newFixture); } // Add / update new fixtures foreach (var fixture in newFixtures) { var found = false; foreach (var(_, existing) in component.Fixtures) { if (!fixture.ID.Equals(existing.ID)) { continue; } if (!fixture.Equals(existing)) { toAddFixtures.Add(fixture); toRemoveFixtures.Add(existing); } found = true; break; } if (!found) { toAddFixtures.Add(fixture); } } // Remove old fixtures foreach (var(_, existing) in component.Fixtures) { var found = false; foreach (var fixture in newFixtures) { if (fixture.ID.Equals(existing.ID)) { found = true; break; } } if (!found) { toRemoveFixtures.Add(existing); } } foreach (var fixture in toRemoveFixtures) { computeProperties = true; DestroyFixture(physics, fixture); } // TODO: We also still need event listeners for shapes (Probably need C# events) // Or we could just make it so shapes can only be updated via fixturesystem which handles it // automagically (friends or something?) foreach (var fixture in toAddFixtures) { computeProperties = true; CreateFixture(physics, fixture); } if (computeProperties) { physics.ResetMassData(); } }