Skip to content
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
15 changes: 15 additions & 0 deletions CHANGELOG.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
Unreleased

- Check generator redstone before the first power pulse so a disabled solar panel cannot produce a startup burst.
- Charge the moved electric drill its existing 250-unit track cost before saving its replacement, instead of charging the removed drill.
- Preserve saved growth chamber stages exactly before the first server tick, including mature crops waiting for output space.
- Stop the electric still consuming oil and power when the whole output batch will not fit.
- Respect modded fluid sources' drain rules and charge pump power only after fluid is collected.
- Keep growth controllers from requesting more electricity than they can store or use.
- Read light above solar panels without changing their generation rates.
- Keep turret beams within their existing range, clear of their own mounting post and blocked by adjacent cover.
- Keep hydroturbines anchored while flowing water turns their blades.
- Read a machine's redstone interlock on its first server tick, then keep the usual eight-tick refresh.
- Send machine sounds to nearby connected players without loading surrounding chunks.
- Use an empty or full-scale hydroelectric display without changing its existing power reading or electricity generation.

Electric Advantage 2.2.3.112021

- Retain unfinished drill progress when rebuilding the mining target after a world or chunk reload.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@ protected void entityInit() {
// do nothing
}

@Override
public boolean isPushedByWater() {
// Anchored to the generator: flow drives rotation, not linear movement.
return false;
}

@Override
public void onUpdate(){
super.onUpdate();
Expand Down
12 changes: 9 additions & 3 deletions src/main/java/com/mcmoddev/electricadvantage/gui/GUIHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,23 @@ public static void drawIndicatorLight(boolean on,GUIContainer gc, int xOffset, i
}

public static void drawProgressBar(int x, int y, float progress, GUIContainer gc){
int n = (int)(8 * (progress + 0.0625f) );
if(n <= 0) return;
int w = 1 + (n * LED_BAR_W8);
int w = progressBarWidth(progress);
if(w == 0) return;
gc.drawTexturedModalRect(x, y, LED_BAR_X, LED_BAR_Y, w, LED_BAR_H);
}

static int progressBarWidth(float progress) {
progress = Float.isFinite(progress) ? Math.max(0F, Math.min(1F, progress)) : 0F;
int n = (int)(8 * (progress + 0.0625f));
return n <= 0 ? 0 : 1 + n * LED_BAR_W8;
}


public static void drawFluidBar(FluidStack fs, float barHeight, int xPos, int yPos,
GUIContainer guiContainer, int x, int y, float z,
ResourceLocation displayImage){

barHeight = Float.isFinite(barHeight) ? Math.max(0F, Math.min(1F, barHeight)) : 0F;
final int w = 16;
final int barSlotHeight = 60;
final int h = (int)(barSlotHeight * barHeight);
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/mcmoddev/electricadvantage/init/GUI.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public static void init(){

Blocks.steam_powered_generator.setGuiID(MachineGUIRegistry.addGUI(new PowerGeneratorGUI()), PowerAdvantage.getInstance());
Blocks.photovoltaic_generator.setGuiID(MachineGUIRegistry.addGUI(new PowerGeneratorGUI()), PowerAdvantage.getInstance());
Blocks.hydroelectric_generator.setGuiID(MachineGUIRegistry.addGUI(new PowerGeneratorGUI()), PowerAdvantage.getInstance());

Blocks.arc_furnace.setGuiID(MachineGUIRegistry.addGUI(new ArcFurnaceGUI()), PowerAdvantage.getInstance());
Blocks.battery_array.setGuiID(MachineGUIRegistry.addGUI(new BatteryArrayGUI()), PowerAdvantage.getInstance());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ private boolean followTrack(){
te.readFromNBT(dataTransfer);
te.setPos(nextPos);
te.validate();
te.subtractEnergy(ENERGY_COST_MOVE, te.getType());
te.markDirty();
Arrays.fill(this.getInventory(), null);

Expand All @@ -161,7 +162,6 @@ private boolean followTrack(){
w.setBlockState(getPos(), Blocks.electric_conduit.getDefaultState(), 2);


this.subtractEnergy(ENERGY_COST_MOVE, getType());
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import net.minecraftforge.fml.common.FMLLog;

import java.util.Arrays;
import java.util.List;

public abstract class ElectricGeneratorTileEntity extends cyano.poweradvantage.api.simple.TileEntitySimplePowerMachine {

Expand Down Expand Up @@ -45,19 +44,26 @@ public ElectricGeneratorTileEntity(String name,int numInputSlots, ConduitType[]


private boolean redstone = false;
private boolean redstoneInitialized = false;
private float oldEnergy = 0f;
@Override
public void powerUpdate(){
super.powerUpdate();

redstone = getWorld().isBlockPowered(getPos());
redstoneInitialized = true;

if(oldEnergy != this.getEnergy(Power.ELECTRIC_POWER)){
this.sync();
}
}

protected boolean hasRedstoneSignal(){
// Generators can check the interlock before their first power-update refresh.
if(!redstoneInitialized && getWorld() != null && !getWorld().isRemote){
redstone = getWorld().isBlockPowered(getPos());
redstoneInitialized = true;
}
return redstone;
}

Expand Down Expand Up @@ -88,10 +94,13 @@ public boolean shouldRefresh(World world, BlockPos pos, IBlockState oldState, IB
protected void playSoundEffect(double x, double y, double z, SoundEvent sound, float volume, float pitch){
if(getWorld().isRemote) return;
final double range = 16;
List<EntityPlayerMP> players = getWorld().getEntitiesWithinAABB(EntityPlayerMP.class, new AxisAlignedBB(
AxisAlignedBB bounds = new AxisAlignedBB(
x - range, y - range, z - range,
x + range, y + range, z + range));
for(EntityPlayerMP player : players){
x + range, y + range, z + range);
// Query the existing player list without loading neighbouring chunks.
for(EntityPlayerMP player : getWorld().getPlayers(EntityPlayerMP.class,
candidate -> !candidate.isSpectator() && candidate.getEntityBoundingBox().intersects(bounds))){
if(player.connection == null) continue;
player.connection.sendPacket(new SPacketCustomSound(sound.getRegistryName().toString(), SoundCategory.BLOCKS,
x, y, z, (float)volume, (float)pitch));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import net.minecraftforge.fml.common.FMLLog;

import java.util.Arrays;
import java.util.List;

public abstract class ElectricMachineTileEntity extends cyano.poweradvantage.api.simple.TileEntitySimplePowerMachine{

Expand Down Expand Up @@ -66,6 +65,7 @@ public ElectricMachineTileEntity(String name,int numInputSlots, int numOutputSlo
}

private boolean redstone = false;
private boolean redstoneInitialized = false;
private float oldEnergy = 0f;
private int[] syncArrayOld = null;
private int[] syncArrayNew = null;
Expand All @@ -74,6 +74,7 @@ public void powerUpdate(){
super.powerUpdate();

redstone = getWorld().isBlockPowered(getPos());
redstoneInitialized = true;

this.setPowerState(this.isPowered());

Expand All @@ -94,6 +95,11 @@ public void powerUpdate(){


protected boolean hasRedstoneSignal(){
// tickUpdate can run before the first scheduled powerUpdate after loading.
if(!redstoneInitialized && getWorld() != null && !getWorld().isRemote){
redstone = getWorld().isBlockPowered(getPos());
redstoneInitialized = true;
}
return redstone;
}

Expand Down Expand Up @@ -348,10 +354,13 @@ public ItemStack insertItemToInputSlots(ItemStack itemStack){
protected void playSoundEffect(double x, double y, double z, SoundEvent sound, float volume, float pitch){
if(getWorld().isRemote) return;
final double range = 16;
List<EntityPlayerMP> players = getWorld().getEntitiesWithinAABB(EntityPlayerMP.class, new AxisAlignedBB(
AxisAlignedBB bounds = new AxisAlignedBB(
x - range, y - range, z - range,
x + range, y + range, z + range));
for(EntityPlayerMP player : players){
x + range, y + range, z + range);
// Query the existing player list without loading neighbouring chunks.
for(EntityPlayerMP player : getWorld().getPlayers(EntityPlayerMP.class,
candidate -> !candidate.isSpectator() && candidate.getEntityBoundingBox().intersects(bounds))){
if(player.connection == null) continue;
player.connection.sendPacket(new SPacketCustomSound(sound.getRegistryName().toString(), SoundCategory.BLOCKS,
x, y, z, (float)volume, (float)pitch));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import com.mcmoddev.poweradvantage.init.Fluids;
import com.mcmoddev.poweradvantage.util.FluidIdHelper;
import net.minecraft.block.Block;
import net.minecraft.block.BlockDynamicLiquid;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.SoundEvents;
Expand Down Expand Up @@ -83,12 +82,13 @@ public void tickUpdate(boolean isServerWorld) {
float cost = ENERGY_COST_PUMP+ENERGY_COST_VERTICAL*(getPos().getY()-fluidSource.getY());
// Found a fluid to suck-up!
IBlockState blockstate = w.getBlockState(fluidSource);
Fluid f = getFluid(blockstate);
if(f != null && getEnergy() >= cost){
this.getTank().fill(new FluidStack(f, Fluid.BUCKET_VOLUME), true);
this.subtractEnergy(cost, Power.ELECTRIC_POWER);
w.setBlockToAir(fluidSource);
success = true;
if(getEnergy() >= cost){
FluidStack drained = drainSource(w, fluidSource, blockstate);
if(drained != null && drained.amount > 0){
this.getTank().fill(drained, true);
this.subtractEnergy(cost, Power.ELECTRIC_POWER);
success = true;
}
}
}
timeUntilNextPump = PUMP_INTERVAL;
Expand Down Expand Up @@ -134,6 +134,25 @@ private Fluid getFluid(IBlockState blockstate) {
return FluidRegistry.lookupFluidForBlock(blockstate.getBlock());
}

private FluidStack drainSource(World world, BlockPos pos, IBlockState state) {
Block block = state.getBlock();
if(block instanceof IFluidBlock){
IFluidBlock source = (IFluidBlock)block;
if(!source.canDrain(world, pos)) return null;
FluidStack preview = source.drain(world, pos, false);
if(preview == null || preview.amount <= 0 || getTank().fill(preview, false) != preview.amount) return null;
// Let the source perform its own real removal, including any mod-specific state.
return source.drain(world, pos, true);
}
if(block instanceof BlockLiquid && state.getValue(BlockLiquid.LEVEL) == 0){
Fluid fluid = getFluid(state);
if(fluid == null) return null;
FluidStack bucket = new FluidStack(fluid, Fluid.BUCKET_VOLUME);
if(getTank().fill(bucket, false) == bucket.amount && world.setBlockToAir(pos)) return bucket;
}
return null;
}



private BlockPos scan(Set<BlockPos> searchSpace, BlockPos coord, int limit) {
Expand Down Expand Up @@ -164,9 +183,9 @@ private BlockPos scan(Set<BlockPos> searchSpace, BlockPos coord, int limit) {
private boolean isSourceBlock( BlockPos coord){
IBlockState bs = getWorld().getBlockState(coord);
if(bs.getBlock() instanceof BlockLiquid){
return (Integer)bs.getValue(BlockDynamicLiquid.LEVEL) == 0;
} else if(bs.getBlock() instanceof BlockFluidClassic){
return ((BlockFluidClassic)bs.getBlock()).isSourceBlock(getWorld(), coord);
return (Integer)bs.getValue(BlockLiquid.LEVEL) == 0;
} else if(bs.getBlock() instanceof IFluidBlock){
return ((IFluidBlock)bs.getBlock()).canDrain(getWorld(), coord);
}else{
return false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ public void tickUpdate(boolean isServerWorld) {
if(!this.hasRedstoneSignal()){
if(getInputTank().getFluidAmount() > 0
&& getEnergy() >= electricityPerDistill
&& canDistill(getInputTank().getFluid())){
&& canDistill(getInputTank().getFluid())
&& hasSpaceForDistillation()){
distill();
if(!wasActive){
this.setActiveState(true);
Expand Down Expand Up @@ -90,6 +91,14 @@ private boolean canDistill(FluidStack fs) {
}
}

private boolean hasSpaceForDistillation() {
DistillationRecipe recipe = DistillationRecipeRegistry.getInstance()
.getDistillationRecipeForFluid(getInputTank().getFluid().getFluid());
// applyRecipe consumes its input, so preview a copy before committing either tank.
FluidStack output = recipe.applyRecipe(getInputTank().getFluid().copy(), speed);
return output != null && getOutputTank().fill(output, false) == output.amount;
}

private void distill(){
DistillationRecipe recipe = DistillationRecipeRegistry.getInstance()
.getDistillationRecipeForFluid(getInputTank().getFluid().getFluid());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,10 @@ public PowerRequest getPowerRequest(ConduitType offer) {
float powerWanted = (this.getEnergyCapacity(Power.GROWTHCHAMBER_POWER) - this.getEnergy(Power.GROWTHCHAMBER_POWER));
powerWanted = Math.min(powerWanted, soil / SOIL_PER_UNIT);
powerWanted = Math.min(powerWanted, tank.getFluidAmount() / WATER_PER_UNIT);
return new PowerRequest(PowerRequest.MEDIUM_PRIORITY,ELECTRICITY_PER_UNIT * powerWanted,this);
float stored = getEnergy(Power.ELECTRIC_POWER);
float room = getEnergyCapacity(Power.ELECTRIC_POWER) - stored;
float electricityWanted = Math.max(0, Math.min(room, ELECTRICITY_PER_UNIT * powerWanted - stored));
return new PowerRequest(PowerRequest.MEDIUM_PRIORITY,electricityWanted,this);
} else {
return PowerRequest.REQUEST_NOTHING;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class GrowthChamberTileEntity extends ElectricMachineTileEntity {
private final int[] progression = new int[GROWTH_AREA];
private final int[] progressionMax = new int[GROWTH_AREA];
private final VirtualCrop[] crops = new VirtualCrop[GROWTH_AREA];
private byte[] pendingGrowth;

public GrowthChamberTileEntity() {
super("tile.electricadvantage.growth_chamber.name",Power.GROWTHCHAMBER_POWER, ENERGY_PER_TICK*64, GROWTH_AREA, 6, 0);
Expand All @@ -30,6 +31,7 @@ public GrowthChamberTileEntity() {
@Override
public void tickUpdate(boolean isServer) {
if(isServer){
restorePendingCrops();
boolean[] recalculate = inventoryChanged();
boolean active = false;
boolean flagSync = false;
Expand Down Expand Up @@ -157,7 +159,8 @@ public float[] getProgress() {

@Override
protected void saveTo(NBTTagCompound tagRoot) {
byte[] growthStages = new byte[GROWTH_AREA];
byte[] growthStages = pendingGrowth == null ? new byte[GROWTH_AREA]
: Arrays.copyOf(pendingGrowth, GROWTH_AREA);
for(int i = 0; i < growthStages.length; i++){
if(crops[i] != null)
growthStages[i] = crops[i].getCurrentGrowth();
Expand All @@ -169,20 +172,34 @@ protected void saveTo(NBTTagCompound tagRoot) {

@Override
protected void loadFrom(NBTTagCompound tagRoot) {
if(tagRoot.hasKey("growth")){
byte[] growthStages = tagRoot.getByteArray("growth");
for(int i = 0; i < growthStages.length && i < GROWTH_AREA; i++){
if(crops[i] == null){
crops[i] = getVirtualCrop(this.getInputSlot(i));
}
if(crops[i] != null){
crops[i].setCurrentGrowth(growthStages[i]);
}
}
Arrays.fill(crops, null);
Arrays.fill(progression, 0);
Arrays.fill(progressionMax, 0);
oldInventory = null;
pendingGrowth = tagRoot.hasKey("growth", 7)
? Arrays.copyOf(tagRoot.getByteArray("growth"), GROWTH_AREA) : null;
if(tagRoot.hasKey("prog", 11)){
int[] saved = tagRoot.getIntArray("prog");
System.arraycopy(saved, 0, progression, 0, Math.min(saved.length, progression.length));
}
if(tagRoot.hasKey("prog")){
System.arraycopy(tagRoot.getIntArray("prog"), 0, progression, 0, progression.length);
}

private void restorePendingCrops() {
if (pendingGrowth == null) return;
for (int i = 0; i < GROWTH_AREA; i++) {
crops[i] = getVirtualCrop(getInputSlot(i));
if (crops[i] != null) {
crops[i].setCurrentGrowth(pendingGrowth[i]);
progressionMax[i] = crops[i].getMaxGrowth() * TICKS_PER_GROWTH;
} else {
progression[i] = 0;
}
}
// Seed the comparison cache so the first tick does not discard restored work.
ItemStack[] inventory = getInventory();
oldInventory = new ItemStack[inventory.length];
for (int i = 0; i < inventory.length; i++) oldInventory[i] = copyStackOrNull(inventory[i]);
pendingGrowth = null;
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ public float getPowerOutput() {
}
}

private final float[] progress = new float[1];

public float[] getProgress() {
progress[0] = isActive() ? 1F : 0F;
return progress;
}

@Override
protected boolean isValidInputItem(ItemStack item) {
return false;
Expand Down
Loading
Loading