Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the growth accelerator accept FE directly #7734

Merged
merged 2 commits into from
Mar 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion guidebook/items-blocks-machines/growth_accelerator.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@ Curiously, it can *also* accelerate the growth of various plants.
<IsometricCamera yaw="195" pitch="30" />
</GameScene>

Power can be provided via the top or bottom, via either AE2's [cables](cables.md), or other mod power cables. It can
accept either AE2's power (AE) or Forge Energy (FE).

To power it manually, place a <ItemLink id="crank" /> on the top or bottom and right-click it.

It only connects to cables on its ends where the pink fluix greebles are.
The top and the bottom can be identified by the pink flux greebles on them.

<GameScene zoom="6" background="transparent">
<ImportStructure src="../assets/assemblies/accelerator_connections.snbt" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;

import appeng.api.config.Actionable;
import appeng.api.config.PowerUnits;
import appeng.api.implementations.blockentities.ICrankable;
import appeng.api.networking.GridHelper;
import appeng.api.networking.IManagedGridNode;
import appeng.api.networking.energy.IAEPowerStorage;
import appeng.api.orientation.BlockOrientation;
import appeng.api.util.AECableType;
import appeng.blockentity.misc.CrankBlockEntity;
import appeng.blockentity.powersink.AEBasePoweredBlockEntity;
import appeng.me.helpers.BlockEntityNodeListener;
import appeng.me.helpers.IGridConnectedBlockEntity;
Expand Down Expand Up @@ -109,4 +113,16 @@ protected void onOrientationChanged(BlockOrientation orientation) {
protected final void onGridConnectableSidesChanged() {
getMainNode().setExposedOnSides(getGridConnectableSides(getOrientation()));
}

public final class Crankable implements ICrankable {
@Override
public boolean canTurn() {
return getInternalCurrentPower() < getInternalMaxPower();
}

@Override
public void applyTurn() {
injectExternalPower(PowerUnits.AE, CrankBlockEntity.POWER_PER_CRANK_TURN, Actionable.MODULATE);
}
}
}
12 changes: 0 additions & 12 deletions src/main/java/appeng/blockentity/misc/ChargerBlockEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -274,16 +274,4 @@ public boolean allowExtract(InternalInventory inv, int slotIndex, int amount) {
return ChargerRecipes.allowExtract(chargerBlockEntity.level, extractedItem);
}
}

class Crankable implements ICrankable {
@Override
public boolean canTurn() {
return getInternalCurrentPower() < getInternalMaxPower();
}

@Override
public void applyTurn() {
injectExternalPower(PowerUnits.AE, CrankBlockEntity.POWER_PER_CRANK_TURN, Actionable.MODULATE);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,15 @@

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;

import appeng.api.config.Actionable;
import appeng.api.ids.AETags;
import appeng.api.implementations.IPowerChannelState;
import appeng.api.implementations.blockentities.ICrankable;
import appeng.api.inventories.InternalInventory;
import appeng.api.networking.IGridNode;
import appeng.api.networking.IGridNodeListener;
import appeng.api.networking.ticking.IGridTickable;
Expand All @@ -39,22 +40,21 @@
import appeng.api.orientation.BlockOrientation;
import appeng.api.orientation.RelativeSide;
import appeng.api.util.AECableType;
import appeng.blockentity.grid.AENetworkBlockEntity;
import appeng.block.misc.GrowthAcceleratorBlock;
import appeng.blockentity.grid.AENetworkPowerBlockEntity;
import appeng.core.AEConfig;

public class GrowthAcceleratorBlockEntity extends AENetworkBlockEntity implements IPowerChannelState {
public class GrowthAcceleratorBlockEntity extends AENetworkPowerBlockEntity implements IPowerChannelState {

// Allow storage of up to 10 cranks
public static final int MAX_STORED_POWER = 10 * CrankBlockEntity.POWER_PER_CRANK_TURN;
// AE per tick
private static final int POWER_PER_TICK = 8;

private boolean hasPower = false;

// For cranking!
private float storedPower;

public GrowthAcceleratorBlockEntity(BlockEntityType<?> blockEntityType, BlockPos pos, BlockState blockState) {
super(blockEntityType, pos, blockState);
setInternalMaxPower(MAX_STORED_POWER);
setPowerSides(getGridConnectableSides(getOrientation()));
getMainNode().setFlags();
getMainNode().setIdlePowerUsage(POWER_PER_TICK);
getMainNode().addService(IGridTickable.class, new IGridTickable() {
Expand All @@ -72,23 +72,35 @@ public TickRateModulation tickingRequest(IGridNode node, int ticksSinceLastCall)
});
}

@Override
public InternalInventory getInternalInventory() {
return InternalInventory.empty();
}

@Override
public Set<Direction> getGridConnectableSides(BlockOrientation orientation) {
return orientation.getSides(EnumSet.of(RelativeSide.FRONT, RelativeSide.BACK));
}

@Override
protected void onOrientationChanged(BlockOrientation orientation) {
super.onOrientationChanged(orientation);
setPowerSides(getGridConnectableSides(getOrientation()));
}

private void onTick(int ticksSinceLastCall) {
// We drain local power in *addition* to network power, which is handled via idle power consumption
if (storedPower > 0) {
storedPower -= POWER_PER_TICK * Math.max(1, ticksSinceLastCall);
if (storedPower <= 0) {
storedPower = 0;
markForUpdate();
}
} else if (!getMainNode().isPowered()) {
var powered = isPowered();
if (powered != getBlockState().getValue(GrowthAcceleratorBlock.POWERED)) {
markForUpdate();
}

if (!powered) {
return;
}

// We drain local power in *addition* to network power, which is handled via idle power consumption
extractAEPower(POWER_PER_TICK * ticksSinceLastCall, Actionable.MODULATE);

for (var direction : Direction.values()) {
var adjPos = getBlockPos().relative(direction);
var adjState = getLevel().getBlockState(adjPos);
Expand All @@ -113,70 +125,25 @@ public AECableType getCableConnectionType(Direction dir) {
return AECableType.COVERED;
}

@Override
public boolean readFromStream(FriendlyByteBuf data) {
final boolean c = super.readFromStream(data);
final boolean hadPower = this.isPowered();
this.setPowered(data.readBoolean());
return this.isPowered() != hadPower || c;
}

@Override
public void writeToStream(FriendlyByteBuf data) {
super.writeToStream(data);
data.writeBoolean(getMainNode().isPowered());
}

@Override
public boolean isPowered() {
if (!isClientSide()) {
return getMainNode().isPowered() || storedPower > 0;
return getMainNode().isPowered() || extractAEPower(POWER_PER_TICK, Actionable.SIMULATE) >= POWER_PER_TICK;
}

return this.hasPower;
return this.getBlockState().getValue(GrowthAcceleratorBlock.POWERED);
}

@Override
public boolean isActive() {
return this.isPowered();
}

private void setPowered(boolean hasPower) {
this.hasPower = hasPower;
}

/**
* Allow cranking from the top or bottom.
*/
@org.jetbrains.annotations.Nullable
public ICrankable getCrankable(Direction direction) {
if (direction == getFront() || direction == getFront().getOpposite()) {
if (getPowerSides().contains(direction)) {
return new Crankable();
}
return null;
}

class Crankable implements ICrankable {
@Override
public boolean canTurn() {
return storedPower < MAX_STORED_POWER;
}

@Override
public void applyTurn() {
if (isClientSide()) {
return; // Only apply crank-turns server-side
}

// Cranking will always add enough power for at least one tick,
// so we should send a transition from unpowered to powered to clients.
boolean needsUpdate = !isPowered();

storedPower = Math.min(MAX_STORED_POWER, storedPower + CrankBlockEntity.POWER_PER_CRANK_TURN);

if (needsUpdate) {
markForUpdate();
}
}
}
}
13 changes: 0 additions & 13 deletions src/main/java/appeng/blockentity/misc/InscriberBlockEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@

import appeng.api.config.Actionable;
import appeng.api.config.PowerMultiplier;
import appeng.api.config.PowerUnits;
import appeng.api.config.Setting;
import appeng.api.config.Settings;
import appeng.api.config.YesNo;
Expand Down Expand Up @@ -609,16 +608,4 @@ public boolean allowInsert(InternalInventory inv, int slot, ItemStack stack) {
return !isSmash();
}
}

class Crankable implements ICrankable {
@Override
public boolean canTurn() {
return getInternalCurrentPower() < getInternalMaxPower();
}

@Override
public void applyTurn() {
injectExternalPower(PowerUnits.AE, CrankBlockEntity.POWER_PER_CRANK_TURN, Actionable.MODULATE);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.block.entity.BlockEntity;

import appeng.api.implementations.IPowerChannelState;
import appeng.api.integrations.igtooltip.TooltipBuilder;
import appeng.api.integrations.igtooltip.TooltipContext;
import appeng.api.integrations.igtooltip.providers.BodyProvider;
Expand All @@ -30,6 +31,13 @@ public void buildTooltip(BlockEntity object, TooltipContext context, TooltipBuil

@Override
public void provideServerData(Player player, BlockEntity object, CompoundTag serverData) {
// Some devices can be powered both externally and through the grid.
// If they are powered externally, they might still be active when the grid itself is down
if (object instanceof IPowerChannelState powerChannelState && powerChannelState.isActive()) {
serverData.putByte(TAG_STATE, (byte) GridNodeState.ONLINE.ordinal());
return;
}

if (object instanceof IGridConnectedBlockEntity gridConnectedBlockEntity) {
var state = GridNodeState.fromNode(gridConnectedBlockEntity.getActionableNode());
serverData.putByte(TAG_STATE, (byte) state.ordinal());
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/appeng/me/energy/StoredEnergyAmount.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ public double insert(double amount, boolean commit) {
}

/**
* Increase the amount, and return what would have exceeded the maximum.
* Decrease the amount, and return how much was actually extracted.
*/
public double extract(double amount, boolean commit) {
if (amount < MIN_AMOUNT) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import net.minecraft.world.level.block.state.properties.BlockStateProperties;

import appeng.api.stacks.AEItemKey;
import appeng.block.misc.GrowthAcceleratorBlock;
import appeng.blockentity.misc.GrowthAcceleratorBlockEntity;
import appeng.blockentity.storage.ChestBlockEntity;
import appeng.core.definitions.AEBlocks;
import appeng.core.definitions.AEItems;
Expand Down Expand Up @@ -94,11 +96,11 @@ public static void testGrowthAccelerator(PlotBuilder plot) {
.setValue(BlockStateProperties.FACING, Direction.UP));
plot.test(helper -> helper.startSequence()
.thenWaitUntil(helper::checkAllInitialized)
// NYI
// .thenWaitUntil(() -> {
// var accel = (GrowthAcceleratorBlockEntity) helper.getBlockEntity(ORIGIN);
// helper.check(accel.isPowered(), "should be powered", ORIGIN);
// })
.thenWaitUntil(() -> {
var accel = (GrowthAcceleratorBlockEntity) helper.getBlockEntity(ORIGIN);
helper.check(accel.isPowered(), "should be powered", ORIGIN);
})
.thenWaitUntil(() -> helper.assertBlockProperty(ORIGIN, GrowthAcceleratorBlock.POWERED, true))
// Ensure that after 1 second, the grid still has no energy
.thenExecuteAfter(20, () -> checkGridHasNoEnergy(helper))
.thenSucceed());
Expand Down
Loading