-
Notifications
You must be signed in to change notification settings - Fork 203
fix(particlesys): Simplify ParticleSystemManagerDummy setup #2740
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -753,6 +753,8 @@ class ParticleSystemManager : public SubsystemInterface, | |
| virtual void reset() override; ///< reset the manager and all particle systems | ||
| virtual void update() override; ///< update all particle systems | ||
|
|
||
| virtual Bool isDummy() const { return false; } | ||
|
|
||
| virtual Int getOnScreenParticleCount() = 0; ///< returns the number of particles on screen | ||
| virtual void setOnScreenParticleCount(int count); | ||
|
|
||
|
|
@@ -761,8 +763,7 @@ class ParticleSystemManager : public SubsystemInterface, | |
| ParticleSystemTemplate *newTemplate( const AsciiString &name ); | ||
|
|
||
| /// given a template, instantiate a particle system | ||
| ParticleSystem *createParticleSystem( const ParticleSystemTemplate *sysTemplate, | ||
| Bool createSlaves = TRUE ); | ||
| virtual ParticleSystem *createParticleSystem( const ParticleSystemTemplate *sysTemplate, Bool createSlaves = TRUE ); | ||
|
|
||
| /** given a template, instantiate a particle system. | ||
| if attachTo is not null, attach the particle system to the given object. | ||
|
|
@@ -835,15 +836,53 @@ class ParticleSystemManager : public SubsystemInterface, | |
| ParticleSystemIDMap m_systemMap; ///< a hash map of all particle systems | ||
| }; | ||
|
|
||
|
|
||
| // TheSuperHackers @feature bobtista 31/01/2026 | ||
| // ParticleSystemManager that does nothing. Used for Headless Mode. | ||
| // ParticleSystemManager that does nothing. Cannot create particle systems and templates. Used for Headless Mode. | ||
| class ParticleSystemManagerDummy : public ParticleSystemManager | ||
| { | ||
| #if RETAIL_COMPATIBLE_CRC | ||
| struct StaticParticleSystemTemplate : public ParticleSystemTemplate | ||
| { | ||
| StaticParticleSystemTemplate() | ||
| : ParticleSystemTemplate("dummy") {} | ||
| }; | ||
| struct StaticParticleSystem : public ParticleSystem | ||
| { | ||
| StaticParticleSystem(const StaticParticleSystemTemplate *sysTemplate) | ||
| : ParticleSystem(sysTemplate, ParticleSystemID(0), false) {} | ||
| }; | ||
| #endif | ||
|
|
||
| public: | ||
| #if RETAIL_COMPATIBLE_CRC | ||
| // Must not overload init to keep loading the particle system templates, | ||
| // which are unfortunately needed to preserve the correct logic crc. | ||
| #else | ||
| virtual void init() override {} | ||
| virtual void reset() override {} | ||
| #endif | ||
| virtual void update() override {} | ||
|
|
||
| virtual Bool isDummy() const override { return true; } | ||
|
|
||
| virtual Int getOnScreenParticleCount() override { return 0; } | ||
| virtual void doParticles(RenderInfoClass &rinfo) override {} | ||
| virtual void queueParticleRender() override {} | ||
|
|
||
| virtual ParticleSystem *createParticleSystem(const ParticleSystemTemplate *sysTemplate, Bool createSlaves = TRUE) override | ||
| { | ||
| #if RETAIL_COMPATIBLE_CRC | ||
| if (sysTemplate == nullptr) | ||
| return nullptr; | ||
| static StaticParticleSystemTemplate dummyTemplate; | ||
| static StaticParticleSystem dummySystem(&dummyTemplate); | ||
| return &dummySystem; | ||
| #else | ||
| return nullptr; | ||
| #endif | ||
| } | ||
|
Comment on lines
+873
to
+884
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This is benign in single-threaded headless mode since Prompt To Fix With AIThis is a comment left during a code review.
Path: Core/GameEngine/Include/GameClient/ParticleSys.h
Line: 873-884
Comment:
**Shared mutable static singleton returned to callers**
`createParticleSystem` returns `&dummySystem` — a single static object shared by every caller. Code in `FXList.cpp` calls `setLocalTransform`, `rotateLocalTransformX/Y/Z`, and `setPosition` on the returned pointer inside a loop where each iteration overwrites the previous iteration's state on the same object. `BeaconClientUpdate.cpp` calls `attachToDrawable` and `tintAllColors` on it, and stores `system->getSystemID()` which always equals `INVALID_PARTICLE_SYSTEM_ID (0)` — causing the beacon to re-enter the creation path on every subsequent call.
This is benign in single-threaded headless mode since `update()` is a no-op and nothing is rendered, but a brief comment explaining that the returned pointer is a non-owning, non-unique token (and that callers must not delete or track it by ID) would prevent future misuse when this class is re-used.
How can I resolve this? If you propose a fix, please make it concise.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We expect single threaded use right now. We could add |
||
|
|
||
| protected: | ||
| virtual void crc( Xfer *xfer ) override {} | ||
| virtual void xfer( Xfer *xfer ) override {} | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After #2742 is merged, we should be able to remove this path, because particle systems will no longer be needed for correct CRC.