Chunk unloads even if ChunkUnloadEvent is cancelled

Discussion in 'Plugin Development' started by GermanCoding, Aug 23, 2013.

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

    GermanCoding

    I post this thread not in the Bukkit Issue Tracker, because I don't know wheter this is a bug or not. Now, let me explain what I do and what the server do:

    First, I've a chunk where always should spawn minecarts (via plugin & redstone). This works fine if a player is in the chunk. If I leave the chunk, minecarts stop spawning. So, I've written a plugin to solve this. This plugin should cancel the ChunkUnloadEvent for the specific chunk. But...the minecarts stop spawing when I leave the chunk even if I cancel the event. So I tried some other things:
    • I tried to spawn an entity (every second one) into the spawn to hold the chunk active
    • I tried to load the chunk every second via a scheduler.
    Nothing works, so I think: The only way to hold the chunk active/loaded is to simulate a player. And: This works! But a simulated player is not the best, because the other players on the server are wondering of this "b0t" and of course it distorted the player-online count. So my question is: Is there another way to solve this? Or should I report this on the issue tracker (if somebody explain me how I can login into the tracker :) ) ?
     
  2. Offline

    rsod

    I don't know answer to your question, but I'd like to ask you how did you "simulated" a player. I was trying to do this some time ago, but I gave up on it.
     
  3. Offline

    GermanCoding

    I'm sorry for the late response, but here is it:

    First, you've to add the craftbukkit.jar to your project, because we have to use NMS and CraftBukkit Code.

    Then, (I am ashamed) I've oriented me on the bukkit plugin playersimulator, because he solve the problems in his plugins you and I may had. The simple explanation is:

    First you have to create a new EntityPlayer. The constructor for the EntityPlayer contains 4 parameters:
    1. The server ("((CraftServer)Bukkit.getServer()).getHandle().getServer()")
    2. The serverConfigurationManager ("((CraftServer)Bukkit.getServer()).getHandle()")
    3. The name of the player (of course as a string)
    4. The PlayerInteractManager for the entity. Create a new one for every simulated player.

    Now, we've our EntityPlayer. Now, we've to spawn it in a world. But here was my problem (and maybe your problem too): If I spawn the entity, the server crashes. Why? Because our "simulated" player has no connection, no adress where the server could send packets. So, we've to simulate a connection. And here, the plugin playersimulator has helped me. I use this code to create a "bot":

    Code:java
    1. public void createNewBot(Location l)
    2. {
    3. World world = l.getWorld();
    4. WorldServer ws = ((CraftWorld)world).getHandle();
    5. int size = getBotSize() + 1;
    6. DedicatedPlayerList serverConfigurationManager = ((CraftServer)Bukkit.getServer()).getHandle();
    7. EntityPlayer bot = new EntityPlayer(((CraftServer)getServer()).getHandle().getServer(), ws, "AKNMBot-" + size, new PlayerInteractManager(ws));
    8. DummyNetServerHandler connection = new DummyNetServerHandler(serverConfigurationManager.getServer(), new DummyNetworkManager(), bot);
    9. Bukkit.getPluginManager().callEvent(new PlayerJoinEvent(bot.getBukkitEntity(), ""));
    10. bot.spawnIn(ws);
    11. bot.setPositionRotation(l.getX(), l.getY(), l.getZ(), l.getYaw(), l.getPitch());
    12. bot.playerInteractManager.a((WorldServer)bot.world);
    13. bot.playerInteractManager.b(ws.getWorldData().getGameType());
    14. ((CraftServer)getServer()).getHandle().players.add(bot);
    15. ws.addEntity(bot);
    16. addBot(new Bot(bot, connection));
    17. ConfigManager.addBotToConfig(l);
    18. ((CraftServer)getServer()).getHandle().a(bot, null);
    19. ws.chunkProvider.getOrCreateChunk(bot.getBukkitEntity().getLocation().getChunk().getX(), bot.getBukkitEntity().getLocation().getChunk().getZ());
    20. }


    The 2 classes, DummyNetServerHandler and DummyNetworkManager I've just copied from the plugin playersimulator (Yes, ban me for that, admin). The class ConfigManager comes from my project, to spawn the entity again when the server restarts. I call a "simulated" join too (Bukkit.getPluginManager().callEvent()), to fix an issue with Essentials. The method getBotSize() is just for give the bot a number (I call every bot, "AKNMBot-n"). The method "addBot()" is to save the bot (and the connection) in my plugin. You can ignore this method, like every other method you don't have.
     
    rsod likes this.
  4. As you already pointed out, using a fake player just to keep a chunk loaded is an overkill solution.

    I hqbe been working successfully with the ChunkUnloadEvent in the past, cancelling it always worked fine for me. Could you post your code for the unload event, maybe the issue is just in there (or with the minecart spawning itself?).

    Keep in mind that the event is called repeatedly whenever the server tries to unload the chunk again, so you have to make sure it keeps getting cancelled.
     
  5. Offline

    GermanCoding

    I don't have the source - I've deleted it. But I've tried it so:
    First, you go in the chunk and type a command. This command saves the chunk (player.getLocation().getChunk()).
    Then, I had a listener, which listens to the ChunkUnloadEvent. If the chunk in the event is equal with the saved chunk it calls event.setCancelled(true). I had a config system too, which saves the chunk even after a reload.
     
  6. Did you debug that code? Print out notifications whenever you cancel the event (to see if it reaches the block, if you compared the chunks with == it might have been not the exact same Chunk instance as when you saved it, you should compare coordinates instead).

    It might not even be the chunk unloading code that is not working, but another side effect of your "minecart spawning". You didn't describe what thing does that (a modified mob spawner block? a redstone-controlled dispenser? custom plugin code?).
     
  7. Offline

    GermanCoding

    Bone008,

    It's not my code, I'm very sure. I and my team have tried it with so many ways. We have written more then one plugin. I know the difference between the equal method and the == operator. And for testing, we used a simple system: We build a clock with redstone, this clock activates a dispenser/dropper. Now, you leave the server and join after a minute again. If the dropper is now empty/has dropped some items, it has worked. I reach this result only with a simulated player.
     
Thread Status:
Not open for further replies.

Share This Page