Solved Inventory#getViewers concurrent moification exception

Discussion in 'Spigot Plugin Development' started by Gober, Aug 11, 2018 at 6:44 AM.

  1. Hey, I'm confused why this happens, I would like to close all inventory when the block is broken.
    Any ideas?
    Code (Java):
     List<HumanEntity> p = TheInventory.getViewers();
            for (HumanEntity play : p) { // Line 71
                play.closeInventory();
            }
     
    Code (Text):

    11.08 07:39:15 [Server] INFO [07:39:15 ERROR]: Could not pass event BlockBreakEvent to ShipmentBox v1.7.0
    11.08 07:39:15 [Server] INFO org.bukkit.event.EventException: null
    11.08 07:39:15 [Server] INFO at org.bukkit.plugin.EventExecutor$2.execute(EventExecutor.java:72) ~[paperspigot-1.12.2.jar:git-Paper-1490]
    11.08 07:39:15 [Server] INFO at co.aikar.timings.TimedEventExecutor.execute(TimedEventExecutor.java:78) ~[paperspigot-1.12.2.jar:git-Paper-1490]
    11.08 07:39:15 [Server] INFO at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62) ~[paperspigot-1.12.2.jar:git-Paper-1490]
    11.08 07:39:15 [Server] INFO at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:527) ~[paperspigot-1.12.2.jar:git-Paper-1490]
    11.08 07:39:15 [Server] INFO at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:512) ~[paperspigot-1.12.2.jar:git-Paper-1490]
    11.08 07:39:15 [Server] INFO at net.minecraft.server.v1_12_R1.PlayerInteractManager.breakBlock(PlayerInteractManager.java:292) ~[paperspigot-1.12.2.jar:git-Paper-1490]
    11.08 07:39:15 [Server] INFO at net.minecraft.server.v1_12_R1.PlayerInteractManager.a(PlayerInteractManager.java:123) ~[paperspigot-1.12.2.jar:git-Paper-1490]
    11.08 07:39:15 [Server] INFO at net.minecraft.server.v1_12_R1.PlayerConnection.a(PlayerConnection.java:914) ~[paperspigot-1.12.2.jar:git-Paper-1490]
    11.08 07:39:15 [Server] INFO at net.minecraft.server.v1_12_R1.PacketPlayInBlockDig.a(SourceFile:40) ~[paperspigot-1.12.2.jar:git-Paper-1490]
    11.08 07:39:15 [Server] INFO at net.minecraft.server.v1_12_R1.PacketPlayInBlockDig.a(SourceFile:10) ~[paperspigot-1.12.2.jar:git-Paper-1490]
    11.08 07:39:15 [Server] INFO at net.minecraft.server.v1_12_R1.PlayerConnectionUtils.lambda$ensureMainThread$0(PlayerConnectionUtils.java:14) ~[paperspigot-1.12.2.jar:git-Paper-1490]
    11.08 07:39:15 [Server] INFO at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_171]
    11.08 07:39:15 [Server] INFO at java.util.concurrent.FutureTask.run(FutureTask.java:266) [?:1.8.0_171]
    11.08 07:39:15 [Server] INFO at net.minecraft.server.v1_12_R1.SystemUtils.a(SourceFile:46) [paperspigot-1.12.2.jar:git-Paper-1490]
    11.08 07:39:15 [Server] INFO at net.minecraft.server.v1_12_R1.MinecraftServer.D(MinecraftServer.java:849) [paperspigot-1.12.2.jar:git-Paper-1490]
    11.08 07:39:15 [Server] INFO at net.minecraft.server.v1_12_R1.DedicatedServer.D(DedicatedServer.java:427) [paperspigot-1.12.2.jar:git-Paper-1490]
    11.08 07:39:15 [Server] INFO at net.minecraft.server.v1_12_R1.MinecraftServer.C(MinecraftServer.java:773) [paperspigot-1.12.2.jar:git-Paper-1490]
    11.08 07:39:15 [Server] INFO at net.minecraft.server.v1_12_R1.MinecraftServer.run(MinecraftServer.java:665) [paperspigot-1.12.2.jar:git-Paper-1490]
    11.08 07:39:15 [Server] INFO at java.lang.Thread.run(Thread.java:748) [?:1.8.0_171]
    11.08 07:39:15 [Server] INFO Caused by: java.util.ConcurrentModificationException
    11.08 07:39:15 [Server] INFO at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909) ~[?:1.8.0_171]
    11.08 07:39:15 [Server] INFO at java.util.ArrayList$Itr.next(ArrayList.java:859) ~[?:1.8.0_171]
    11.08 07:39:15 [Server] INFO at com.gmail.JyckoSianjaya.ShipmentBox.Objects.TheBox.deleteBox(TheBox.java:71) ~[?:?]
    11.08 07:39:15 [Server] INFO at com.gmail.JyckoSianjaya.ShipmentBox.Events.EventHandlers.ManageBoxBreak(EventHandlers.java:123) ~[?:?]
    11.08 07:39:15 [Server] INFO at com.gmail.JyckoSianjaya.ShipmentBox.Events.Events.onBoxBreak(Events.java:29) ~[?:?]
    11.08 07:39:15 [Server] INFO at com.destroystokyo.paper.event.executor.asm.generated.GeneratedEventExecutor229.execute(Unknown Source) ~[?:?]
    11.08 07:39:15 [Server] INFO at org.bukkit.plugin.EventExecutor$2.execute(EventExecutor.java:70) ~[paperspigot-1.12.2.jar:git-Paper-1490]
    11.08 07:39:15 [Server] INFO ... 18 more
     
  2. CloseInventory removes the player from the list of viewers, over which youre looping.
    ConcurrentModifErrors get thrown when a list youre looping over changes in the middle of the loop. An easy fix is to clone the list beforehand and loop over that clone.
     
    • Agree Agree x 2
  3. Fixed.
    Here's the code:
    Code (Java):
            List<HumanEntity> viewers = Inventory.getViewers();
            ArrayList<HumanEntity> newa = new ArrayList<>();
            for(HumanEntity p : viewers){
                newa.add(p);
            }
            for (HumanEntity pp : newa) {
                pp.closeInventory();
            }
    Anything better feel free to suggest.
     
  4. You can avoid cloning the list by using an Iterator as FrostedSnowman suggested:
    Code (Java):
    Iterator<HumanEntity> viewers = inventory.getViewers().iterator();
    while(viewers.hasNext()) {
        viewers.next().closeInventory();
    }

    Edit 2: DarkSeraphim is right

    Edit 1: also, to clone the list, this would have been enough:
    Code (Text):
    for (HumanEntity viewer : new ArrayList<>(viewers)) {
        viewer.closeInventory();
    }
     
    #5 jetp250, Aug 11, 2018 at 7:54 AM
    Last edited: Aug 11, 2018 at 12:40 PM
    • Agree Agree x 1
    • Winner Winner x 1
  5. Wouldn't an iterator still throw an error as the collection is modified directly, rather than with Iterator::remove()?
     
    • Like Like x 1
    • Agree Agree x 1
  6. Woops, true

    Another way to do this without cloning the List would be by iterating backwards:
    Code (Java):
    for (int i = list.size() - 1; i >= 0; --i) {
        list.get(i).closeInventory();
    }
    But not sure how pretty that is, and it's not like cloning a List - especially that small - would be a problem
     

Share This Page