diff --git a/src/main/java/com/simibubi/create/foundation/tileEntity/SmartTileEntity.java b/src/main/java/com/simibubi/create/foundation/tileEntity/SmartTileEntity.java index 9404b3544..37605d859 100644 --- a/src/main/java/com/simibubi/create/foundation/tileEntity/SmartTileEntity.java +++ b/src/main/java/com/simibubi/create/foundation/tileEntity/SmartTileEntity.java @@ -17,7 +17,9 @@ import net.minecraftforge.items.CapabilityItemHandler; public abstract class SmartTileEntity extends SyncedTileEntity implements ITickableTileEntity { - private Map, TileEntityBehaviour> behaviours; + private final Map, TileEntityBehaviour> behaviours; + // Internally maintained to be identical to behaviorMap.values() in order to improve iteration performance. + private final List behaviourList; private boolean initialized; private boolean firstNbtRead; private int lazyTickRate; @@ -36,6 +38,9 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka ArrayList list = new ArrayList<>(); addBehaviours(list); list.forEach(b -> behaviours.put(b.getType(), b)); + + behaviourList = new ArrayList<>(list.size()); + updateBehaviorList(); } public abstract void addBehaviours(List behaviours); @@ -58,13 +63,11 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka lazyTick(); } - behaviours.values() - .forEach(TileEntityBehaviour::tick); + behaviourList.forEach(TileEntityBehaviour::tick); } public void initialize() { - behaviours.values() - .forEach(TileEntityBehaviour::initialize); + behaviourList.forEach(TileEntityBehaviour::initialize); lazyTick(); } @@ -99,10 +102,11 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka ArrayList list = new ArrayList<>(); addBehavioursDeferred(list); list.forEach(b -> behaviours.put(b.getType(), b)); + + updateBehaviorList(); } super.read(compound); - behaviours.values() - .forEach(tb -> tb.read(compound, clientPacket)); + behaviourList.forEach(tb -> tb.read(compound, clientPacket)); } /** @@ -110,8 +114,7 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka */ protected void write(CompoundNBT compound, boolean clientPacket) { super.write(compound); - behaviours.values() - .forEach(tb -> tb.write(compound, clientPacket)); + behaviourList.forEach(tb -> tb.write(compound, clientPacket)); } @Override @@ -130,19 +133,31 @@ public abstract class SmartTileEntity extends SyncedTileEntity implements ITicka } protected void forEachBehaviour(Consumer action) { - behaviours.values() - .forEach(action); + behaviourList.forEach(action); } protected void attachBehaviourLate(TileEntityBehaviour behaviour) { behaviours.put(behaviour.getType(), behaviour); behaviour.initialize(); + + updateBehaviorList(); } protected void removeBehaviour(BehaviourType type) { TileEntityBehaviour remove = behaviours.remove(type); - if (remove != null) + if (remove != null) { remove.remove(); + updateBehaviorList(); + } + } + + // We don't trust the input to the API will be sane, so we + // update all the contents whenever something changes. It's + // simpler than trying to manipulate the list one element at + // a time. + private void updateBehaviorList() { + behaviourList.clear(); + behaviourList.addAll(behaviours.values()); } @SuppressWarnings("unchecked")