Skip to content
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

Added better handling for automatic dependency resolution between plugins #1412

Merged
merged 4 commits into from
Nov 1, 2020

Conversation

TheDudeFromCI
Copy link
Member

In sitations where Plugin A relies on Plugin B to work, it's useful for plugin A to automatically trigger plugin B to load if the user does not specify this directly. This allows for better API compatibility. (A plugin can add a new plugin dependency to the bot without breaking existing bots that don't load plugin B by default.)

This also makes it much easier to load plugin trees that contain several nested plugins, all by simply loading the parent plugin.

This PR works by safely allowing the bot.loadPlugin to be called more than once without actually loading the plugin twice.

Bot:

const { pluginA } = require('mineflayer-plugin-a')
const bot = mineflayer.createBot({...})
bot.loadPlugin(pluginA)

Plugin A:

const { pluginB } = require('mineflayer-plugin-b')

function pluginA (bot) {
  bot.loadPlugin(pluginB)

  bot.pluginA = {}
  bot.pluginA.someFunction = function () {}
}

module.exports = {
  pluginA
}

Using this, Plugin A can safely load Plugin B when injected. If the user already has PluginB loaded, nothing happens.

Signed-off-by: TheDudeFromCI <thedudefromci@gmail.com>
Signed-off-by: TheDudeFromCI <thedudefromci@gmail.com>
@TheDudeFromCI
Copy link
Member Author

I also added the bot.hasPlugin(plugin) function that can similarly be used for soft dependencies.

Signed-off-by: TheDudeFromCI <thedudefromci@gmail.com>
Signed-off-by: TheDudeFromCI <thedudefromci@gmail.com>
Copy link
Member

@wvffle wvffle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if plugin-a requires plugin-c@1.0.0 and plugin-b requires plugin-c@2.0.0?

@TheDudeFromCI
Copy link
Member Author

TheDudeFromCI commented Oct 29, 2020

Obviously two versions of the same plugin usually cannot be loaded at the same time.

The name space wouldn't event allow it unless you wrote something like bot.myplugin2 for version 2.0.0 or something.

The end user must choose between whether they want to use plugin a or plugin b. Or hopefully convince one of the maintainers for plugin a or b to add support for both versions and just load the ideal version manually.

@TheDudeFromCI
Copy link
Member Author

Also, wouldn't this kind of issue be resolved by npm, anyway?

@wvffle
Copy link
Member

wvffle commented Oct 30, 2020

Also, wouldn't this kind of issue be resolved by npm, anyway?

Don't think so.

Copy link
Member

@wvffle wvffle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The end user must choose between whether they want to use plugin a or plugin b.

In such case I agree.

Copy link
Member

@wvffle wvffle left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(And I wanted to approve it.)

Copy link
Member

@rom1504 rom1504 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is using the object reference as a plugin key
can you double-check this work in all circumstances?
for example, if you do a require in 2 different files for the plugin, do you get exactly the same reference?

@TheDudeFromCI
Copy link
Member Author

this is using the object reference as a plugin key
can you double-check this work in all circumstances?
for example, if you do a require in 2 different files for the plugin, do you get exactly the same reference?

Yes, I did check.

While it works oin most usecases, I found 2 situations where issues arise.

  1. When npm does not de-dupe dependencies and multiple versions of the same library are loaded. This triggers multiple versions of the same object to be generated. This is most commonly caused from people pinning dependencies.

  2. When functions are "generated" instead of static.

module.exports = funcition(properties) {
  return function () {
    // stuff
  }
}

Ideally, I would much rather use plugin metadata than object reference. (See #1244)
However, until a plugin standard is agreed on and initiated, that's not yet possible.

@rom1504 rom1504 merged commit 6640cdb into PrismarineJS:master Nov 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants