Files
Applied-Energistics-2/src/main/java/appeng/me/cache/SpatialPylonCache.java
T
shartte 5b3c4aef79 When blocks adjacent to multiblock-capable blocks are updated, (#4474)
do not always recalculate existing multiblocks. Only do so,
if the adjacent block is either part of the multiblock's bounding
box, or if the adjacent block would be a valid part of the multiblock.
2020-07-18 18:18:24 +02:00

244 lines
9.1 KiB
Java

/*
* 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 <http://www.gnu.org/licenses/lgpl>.
*/
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.SpatialIOPortTileEntity;
import appeng.tile.spatial.SpatialPylonTileEntity;
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<SpatialIOPortTileEntity> ioPorts = new ArrayList<>();
private HashMap<SpatialPylonCluster, SpatialPylonCluster> 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(SpatialIOPortTileEntity.class)) {
this.ioPorts.add((SpatialIOPortTileEntity) gm.getMachine());
}
final IReadOnlyCollection<IGridNode> set = grid.getMachines(SpatialPylonTileEntity.class);
for (final IGridNode gm : set) {
if (gm.meetsChannelRequirements()) {
final SpatialPylonCluster c = ((SpatialPylonTileEntity) 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) {
}
}