1e20cd8c08
# Conflicts: # build.gradle # gradle.properties # src/api/java/appeng/api/config/Upgrades.java # src/api/java/appeng/api/recipes/ResolverResult.java # src/main/java/appeng/block/AEBaseBlockItemChargeable.java # src/main/java/appeng/block/crafting/CraftingStorageItem.java # src/main/java/appeng/block/misc/ChargerBlock.java # src/main/java/appeng/block/networking/CableBusBlock.java # src/main/java/appeng/block/storage/ChestBlock.java # src/main/java/appeng/block/storage/DriveSlotCellType.java # src/main/java/appeng/capabilities/Capabilities.java # src/main/java/appeng/client/me/ItemRepo.java # src/main/java/appeng/client/render/cablebus/FacadeBuilder.java # src/main/java/appeng/client/render/effects/ChargedOreFX.java # src/main/java/appeng/client/render/effects/CraftingFx.java # src/main/java/appeng/client/render/effects/EnergyFx.java # src/main/java/appeng/client/render/effects/LightningArcFX.java # src/main/java/appeng/client/render/effects/LightningFX.java # src/main/java/appeng/client/render/effects/MatterCannonFX.java # src/main/java/appeng/client/render/effects/VibrantFX.java # src/main/java/appeng/client/render/spatial/SpatialPylonRendering.java # src/main/java/appeng/client/render/tesr/DriveLedTileEntityRenderer.java # src/main/java/appeng/container/AEBaseContainer.java # src/main/java/appeng/container/implementations/CellWorkbenchContainer.java # src/main/java/appeng/container/implementations/MolecularAssemblerContainer.java # src/main/java/appeng/container/implementations/PatternTermContainer.java # src/main/java/appeng/container/implementations/QuartzKnifeContainer.java # src/main/java/appeng/core/AEConfig.java # src/main/java/appeng/core/AEItemGroup.java # src/main/java/appeng/core/Api.java # src/main/java/appeng/core/AppEng.java # src/main/java/appeng/core/Registration.java # src/main/java/appeng/core/api/definitions/ApiBlocks.java # src/main/java/appeng/core/api/definitions/ApiParts.java # src/main/java/appeng/core/features/registries/MovableTileRegistry.java # src/main/java/appeng/core/features/registries/P2PTunnelRegistry.java # src/main/java/appeng/core/features/registries/WirelessRegistry.java # src/main/java/appeng/core/features/registries/WorldGenRegistry.java # src/main/java/appeng/core/features/registries/cell/BasicItemCellGuiHandler.java # src/main/java/appeng/core/sync/BasePacketHandler.java # src/main/java/appeng/core/sync/packets/ClickPacket.java # src/main/java/appeng/core/sync/packets/PatternSlotPacket.java # src/main/java/appeng/crafting/CraftingTreeProcess.java # src/main/java/appeng/debug/ReplicatorCardItem.java # src/main/java/appeng/entity/ChargedQuartzEntity.java # src/main/java/appeng/entity/SingularityEntity.java # src/main/java/appeng/entity/TinyTNTPrimedEntity.java # src/main/java/appeng/fluids/helper/DualityFluidInterface.java # src/main/java/appeng/fluids/helper/FluidCellConfig.java # src/main/java/appeng/fluids/parts/FluidFormationPlanePart.java # src/main/java/appeng/fluids/parts/FluidHandlerAdapter.java # src/main/java/appeng/forge/data/providers/IAE2DataProvider.java # src/main/java/appeng/forge/data/providers/recipes/SlabStairRecipes.java # src/main/java/appeng/helpers/CraftingPatternDetails.java # src/main/java/appeng/helpers/DualityInterface.java # src/main/java/appeng/helpers/WirelessTerminalGuiObject.java # src/main/java/appeng/hooks/IBlockTool.java # src/main/java/appeng/hooks/TickHandler.java # src/main/java/appeng/integration/modules/jei/CondenserCategory.java # src/main/java/appeng/integration/modules/jei/JEIPlugin.java # src/main/java/appeng/items/misc/EncodedPatternItem.java # src/main/java/appeng/items/parts/FacadeItem.java # src/main/java/appeng/items/parts/PartItem.java # src/main/java/appeng/items/storage/AbstractStorageCell.java # src/main/java/appeng/items/storage/CreativeStorageCellItem.java # src/main/java/appeng/items/tools/powered/ColorApplicatorItem.java # src/main/java/appeng/items/tools/powered/EntropyManipulatorItem.java # src/main/java/appeng/items/tools/powered/MatterCannonItem.java # src/main/java/appeng/items/tools/powered/WirelessTerminalItem.java # src/main/java/appeng/me/cluster/implementations/CraftingCPUCluster.java # src/main/java/appeng/me/storage/MEMonitorIFluidHandler.java # src/main/java/appeng/parts/PartPlacement.java # src/main/java/appeng/parts/automation/FormationPlanePart.java # src/main/java/appeng/parts/p2p/FluidP2PTunnelPart.java # src/main/java/appeng/parts/reporting/PatternTerminalPart.java # src/main/java/appeng/spatial/CachedPlane.java # src/main/java/appeng/spatial/StorageChunkGenerator.java # src/main/java/appeng/spatial/StorageHelper.java # src/main/java/appeng/tile/crafting/CraftingBlockEntity.java # src/main/java/appeng/tile/crafting/CraftingStorageBlockEntity.java # src/main/java/appeng/tile/crafting/MolecularAssemblerBlockEntity.java # src/main/java/appeng/tile/inventory/AppEngInternalAEInventory.java # src/main/java/appeng/tile/misc/ChargerBlockEntity.java # src/main/java/appeng/tile/misc/CondenserBlockEntity.java # src/main/java/appeng/tile/misc/InscriberBlockEntity.java # src/main/java/appeng/tile/misc/InscriberRecipes.java # src/main/java/appeng/tile/qnb/QuantumBridgeBlockEntity.java # src/main/java/appeng/tile/storage/ChestBlockEntity.java # src/main/java/appeng/tile/storage/DriveBlockEntity.java # src/main/java/appeng/util/Platform.java # src/main/java/team/chisel/ctm/api/IFacade.java # src/main/resources/assets/appliedenergistics2/models/block/chest/base.json # src/unported/java/appeng/client/render/FacadeItemModel.java # src/unported/java/appeng/client/render/model/DriveBakedModel.java # src/unported/java/appeng/client/render/model/DriveModel.java # src/unported/java/appeng/core/PluginLoader.java
372 lines
13 KiB
Java
372 lines
13 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.EnumSet;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
|
|
import appeng.tile.networking.ControllerBlockEntity;
|
|
import net.minecraft.entity.player.PlayerEntity;
|
|
import net.minecraft.server.network.ServerPlayerEntity;
|
|
|
|
import appeng.api.features.AEFeature;
|
|
import appeng.api.networking.GridFlags;
|
|
import appeng.api.networking.IGrid;
|
|
import appeng.api.networking.IGridBlock;
|
|
import appeng.api.networking.IGridConnection;
|
|
import appeng.api.networking.IGridHost;
|
|
import appeng.api.networking.IGridMultiblock;
|
|
import appeng.api.networking.IGridNode;
|
|
import appeng.api.networking.IGridStorage;
|
|
import appeng.api.networking.events.MENetworkBootingStatusChange;
|
|
import appeng.api.networking.events.MENetworkChannelChanged;
|
|
import appeng.api.networking.events.MENetworkControllerChange;
|
|
import appeng.api.networking.events.MENetworkEventSubscribe;
|
|
import appeng.api.networking.pathing.ControllerState;
|
|
import appeng.api.networking.pathing.IPathingGrid;
|
|
import appeng.api.util.AEPartLocation;
|
|
import appeng.api.util.DimensionalCoord;
|
|
import appeng.core.AEConfig;
|
|
import appeng.core.Api;
|
|
import appeng.core.AppEng;
|
|
import appeng.core.stats.IAdvancementTrigger;
|
|
import appeng.me.GridConnection;
|
|
import appeng.me.GridNode;
|
|
import appeng.me.pathfinding.AdHocChannelUpdater;
|
|
import appeng.me.pathfinding.ControllerChannelUpdater;
|
|
import appeng.me.pathfinding.ControllerValidator;
|
|
import appeng.me.pathfinding.IPathItem;
|
|
import appeng.me.pathfinding.PathSegment;
|
|
|
|
public class PathGridCache implements IPathingGrid {
|
|
|
|
private final List<PathSegment> active = new ArrayList<>();
|
|
private final Set<ControllerBlockEntity> controllers = new HashSet<>();
|
|
private final Set<IGridNode> requireChannels = new HashSet<>();
|
|
private final Set<IGridNode> blockDense = new HashSet<>();
|
|
private final IGrid myGrid;
|
|
private int channelsInUse = 0;
|
|
private int channelsByBlocks = 0;
|
|
private double channelPowerUsage = 0.0;
|
|
private boolean recalculateControllerNextTick = true;
|
|
private boolean updateNetwork = true;
|
|
private boolean booting = false;
|
|
private ControllerState controllerState = ControllerState.NO_CONTROLLER;
|
|
private int ticksUntilReady = 20;
|
|
private int lastChannels = 0;
|
|
private HashSet<IPathItem> semiOpen = new HashSet<>();
|
|
|
|
public PathGridCache(final IGrid g) {
|
|
this.myGrid = g;
|
|
}
|
|
|
|
@Override
|
|
public void onUpdateTick() {
|
|
if (this.recalculateControllerNextTick) {
|
|
this.recalcController();
|
|
}
|
|
|
|
if (this.updateNetwork) {
|
|
if (!this.booting) {
|
|
this.myGrid.postEvent(new MENetworkBootingStatusChange());
|
|
}
|
|
|
|
this.booting = true;
|
|
this.updateNetwork = false;
|
|
this.setChannelsInUse(0);
|
|
|
|
if (this.controllerState == ControllerState.NO_CONTROLLER) {
|
|
final int requiredChannels = this.calculateRequiredChannels();
|
|
int used = requiredChannels;
|
|
if (requiredChannels > 8) {
|
|
used = 0;
|
|
}
|
|
|
|
final int nodes = this.myGrid.getNodes().size();
|
|
this.setChannelsInUse(used);
|
|
|
|
this.ticksUntilReady = 20 + Math.max(0, nodes / 100 - 20);
|
|
this.setChannelsByBlocks(nodes * used);
|
|
this.setChannelPowerUsage(this.getChannelsByBlocks() / 128.0);
|
|
|
|
this.myGrid.getPivot().beginVisit(new AdHocChannelUpdater(used));
|
|
} else if (this.controllerState == ControllerState.CONTROLLER_CONFLICT) {
|
|
this.ticksUntilReady = 20;
|
|
this.myGrid.getPivot().beginVisit(new AdHocChannelUpdater(0));
|
|
} else {
|
|
final int nodes = this.myGrid.getNodes().size();
|
|
this.ticksUntilReady = 20 + Math.max(0, nodes / 100 - 20);
|
|
final HashSet<IPathItem> closedList = new HashSet<>();
|
|
this.semiOpen = new HashSet<>();
|
|
|
|
// myGrid.getPivot().beginVisit( new AdHocChannelUpdater( 0 )
|
|
// );
|
|
for (final IGridNode node : this.myGrid.getMachines(ControllerBlockEntity.class)) {
|
|
closedList.add((IPathItem) node);
|
|
for (final IGridConnection gcc : node.getConnections()) {
|
|
final GridConnection gc = (GridConnection) gcc;
|
|
if (!(gc.getOtherSide(node).getMachine() instanceof ControllerBlockEntity)) {
|
|
final List<IPathItem> open = new ArrayList<>();
|
|
closedList.add(gc);
|
|
open.add(gc);
|
|
gc.setControllerRoute((GridNode) node, true);
|
|
this.active.add(new PathSegment(this, open, this.semiOpen, closedList));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!this.active.isEmpty() || this.ticksUntilReady > 0) {
|
|
final Iterator<PathSegment> i = this.active.iterator();
|
|
while (i.hasNext()) {
|
|
final PathSegment pat = i.next();
|
|
if (pat.step()) {
|
|
pat.setDead(true);
|
|
i.remove();
|
|
}
|
|
}
|
|
|
|
this.ticksUntilReady--;
|
|
|
|
if (this.active.isEmpty() && this.ticksUntilReady <= 0) {
|
|
if (this.controllerState == ControllerState.CONTROLLER_ONLINE) {
|
|
final Iterator<ControllerBlockEntity> controllerIterator = this.controllers.iterator();
|
|
if (controllerIterator.hasNext()) {
|
|
final ControllerBlockEntity controller = controllerIterator.next();
|
|
controller.getGridNode(AEPartLocation.INTERNAL).beginVisit(new ControllerChannelUpdater());
|
|
}
|
|
}
|
|
|
|
// check for achievements
|
|
this.achievementPost();
|
|
|
|
this.booting = false;
|
|
this.setChannelPowerUsage(this.getChannelsByBlocks() / 128.0);
|
|
this.myGrid.postEvent(new MENetworkBootingStatusChange());
|
|
}
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void removeNode(final IGridNode gridNode, final IGridHost machine) {
|
|
if (machine instanceof ControllerBlockEntity) {
|
|
this.controllers.remove(machine);
|
|
this.recalculateControllerNextTick = true;
|
|
}
|
|
|
|
final EnumSet<GridFlags> flags = gridNode.getGridBlock().getFlags();
|
|
|
|
if (flags.contains(GridFlags.REQUIRE_CHANNEL)) {
|
|
this.requireChannels.remove(gridNode);
|
|
}
|
|
|
|
if (flags.contains(GridFlags.CANNOT_CARRY_COMPRESSED)) {
|
|
this.blockDense.remove(gridNode);
|
|
}
|
|
|
|
this.repath();
|
|
}
|
|
|
|
@Override
|
|
public void addNode(final IGridNode gridNode, final IGridHost machine) {
|
|
if (machine instanceof ControllerBlockEntity) {
|
|
this.controllers.add((ControllerBlockEntity) machine);
|
|
this.recalculateControllerNextTick = true;
|
|
}
|
|
|
|
final EnumSet<GridFlags> flags = gridNode.getGridBlock().getFlags();
|
|
|
|
if (flags.contains(GridFlags.REQUIRE_CHANNEL)) {
|
|
this.requireChannels.add(gridNode);
|
|
}
|
|
|
|
if (flags.contains(GridFlags.CANNOT_CARRY_COMPRESSED)) {
|
|
this.blockDense.add(gridNode);
|
|
}
|
|
|
|
this.repath();
|
|
}
|
|
|
|
@Override
|
|
public void onSplit(final IGridStorage storageB) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public void onJoin(final IGridStorage storageB) {
|
|
|
|
}
|
|
|
|
@Override
|
|
public void populateGridStorage(final IGridStorage storage) {
|
|
|
|
}
|
|
|
|
private void recalcController() {
|
|
this.recalculateControllerNextTick = false;
|
|
final ControllerState old = this.controllerState;
|
|
|
|
if (this.controllers.isEmpty()) {
|
|
this.controllerState = ControllerState.NO_CONTROLLER;
|
|
} else {
|
|
final IGridNode startingNode = this.controllers.iterator().next().getGridNode(AEPartLocation.INTERNAL);
|
|
if (startingNode == null) {
|
|
this.controllerState = ControllerState.CONTROLLER_CONFLICT;
|
|
return;
|
|
}
|
|
|
|
final DimensionalCoord dc = startingNode.getGridBlock().getLocation();
|
|
final ControllerValidator cv = new ControllerValidator(dc.x, dc.y, dc.z);
|
|
|
|
startingNode.beginVisit(cv);
|
|
|
|
if (cv.isValid() && cv.getFound() == this.controllers.size()) {
|
|
this.controllerState = ControllerState.CONTROLLER_ONLINE;
|
|
} else {
|
|
this.controllerState = ControllerState.CONTROLLER_CONFLICT;
|
|
}
|
|
}
|
|
|
|
if (old != this.controllerState) {
|
|
this.myGrid.postEvent(new MENetworkControllerChange());
|
|
}
|
|
}
|
|
|
|
private int calculateRequiredChannels() {
|
|
this.semiOpen.clear();
|
|
|
|
int depth = 0;
|
|
for (final IGridNode nodes : this.requireChannels) {
|
|
if (!this.semiOpen.contains(nodes)) {
|
|
final IGridBlock gb = nodes.getGridBlock();
|
|
final EnumSet<GridFlags> flags = gb.getFlags();
|
|
|
|
if (flags.contains(GridFlags.COMPRESSED_CHANNEL) && !this.blockDense.isEmpty()) {
|
|
return 9;
|
|
}
|
|
|
|
depth++;
|
|
|
|
if (flags.contains(GridFlags.MULTIBLOCK)) {
|
|
final IGridMultiblock gmb = (IGridMultiblock) gb;
|
|
final Iterator<IGridNode> i = gmb.getMultiblockNodes();
|
|
while (i.hasNext()) {
|
|
this.semiOpen.add((IPathItem) i.next());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return depth;
|
|
}
|
|
|
|
private void achievementPost() {
|
|
if (this.lastChannels != this.getChannelsInUse() && AEConfig.instance().isFeatureEnabled(AEFeature.CHANNELS)) {
|
|
final IAdvancementTrigger currentBracket = this.getAchievementBracket(this.getChannelsInUse());
|
|
final IAdvancementTrigger lastBracket = this.getAchievementBracket(this.lastChannels);
|
|
if (currentBracket != lastBracket && currentBracket != null) {
|
|
for (final IGridNode n : this.requireChannels) {
|
|
PlayerEntity player = Api.instance().registries().players().findPlayer(n.getPlayerID());
|
|
if (player instanceof ServerPlayerEntity) {
|
|
currentBracket.trigger((ServerPlayerEntity) player);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this.lastChannels = this.getChannelsInUse();
|
|
}
|
|
|
|
private IAdvancementTrigger getAchievementBracket(final int ch) {
|
|
if (ch < 8) {
|
|
return null;
|
|
}
|
|
|
|
if (ch < 128) {
|
|
return AppEng.instance().getAdvancementTriggers().getNetworkApprentice();
|
|
}
|
|
|
|
if (ch < 2048) {
|
|
return AppEng.instance().getAdvancementTriggers().getNetworkEngineer();
|
|
}
|
|
|
|
return AppEng.instance().getAdvancementTriggers().getNetworkAdmin();
|
|
}
|
|
|
|
@MENetworkEventSubscribe
|
|
void updateNodReq(final MENetworkChannelChanged ev) {
|
|
final IGridNode gridNode = ev.node;
|
|
|
|
if (gridNode.getGridBlock().getFlags().contains(GridFlags.REQUIRE_CHANNEL)) {
|
|
this.requireChannels.add(gridNode);
|
|
} else {
|
|
this.requireChannels.remove(gridNode);
|
|
}
|
|
|
|
this.repath();
|
|
}
|
|
|
|
@Override
|
|
public boolean isNetworkBooting() {
|
|
return !this.booting && !this.active.isEmpty();
|
|
}
|
|
|
|
@Override
|
|
public ControllerState getControllerState() {
|
|
return this.controllerState;
|
|
}
|
|
|
|
@Override
|
|
public void repath() {
|
|
// clean up...
|
|
this.active.clear();
|
|
|
|
this.setChannelsByBlocks(0);
|
|
this.updateNetwork = true;
|
|
}
|
|
|
|
double getChannelPowerUsage() {
|
|
return this.channelPowerUsage;
|
|
}
|
|
|
|
private void setChannelPowerUsage(final double channelPowerUsage) {
|
|
this.channelPowerUsage = channelPowerUsage;
|
|
}
|
|
|
|
public int getChannelsByBlocks() {
|
|
return this.channelsByBlocks;
|
|
}
|
|
|
|
public void setChannelsByBlocks(final int channelsByBlocks) {
|
|
this.channelsByBlocks = channelsByBlocks;
|
|
}
|
|
|
|
public int getChannelsInUse() {
|
|
return this.channelsInUse;
|
|
}
|
|
|
|
public void setChannelsInUse(final int channelsInUse) {
|
|
this.channelsInUse = channelsInUse;
|
|
}
|
|
}
|