/* * This file is part of Applied Energistics 2. * Copyright (c) 2013 - 2014, AlgorithmX2, All rights reserved. * * Applied Energistics 2 is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Applied Energistics 2 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with Applied Energistics 2. If not, see . */ package appeng.me.cache; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import appeng.api.networking.IGrid; import appeng.api.networking.IGridHost; import appeng.api.networking.IGridNode; import appeng.api.networking.IGridStorage; import appeng.api.networking.events.MENetworkBootingStatusChange; import appeng.api.networking.events.MENetworkEventSubscribe; import appeng.api.networking.spatial.ISpatialCache; import appeng.api.util.DimensionalCoord; import appeng.api.util.IReadOnlyCollection; import appeng.core.AEConfig; import appeng.me.cluster.implementations.SpatialPylonCluster; import appeng.tile.spatial.SpatialIOPortBlockEntity; import appeng.tile.spatial.SpatialPylonBlockEntity; public class SpatialPylonCache implements ISpatialCache { private final IGrid myGrid; private long powerRequired = 0; private double efficiency = 0.0; private DimensionalCoord captureMin; private DimensionalCoord captureMax; private boolean isValid = false; private List ioPorts = new ArrayList<>(); private HashMap clusters = new HashMap<>(); public SpatialPylonCache(final IGrid g) { this.myGrid = g; } @MENetworkEventSubscribe public void bootingRender(final MENetworkBootingStatusChange c) { this.reset(this.myGrid); } private void reset(final IGrid grid) { this.clusters = new HashMap<>(); this.ioPorts = new ArrayList<>(); for (final IGridNode gm : grid.getMachines(SpatialIOPortBlockEntity.class)) { this.ioPorts.add((SpatialIOPortBlockEntity) gm.getMachine()); } final IReadOnlyCollection set = grid.getMachines(SpatialPylonBlockEntity.class); for (final IGridNode gm : set) { if (gm.meetsChannelRequirements()) { final SpatialPylonCluster c = ((SpatialPylonBlockEntity) gm.getMachine()).getCluster(); if (c != null) { this.clusters.put(c, c); } } } this.captureMax = null; this.captureMin = null; this.isValid = true; int pylonBlocks = 0; for (final SpatialPylonCluster cl : this.clusters.values()) { if (this.captureMax == null) { this.captureMax = new DimensionalCoord(cl.getWorld(), cl.getBoundsMax()); } if (this.captureMin == null) { this.captureMin = new DimensionalCoord(cl.getWorld(), cl.getBoundsMin()); } pylonBlocks += cl.tileCount(); this.captureMin.x = Math.min(this.captureMin.x, cl.getBoundsMin().getX()); this.captureMin.y = Math.min(this.captureMin.y, cl.getBoundsMin().getY()); this.captureMin.z = Math.min(this.captureMin.z, cl.getBoundsMin().getZ()); this.captureMax.x = Math.max(this.captureMax.x, cl.getBoundsMax().getX()); this.captureMax.y = Math.max(this.captureMax.y, cl.getBoundsMax().getY()); this.captureMax.z = Math.max(this.captureMax.z, cl.getBoundsMax().getZ()); } double maxPower = 0; double minPower = 0; if (this.hasRegion()) { this.isValid = this.captureMax.x - this.captureMin.x > 1 && this.captureMax.y - this.captureMin.y > 1 && this.captureMax.z - this.captureMin.z > 1; for (final SpatialPylonCluster cl : this.clusters.values()) { switch (cl.getCurrentAxis()) { case X: this.isValid = this.isValid && ((this.captureMax.y == cl.getBoundsMin().getY() || this.captureMin.y == cl.getBoundsMax().getY()) || (this.captureMax.z == cl.getBoundsMin().getZ() || this.captureMin.z == cl.getBoundsMax().getZ())) && ((this.captureMax.y == cl.getBoundsMax().getY() || this.captureMin.y == cl.getBoundsMin().getY()) || (this.captureMax.z == cl.getBoundsMax().getZ() || this.captureMin.z == cl.getBoundsMin().getZ())); break; case Y: this.isValid = this.isValid && ((this.captureMax.x == cl.getBoundsMin().getX() || this.captureMin.x == cl.getBoundsMax().getX()) || (this.captureMax.z == cl.getBoundsMin().getZ() || this.captureMin.z == cl.getBoundsMax().getZ())) && ((this.captureMax.x == cl.getBoundsMax().getX() || this.captureMin.x == cl.getBoundsMin().getX()) || (this.captureMax.z == cl.getBoundsMax().getZ() || this.captureMin.z == cl.getBoundsMin().getZ())); break; case Z: this.isValid = this.isValid && ((this.captureMax.y == cl.getBoundsMin().getY() || this.captureMin.y == cl.getBoundsMax().getY()) || (this.captureMax.x == cl.getBoundsMin().getX() || this.captureMin.x == cl.getBoundsMax().getX())) && ((this.captureMax.y == cl.getBoundsMax().getY() || this.captureMin.y == cl.getBoundsMin().getY()) || (this.captureMax.x == cl.getBoundsMax().getX() || this.captureMin.x == cl.getBoundsMin().getX())); break; case UNFORMED: this.isValid = false; break; } } final int reqX = this.captureMax.x - this.captureMin.x; final int reqY = this.captureMax.y - this.captureMin.y; final int reqZ = this.captureMax.z - this.captureMin.z; final int requirePylonBlocks = Math.max(6, ((reqX * reqZ + reqX * reqY + reqY * reqZ) * 3) / 8); this.efficiency = (double) pylonBlocks / (double) requirePylonBlocks; if (this.efficiency > 1.0) { this.efficiency = 1.0; } if (this.efficiency < 0.0) { this.efficiency = 0.0; } minPower = (double) reqX * (double) reqY * reqZ * AEConfig.instance().getSpatialPowerMultiplier(); maxPower = Math.pow(minPower, AEConfig.instance().getSpatialPowerExponent()); } final double affective_efficiency = Math.pow(this.efficiency, 0.25); this.powerRequired = (long) (affective_efficiency * minPower + (1.0 - affective_efficiency) * maxPower); for (final SpatialPylonCluster cl : this.clusters.values()) { final boolean myWasValid = cl.isValid(); cl.setValid(this.isValid); if (myWasValid != this.isValid) { cl.updateStatus(false); } } } @Override public boolean hasRegion() { return this.captureMin != null; } @Override public boolean isValidRegion() { return this.hasRegion() && this.isValid; } @Override public DimensionalCoord getMin() { return this.captureMin; } @Override public DimensionalCoord getMax() { return this.captureMax; } @Override public long requiredPower() { return this.powerRequired; } @Override public float currentEfficiency() { return (float) this.efficiency * 100; } @Override public void onUpdateTick() { } @Override public void removeNode(final IGridNode node, final IGridHost machine) { } @Override public void addNode(final IGridNode node, final IGridHost machine) { } @Override public void onSplit(final IGridStorage storageB) { } @Override public void onJoin(final IGridStorage storageB) { } @Override public void populateGridStorage(final IGridStorage storage) { } }