How to make sure your plugin won't break in 1.2

Discussion in 'Plugin Development' started by Dinnerbone, Feb 15, 2012.

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

    Dinnerbone Bukkit Team Member

    Do you use the world height anywhere?

    Bukkit has a method "getMaxHeight()" that will guarantee your plugin will work with either the current height, 1.2's height, or the height five years from now. Please use that instead of hardcoding 127! Also, if you use the sea level - don't just hardcode 64 or height/2, use world.getSeaLevel()!

    Do you use net.minecraft.server stuff, or build for CraftBukkit?

    Please don't! This is a *guaranteed* way that your plugin will break, and we can't help you when it does. Please review every use of you using that code and ask yourself if it's still needed - we've added a lot of cool new API lately that should remove the need for anyone to depend on CraftBukkit!

    Do you use any deprecated methods?

    We're planning to remove all deprecated methods (apart from Player.updateInventory()) in R5. Save yourself a lot of time and effort by making sure you're up to date with the latest code!

    Are you building with an old version of Bukkit?

    We may have changed some API around or deprecated some things since you last downloaded Bukkit. Go download the latest version now, compile and make sure it's all fine. If you're using maven, the latest <version> is "1.1-R4".

    Do you access any of Minecraft's save files directly?

    They're all changing in 1.2, so your plugin likely won't work correctly. Please make absolute sure that you still need to use these files, because we've added a lot of API recently which may be exactly what you need!

    Have a look at the latest specifics on what to change!

    It's just a few pages later in this topic!
     
    dadaemon, Juze, RROD and 7 others like this.
  2. Offline

    jca2323

    Will the old (deceperated) way of registering events, Event.Type.EVENT_TYPE, Be removed? Because that will break alot of plugins.
     
  3. Offline

    desht

    • Will there be a Bukkit way to do efficiently perform mass block updates? block.setTypeId() and block.setTypeIdAndData() carry out re-lighting whenever they're done, so it's impossible to efficiently update a large cuboid of blocks using Bukkit right now. I'm using the net.minecraft.server methods to directly set cuboids, update lighting and ensuring clients get notified. It's orders of magnitude more efficient than using the Bukkit block setting methods.
    • Will be there be a Bukkit way to force the light level of a block? I'm using the net.minecraft.server.World a() method right now, a Bukkit block.setLightLevel() or equivalent would be nice. (I appreciate that there are complexities regarding light from the sky and light from nearby blocks...)
    See https://github.com/desht/ChessCraft...va/me/desht/chesscraft/blocks/BlockUtils.java and https://github.com/desht/ChessCraft.../java/me/desht/chesscraft/regions/Cuboid.java (sendClientChanges() and forceLightLevel() in particular) for my current direct usage of net.minecraft.server methods.

    Oh, is there a summary of new 1.2 API features somewhere? Are there any published javadocs yet?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 24, 2016
  4. Offline

    Fyre

    Look in the Bukkit Preview section, it's a subforum of Plugin Development.
     
  5. Offline

    Zeerix

    You could implement your methods with the new API methods to remove the NMS dependency for that code.

    Why do you want to find the entities? Do you want to remove some of them?
    Also, do you have an idea how to improve those methods?
     
  6. Offline

    Fyre

    I want to find the entities so I can alter the items that have already been dropped, or remove them so I can drop what I want. The simple way to improve that getDrops() method is to have it return a collection of the Item Entities instead of the ItemStacks.
     
  7. Offline

    Zeerix

    But that would return a new set of entities instead of the entities dropped by breaking. That wouldn't help you at all, would it?

    How are you doing it currently?
     
  8. Offline

    Fyre

    The way I do it in cases of entities with unique drops, is to remove all types of that item when it spawns within a few seconds of its relevant entity's death. I then drop the items I want by spawning an item that does not normally spawn (I use block 36) and then changing the entity's ItemStack to the one I want to drop. I track the entity by spawning it like this:
    Code:java
    1. Location loc = entity.getLocation();
    2. ItemStack dummyStack = new ItemStack(36, 1);
    3. ItemStack realStack = new ItemStack(blahblahblah);
    4. Item newDrop = world.dropItemNaturally(loc, dummyStack);
    5. newDrop.setItemStack(realStack);
     
  9. Offline

    Zeerix

    Hmmm, think I see what you mean now.
    EntityDeathEvent.getDrops returns the List<ItemStack> and the event doesn't have a setDrops.
    However, you can modify the list returned by getDrops and add/remove whatever items you want.

    With BlockBreakEvent, you can cancel the event and handle it yourself (remove block, drop the items you want).
    Since this is a hack, it might be better to include a getDrops in BlockBreakEvent just like in EntityDeath.

    btw. Sorry for hijacking the thread.
     
  10. Offline

    Fyre

    Actually EntityDeathEvent.getDrops() doesn't work either, because all you're doing is altering a List of ItemStacks created from the drops, you aren't altering the actual drops.
     
  11. Offline

    Zeerix

    Proof?
    CraftEventFactory.java #L347
     
  12. Offline

    Fyre

    When you use event.getDrops() you call it like this:
    Code:java
    1. List<ItemStack> drops = event.getDrops();

    You're making your own isolated list out of the actual list of drops. So even if Bukkit later calls that same method and uses it to drop items, it doesn't call the list you modified, it calls the original, you can't stop the items from being dropped, or alter the items, at least not until after they're dropped. Considering that EntityDeathEvent isn't Cancellable, it's difficult to work around this.
     
  13. Offline

    Zeerix

    No. Java doesn't copy objects unless you .clone()! We are not in C++ country.
     
  14. Offline

    rymate1234

    Hey dinnerbone, any chance of being able to use vanilla populators in World gen plugins? :p

    It would help some people quite a lot :)
     
  15. Offline

    mbaxter ʇıʞʞnq ɐ sɐɥ ı

    For those of you wondering "will X be removed? Will my plugin break?" a good first start is attempting to compile against the latest bukkit dev build. Revealed to me that what I thought was properly updated code was in fact incorrect, when discovering a custom event still had a super(String) call in the constructor that was no longer applicable. :)
     
  16. Offline

    AdventurerOK

    Trying to create some classes to mimic vanilla classes is hard, as bukkit has so many variables missing. Please can you add some of these. Examples:
    • Biome.topBlock
    • Biome.fillerBlock
    • Biome.cactiPerChunk (and similar ones for trees, reeds and everything else like this)
    • World.heightShift (I think this changes in 1.2 and it means I have to do a lot of recoding since it is not avaliabe without CraftBukkit.jar's World.class)
    • World.xShift
    • World.worldMaxY (World.getMaxHeight - 1)
    • Material.isLiquid
    • Material.isAir
    Other things which I think are missing:
    • A way to use BlockPopulators over multiple chunks
     
  17. I updated my plugin, to not use anny deprated api's, now I need to upload it (I also edited my chunk generators)
     
  18. Offline

    feildmaster

    A quick little notice, for Custom Events.

    The constructors for Custom Events were removed. What does this mean? It means if you created Custom Events with super("Event Name"), it will not work! Please make sure you create events with the methods described here. Want a custom name that doesn't equal the event name for the class?

    Code:java
    1. @Override
    2. public String getEventName() {
    3. return "Your Event Name";
    4. }
     
  19. Offline

    daddychurchill

    Will there be a shift away from chunk generation using byte arrays (maybe a word array) to support the extra 4 bits of data?
     
  20. Offline

    troed

    Same here. Was sure I didn't need to update and was caught out on that one as well.

    Yeah, I use getEventName() through the legacy super(String) support - that was how we were supposed to do it. Now we've been able to override that method for a full three days. That means I cannot upload a version that will work with R4, and when R5 has been released the plugin is already failing.

    I agreed with all deprecation timing up until this one.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 24, 2016
  21. Offline

    feildmaster

    There's no way to deprecate a constructor nicely and cleanly, anyway. That constructor should have been deprecated a long time ago, as well. It was *only* for use with the OLD event system.

    Also, don't worry about the name override for now. It's only used in a single place.
     
  22. Offline

    troed

    I'm not sure I follow. I wrote my custom event code according to the information given at the time, which means my code uses getEventName() in the Listener to separate two event states from each other. When the new Event system appeared I converted all code over to it - but there's no way to use getEventName() without using the super(String) constructor in R4 and so I cannot stop using that "deprecated" (no indication) constructor and have a working plugin out for download.

    I can only stop using super(String) and instead @Override getEventName() in an R5-devbuild from the last three days. That will work with R5, but it won't work on R4. This forces me to have a plugin out that _will_ break on R5, additionally forcing all server admins to update both Bukkit and my plugin at the same time.

    So, sorry - but I will worry ;) Since handling this deprecation hasn't even been possible for one single release I think the super(String) constructor should stay for now.
     
  23. Offline

    feildmaster

    Custom Events no longer need to getEventName(), to be honest, I was going to remove that function, but thought differently.

    You can now listen directly to custom events, Just like normal events. Remove the super(String), and if you still want to customize your name later, you will have to do it in a later patch.

    EG:
    @EventHandler
    public void customListener(CustomEvent event) {}
     
    iPhysX likes this.
  24. Offline

    troed

    I am doing that. Sorry, I've been unclear. The code below is for R4 and the new event system, if you ask me. Yet this is the code that will break in R5. I can manually change this to use something else besides getEventName() - but please remember that there has been no deprecation-indicator for this case (the constructor) and that we're at least two in this thread who didn't understand this would break now.

    My Custom Events:
    https://github.com/troed/Courier/blob/master/src/se/troed/plugin/Courier/CourierDeliveryEvent.java

    The Listener-method:
    https://github.com/troed/Courier/bl.../plugin/Courier/CourierEventListener.java#L29

    And this is how I create them:
    https://github.com/troed/Courier/bl.../plugin/Courier/CourierEventListener.java#L87

    I guess I just failed to see the "Stop using super(String) and getEventName() in the new Event system". There have been no deprecation-warnings, and my R4 code breaks in R5.
     
  25. Offline

    feildmaster

    Why not make sub events?

    EG:
    Code:Java
    1. class CourierDeliveredEvent extends CourierDeliveryEvent {
    2. public CourierDeliveredEvent(Player player, int id) {
    3. super(player, id);
    4. }
    5. }

    By the way: The above getEventName() would return "CourierDeliveredEvent";
     
  26. Offline

    troed


    Because they are aspects of the same delivery event. My point is that there have been no deprecation warnings for the code in question when I updated for the new Event system.

     
  27. Offline

    nisovin

    I think the point is you don't need to use the event name anymore, just create and listen for two different events.
     
  28. Offline

    feildmaster

    You don't even have to listen for two different events. As long as both events extends your base event...
    A sub event is the same as what you're doing now, only nicer.

    You could even name the classes: COURIER_DELIVERED.java, COURIER_READ.java, that would be the *exact* same as what you're doing right now.
     
  29. Offline

    troed

    Yes, but it's still completely beside the point. There are as many ways to code around this as there are coders - it's removing this without deprecation warnings. Do remember that they way this code works is exactly how custom events were written, and a minimal API-compliant conversion to the new system is exactly what was done.
     
  30. Offline

    feildmaster

    You fail to see the point that you still used the name constructor even though no supported tutorials would tell you to do so. I wasn't in charge of deprecating methods before, but this was quite an obvious change. Why would you build your custom events the same way as the old method anyway? Old code had to be removed.
     
  31. Offline

    Zarius

    I'm not sure about everyone else but I don't go back and read tutorials after I've implemented a feature - I might not even keep track of the forum much at all and just rely on deprecation when I go to update my plugin.
     
Thread Status:
Not open for further replies.

Share This Page