feat: Add solar panel blocks, BE, and renderer#3
Conversation
Introduce a new Tier 1 Solar Panel: block, block entity, energy handler and pooled-array logic. Adds SolarPanelBlock/SolarPanelBlockEntity, SolarArray (flood-fill pooled storage/generation), SolarTier constants and tuning, and an extract-only SolarEnergy handler. Client: SolarPanelRenderState & SolarPanelRenderer to draw a sun-tracking, night-folding deck that joins with same-tier neighbours. Resources and data: models, blockstate, item model, texture, loot table, recipe, advancement, language entry, and data-gen updates (loot/tags/models/recipes). Registration: block, item, block entity, capability exposure, creative tab and datagen wiring. Behavior: generation scales with sun/weather/dimension, arrays balance buffers across members, comparator/readout support, and server-side ticking for pooled generation.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4c422c5132
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| for (SolarPanelBlockEntity panel : panels) { | ||
| panel.generate(panel.generationThisTick(level)); | ||
| total += panel.energy().getAmountAsInt(); |
There was a problem hiding this comment.
Preserve array generation before per-panel clamping
When an array member is full but another member has been drained in the same tick, this per-panel generate() clamps and discards that panel's contribution before the buffers are rebalanced, even though the pooled array still has capacity. For example, a two-panel array with one full panel and one panel drained by a pipe loses the full panel's 20 FE/tick instead of adding the sum across panels as the class contract describes; sum stored energy plus each panel's generation, clamp to total array capacity, then distribute.
Useful? React with 👍 / 👎.
| if (space) { | ||
| daylight = 1.0F; // permanent sun in orbit / on an airless moon |
There was a problem hiding this comment.
Require sky access in space dimensions
In the SPACE dimension this branch skips the canSeeSky(above) gate entirely, so a solar panel buried under station blocks or inside a sealed room still generates at the doubled space rate. ModDimensionTypes.SPACE is registered with skylight, so roofed-vs-exposed panels can still be distinguished there; keep the permanent daylight/no-weather behavior, but do not bypass the sky-access requirement.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
Adds a new Tier 1 Solar Panel feature to Nerospace, including server-side pooled generation/storage via connected “arrays”, client-side rendering of a sun-tracking panel surface, and full registration + data/resources for crafting, loot, models, tags, and localization.
Changes:
- Implement Tier 1 solar panel block + block entity, with pooled-array generation/buffer balancing and comparator/readout support.
- Add client renderer + render state for a tilting, neighbour-joining solar deck.
- Add tuning constants and datagen/resources/registration wiring (block/item/BE/capabilities/creative tab/recipes/loot/tags/models/lang).
Reviewed changes
Copilot reviewed 21 out of 31 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/gen_textures.py | Adds procedural texture generation for the Tier 1 solar panel. |
| tools/gen_bbmodels.py | Includes the solar panel Blockbench model in the generation list. |
| src/main/java/za/co/neroland/nerospace/Tuning.java | Adds tiered solar output + buffer tuning and lookup helpers. |
| src/main/java/za/co/neroland/nerospace/solar/SolarTier.java | Introduces tier enum (tier number, footprint, tuned stats). |
| src/main/java/za/co/neroland/nerospace/solar/SolarPanelBlockEntity.java | Implements server tick + FE buffer + solar factor logic. |
| src/main/java/za/co/neroland/nerospace/solar/SolarPanelBlock.java | Adds the block, shape, ticker, readout, comparator output. |
| src/main/java/za/co/neroland/nerospace/solar/SolarArray.java | Implements flood-fill array build + pooled generation/balancing. |
| src/main/java/za/co/neroland/nerospace/registry/ModItems.java | Registers the solar panel block item. |
| src/main/java/za/co/neroland/nerospace/registry/ModCreativeModeTabs.java | Adds solar panel to creative tab. |
| src/main/java/za/co/neroland/nerospace/registry/ModCapabilities.java | Exposes solar panel energy capability. |
| src/main/java/za/co/neroland/nerospace/registry/ModBlocks.java | Registers the Tier 1 solar panel block. |
| src/main/java/za/co/neroland/nerospace/registry/ModBlockEntities.java | Registers the solar panel block entity type. |
| src/main/java/za/co/neroland/nerospace/NerospaceClient.java | Registers the solar panel block entity renderer. |
| src/main/java/za/co/neroland/nerospace/datagen/ModRecipeProvider.java | Adds recipe datagen for solar panel crafting. |
| src/main/java/za/co/neroland/nerospace/datagen/ModModelProvider.java | Adds model/datagen for the solar panel base housing model. |
| src/main/java/za/co/neroland/nerospace/datagen/ModLanguageProvider.java | Adds block name + readout translation key. |
| src/main/java/za/co/neroland/nerospace/datagen/ModBlockTagProvider.java | Adds solar panel to tool requirement/mining tags. |
| src/main/java/za/co/neroland/nerospace/datagen/ModBlockLootSubProvider.java | Adds solar panel loot (drop self). |
| src/main/java/za/co/neroland/nerospace/client/SolarPanelRenderState.java | Adds render state (tilt angle + neighbour connections). |
| src/main/java/za/co/neroland/nerospace/client/SolarPanelRenderer.java | Adds BE renderer for tilting/seam-joining deck geometry. |
| src/generated/resources/data/nerospace/recipe/solar_panel_t1.json | Generated shaped crafting recipe. |
| src/generated/resources/data/nerospace/loot_table/blocks/solar_panel_t1.json | Generated block loot table. |
| src/generated/resources/data/nerospace/advancement/recipes/redstone/solar_panel_t1.json | Generated recipe advancement unlock. |
| src/generated/resources/data/minecraft/tags/block/needs_iron_tool.json | Generated mining level tag update. |
| src/generated/resources/data/minecraft/tags/block/mineable/pickaxe.json | Generated mineable tag update. |
| src/generated/resources/assets/nerospace/models/block/solar_panel_t1.json | Generated block model. |
| src/generated/resources/assets/nerospace/lang/en_us.json | Generated lang update including block + readout key. |
| src/generated/resources/assets/nerospace/items/solar_panel_t1.json | Generated item model reference. |
| src/generated/resources/assets/nerospace/blockstates/solar_panel_t1.json | Generated blockstate definition. |
| art/blockbench/block/solar_panel_t1.bbmodel | Adds Blockbench source model for the solar panel. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| continue; | ||
| } | ||
| members.add(pos); | ||
| for (Direction dir : Direction.values()) { |
| private final SolarTier tier; | ||
| private final List<BlockPos> members; | ||
| private final LongOpenHashSet memberSet; | ||
| private boolean valid = true; | ||
| private long lastTick = -1L; | ||
|
|
||
| private SolarArray(SolarTier tier, List<BlockPos> members, LongOpenHashSet memberSet) { | ||
| this.tier = tier; | ||
| this.members = members; | ||
| this.memberSet = memberSet; |
| */ | ||
| public class SolarPanelRenderState extends BlockEntityRenderState { | ||
|
|
||
| /** Surface tilt in degrees about the east-west (Z) axis: 0 = flat (folded / noon), +-tilt by day. */ |
| // Front face (normal +Y). Back face (normal -Y, reversed winding) so the steeply-tilted deck is | ||
| // visible from below too. The render type is no-cull, so both always draw. |
Introduce a distinct static base for the T1 solar panel and adapt rendering/data generation to match. Added a Blockbench model (.bbmodel) and a base texture (solar_panel_t1_base.png), updated the generated block model to use the _base texture and to include a post and torque tube element. Refactored SolarPanelRenderer to pivot on the pole top, compute openness/track separately, cap tilt, and draw the photovoltaic deck as a 1px-thick box (double-sided faces, proper UVs and lighting). Updated data-gen (ModModelProvider) to reference the base texture/model and modified tooling (gen_bbmodels.py, gen_textures.py) to generate the new base assets.
Add a new Solar-Panel wiki page detailing crafting, mechanics (sun-tracking generation, array pooling, tiers, buffer/output, weather and off-world bonuses), and implementation details. Also update Roadmap.md to list Solar Panels in upcoming features and add a link to the Solar Panel page in the sidebar for navigation.
Introduce Tier 2 and Tier 3 solar panels: adds block/item models, blockstates, textures, blockbench sources, loot tables, recipes and recipe advancements. Update datagen (models, tags, loot, recipes, language) to include new tiers and mark T2/T3 as mineable/need iron. Rendering: extend SolarPanelRenderState with footprint and anchor flags and update SolarPanelRenderer to support T1 tracking (east-west on a T-pole) and T2/T3 N×N multiblock lids (single-anchor rendering, hinged at housing top). Adjust block loot so multiblock filler cells drop nothing (anchor handles unit drop). Misc: minor updates to generated resources and docs.
Render and data changes for solar panels: each panel cell now renders the same sun-tracking deck (lockstep across multiblock fields) and draws small connector stubs toward any adjacent energy-capable neighbour (capability-based, skipping other solar panels). Added SolarPanelRenderState.connector flags, energyHookup detection and connector geometry in SolarPanelRenderer, and minor import/constant updates. Model/datagen changes consolidate the solar housing model for all tiers and update generated JSON to include the housing elements. Gallery command and harness were extended to build and capture a solar-array showcase (including a battery→pipe→panel hookup). SolarArray no longer stores an anchorSet (constructor/field simplified).
Overhaul solar-panel rendering and assets: use the local dimension clock (getDefaultClockTime) in both renderer and block entity so panels fold to the sky the player actually sees. Replace per-cell seam-join geometry with a simpler scheme: T1 remains a 1×1 pitching deck, T2/T3 are drawn as a single N×N deck by the multiblock anchor (only the min-corner draws the deck and central mast). Connector stubs are now per-cell and always drawn from the base sprite; added mast/base geometry, tilt caps for larger footprints, and helper methods to submit multiblock decks. Data-gen/model changes produce flat 3px bases for multiblocks and keep the moving deck renderer-driven. Texture generator updated to a unified blue/green PV design with tier-coloured edge ring; updated PNG assets accordingly. Misc: cleaned up unused neighbor logic and improved comments.
Summary
Introduce a new Tiered Solar Panels: block, block entity, energy handler and pooled-array logic. Adds SolarPanelBlock/SolarPanelBlockEntity, SolarArray (flood-fill pooled storage/generation), SolarTier constants and tuning, and an extract-only SolarEnergy handler. Client: SolarPanelRenderState & SolarPanelRenderer to draw a sun-tracking, night-folding deck that joins with same-tier neighbours. Resources and data: models, blockstate, item model, texture, loot table, recipe, advancement, language entry, and data-gen updates (loot/tags/models/recipes). Registration: block, item, block entity, capability exposure, creative tab and datagen wiring. Behavior: generation scales with sun/weather/dimension, arrays balance buffers across members, comparator/readout support, and server-side ticking for pooled generation.
Related issue
Type of change
Checklist
./gradlew runData(if datagen changed) and./gradlew buildboth pass (BUILD SUCCESSFUL).Notes for reviewers