Jump to content
View in the app

A better way to browse. Learn more.

Forge Forums

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Featured Replies

Posted

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

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

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...

Important Information

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

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.