Skip to content

Instantly share code, notes, and snippets.

@main--
Created December 10, 2012 15:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save main--/4251302 to your computer and use it in GitHub Desktop.
Save main--/4251302 to your computer and use it in GitHub Desktop.
Bukkit plugins vs CraftBukkit plugins

Before the change

Bukkit plugin

  • accesses only the bukkit API
  • doesn't care about the implementation/doesn't touch it
  • limited possibilities because things like packet manipulation can't go into Bukkit
  • (almost) fully downwards compatible
  • is a org.bukkit.plugin.Plugin
  • compiled against bukkit.jar

CraftBukkit plugin

  • accesses Bukkit and minecraft internals/craftbukkit
  • touches the implementation because it has to
  • many possibilities because you can modify the entire server
  • poor or no compatibility with other version
  • so usually version checked
  • is a org.bukkit.plugin.Plugin
  • compiled against craftbukkit.jar and bukkit.jar [shaded]
  • discouraged but still needs to happen

Thoughts

WTF why is a CraftBukkit plugin a Bukkit plugin? What happens if a "i-don-care"-dev creates a CraftBukkit plugin without version checks? It would explode (from the server admin perspective) if a third-party Bukkit implementation loads it and it might even corrupt the worlds if it's loaded on an unsupported version.

After the change

The change

Now the nms code is shaded into a package with the minecraft version in its name, so all CraftBukkit plugins will break if they were compiled for the wrong version.

Reason

According to EvilSeph, the purpose of this change was to make CraftBukkit plugin devs re-do their plugins with every new minecraft version, as they should. (is that right?)

Reaction

  • War. Hundreds of commit comments and angry server admins.
  • "It's broken, so let's fix it": Building converters that automatically relocate all nms calls in a plugin is easy. You could even do that dynamically, simply change the plugin class loader. And that's what happened. What will a server admin do, wait until the dev recompiles the plugin or simply use the converter that works for 65% of all plugins and give it a try?
  • Result: silent breakages, data corruption, doom....

Solution?

EvilSeph called it a "pandora's box" and that's a pretty accurate description of this problem. However, while it's not fixable, it's improvable.

  • Deny nms access in the bukkit plugin class loader. Even though plugins can bypass this, it should even make the dumbest plugin dev think twice.
  • Throw a plugin loader into CraftBukkit.

WTF? CraftBukkit plugins?

Please note that I'm not talking about a "CraftBukkit API" because that is simply not possible. An API requires things such as backwards compatibility while CraftBukkit is based on Minecraft and could change at any time. The "CraftBukkit API" exists already and it's called Bukkit.

What I'm suggesting is a plugin loader that nms-version-checks each plugin and simply won't load it if the version doesn't match. The plugin is (if the version matches) free to do whatever it wants.

It also has a different structure. Maybe:

  • loaded from a different folder ("craftplugins")
  • "craftplugin.yml" instead of "plugin.yml"
  • ...

Update: As @h31ix points out in the comments, such "hard" differences would probably be too much work for supporters. I understand that. So what about this, it would integrate seamlessly into the current system:

  • CB plugins are still in the plugins/ folder
  • "craftplugin.yml" instead of "plugin.yml" (devs should be able to understand the change)
  • "craftplugins: bool" in bukkit.yml

Now if a plugin is loaded that contains not a plugin.yml but a craftplugin.yml but craftplugins are disabled, the server displays a warning ("this is a craftplugin, internal access, more information [wiki link]"). If a the plugin class loader detects and denies nms access, we can use the author nag mechanism. Maybe even additionally a disclaimer on startup if craftplugins are enabled.

Result:

  • No difference at all for servers with only Bukkit plugins
  • It's clear to everybody that craftplugins are discouraged
  • Wiki links in the server messages directly provide admins with all necessary information, so no extra work here for supporters.
  • even less work for supporters because less server admins will complain about their servers breaking because of updates

Advantages

Now if a dev wants to create a plugin and has to access nms code he will see the restriction on Bukkit plugins and the possibility of CraftBukkit plugins. He will (if he's not completely dumb) choose the latter. Now it is clear to the server admin that that plugin has to be updated whenever CraftBukkit is updated. While converters would still be easily possible, the motivation of using them would be gone because server admins know that the plugins in craftplugins/ can break their server and steal their children.

I don't care

Huh? We have bukkitdev and according to TnT all plugins are 100% checked before they are approved. There you are doing a shitload for server admins but here you don't want something that needs basically no maintenance but would really improve server admin's lives?

Discussion

An entirely new plugin system? Wouldn't that be too much work?

Bukkit plugins and CraftBukkit plugins should never be mixed up. I think that is a valid argument against this.

You're wasting my time! Read the FAQ! (EvilSeph)

So let's go through the FAQ:

[The change] serves many purposes which I'll cover below, but the MAIN purpose of this change is to force plugin developers to be completely and absolutely responsible for their actions and the decisions they make.

Plugin developers are always 100% responsible for their actions and decisions. I don't understand this.

a lot of change is likely coming to the inner workings of Minecraft given that Mojang is working towards the Minecraft Plugin API. This means that the chance for plugins that don’t just use the Bukkit API silently breaking servers will likely increase significantly.

It's well-known that nms plugins could break at any time, so that should not be a surprise for anybody.

As a result of this change, If a plugin developer releases a plugin that uses Minecraft or CraftBukkit internals and ends up breaking servers, they are fully responsible for the damage caused. They did not go through the proper procedure to ensure that their plugin actually worked on a new Minecraft update prior to releasing it and put servers at risk as a result.

As I said, it's well-known that CraftBukkit is extremely volatile and that nms plugin devs must always verify that everything works when they update their plugins.

Before this change the responsibility fell back on us, since there was still a chance that the issues were caused by our code (which is why we seriously looked into each report even if we pretty much knew it was a plugin causing it). Now if plugin developers continuously release untested code, it will affect them personally and they will be required to take full responsibility for their recklessness.

There is always a chance that issues are caused by CraftBukkit code.

Side benefits of this change include:

  • Servers will not be able to blindly run untested code on a new Minecraft update, they now have to make the conscious decision of doing so. Or have to be tricked into doing so by the plugin developer.

True. But this also shows a lack of communication: Many server admins don't understand why some developers tell them that their plugin has to be updated for every new CB version while other developers explain that backwards compatibility and being independent from the code underneath the interface is the entire point in Bukkit or an API in general. Most of these cases where server owners blindly run outdated nms plugin versions are caused by the server owners not knowing what a CraftBukkit plugin is or how it is different from Bukkit plugins. Yes, outdated plugins won't corrupt the server with this change but server admins will have no idea what's going on. That means work for the Bukkit support team and for the plugin developer.

  • This will push developers to try and use or develop the Bukkit API, resulting in the betterment of the Bukkit project as a whole for everyone.

I may be wrong but I think the influence on that aspect by this change is negligible. As I said, CraftBukkit's volatility is (in my opinion) well-known and I belive that developers were only using nms when it was absolutely necessary before this change.

  • Easier to implement versioning for plugins (if we end up keeping this change, we’ll be writing tips and tutorials on how to adapt your plugins for this change).

I would appreciate further explanations on this because I don't understand it.

  • We'll be able to quickly close any tickets that no longer fall under our responsibility, giving us more time to direct our attention to things that really matter.

You might get less tickets about strange bugs because of outdated plugins. But the actual problem here (the lack of knowledge/communication, look above) isn't fixed by this commit.

How does this affect me?

If you're a plugin developer that can't only use the Bukkit API, you will have to update your plugin whenever a Minecraft update is released. This should be no more than what you had to do and should have been doing prior to this change. The proper and responsible update procedure when Minecraft updates is that you should be spending a few hours stepping through the code you are using to ensure it did and still does what you thought it did with the update. The reason why I specifically said "a few hours" is because that is how long it should take you: you should be reviewing each and every function in the internals of both Minecraft and CraftBukkit to ensure that the code you use, as well as anything that calls that code or any code it calls, still functions in a safe manner.

I fully agree.

But it is so easy to get around this!

Then by all means, do so. We have not gone out of our way to make this difficult to bypass, as that is not our intention, nor will we be going out of our way to stop people discussing it. Keep in mind, however, that by bypassing this failsafe you're accepting full responsibility for anything your plugin does.

As EvilSeph would say: I have already explained 5+ times why this doesn't make sense. [no further explanation]

(In other words: Plugins devs have and always had full responsibility for anything their plugins do!)

If your plugin damages a server it is entirely due to your being negligent: you did not follow the proper procedure to ensure the internals your plugin is touching continues to do EXACTLY what you intended, and no more. If a plugin doing this is brought to our attention, we will not hesitate to communicate exactly this and direct the reporter back to you. If you continue to blindly update your plugins and they continue causing problems, people will stop using your work.

It also was/is like that before this change! (Since you (Bukkit team) disagree with that: Why was/is it not like that?)

It is also important to note that some of the workarounds people have been suggesting may result in your plugin being denied on BukkitDev for security reasons. If your plugin is utilising dynamic code generation, or using a plugin/library that does, for example, we will have no choice but to deny your plugin until this security risk is removed. I wish we didn’t have to do this, but there is no way for our BukkitDev staff to verify that your code is non-malicious in this case.

If you are referring to custom classloaders: It is clearly visible whether a classloader touches bytecode and as long as that doesn't hapen, I wouldn't call it dynamic code generation.

To sum the current situation up:

  • Many people are complaining about this change
  • You say that it is necessary because you want to force developers to verify all their nms calls (as they should) when they update their plugins
  • Now you say that you know that this change is easily bypassable and that you don't want to do anything about that.

So you know that there are some lazy plugin developers and you want to force them to carefully update their plugins, just like all other plugin developers. Now tell me, what will mr-super-lazy-dev do? Step through nms code for hours? Or simply press the replace all button in his IDE and change the imports?

This change is unable to achieve what it was made for.

Why can't you just add a built in failsafe to CraftBukkit?

This goes against the goal and point of the Bukkit project. Remember, CraftBukkit exists purely as a means for us to implement the Bukkit API into the Minecraft server. Nothing less, nothing more. We do not support it in any way and will not hesitate to make any changes that are necessary for the Bukkit API to function and grow. To that end, we will never add anything or make any changes to the project that encourage or enable people to use Minecraft or CraftBukkit internals. CraftBukkit is meant to be as volatile as Minecraft itself; we essentially do not have control over the code within it - it changes as Minecraft does and as it needs to for the Bukkit API to work.

You are answering the question "Why can't you just add a built in failsafe to CraftBukkit?" with no, however a few lines above you are calling the commit "this failsafe". WTF?

And once again in this entire discussion I have to say: CraftBukkit plugins are necessary! Things like custom network packets are simply impossible through Bukkit.

Why not add support for CraftBukkit plugins?

This simply would not work. Let's forget what was mentioned above and say we do support CraftBukkit. What does this mean? Making changes necessary for the Bukkit API to function will now have to wait on our performing changes to CraftBukkit responsibly (being aware of breaks and communicating them ahead of time). Changes and improvements to the Bukkit API would have to be delayed each time to wait for the breakage grace period to end before we could make the changes we needed. Updating the Bukkit project whenever a new version of Minecraft was released would take months to a year, if not be absolutely impossible. In fact, I would go so far as to say adding support for CraftBukkit plugins would very well completely stall any progress within the project. We would not be able to make any changes any more.

As I am saying in this text, I understand that a CraftBukkit API is impossible because it would be nothing else than Bukkit. But you need to understand that there's a difference between supporting and allowing. I'm suggesting "Craftplugins" (plugins specifically for CraftBukkit), but I'm explicitly NOT suggesting support for that because I know that that's impossible. A simple plugin loader that provides plugins with the CraftServer object should be enough. That kind of setup would require maintenance once in a blue moon. And with the craftplugin.yml version check and a big warning message with a wiki link, the communication/knowledge problem would be solved.

Why not add a plugin.yml setting?

As stated before, we will never add anything or make any changes to the project that encourage or enable the use of Minecraft or CraftBukkit internals - this change would do that. We don't want people to be building against code we have no control over. We simply can't provide any reassurances and it isn't something we can support, even if we wanted to. A plugin.yml setting that lets developers specify what version is required for their plugin to run would not only hinder developers that only use the Bukkit API, but it would also run a very real risk of pushing people to bypass the API and just use the internals.

This is obvious, the plugin.yml belongs to Bukkit and CB-specific things can't go in there. That's why I'm suggesting craftplugin.yml.

If this is what you want, there is no point in the Bukkit project existing. We would have no reason to continue working on the API because everyone would be using the internals instead. Everyone should just go back to modding Minecraft directly then.

Drama much? You are probably referring to the fact that API and implementation should never be mixed up which is exactly what would happen with CB-specific stuff in the plugin.yml. Yes, that's right.

I'm going to skip the next paragraphs, they are only for users that haven't understood the concept of Bukkit plugins vs CraftBukkit plugins yet. But I expect the reader of this document to know that when he reaches this point.

Why now? Why can't this wait until Bukkit's API is 'more complete'?

[...]

In terms of making the API ‘more complete’, this will never be achieved. There will always be work to do on an API - this is the nature of an API. Regardless, we are making many changes within the project that will improve the speed at which we get API done, through the help of the community and our various initiatives.

And this is exactly why CraftBukkit plugins are necessary!

EvilSeph: If I offended you with that "as EvilSeph would say", I would like to apologize. But you have been answering that way a lot and that was ... not really nice. You told me to read your FAQ and that's what I did, so I'm now looking forward to your reply.


UPDATE: Thanks for your response, EvilSeph. Now I know that my assumptions concerning plugin developers and blaming were wrong, I can finally fully understand this decision.

And thanks for your comment, mbax. With "supporting" I was referring to the scenario of a CraftBukkit API that EvilSeph mentioned. And in my opinion, craftplugins are still "allowing" if it's no more than a plugin loader.

I still believe that my suggestion would improve the situation but EvilSeph made clear that he doesn't want anything like that, so the discussion is probably over now.

@gravitylow
Copy link

As a BukkitDev staff member, I think this is a solution that will cause more problems that it's worth. Several other communities have decided to take this route and divide different sort of tasks between different "APIs" (bear with me, I know you're not suggesting a new API) and it just results in fragmentation of the community, confusion, and a lot more work on our part.

I would probably go crazy if I had to explain to 3 billion people the difference between a craftbukkit and bukkit plugin, how to use both, why it isn't working because they tried to treat it like the opposite one, etc. Server admins have quite enough on their hands without having to deal with two different sorts of addons.

The problem is that author's don't do what you're describing; they don't always update on new releases, and sometimes even attempt to write code that doesn't need to be updated at all when it's hooking into vital code that makes the server run. It's work updating these plugins, but those who are good at what they do do it quite well. Simply adding the concept of a craftbukkit plugin doesn't change any of this; it leaves those who were trying to accomplish hooking into NMS in a more laid-back way doing it the same way, and those who update the right way continuing that. Essentially, it causes a bunch of pain for no overall positive outcome.

Furthermore, we'd have to do so much in the way of services (like BukkitDev) we provide to get it ready to handle something like this. Everything would need to change, and everyone would need to change with it, including the server admins. At this point, server admins don't necessarily have to or need to ever care about what's happening, but with this change they would. People already bug us at BukkitDev about why some inane plugin gets approved before theirs when it was submitted after theirs because they don't know that there are bunches of staff working at the same time, so how would we deal with the massive amount of spam/anger we would get from authors about why CB plugins take longer than Bukkit ones or some other stupid issue? Because believe me, it's a LOT of work. More work than we ever talk about just as it is, but it is for the community that we do it. Having to deal with a change like this would likely be the definition of my own personal nightmare.

Copy link

ghost commented Dec 11, 2012

I think it would be interesting to have something like this except maybe some "CraftJavaPlugin" class or something in CraftBukkit. These would have a normal class loader, and normal JavaPlugins would have class loaders blocking NMS. Just an idea though.

Copy link

ghost commented Dec 11, 2012

I think it would be interesting to have something like this except maybe some "CraftJavaPlugin" class or something in CraftBukkit. These would have a normal class loader, and normal JavaPlugins would have class loaders blocking NMS. That way the API would still stay implementation-independent and CraftBukkit itself would have the extras. Just an idea though.

Copy link

ghost commented Dec 11, 2012

Meant to hit edit instead of reposting, sorry about that...

@EvilSeph
Copy link

I find it ironic that you're breaking apart the FAQ, piece by piece, and yet you're responding in a manner that shows you have not read the FAQ.

Plugin developers are always 100% responsible for their actions and decisions. I don't understand this.

As covered in the FAQ you're breaking apart... prior to this change there was still a chance where we were responsible for a bug caused by a plugin. After this change, plugin developers are now forced to re-evaluate their code in whatever manner they wish. It doesn't matter what they choose to do, what matters is that they have to do something and now take full responsibility for anything their plugin does with or without their knowledge.

It's well-known that nms plugins could break at any time, so that should not be a surprise for anybody.

Yet many people in the commit discussion are claiming that NMS and OBC are future proof. You're preaching to the choir here and it makes me wonder if you're even following along with the discussion you're trying to be a part of...

As I said, it's well-known that CraftBukkit is extremely volatile and that nms plugin devs must always verify that everything works when they update their plugins.

Again, many people in the commit discussion are complaining that this commit makes them do extra work. In which case, they refute your point... Preaching to the choir, I'm afraid :(

There is always a chance that issues are caused by CraftBukkit code.

We haven't said otherwise anywhere, but with this change we can look into an issue, figure out it is a plugin and direct the server admins back to the plugin developer with a clear explanation stating that they willingly put their server at risk.

True. But this also shows a lack of communication: Many server admins don't understand why some developers tell them that their plugin has to be updated for every new CB version while other developers explain that backwards compatibility and being independent from the code underneath the interface is the entire point in Bukkit or an API in general. Most of these cases where server owners blindly run outdated nms plugin versions are caused by the server owners not knowing what a CraftBukkit plugin is or how it is different from Bukkit plugins. Yes, outdated plugins won't corrupt the server with this change but server admins will have no idea what's going on. That means work for the Bukkit support team and for the plugin developer.

If this means less servers being silently damaged or destroyed, so be it. Plugin developers refused to implement versioning themselves. Had they done so and been responsible, we would not be forced to make this change.

I may be wrong but I think the influence on that aspect by this change is negligible. As I said, CraftBukkit's volatility is (in my opinion) well-known and I belive that developers were only using nms when it was absolutely necessary before this change.

I'll quote something someone just said on IRC to me and you can tell me if this won't make a difference. Since pushing this commit to our development builds, we've already started working with several developers to figure out if they can move completely to the Bukkit API.

" ( AlphaBlend ) EvilSeph: If anything for us, this is a good opportunity to see if we have any pointless references to CB, that we could instead replace with bukkit's API"

I would appreciate further explanations on this because I don't understand it.

Like it says, when the time comes that we've determined this change stays, we'll be writing tips and tutorials to make versioning your plugins easy (i.e. adapt your plugins to work with this change). Look at @mbax's plugins for some idea of what I mean.

You might get less tickets about strange bugs because of outdated plugins. But the actual problem here (the lack of knowledge/communication, look above) isn't fixed by this commit.

That's fine, we don't care. That isn't the point of the commit (see the FAQ for what this commit is meant to achieve...).

As you keep bringing up CraftBukkit plugins, I have nothing further to add. All of this is covered in the FAQ. We simply cannot add CraftBukkit plugins without it severely affecting the project as a whole. Even when breaking apart the FAQ, it appears you are glancing over things that don't support your point.

Let me make it clear:
The point of this change is to force plugin developers to be fully responsible for what their plugins do. Nothing more, nothing less. This is also covered in the FAQ...

@mbax
Copy link

mbax commented Dec 12, 2012

Duplicated from the commit stream -

In the same paragraph where you state you are not suggesting support for obc/nms plugin, you suggest a solution that adds support for them.

You do have a good point here:

But you need to understand that there's a difference between supporting and allowing.

We do understand this difference. Supporting would be creating "CraftPlugins" or craftplugin.yml, which we will not do. Allowing is what we do. We don't obfuscate the internals of nms/obc and we accept plugins on BukkitDev that hook into these classes.

Allowing has been a pretty clear policy, and this commit doesn't change that. Supporting has been commonly suggested in this commit thread, and that's not going to happen.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment