Safeguard Versioning Policy

Discussion in 'Bukkit News' started by EvilSeph, Jan 16, 2013.

Thread Status:
Not open for further replies.
  1. Offline

    EvilSeph Retired Staff

    To protect servers against incompatible plugins that have been developed using the unpredictable and volatile Minecraft code (which we’ll be referring to as “non-Bukkit API plugins” from this point onward), we made the difficult decision of implementing a controversial safeguard into Bukkit. This safeguard forcefully disables non-Bukkit API plugins from running on your server if they have not been verified by their developer to work with the Minecraft version on which your Bukkit server is running. As Bukkit has no control over what changes are made to Minecraft itself, developers should not be relying on its code in any way, shape or form.

    Without this Safeguard in place, running non-Bukkit API plugins on your server had been putting it at risk of instability due to unpredictable behaviour. With the Safeguard in place, developers of non-Bukkit API plugins now have to responsibly check that their plugin works with each Minecraft update, then upload a tested version before the plugin will be able to run on your server.

    When we first implemented the Safeguard, the intention was to forcefully disable incompatible non-Bukkit API plugins with every new Minecraft version, no matter how small the changes. However, since we have the freedom of a flexible release schedule (which Mojang does not), we're usually able to fix bugs faster than Mojang can release Minecraft updates, often removing the need for us to update Bukkit and trigger the Safeguard needlessly (as was the case with Minecraft 1.4.7).

    As such, we're making changes to when we trigger the Safeguard (implementing a versioning policy): instead of triggering the safeguard with every Minecraft update, we will only be triggering it when necessary. This means that non-Bukkit API plugins will only break if a Minecraft update or a rename update has altered the code, instead of with every Minecraft update. As a result, with a Minecraft update like 1.4.7, non-Bukkit API plugins would not break unless we've had to alter the code with a rename update (which we've done for 1.4.7).

    The technical meaning behind this change is: instead of classes being named "name.of.class.v1_4_6", we will now be following a versioning policy of "name.of.class.v1_4_R1" where "R1" is the internal counter for either Minecraft or a rename altering CraftBukkit or Minecraft code.

    This new Safeguard Versioning Policy will allow us to keep up with Minecraft updates without needlessly triggering the safeguard and breaking non-Bukkit API plugins when we've already fixed all the issues the Minecraft update addresses, while still protecting your servers from running unchecked and untested plugins.
  2. Offline


    The point is to support multiple (rather minor) versions of Minecraft for a library to be used by other plugins. Writing "v1_4_R1" or not has nothing to do with it.

    The main problem i see is maintaining multiple modules with the penalty of copy and paste of all used nms/obc. If you can remap parts of it and write the mini-modules for only changing parts, it would be a win, but the point here is to make the whole process somewhat convenient to use and to maintain. If that is not satisfied, then this solution is not such a good option either. So the objective would be to find a way to only provide code when it is needed to change, disregarding the version-package prefixes.

    In fact using modules with a "smart" package-remapper would probably come closest. The demand would be that the system always uses the latest available module equal or earlier to to the target version, for the remapping, if no specific module is present for one of the target versions. This means something like automatically generating the code for a maven module with a specific dependency. It certainly is possible, but i am not sure if it is any convenient, also potentially losing the source code verification features, though compile errors still should be there as a safe-guard.
  3. Offline


    The most interesting and informational post in all posts I have seen related to this. I really like how you went through everything that is going on, and you managed to show perfectly what can be done/should be done/is done.

    Full deobfuscation is basically what I am aiming for, which your last example shows. Where possible I am adding translations of methods, calling super and overriding the method. Examples of this being done:
    But preferably I want to switch to wrapper classeswhere possible. Working with CommonTags (which store a handle to the NBT Tag in NMS) works great, and by utilizing some separate (hidden) classes that deal with the NMS itself, I can add additional methods to set tags without creating a new wrapper instance.

    For the cases where I have to use NMS-extended types I would preferably use some sort of injector system instead. For example, where EntityMinecart can be swapped (in the server) with EntityMinecartInjector. In this injector it stores a delegate for all sorts of methods, like onTick and onInteract. This is a lot more reliable than forcing plugins to extends the base class, ending with class hierarchy errors. Additionally, you could make the delegate implement Minecart (not extending CraftMinecart, hierarchy...) this way allowing Bukkit entities to be casted to your custom entity.

    The reason I haven't done all this is, simply, because it takes a lot of time. The plugins that use this are working now, and I do not want to waste 2 weeks on this and end with a buggy, untested system. At least what I had was working well...

    Downside of taking this approach is type conversion...this Class is becoming larger and larger each day...

    Byte code remapping or editing is incredibly unstable, be it only because it fails on secured plugins. (those with a sort of copyright protection thingo) There is a reason I warned for this.

    Including past versions of classes or methods work if you have about 5 methods to 'translate', but it becomes a huge mess if you take BKCommonLib. It has to deal with so many unrelated aspects, storing accessors for all types of servers, versions and classes is going to become un-doable. Main issue is that the library would become about 100 kb larger every new version...

    I did consider including a translation text file with all class, method and field mappings, which is then downloaded from a server. Downside is that this fails when methods are need byte code generation for that, which is sadly not allowed.
Thread Status:
Not open for further replies.

Share This Page