Jump to content

[1.11] Avoiding a Concurrent Mod. Except.


Lambda

Recommended Posts

Hey there!

 

So I'm creating a network that has 'tethers' that send energy to nearby acceptable tiles (5x5) however, it seems I'm getting a concurrent modification execption, I know where the error is happening, but I do not know how to 'avoid' it.

 

Here is the code:

public class TileEntityNetworkTethers extends TileEntityBase implements ISharingEnergyHandler {

    public CustomEnergyStorage storage = new CustomEnergyStorage(50000, 50, 50);

    public static final int MAX_SEND = 50;

    public boolean removingFromList = false;

    public List<TileEntity> energyUsers = new ArrayList<>();

    public TileEntityNetworkTethers() {
        super("networkTethers");
    }

    @Override
    public void updateEntity() {
        super.updateEntity();

        if(!world.isRemote) {
            storage.receiveEnergyInternal(2, false);
            Iterable<BlockPos> blockPos = BlockPos.getAllInBox(pos.add(-5, -5, -5),
                                                               pos.add(+5, +5, +5));
            if(blockPos != null) {
                for (BlockPos position : blockPos) {
                    TileEntity te = world.getTileEntity(position);
                    if (te != null) {
                        if (!energyUsers.contains(te)) {
                            energyUsers.add(te);
                        }
                    }
                }
            }

            if(energyUsers.size() != 0) {
                for(TileEntity te : energyUsers) {
                    if(te != null) {
                        System.out.println(removingFromList);
                        for(EnumFacing facing : EnumFacing.VALUES) {
                            handleEnergy(te, facing, MAX_SEND);
                        }
                    }
                }
            }

            validateList();

            if(sendUpdateWithInterval()) {

            }
        }
    }

    public void handleEnergy(TileEntity te, EnumFacing facing, int amount) {
        if (te.hasCapability(CapabilityEnergy.ENERGY, facing)) {
            IEnergyStorage cap = te.getCapability(CapabilityEnergy.ENERGY, facing);
            if (cap != null) {
                if (cap.canReceive()) {
                    if(storage.getEnergyStored() - amount >= 0)  {
                        storage.extractEnergyInternal(amount, false);
                        cap.receiveEnergy(amount, false);
                    }
                }
                if(cap.canExtract()) {
                    if(storage.getEnergyStored() + amount <= storage.getMaxEnergyStored()) {
                        this.storage.receiveEnergyInternal(amount, false);
                        cap.extractEnergy(amount, false);
                    }
                }
            }
        }
    }

    public void validateList() {
        if (energyUsers != null && energyUsers.size() != 0) {
            for (TileEntity te : energyUsers) {
                if(te != null) {
                    if (world.getTileEntity(te.getPos()) == null) {
                        energyUsers.remove(te);
                    }
                }
            }
        }
    }

    @Override
    public IEnergyStorage getEnergyStorage(EnumFacing facing) {
        return storage;
    }

    @Override
    public int getEnergyToSplitShare() {
        return storage.getEnergyStored();
    }

    @Override
    public boolean doesShareEnergy() {
        return true;
    }

    @Override
    public EnumFacing[] getEnergyShareSides() {
        return EnumFacing.VALUES;
    }

    @Override
    public boolean canShareTo(TileEntity tile) {
        return true;
    }
}

 

Here is the crash:

net.minecraft.util.ReportedException: Ticking block entity
at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:800) ~[MinecraftServer.class:?]
at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:698) ~[MinecraftServer.class:?]
at net.minecraft.server.integrated.IntegratedServer.tick(IntegratedServer.java:156) ~[integratedServer.class:?]
at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:547) [MinecraftServer.class:?]
at java.lang.Thread.run(Thread.java:745) [?:1.8.0_91]
Caused by: java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901) ~[?:1.8.0_91]
at java.util.ArrayList$Itr.next(ArrayList.java:851) ~[?:1.8.0_91]
at com.lambda.plentifulutilities.block.tile.TileEntityNetworkTethers.validateList(TileEntityNetworkTethers.java:95) ~[TileEntityNetworkTethers.class:?]
at com.lambda.plentifulutilities.block.tile.TileEntityNetworkTethers.updateEntity(TileEntityNetworkTethers.java:64) ~[TileEntityNetworkTethers.class:?]
at com.lambda.plentifulutilities.block.tile.TileEntityBase.update(TileEntityBase.java:171) ~[TileEntityBase.class:?]
at net.minecraft.world.World.updateEntities(World.java:1942) ~[World.class:?]
at net.minecraft.world.WorldServer.updateEntities(WorldServer.java:647) ~[WorldServer.class:?]
at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:794) ~[MinecraftServer.class:?]
... 4 more
[14:53:56] [server thread/ERROR]: This crash report has been saved to: F:\Minecraft Workspace\PlentifulUtilities\PlentifulUtilities\run\.\crash-reports\crash-2017-01-06_14.53.56-server.txt
[14:53:56] [server thread/INFO]: Stopping server
[14:53:56] [server thread/INFO]: Saving players
[14:53:56] [Client thread/INFO] [sTDOUT]: [net.minecraft.init.Bootstrap:printToSYSOUT:600]: ---- Minecraft Crash Report ----
// Uh... Did I do that?

 

Where its happening:

                            public void validateList() {
        if (energyUsers != null && energyUsers.size() != 0) {
            for (TileEntity te : energyUsers) {
                if(te != null) {
                    if (world.getTileEntity(te.getPos()) == null) {
                        energyUsers.remove(te); //--------HERE--------
                    }
                }
            }
        }
    }

 

Maybe there is a better way to store a TE other than an list? A map wont work due to them not being able to store duplicate keys.

 

Thanks,

Relatively new to modding.

Currently developing:

https://github.com/LambdaXV/DynamicGenerators

Link to comment
Share on other sites

Well of course there's a ConcurrentModificationException, you're trying to remove something from a list you're currently iterating over. You can manually use the list's Iterator so you have access to the Iterator.remove function:

 

Iterator<TileEntity> iterator = energyUsers.iterator();
while (iterator.hasNext()) {
    TileEntity te = iterator.next();
    if (te != null && world.getTileEntity(te.getPos()) == null) {
        iterator.remove();
    }
}

 

Additionally, you shouldn't need that

te != null

check and you probably shouldn't be storing

null

in your list.

 

Also you could probably use TileEntity.isInvalid instead of the weird null-check stuff you're currently doing.

Don't make mods if you don't know Java.

Check out my website: http://shadowfacts.net

Developer of many mods

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.