Exemple #1
0
        /// <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();
        }
Exemple #2
0
 private void OnGetState(EntityUid uid, FixturesComponent component, ref ComponentGetState args)
 {
     args.State = new FixtureManagerComponentState
     {
         Fixtures = component.Fixtures.Values.ToList(),
     };
 }
Exemple #3
0
        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;
        }
Exemple #4
0
        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)}"
             * }
             */
        }
Exemple #5
0
        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);
                }
            }
        }
Exemple #6
0
        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();
            }
        }