Add support for solar energy scaling during day (#2497)
This commit is contained in:
parent
dcca103f9a
commit
56dcc4dd16
4 changed files with 54 additions and 52 deletions
|
@ -59,6 +59,10 @@ public enum ObjectBufferUtils {
|
|||
buffer.writeFloat(pos);
|
||||
}, ExtendedPacketBuffer::readFloat),
|
||||
|
||||
BOOLEAN(Boolean.class, (value, buffer) -> {
|
||||
buffer.writeBoolean(value);
|
||||
}, ExtendedPacketBuffer::readBoolean),
|
||||
|
||||
BLOCK_POS(BlockPos.class, (pos, buffer) -> {
|
||||
buffer.writeBlockPos(pos);
|
||||
}, PacketByteBuf::readBlockPos),
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
package techreborn.blockentity.generator;
|
||||
|
||||
import java.util.List;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
|
@ -52,20 +53,12 @@ import techreborn.init.TRBlockEntities;
|
|||
import techreborn.init.TRContent;
|
||||
import techreborn.init.TRContent.SolarPanels;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SolarPanelBlockEntity extends PowerAcceptorBlockEntity implements IToolDrop, BuiltScreenHandlerProvider {
|
||||
|
||||
private boolean generating = false;
|
||||
|
||||
// State ZEROGEN: No exposure to sun
|
||||
// State NIGHTGEN: Has direct exposure to sun
|
||||
// State DAYGEN: Has exposure to sun and weather is sunny and not raining/thundering
|
||||
public static final int ZEROGEN = 0;
|
||||
public static final int NIGHTGEN = 1;
|
||||
public static final int DAYGEN = 2;
|
||||
|
||||
private int state = ZEROGEN;
|
||||
private int prevState = ZEROGEN;
|
||||
// Range of panel between day/night production; we calculate this only when panel is updated
|
||||
private int dayNightRange = 0;
|
||||
|
||||
private SolarPanels panel;
|
||||
|
||||
|
@ -82,20 +75,25 @@ public class SolarPanelBlockEntity extends PowerAcceptorBlockEntity implements I
|
|||
if (world == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Block panelBlock = world.getBlockState(pos).getBlock();
|
||||
if (panelBlock instanceof BlockSolarPanel solarPanelBlock) {
|
||||
panel = solarPanelBlock.panelType;
|
||||
}
|
||||
|
||||
dayNightRange = getPanel().generationRateD - getPanel().generationRateN;
|
||||
}
|
||||
|
||||
|
||||
// Setters and getters for the GUI to sync
|
||||
private void setSunState(int state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public int getSunState() {
|
||||
return state;
|
||||
// Setters/getters that provide boolean interface to underlying generating int; something about
|
||||
// screen auto-sync REQUIRES an integer value (booleans don't get transmitted?!), so resorted to
|
||||
// this ugly approach
|
||||
public boolean isGenerating() { return generating; }
|
||||
private void setIsGenerating(boolean isGenerating) {
|
||||
if (isGenerating != isGenerating()) {
|
||||
// Update block state if necessary
|
||||
world.setBlockState(pos, world.getBlockState(pos).with(BlockMachineBase.ACTIVE, isGenerating));
|
||||
}
|
||||
this.generating = isGenerating;
|
||||
}
|
||||
|
||||
SolarPanels getPanel() {
|
||||
|
@ -109,35 +107,39 @@ public class SolarPanelBlockEntity extends PowerAcceptorBlockEntity implements I
|
|||
if (world == null) {
|
||||
return;
|
||||
}
|
||||
if (world.isSkyVisible(pos.up())) {
|
||||
this.setSunState(NIGHTGEN);
|
||||
|
||||
if (!world.isRaining() && !world.isThundering() && world.isDay()) {
|
||||
this.setSunState(DAYGEN);
|
||||
}
|
||||
} else {
|
||||
this.setSunState(ZEROGEN);
|
||||
}
|
||||
// Nether and The End
|
||||
if (!world.getDimension().hasSkyLight()) {
|
||||
this.setSunState(NIGHTGEN);
|
||||
}
|
||||
|
||||
if (prevState != this.getSunState()) {
|
||||
boolean isGenerating = getSunState() == DAYGEN;
|
||||
|
||||
world.setBlockState(pos, world.getBlockState(pos).with(BlockMachineBase.ACTIVE, isGenerating));
|
||||
|
||||
prevState = this.getSunState();
|
||||
}
|
||||
// Generation is only possible if sky is visible above us
|
||||
setIsGenerating(world.isSkyVisible(pos.up()));
|
||||
}
|
||||
|
||||
public int getGenerationRate() {
|
||||
return switch (getSunState()) {
|
||||
case DAYGEN -> getPanel().generationRateD;
|
||||
case NIGHTGEN -> getPanel().generationRateN;
|
||||
default -> 0;
|
||||
};
|
||||
if (!isGenerating()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
float skyAngle = world.getSkyAngle(0);
|
||||
|
||||
// Ok, we are actively generating power, but check for a few conditions that would restrict
|
||||
// the generation to minimal production...
|
||||
if (!world.getDimension().hasSkyLight() || // No light source in dimension (e.g. nether or end)
|
||||
(skyAngle > 0.25 && skyAngle < 0.75) || // Light source is below horizon
|
||||
(world.isRaining() || world.isThundering())) { // Weather is present
|
||||
return getPanel().generationRateN;
|
||||
}
|
||||
|
||||
// At this point, we know a light source is present and it's clear weather. We need to determine
|
||||
// the level of generation based on % of time through the day, with peak production at noon and
|
||||
// a smooth transition to night production as sun rises/sets
|
||||
float multiplier = 0.0f;
|
||||
if (skyAngle > 0.75) {
|
||||
// Morning to noon
|
||||
multiplier = (0.25f - (1 - skyAngle)) / 0.25f;
|
||||
} else {
|
||||
// Noon to sunset
|
||||
multiplier = (0.25f - skyAngle) / 0.25f;
|
||||
}
|
||||
|
||||
return (int)Math.ceil(getPanel().generationRateN + (dayNightRange * multiplier));
|
||||
}
|
||||
|
||||
|
||||
|
@ -287,7 +289,7 @@ public class SolarPanelBlockEntity extends PowerAcceptorBlockEntity implements I
|
|||
public BuiltScreenHandler createScreenHandler(int syncID, final PlayerEntity player) {
|
||||
return new ScreenHandlerBuilder("solar_panel").player(player.getInventory()).inventory().hotbar().addInventory()
|
||||
.blockEntity(this).syncEnergyValue()
|
||||
.sync(this::getSunState, this::setSunState)
|
||||
.sync(this::isGenerating, this::setIsGenerating)
|
||||
.addInventory().create(this, syncID);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,10 +48,8 @@ public class GuiSolar extends GuiBase<BuiltScreenHandler> {
|
|||
|
||||
builder.drawMultiEnergyBar(matrixStack, this, 156, 19, (int) blockEntity.getEnergy(), (int) blockEntity.getMaxStoredPower(), mouseX, mouseY, 0, layer);
|
||||
|
||||
switch (blockEntity.getSunState()) {
|
||||
case SolarPanelBlockEntity.DAYGEN -> builder.drawText(matrixStack, this, new TranslatableText("techreborn.message.daygen"), 10, 20, 15129632);
|
||||
case SolarPanelBlockEntity.NIGHTGEN -> builder.drawText(matrixStack, this, new TranslatableText("techreborn.message.nightgen"), 10, 20, 7566195);
|
||||
case SolarPanelBlockEntity.ZEROGEN -> builder.drawText(matrixStack, this, new TranslatableText("techreborn.message.zerogen"), 10, 20, 12066591);
|
||||
if (!blockEntity.isGenerating()) {
|
||||
builder.drawText(matrixStack, this, new TranslatableText("techreborn.message.panel_blocked"), 10, 20, 12066591);
|
||||
}
|
||||
|
||||
builder.drawText(matrixStack, this, new LiteralText("Generating: " + blockEntity.getGenerationRate() + " E/t"), 10, 30, 0);
|
||||
|
|
|
@ -720,9 +720,7 @@
|
|||
"techreborn.message.allPlayers": "All Players",
|
||||
"techreborn.message.onlyOtherPlayers": "Only Other Players",
|
||||
"techreborn.message.onlyYou": "Only You",
|
||||
"techreborn.message.daygen": "Panel in direct sunlight",
|
||||
"techreborn.message.nightgen": "Panel in reduced sunlight",
|
||||
"techreborn.message.zerogen": "Panel obstructed from sky",
|
||||
"techreborn.message.panel_blocked": "Panel obstructed from sky",
|
||||
|
||||
"techreborn.message.info.item.techreborn.overclocker_upgrade": "Increases speed at the cost of more energy used per tick",
|
||||
"techreborn.message.info.item.techreborn.transformer_upgrade": "Increase energy tier",
|
||||
|
|
Loading…
Reference in a new issue