Spawned mobs are not fully cloned from reference.
Opened this issue · 1 comments
Currently, when you spawn a mob, it will have a keywords property equal to the prototype (entity definition). Since keywords is an array, the modifying it means you'll end up modifying the keywords for every other instance spawned, including the definition as stored in the MobFactory. This seems like a bug.
Use case: We let players buy pets. Such pets can be nicknamed (at time of purchase or anytime thereafter) for the purpose of making it easier to control your pet. (e.g., order fido sit
). To facilitate appropriate contextual mob-referencing, we would normally unshift the nickname onto the mob's keywords. So you might have something like: pet.keywords : [fido, dog, puppy, pooch]
. However, the .shift() method does not return a new array, so you end up realizing that every dog spawned can now be referenced by "fido".
We can obviously do something like pet.keywords = ['fido', ...pet.keywords];
as a workaround. But it's probably better to make sure that mobs returned from the factory are fully cloned so that you're not modifying the entity definition.
I took a look at this, and the only mutable properties that a spawned mob shares with its entity definition are this.keywords
and this.quests
. The rest are new objects (like CommandQueue
or Map
), strings (which are immutable), or helpers which are used only during hydration and aren't modified once copied from the entity definition.
I created #121 to address this.keywords
for the use case above.
That leaves this.quests = data.quests || [];
as the only mutable property on a Npc
. The quest/questor relationship is in need of a refactor anyways because BundleManager
currently ties the Npc
to the quest's entity definition when an Area
is loaded. I think that should be handled in a new issue.