From b6ddd795b1569e7b4bd600afdd05922096499a3c Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 9 Oct 2025 20:20:28 +0200 Subject: [PATCH 001/424] Add ModuleContainerPanYOnlyWithScrollCache class Introduced a scroll position cache for the observatory asteroid list, allowing restoration of scroll positions across GUI layouts. fixes observatory scroll reset when selecting asteroid. --- ...oduleContainerPanYOnlyWithScrollCache.java | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleContainerPanYOnlyWithScrollCache.java diff --git a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleContainerPanYOnlyWithScrollCache.java b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleContainerPanYOnlyWithScrollCache.java new file mode 100644 index 000000000..229933deb --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleContainerPanYOnlyWithScrollCache.java @@ -0,0 +1,54 @@ +package zmaster587.advancedRocketry.inventory.modules; + +import zmaster587.libVulpes.inventory.modules.ModuleContainerPanYOnly; +import zmaster587.libVulpes.inventory.modules.ModuleBase; +import net.minecraft.util.ResourceLocation; +import java.util.concurrent.ConcurrentHashMap; +import java.util.Map; +import java.util.List; + +public class ModuleContainerPanYOnlyWithScrollCache extends ModuleContainerPanYOnly { + + /** + * Scroll position cache for the observatory asteroid list. + * - One entry (per GUI layout) per client; cleared on new scan or scroll. + * - Minimal memory use (single Integer per layout). + * - Client-side only; no multiplayer or server impact. + * - Thread-safe for typical GUI use. + * - If reused, ensure cacheKey is unique per list type / GUI layout. + */ + + // Cache: only stores latest scroll position per key + private static final Map scrollCache = new ConcurrentHashMap<>(); + private final String cacheKey; + + public ModuleContainerPanYOnlyWithScrollCache(int offsetX, int offsetY, List moduleList, List staticModules, ResourceLocation backdrop, int screenSizeX, int screenSizeY, int paddingX, int paddingY, int containerSizeX, int containerSizeY) { + super(offsetX, offsetY, moduleList, staticModules, backdrop, screenSizeX, screenSizeY, paddingX, paddingY, containerSizeX, containerSizeY); + + // Create unique cache key + this.cacheKey = "observatory_asteroid_list:" + offsetX + ":" + offsetY + ":" + screenSizeX + ":" + screenSizeY; + + // Restore scroll position if available + Integer cachedPos = scrollCache.get(cacheKey); + if (cachedPos != null) { + super.setOffset2(-cachedPos); + } + } + + @Override + protected void moveContainerInterior(int deltaY) { + super.moveContainerInterior(deltaY); + scrollCache.put(cacheKey, super.getScrollY()); + } + + @Override + public void onScroll(int dwheel) { + super.onScroll(dwheel); + scrollCache.put(cacheKey, super.getScrollY()); + } + + // Public method to clear cache (for new asteroid scans) + public static void clearScrollCache() { + scrollCache.clear(); + } +} From 43d6135c17f9f2a53c2cd115c0e82e060ba91ba5 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 9 Oct 2025 20:23:43 +0200 Subject: [PATCH 002/424] Refactor TileObservatory to use scroll cache module Updated the TileObservatory class to use ModuleContainerPanYOnlyWithScrollCache for asteroid listing and added cache clearing on new data scanning. -fixes scroll reset when selecting asteroid --- .../tile/multiblock/TileObservatory.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java index 576661819..89f59d102 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java @@ -20,6 +20,7 @@ import zmaster587.advancedRocketry.api.DataStorage.DataType; import zmaster587.advancedRocketry.inventory.TextureResources; import zmaster587.advancedRocketry.inventory.modules.ModuleData; +import zmaster587.advancedRocketry.inventory.modules.ModuleContainerPanYOnlyWithScrollCache; import zmaster587.advancedRocketry.item.ItemAsteroidChip; import zmaster587.advancedRocketry.item.ItemData; import zmaster587.advancedRocketry.tile.hatch.TileDataBus; @@ -405,9 +406,10 @@ public List getModules(int ID, EntityPlayer player) { modules.add(new ModuleScaledImage(baseX, 2 * baseY + sizeY, sizeX, -3, TextureResources.horizontalBar)); } - //Relying on a bug, is this safe? + //listing of asteroids with scrollcaching if (lastSeed != -1) { - ModuleContainerPanYOnly pan = new ModuleContainerPanYOnly(baseX, baseY, list2, new LinkedList<>(), null, sizeX - 2, sizeY, 0, -48, 0, 72); + ModuleContainerPanYOnlyWithScrollCache pan = new ModuleContainerPanYOnlyWithScrollCache( + baseX, baseY, list2, new LinkedList<>(), null, sizeX - 2, sizeY, 0, -48, 0, 72); modules.add(pan); } @@ -499,26 +501,30 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, else if (id == TAB_SWITCH && !world.isRemote) { tabModule.setTab(nbt.getShort("tab")); player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), getWorld(), pos.getX(), pos.getY(), pos.getZ()); - } else if (id == BUTTON_PRESS && !world.isRemote) { + } + else if (id == BUTTON_PRESS && !world.isRemote) { lastButton = nbt.getShort("button"); lastType = buttonType.get(lastButton - LIST_OFFSET); markDirty(); world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), getWorld(), pos.getX(), pos.getY(), pos.getZ()); - - } else if (id == SEED_CHANGE) { + } + else if (id == SEED_CHANGE) { if (extractData(dataConsumedPerRefresh, DataType.DISTANCE, EnumFacing.UP, false) >= dataConsumedPerRefresh) { lastSeed = world.getTotalWorldTime() / 100; lastButton = -1; lastType = ""; + + // Clear scroll cache when scanning new data + ModuleContainerPanYOnlyWithScrollCache.clearScrollCache(); + extractData(dataConsumedPerRefresh, DataType.DISTANCE, EnumFacing.UP, true); world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); markDirty(); player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), getWorld(), pos.getX(), pos.getY(), pos.getZ()); } - - - } else if (id == PROCESS_CHIP && !world.isRemote) { + } + else if (id == PROCESS_CHIP && !world.isRemote) { if (inv.getStackInSlot(2).isEmpty() && isOpen && hasEnergy(500) && lastButton != -1) { ItemStack stack = inv.decrStackSize(1, 1); From 9783d2728747e0e4f6eb12d1de9697d7af972839 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 9 Oct 2025 23:23:39 +0200 Subject: [PATCH 003/424] Change parent model to cube_all for guidance hatch cleaner logic. (trying to fix transparent texture for blockstate varient14) --- .../models/block/guidancecomputeraccesshatch.json | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/models/block/guidancecomputeraccesshatch.json b/src/main/resources/assets/advancedrocketry/models/block/guidancecomputeraccesshatch.json index 64a7115ed..7c3692ed9 100644 --- a/src/main/resources/assets/advancedrocketry/models/block/guidancecomputeraccesshatch.json +++ b/src/main/resources/assets/advancedrocketry/models/block/guidancecomputeraccesshatch.json @@ -1,8 +1,6 @@ { - "parent": "block/orientable", + "parent": "block/cube_all", "textures": { - "top": "advancedrocketry:blocks/guidancecomputeraccesshatch", - "front": "advancedrocketry:blocks/guidancecomputeraccesshatch", - "side": "advancedrocketry:blocks/guidancecomputeraccesshatch" + "all": "advancedrocketry:blocks/guidancecomputeraccesshatch" } } From 6d46b7de4fc7eb38db9bf65d1c6ffea193580db9 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 10 Oct 2025 01:01:12 +0200 Subject: [PATCH 004/424] guidancecompteraccesshatch render bugfix forcing rendering all sides. fixing transparent texture when varient = 14 --- .../block/multiblock/BlockARHatch.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/multiblock/BlockARHatch.java b/src/main/java/zmaster587/advancedRocketry/block/multiblock/BlockARHatch.java index d45817de4..8fd68b7e7 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/multiblock/BlockARHatch.java +++ b/src/main/java/zmaster587/advancedRocketry/block/multiblock/BlockARHatch.java @@ -35,17 +35,24 @@ public void getSubBlocks(CreativeTabs tab, } @Override - public boolean shouldSideBeRendered(IBlockState blockState, - IBlockAccess blockAccess, BlockPos pos, EnumFacing direction) { + public boolean shouldSideBeRendered(IBlockState blockState, IBlockAccess blockAccess, BlockPos pos, EnumFacing direction) { + int variant = blockState.getValue(VARIANT); + // Always render sides for guidancecomputeraccesshatch variants (6 and 14) + if (variant == 6 || variant == 14) { + return true; + } - boolean isPointer = blockAccess.getTileEntity(pos.offset(direction.getOpposite())) instanceof TilePointer; - if (blockState.getValue(VARIANT) == 8) + // Keep + if (variant == 8) return false; - if (isPointer || blockState.getValue(VARIANT) < 2) + + boolean isPointer = blockAccess.getTileEntity(pos.offset(direction.getOpposite())) instanceof TilePointer; + if (isPointer || variant < 2) return super.shouldSideBeRendered(blockState, blockAccess, pos, direction); - return true; + + return true; } @Override From 2f9d0f3ead0149f51fa08e74897c9e65c221f031 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Tue, 14 Oct 2025 20:02:12 +0200 Subject: [PATCH 005/424] Implement inventory validation for satellite chassis Added inventory validation for satellite modules to ensure only valid items are placed in slots. Fixes crash when player tries to assemble satellite without valid primaryfunction. UX improvement. --- .../advancedRocketry/item/ItemSatellite.java | 38 ++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java b/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java index 8510fc3f4..61f471d58 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java @@ -17,8 +17,44 @@ public class ItemSatellite extends ItemIdWithName { + //Guarding inventory to ensure only valid items are placed in slots. + public static class SatelliteModuleInventory extends EmbeddedInventory { + public SatelliteModuleInventory() { super(7); } // slots 0-6 embedded from chassis + + @Override + public boolean isItemValidForSlot(int slot, @Nonnull ItemStack stack) { + if (stack.isEmpty()) return false; + + // Registry-driven: only accept items that have SatelliteProperties + SatelliteProperties p = SatelliteRegistry.getSatelliteProperty(stack); + if (p == null) return false; + int f = p.getPropertyFlag(); + + // Slot 0: ONLY primary function meta 0-6 + if (slot == 0) { + return SatelliteProperties.Property.MAIN.isOfType(f); + } + + // Slots 1–6: power gen, battery, or data modules + if (slot >= 1 && slot <= 6) { + return SatelliteProperties.Property.POWER_GEN.isOfType(f) || + SatelliteProperties.Property.BATTERY.isOfType(f) || + SatelliteProperties.Property.DATA.isOfType(f); + } + + return false; + } + + @Override + public void setInventorySlotContents(int index, ItemStack stack) { + if (!stack.isEmpty() && !isItemValidForSlot(index, stack)) return; + super.setInventorySlotContents(index, stack); + } + } + + public EmbeddedInventory readInvFromNBT(@Nonnull ItemStack stackIn) { - EmbeddedInventory inv = new EmbeddedInventory(7); + EmbeddedInventory inv = new SatelliteModuleInventory(); // <-- guarded if (!stackIn.hasTagCompound() || !stackIn.getTagCompound().hasKey("inv")) return inv; From 636c99ce2800a77745b0b3d307e8c9fc781c4ab9 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Tue, 14 Oct 2025 20:32:49 +0200 Subject: [PATCH 006/424] Update comment for EmbeddedInventory initialization Clarify comment regarding EmbeddedInventory instantiation. --- .../java/zmaster587/advancedRocketry/item/ItemSatellite.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java b/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java index 61f471d58..c26b9d0c5 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java @@ -54,7 +54,7 @@ public void setInventorySlotContents(int index, ItemStack stack) { public EmbeddedInventory readInvFromNBT(@Nonnull ItemStack stackIn) { - EmbeddedInventory inv = new SatelliteModuleInventory(); // <-- guarded + EmbeddedInventory inv = new SatelliteModuleInventory(); // slots 0-6 embedded from chassis, guarded by class above if (!stackIn.hasTagCompound() || !stackIn.getTagCompound().hasKey("inv")) return inv; From 2a85aa6a8a7be58ebb2ababaeb22d75ce211c6bc Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 10:03:59 +0200 Subject: [PATCH 007/424] Add German translations for satellite features --- .../resources/assets/advancedrocketry/lang/de_DE.lang | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/de_DE.lang b/src/main/resources/assets/advancedrocketry/lang/de_DE.lang index c0dc83148..d832ae4e5 100644 --- a/src/main/resources/assets/advancedrocketry/lang/de_DE.lang +++ b/src/main/resources/assets/advancedrocketry/lang/de_DE.lang @@ -406,4 +406,10 @@ msg.notconnected=Nicht verbunden msg.unprogrammed=Unprogrammiert msg.programfail=Programmierung fehlgeschlagen msg.modules=Module -msg.na=Nicht verfügbar \ No newline at end of file +msg.na=Nicht verfügbar + +jei.sb.satellitepreview=Bereit für den Orbit! +jei.sb.copy.source=Quelle +jei.sb.copy.output=Neue Kopie +jei.sb.assemblyhint=Mindestens ein Solarpanel +jei.sb.copychiphint=Erstelle Sicherungskopien! From 84e95ec8e97bf54490f26df363d83927134d6f50 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 10:04:23 +0200 Subject: [PATCH 008/424] Add new language entries for satellite preview and hints --- src/main/resources/assets/advancedrocketry/lang/en_US.lang | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index fc1e8d6b3..502730313 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -507,3 +507,10 @@ msg.chat.nostation3=You must be on a space station to be in this dimension, and commands.weather.always_not_clear=This planet is always not clear... commands.weather.cannot_rain=Cannot start a rain here commands.weather.cannot_thunder=Cannot start a thunder here + +jei.sb.satellitepreview=Ready for orbit! +jei.sb.copy.source=Source +jei.sb.copy.output=New Copy +jei.sb.assemblyhint=Atleast one solar panel +jei.sb.copychiphint=Make backups! + From 56e596923ed39450898bc331c36518ee286763fb Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 10:04:45 +0200 Subject: [PATCH 009/424] Add Spanish translations for satellite features Added Spanish translations for satellite preview and hints. --- .../resources/assets/advancedrocketry/lang/es_ES.lang | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/es_ES.lang b/src/main/resources/assets/advancedrocketry/lang/es_ES.lang index d17daaf60..76c126f26 100644 --- a/src/main/resources/assets/advancedrocketry/lang/es_ES.lang +++ b/src/main/resources/assets/advancedrocketry/lang/es_ES.lang @@ -131,4 +131,10 @@ fluid.oxygen=Oxígeno fluid.hydrogen=Hidrógeno fluid.rocketFuel=Combustible de cohete -mission.asteroidmining.name=Minería de asteroides \ No newline at end of file +mission.asteroidmining.name=Minería de asteroides + +jei.sb.satellitepreview=¡Listo para la órbita! +jei.sb.copy.source=Fuente +jei.sb.copy.output=Nueva copia +jei.sb.assemblyhint=Al menos un panel solar +jei.sb.copychiphint=¡Haz copias de seguridad! From d553900fed2fd547f56f35b18ebd6f292e6848ab Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 10:05:07 +0200 Subject: [PATCH 010/424] Update Finnish language translations in fi_FI.lang --- .../assets/advancedrocketry/lang/fi_FI.lang | 312 +++++++++--------- 1 file changed, 159 insertions(+), 153 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/fi_FI.lang b/src/main/resources/assets/advancedrocketry/lang/fi_FI.lang index f5270fc2a..4a741dd86 100644 --- a/src/main/resources/assets/advancedrocketry/lang/fi_FI.lang +++ b/src/main/resources/assets/advancedrocketry/lang/fi_FI.lang @@ -18,34 +18,34 @@ tile.seat.name=Istuin tile.pad.name=Laukaisualusta tile.structuretower.name=Rakennetorni tile.rocketAssembler.name=Raketin Kokoamislaite -tile.turf.name=Kuuply -tile.turfDark.name=Tumma Kuuply +tile.turf.name=Kuupöly +tile.turfDark.name=Tumma Kuupöly tile.cuttingMachine.name=Leikkuulaite -tile.sawBlade.name=Sahanter Kokoonpano -tile.controlComp.name=Tehtvn Ohjaustietokone +tile.sawBlade.name=Sahanterä Kokoonpano +tile.controlComp.name=Tehtävän Ohjaustietokone tile.precisionAssemblingMachine.name=Tarkkuuskokoaja tile.spaceLaser.name=Kiertorata Laser Pora -tile.Crystallizer.name=Kiteyttj -tile.blastBrick.name=Lmmnkestv tiili -tile.blastFurnaceController.name=Lmmnkestvn Uunin Ohjain +tile.Crystallizer.name=Kiteyttäjä +tile.blastBrick.name=Lämmönkestävä tiili +tile.blastFurnaceController.name=Lämmönkestävän Uunin Ohjain tile.fuelStation.name=Tankkausasema -tile.loader.0.name=Datavyl +tile.loader.0.name=Dataväylä tile.loader.1.name=Satelliittiasema tile.loader.2.name=Rakettipurkaja -tile.loader.3.name=Rakettityttj +tile.loader.3.name=Rakettitäyttäjä tile.loader.4.name=Rakettinestepurkaja -tile.loader.5.name=Rakettinestetyttj -tile.loader.6.name=Ohjaustietokoneen psyluukku +tile.loader.5.name=Rakettinestetäyttäjä +tile.loader.6.name=Ohjaustietokoneen pääsyluukku tile.observatory.name=Observatorio tile.satelliteBuilder.name=Satelliittirakentaja tile.rocket.name=Yksiajoaineinen Rakettimoottori tile.bipropellantrocket.name=Kaksiajoaineinen Rakettimoottori -tile.nuclearrocket.name=Ydinlamprakettimoottori +tile.nuclearrocket.name=Ydinlampörakettimoottori tile.fuelTank.name=Yksiajoainetankki tile.bipropellantfueltank.name=Kaksiajoainetankki tile.oxidizerfueltank.name=Hapetinpolttoainetankki -tile.nuclearfueltank.name=Ydinlmptystmisnestetankki -tile.nuclearcore.name=Ydinlmpfissioydin +tile.nuclearfueltank.name=Ydinlämpötyöstämisnestetankki +tile.nuclearcore.name=Ydinlämpöfissioydin tile.monitoringstation.name=Raketin Tarkkailuasema tile.satelliteMonitor.name=Satelliitti Terminaali tile.lightwoodlog.name=Valopuu @@ -56,7 +56,7 @@ tile.chipStorage.name=Satelliitti Id Varasto tile.planetanalyser.name=Avaruusobjekti Data Prosessori tile.lunaranalyser.name=Kuuanalysaattori tile.guidanceComputer.name=Ohjaustietokone -tile.electricArcFurnace.name=Shkinen Valokaariuuni +tile.electricArcFurnace.name=Sähköinen Valokaariuuni tile.hotDryturf.name=Hapetettu rautahiekka tile.concrete.name=Betoni tile.lathe.name=Sorvi @@ -78,35 +78,35 @@ tile.oxygenCharger.name=Kaasulataustyyny tile.dockingPad.name=Telakointialusta tile.stationmonitor.name=Hyperavaruusohjain tile.warpCore.name=Hyperavaruusydin -tile.atmosphereDetector.name=Ilmakehtunnistin +tile.atmosphereDetector.name=Ilmakehätunnistin tile.unlittorch.name=Sammunut Soihtu tile.geode.name=Geodikuutio -tile.electricMushroom.name=Shkinen Sieni +tile.electricMushroom.name=Sähköinen Sieni tile.charcoallog.name=Puuhiilitukki tile.vitrifiedSand.name=Lasittunut Hiekka tile.ruby.name=Punainen Kristallikuutio -tile.emerald.name=Vihre Kristallikuutio +tile.emerald.name=Vihreä Kristallikuutio tile.sapphire.name=Sininen Kristallikuutio tile.citrine.name=Keltainen Kristallikuutio tile.wulfentite.name=Oranssi Kristallikuutio tile.amethyst.name=Violetti Kristallikuutio tile.gravityControl.name=Avaruusaseman Painovoiman Ohjain tile.drill.name=Pora -tile.dataPipe.name=Datakaapeli(Poistettu kytst) -tile.liquidPipe.name=Nesteputki(Poistettu kytst) -tile.rfOutput.name=Redstone Flux Lhtpistoke +tile.dataPipe.name=Datakaapeli(Poistettu käytöstä) +tile.liquidPipe.name=Nesteputki(Poistettu käytöstä) +tile.rfOutput.name=Redstone Flux Lähtöpistoke tile.microwaveReciever.name=Mikroaaltovastaanotin tile.solarPanel.name=Aurinkopaneeli -tile.suitWorkStation.name=Pukutyasema +tile.suitWorkStation.name=Pukutyöasema tile.orientationControl.name=Suuntaohjain tile.biomeScanner.name=Biomiskanneri -tile.atmoshereTerraformer.name=Ilmakehterraformaattori -tile.deployableRocketAssembler.name=Miehittmttomn Kulkuneuvon Kokoaja +tile.atmoshereTerraformer.name=Ilmakehäterraformaattori +tile.deployableRocketAssembler.name=Miehittämättomän Kulkuneuvon Kokoaja tile.pressurizedTank.name=Paineistettu Tankki -tile.gasIntake.name=Kaasun Sisnotto -tile.atmosphereTerraformer.name=Ilmakehterraformaattori +tile.gasIntake.name=Kaasun Sisäänotto +tile.atmosphereTerraformer.name=Ilmakehäterraformaattori tile.circleLight.name=Asemavalo -tile.energyPipe.name=Shkputki(Poistettu kytst) +tile.energyPipe.name=Sähköputki(Poistettu käytöstä) tile.solarGenerator.name=Aurinkogeneraattori tile.stationMarker.name=Asematelakointiportti tile.qcrucible.name=Kvartsi Sulatusastia @@ -116,15 +116,15 @@ tile.advRocket.name=Edistynyt Yksiajoainerakettimoottori tile.advbipropellantRocket.name=Edistynyt Kaksiajoainerakettimoottori tile.planetHoloSelector.name=Holographinen Planeettavalitsin tile.lens.name=Linssi -tile.forceField.name=Voimakentt -tile.forceFieldProjector.name=Voimakenttprojektori -tile.vacuumLaser.name=Suuritehoinen Tyhjikammiolaser +tile.forceField.name=Voimakenttä +tile.forceFieldProjector.name=Voimakenttäprojektori +tile.vacuumLaser.name=Suuritehoinen Tyhjiökammiolaser tile.gravityMachine.name=Aluepainovoimaohjain tile.pipeSeal.name=Putkitiiviste tile.spaceElevatorController.name=Avaruushissi tile.beacon.name=Merkkivalo tile.thermiteTorch.name=Termiittisoihtu -tile.wirelessTransciever.name=Langaton Lhetin-Vastaanotin +tile.wirelessTransciever.name=Langaton Lähetin-Vastaanotin tile.blackholegenerator.name=Musta Aukko Generaattori tile.pump.name=Nestepumppu tile.centrifuge.name=Sentrifugi @@ -146,46 +146,46 @@ item.circuitIC.3.name=Ohjauspiiti item.circuitIC.4.name=Tavara IO Piiri item.circuitIC.5.name=Neste IO Piiri item.OreScanner.name=Malmiskanneri -item.dataUnit.0.name=Datatallennusyksikk -item.sawBlade.0.name=Rautainen Sahanter +item.dataUnit.0.name=Datatallennusyksikkö +item.sawBlade.0.name=Rautainen Sahanterä item.satellite.name=Satelliitti item.satellitePowerSource.0.name=Perusaurinkopaneeli item.satellitePowerSource.1.name=Iso Aurinkopaneeli item.satellitePrimaryFunction.0.name=Optinen Sensori item.satellitePrimaryFunction.1.name=Koostumussensori item.satellitePrimaryFunction.2.name=Massasensori -item.satellitePrimaryFunction.3.name=Mikroaaltolhetin +item.satellitePrimaryFunction.3.name=Mikroaaltolähetin item.satellitePrimaryFunction.4.name=Malmikartoittaja item.satellitePrimaryFunction.5.name=Biomimuuttaja item.satelliteIdChip.name=Satelliitti ID-Siru item.planetIdChip.name=Planeetta ID-Siru item.asteroidChip.name=Asteroidi ID-Siru -item.miscpart.0.name=Kyttliittym +item.miscpart.0.name=Käyttöliittymä item.miscpart.1.name=Hiilitiili item.station.name=Avaruusasemakontti item.stationChip.name=Avaruusasema ID-Siru -item.stationchip.openmenu=Kyyki ja klikkaa hiiren oikeaa nppint avataksesi asetusvalikon -item.spaceHelmet.name=Avaruuspukukypt +item.stationchip.openmenu=Kyyki ja klikkaa hiiren oikeaa näppäintä avataksesi asetusvalikon +item.spaceHelmet.name=Avaruuspukukypätä item.spaceChest.name=Avaruuspukupaita item.spaceLeggings.name=Avaruuspukuhousut -item.spaceBoots.name=Avaruuspukukengt +item.spaceBoots.name=Avaruuspukukengät item.smallAirlock.name=Pieni Ilmalukko-ovi -item.carbonScrubberCartridge.name=Hiilenkeryspatruuna +item.carbonScrubberCartridge.name=Hiilenkeräyspatruuna item.jackhammer.name=Nokkavasara item.sealDetector.name=Vuototunnistin -item.itemUpgrade.0.name=Leijumispivitys -item.itemUpgrade.1.name=Lentonopeuden Ohjauspivitys -item.itemUpgrade.2.name=Bioninen Jalkapivitys -item.itemUpgrade.3.name=Pehmustetut Laskeutumiskengt +item.itemUpgrade.0.name=Leijumispäivitys +item.itemUpgrade.1.name=Lentonopeuden Ohjauspäivitys +item.itemUpgrade.2.name=Bioninen Jalkapäivitys +item.itemUpgrade.3.name=Pehmustetut Laskeutumiskengät item.itemUpgrade.4.name=Sumunestovisiiri item.itemUpgrade.5.name=Maankirkas Visiiri -item.atmAnalyser.name=Ilmakehanalysaattori -item.biomeChanger.name=Biomin vaihtokaukosdin +item.atmAnalyser.name=Ilmakehäanalysaattori +item.biomeChanger.name=Biomin vaihtokaukosäädin item.basicLaserGun.name=Peruslaserpyssy -item.beaconFinder.name=Merkkivalon Lytj +item.beaconFinder.name=Merkkivalon Löytäjä item.thermite.name=Termiitti item.hovercraft.name=Leijualus -item.hovercraft.tooltip=Pitkn kestv dilitiumvoimanlhde. Se el todennkisesti pitempn kuin sin. +item.hovercraft.tooltip=Pitkään kestävä dilitiumvoimanlähde. Se elää todennäköisesti pitempään kuin sinä. item.jetPack.name=Asurakettireppu item.pressureTank.0.name=Matalapainetankki @@ -200,14 +200,14 @@ container.monitoringstation=Tarkkailuasema material.TitaniumAluminide.name=Titaanialuminidi material.TitaniumIridium.name=Titaani-Iridiumseos -enchantment.spaceBreathing=Ilmanpitv Tiiviste +enchantment.spaceBreathing=Ilmanpitävä Tiiviste data.undefined.name=Jotain Satunnaista Dataa -data.distance.name=Etisyys +data.distance.name=Etäisyys data.humidity.name=Ilmankosteus -data.temperature.name=Lmptila +data.temperature.name=Lämpötila data.composition.name=Koostumus -data.atmospheredensity.name=Ilmakehn Tiheys +data.atmospheredensity.name=Ilmakehän Tiheys data.mass.name=Massa fluid.oxygenHappi @@ -217,116 +217,116 @@ fluid.rocketFuel=Rakettipolttoaine fluid.enrichedLava=Rikastettu Laava mission.asteroidmining.name=Asteroidin Louhinta -mission.gascollection.name=Kaasun Kerys +mission.gascollection.name=Kaasun Keräys -error.rocket.cannotGetThere=Mrnp Tavoittamaton -error.rocket.destinationNotExist=Ei voi laukaista: Mrnp ei ole olemassa -error.rocket.notSameSystem=Ei voi laukaista: Mrnp ei ole samassa planeettasysteemiss +error.rocket.cannotGetThere=Määränpää Tavoittamaton +error.rocket.destinationNotExist=Ei voi laukaista: Määränpää ei ole olemassa +error.rocket.notSameSystem=Ei voi laukaista: Määränpää ei ole samassa planeettasysteemissä advancement.holographic=Holografinen advancement.holographic.desc=Rakenna Holo-Projektori -advancement.flattening=Litistv +advancement.flattening=Litistävä advancement.flattening.desc=Rakenna Pieni Levy Puristin -advancement.feelTheHeat=Tunne lmp! +advancement.feelTheHeat=Tunne lämpö! advancement.feelTheHeat.desc=Rakenna Valokaariuuni -advancement.electrifying=Shkistv! +advancement.electrifying=Sähköistävää! advancement.electrifying.desc=Rakenna Elekrolysaattori -advancement.spinDoctor=Pyrimistohtori +advancement.spinDoctor=Pyörimistohtori advancement.spinDoctor.desc=Rakenna Sorvi advancement.rollin=Rullaan advancement.rollin.desc=Rakenna Rullauskone advancement.crystalline=Kiteinen -advancement.crystalline.desc=Rakenna Kiteyttj +advancement.crystalline.desc=Rakenna Kiteyttäjä advancement.warp=Hyperavaruus advancement.warp.desc=Rakenna Hyperavaruusydin advancement.moonLanding=Kuulaskeutuminen! advancement.moonLanding.desc=Laskeudu Kuuhun advancement.oneSmallStep=Yksi Pieni Askel... -advancement.oneSmallStep.desc=Ole ensimminen joka laskeutuu kuuhun! +advancement.oneSmallStep.desc=Ole ensimmäinen joka laskeutuu kuuhun! advancement.weReallyWentToTheMoon=Me Oikeasti Menimme Kuuhun! -advancement.weReallyWentToTheMoon.desc=Lyd Apollo 11:n laskeutumispaikka Kuussa +advancement.weReallyWentToTheMoon.desc=Löydä Apollo 11:n laskeutumispaikka Kuussa advancement.dilithium=Dilitium -advancement.dilithium.desc=Lyd Dilitiummalmia -advancement.givingItAllShesGot=Annetaan kaikki mit hnell on! -advancement.givingItAllShesGot.desc=Lenn Hyperavaruuteen kykenevss aluksessa +advancement.dilithium.desc=Löydä Dilitiummalmia +advancement.givingItAllShesGot=Annetaan kaikki mitä hänellä on! +advancement.givingItAllShesGot.desc=Lennä Hyperavaruuteen kykenevässä aluksessa advancement.flightOfThePhoenix=Feeniksin Lento -advancement.flightOfThePhoenix.desc=Rakenna ja Lenn ensimmist Hyperavaruuteen kykenev alusta +advancement.flightOfThePhoenix.desc=Rakenna ja Lennä ensimmäistä Hyperavaruuteen kykenevää alusta advancement.beerOnTheSun=Aikuisten Juomia Auringossa -advancement.beerOnTheSun.desc=Tulet tarvitsemaan enemmn TNT pstksesi kiertoradalle +advancement.beerOnTheSun.desc=Tulet tarvitsemaan enemmän TNTä päästäksesi kiertoradalle advancement.suitedUp=Pukeutunut -advancement.suitedUp.desc=Pid yllsi kokonaista avaruuspukua +advancement.suitedUp.desc=Pidä ylläsi kokonaista avaruuspukua key.controls.advancedrocketry=Advanced Rocketry key.openRocketUI=Avaa Raketti GUI -key.toggleJetpack=Kynnist/Sammuta Rakettireppu -key.togglercs=Kynnist/Sammuta RCS -key.turnRocketLeft=Knn Kulkuneuvoa Vasemmalle -key.turnRocketRight=Knn Kulkuneuvoa Oikealle -key.turnRocketUp=Nosta Kulkuneuvoa Yls +key.toggleJetpack=Käynnistä/Sammuta Rakettireppu +key.togglercs=Käynnistä/Sammuta RCS +key.turnRocketLeft=Käännä Kulkuneuvoa Vasemmalle +key.turnRocketRight=Käännä Kulkuneuvoa Oikealle +key.turnRocketUp=Nosta Kulkuneuvoa Ylös key.turnRocketDown=Laske Kulkuneuvoa Alas -enchantment.advancedrocketry.spacebreathing.desc=Mahdollistaa haarniskan palan luomaan ilmanpitvn eristeen +enchantment.advancedrocketry.spacebreathing.desc=Mahdollistaa haarniskan palan luomaan ilmanpitävän eristeen machine.tooltip.smallplatepress=Tarvitsee obsidiaani kaksi kuutiota alapuolella toimiakseen msg.crystalliser.gravityTooHigh=Painovoima ei ole tarpeeksi alhainen! -msg.observetory.scan.tooltip=Skannaa uusia asteroideja, kytt 100 etisyys dataa +msg.observetory.scan.tooltip=Skannaa uusia asteroideja, käyttää 100 etäisyys dataa msg.observetory.scan.button=Skannaa! msg.observetory.text.asteroids=Asteroidit msg.observetory.text.composition=Koostumus -msg.observetory.text.processdiscovery=Prosessoi lyt -msg.observetory.text.observabledistance=Havaittava etisyys: -msg.observetory.text.missionTime=Tehtvaika: +msg.observetory.text.processdiscovery=Prosessoi löytö +msg.observetory.text.observabledistance=Havaittava etäisyys: +msg.observetory.text.missionTime=Tehtäväaika: msg.tooltip.data=Data msg.tooltip.asteroidselection=Asteroidivalikko msg.label.name=Nimi -msg.label.clear=Tyhjenn -msg.label.add=Lis Uusi -msg.label.rename=Nime Uudelleen +msg.label.clear=Tyhjennä +msg.label.add=Lisää Uusi +msg.label.rename=Nimeä Uudelleen msg.label.delete=Poista -msg.label.noneSelected=Ei Valittua Mrnpt -msg.label.selectDst=Valitse mrnp -msg.label.destName=Mrnpn nimi +msg.label.noneSelected=Ei Valittua Määränpäätä +msg.label.selectDst=Valitse määränpää +msg.label.destName=Määränpään nimi msg.label.coords=Koordinaatit msg.spaceElevator.button.summon=Luo Kapseli -msg.spaceElevator.sameDimensionError=Ei voi yhdist kahta hissi samalla planeetalla! +msg.spaceElevator.sameDimensionError=Ei voi yhdistää kahta hissiä samalla planeetalla! msg.spaceElevator.linkNotGeostationaryError=Asema ei ole geostationaarisella kiertoradalla! -msg.spaceElevator.tetherWouldBreakError=Aseman tytyy olla oikeinpin ja paikalleen vastaanottaakseen kaapelin! -msg.spaceElevator.linkCannotChangeError=Hissikaapelit eivt voi vaihtaa paikkaa kun ne ovat jo yhdistettyj! +msg.spaceElevator.tetherWouldBreakError=Aseman täytyy olla oikeinpäin ja paikalleen vastaanottaakseen kaapelin! +msg.spaceElevator.linkCannotChangeError=Hissikaapelit eivät voi vaihtaa paikkaa kun ne ovat jo yhdistettyjä! msg.spaceElevator.newDstAdded=Hissikaapeli Yhdistetty! msg.spaceElevator.ascentReady=Valmiina nousuun -msg.spaceElevator.warning.anchored0=Tll hissikaapelilla on +msg.spaceElevator.warning.anchored0=Tällä hissikaapelilla on msg.spaceElevator.warning.anchored1=asema ankkuroituna! -msg.spaceElevator.warning.unanchored=Tll hissill ei ole kaapelia -msg.spaceElevator.turnedOff=Hissi on poissa plt -msg.fuelingStation.link=Sin ohjelmoit yhdistjn tankkausaseman kanssa, joka on koordinaateissa -msg.monitoringStation.missionProgressNA=Tehtvn Edistys: N/A -msg.monitoringStation.link=Sin ohjelmoit yhdistjn tarkkailuaseman kanssa, joka on koordinaateissa +msg.spaceElevator.warning.unanchored=Tällä hissillä ei ole kaapelia +msg.spaceElevator.turnedOff=Hissi on poissa päältä +msg.fuelingStation.link=Sinä ohjelmoit yhdistäjän tankkausaseman kanssa, joka on koordinaateissa +msg.monitoringStation.missionProgressNA=Tehtävän Edistys: N/A +msg.monitoringStation.link=Sinä ohjelmoit yhdistäjän tarkkailuaseman kanssa, joka on koordinaateissa msg.monitoringStation.progress= Edistys: msg.guidanceComputerHatch.loadingState=Lastaustila: -msg.guidanceComputerHatch.ejectonlanding=Poista automaattisesti laskeutumisen jlkeen +msg.guidanceComputerHatch.ejectonlanding=Poista automaattisesti laskeutumisen jälkeen msg.guidanceComputerHatch.ejectonsatlanding=Salli Satelliittisirujen poistaminen msg.guidanceComputerHatch.ejectonplanetlanding=Salli Planeettasirujen poistaminen msg.guidanceComputerHatch.ejectonstationlanding=Salli Asemasirujen poistaminen -msg.guidanceComputerHatch.link=Sin ohjelmoit yhdistjn ohjaustietokoneen psyluukun kanssa, joka on koordinaateissa +msg.guidanceComputerHatch.link=Sinä ohjelmoit yhdistäjän ohjaustietokoneen pääsyluukun kanssa, joka on koordinaateissa msg.fluidLoader.loadingState=Lastaustila: msg.fluidLoader.allowLoading=Salli Lastaus: -msg.fluidLoader.allowredstoneinput=Salli redstone sisntulo +msg.fluidLoader.allowredstoneinput=Salli redstone sisääntulo msg.fluidLoader.allowredstoneoutput=Salli redstone ulosmeno -msg.fluidLoader.none=Ei mitn -msg.fluidLoader.link=Sin ohjelmoit yhdistjn nestelastaajan kanssa, joka on koordinaateissa +msg.fluidLoader.none=Ei mitään +msg.fluidLoader.link=Sinä ohjelmoit yhdistäjän nestelastaajan kanssa, joka on koordinaateissa msg.rocketLoader.loadingState=Lastaustila: msg.rocketLoader.allowLoading=Salli Lastaus: -msg.rocketLoader.allowredstoneinput=Salli redstone sisntulo +msg.rocketLoader.allowredstoneinput=Salli redstone sisääntulo msg.rocketLoader.allowredstoneoutput=Salli redstone ulosmeno -msg.rocketLoader.none=Ei mitn -msg.rocketLoader.link=Sin ohjelmoit yhdistjn rakettilastaajan kanssa, joka on koordinaateissa +msg.rocketLoader.none=Ei mitään +msg.rocketLoader.link=Sinä ohjelmoit yhdistäjän rakettilastaajan kanssa, joka on koordinaateissa msg.microwaverec.notgenerating=Tuottaa 0 FE/t msg.microwaverec.generating=Tuottaa msg.abdp.compositionresearch=Koostumustutkimus -msg.abdp.distanceresearch=Etisyystutkimus +msg.abdp.distanceresearch=Etäisyystutkimus msg.abdp.massresearch=Massatutkimus msg.terraformer.atminc=Nosta Ilmanpainetta msg.terraformer.atmdec=Laske Ilmanpainetta @@ -336,22 +336,22 @@ msg.terraformer.outofgas=Peruutettu: Kaasut loppuivat msg.terraformer.notrunning=Ei toimi msg.terraformer.status=Tila msg.terraformer.pressure=Paine -msg.biomescanner.gas=nyehhh, Kaasuista, eik? +msg.biomescanner.gas=nyehhh, Kaasuista, eikö? msg.biomescanner.star=Jos vain minun sensoreilla olisi aurinkolasit -msg.gravitycontroller.radius=Sde: +msg.gravitycontroller.radius=Säde: msg.gravitycontroller.targetgrav=Tavoitepainovoima: msg.gravitycontroller.none=Asettamaton msg.gravitycontroller.activeset=Aktiivinen: aseta -msg.gravitycontroller.activeadd=Aktiivinen: lis +msg.gravitycontroller.activeadd=Aktiivinen: lisää msg.gravitycontroller.targetdir.1=Kohde-> msg.gravitycontroller.targetdir.2=Suunta msg.railgun.transfermin=Minimi Siirtokoko msg.spacelaser.reset=Nollaa msg.satctrlcenter.toofar=Liian Kaukana -msg.satctrlcenter.nolink=Ei Linkki... +msg.satctrlcenter.nolink=Ei Linkkiä... msg.satctrlcenter.info=Info: msg.satctrlcenter.destroysat=Tuhoa Satelliitti -msg.satctrlcenter.connect=Yhdist! +msg.satctrlcenter.connect=Yhdistä! msg.satbuilder.writesecondchip=Kirjoita toiselle sirulle msg.dockingport.target=Kohde Id msg.dockingport.me=Minun Id @@ -370,113 +370,119 @@ msg.warpmon.tab.tracking=Planeettatarkkailu msg.warpmon.selectplanet=Valitse planeetta msg.warpmon.corestatus=Ytimen Tila: msg.warpmon.anchored=Asema on ankkuroitu! -msg.warpmon.nowhere=Ei ole minnekkn minne menn +msg.warpmon.nowhere=Ei ole minnekkään minne mennä msg.warpmon.missingart=Artefakti Puuttuu msg.warpmon.ready=Valmis! msg.warpmon.notready=Ei ole Valmis msg.warpmon.warp=Hyperavaruus! msg.warpmon.fuelcost=Polttoainekustannus: msg.warpmon.fuel=Polttoaine: -msg.warpmon.dest=Mrnp: +msg.warpmon.dest=Määränpää: msg.warpmon.na=N/A msg.warpmon.search=Etsi planeetta msg.warpmon.chip=Ohjelmoi sirusta -msg.warpmon.datareq=Tarvitaan 100 jokaista datatyyppi +msg.warpmon.datareq=Tarvitaan 100 jokaista datatyyppiä msg.warpmon.artifact=Artefaktit msg.rocketbuilder.success=Valmis laukaisuun! msg.rocketbuilder.nofuel=Ei tarpeeksi polttoainekapasiteettia! msg.rocketbuilder.noseat=Istuin tai satelliittiasema puuttuu! -msg.rocketbuilder.noengines=Sinulla ei ole tarpeeksi tyntvoimaa! +msg.rocketbuilder.noengines=Sinulla ei ole tarpeeksi työntövoimaa! msg.rocketbuilder.noguidance=Ohjaustietokone Puuttuu msg.rocketbuilder.unscanned=Raketti skannaamaton msg.rocketbuilder.success_station=Valmis! -msg.rocketbuilder.empty=Ei mitn tll +msg.rocketbuilder.empty=Ei mitään täällä msg.rocketbuilder.finished=Rakennus Valmis! -msg.rocketbuild.invalidblock=Ptemtn kuutio! +msg.rocketbuild.invalidblock=Pätemätön kuutio! msg.rocketbuilder.incompletestructure=Virheellinen Laukaisualustarakennus! msg.rocketbuilder.nosatellitehatch=Satelliittiasema Puuttuu msg.rocketbuilder.nosatellitechip=Siru Puuttuu msg.rocketbuilder.outputblocked=Ulostulo aukko tukittu -msg.rocketbuilder.thrust=Tyntvoima +msg.rocketbuilder.thrust=Työntövoima msg.rocketbuilder.weight=Paino msg.rocketbuilder.fuel=Polttoaine msg.rocketbuilder.acc=Kiihtyvyys msg.rocketbuilder.build=Rakenna msg.rocketbuilder.scan=Skannaa -msg.rocketbuild.combinedthrust=Polttoainetyyppej ei voi yhdist! -msg.solar.collectingEnergy=Energiankerys: -msg.solar.cannotcollectEnergy=Ei pysty kermn Energiaa +msg.rocketbuild.combinedthrust=Polttoainetyyppejä ei voi yhdistää! +msg.solar.collectingEnergy=Energiankeräys: +msg.solar.cannotcollectEnergy=Ei pysty keräämään Energiaa msg.asteroidChip.asteroid=Asteroidi -msg.atmanal.atmtype=Ilmakehtyyppi: -msg.atmanal.canbreathe=Hengitettv: +msg.atmanal.atmtype=Ilmakehätyyppi: +msg.atmanal.canbreathe=Hengitettävä: msg.biomechanger.scan=Skannaa Biomi -msg.biomechanger.nosat=Satelliitti ei ole viel laukaistu +msg.biomechanger.nosat=Satelliitti ei ole vielä laukaistu msg.biomechanger.selBiome=Valittu Biomi: -msg.biomechanger.numBiome=Skannattujen Biomien Mr: -msg.itemorescanner.nosat=Satelliitti ei ole viel laukaistu +msg.biomechanger.numBiome=Skannattujen Biomien Määrä: +msg.itemorescanner.nosat=Satelliitti ei ole vielä laukaistu msg.itemorescanner.maxzoom=Maksimi zoomaus: msg.itemorescanner.filter=Pystyy suodattamaan malmeja: msg.itemorescanner.value=Arvo: msg.itemplanetidchip.planetname=Planeetan Nimi: msg.itemplanetidchip.stationid=Asema Id: msg.itemplanetidchip.artifacts=Artefaktit: -msg.vent.trace=Happijlki +msg.vent.trace=Happijälki -msg.itemsatellite.pwr=Shkn Varastointi: -msg.itemsatellite.nopwr=Ei Shkn Varastointia -msg.itemsatellite.pwrgen=Shkn Tuotanto: -msg.itemsatellite.nopwrgen=Ei Shkn Tuotantoa! -msg.itemsatellite.microwavestatus=Shkn Kerys +msg.itemsatellite.pwr=Sähkön Varastointi: +msg.itemsatellite.nopwr=Ei Sähkön Varastointia +msg.itemsatellite.pwrgen=Sähkön Tuotanto: +msg.itemsatellite.nopwrgen=Ei Sähkön Tuotantoa! +msg.itemsatellite.microwavestatus=Sähkön Keräys msg.itemsatellite.data=Datan Varastointi: msg.itemsatellite.nodata=Ei Datan Varastointia! -msg.itemsatellite.empty=Tyhj Runko +msg.itemsatellite.empty=Tyhjä Runko msg.itemsatchip.id=ID: msg.itemsatchip.planet=Planeetta: msg.itemsatchip.planetunk=Planeetta: Tuntematon msg.itemsatchip.sat=Satelliitti: msg.itemsatchip.satlost=Satelliitti: Yhteys Menetetty -msg.sealdetector.sealed=Pitisi pit hyvn eristeen. -msg.sealdetector.notsealmat=Materiaali ei pid eristett. -msg.sealdetector.notsealblock=Kuutio ei pid eristett. -msg.sealdetector.notfullblock=Ilma kiert tmn kuution ymprilt. -msg.sealdetector.fluid=Ilma kuplii tmn kuution lpi. -msg.sealdetector.other=Ilma karkaa tmn kuution lpi. +msg.sealdetector.sealed=Pitäisi pitää hyvän eristeen. +msg.sealdetector.notsealmat=Materiaali ei pidä eristettä. +msg.sealdetector.notsealblock=Kuutio ei pidä eristettä. +msg.sealdetector.notfullblock=Ilma kiertää tämän kuution ympäriltä. +msg.sealdetector.fluid=Ilma kuplii tämän kuution läpi. +msg.sealdetector.other=Ilma karkaa tämän kuution läpi. msg.stationchip.sation=Asema -msg.entity.rocket.descend.1=Paina Vlilynti laskeutuaksesi! +msg.entity.rocket.descend.1=Paina Välilyöntiä laskeutuaksesi! msg.entity.rocket.descend.2=Automaattinen laskeutuminen -msg.entity.rocket.ascend.1=Paina Vlilynti laukaisemiseen! -msg.entity.rocket.ascend.2=Mrnp: +msg.entity.rocket.ascend.1=Paina Välilyöntiä laukaisemiseen! +msg.entity.rocket.ascend.2=Määränpää: msg.entity.rocket.launch=Laukaisu T- -msg.entity.rocket.launch2=Paina [Vlilynti] keskeyttksesi +msg.entity.rocket.launch2=Paina [Välilyönti] keskeyttääksesi msg.entity.rocket.station=Asema msg.entity.rocket.pad=Alusta: msg.entity.rocket.disass=Pura -msg.entity.rocket.seldst=Valitse Mrnp -msg.entity.rocket.clear=Tyhjenn +msg.entity.rocket.seldst=Valitse Määränpää +msg.entity.rocket.clear=Tyhjennä msg.entity.rocket.rcs=RCS Moodi msg.entity.rocket.none=Ei Valittu msg.wirelessTransciever.extract=ota talteen msg.powerunit.rfpertick=FE/t -msg.linker.error.firstMachine=Tmn tytyy olla ensimminen yhdistettv laite! -msg.linker.program=Koordinaatit ohjelmoitu yhdistjn +msg.linker.error.firstMachine=Tämän täytyy olla ensimmäinen yhdistettävä laite! +msg.linker.program=Koordinaatit ohjelmoitu yhdistäjään msg.linker.success=Onnistuneesti Yhdistetty -msg.notenoughpower=Ei Tarpeeksi shk! -msg.empty=Tyhj -msg.yes=kyll +msg.notenoughpower=Ei Tarpeeksi sähköä! +msg.empty=Tyhjä +msg.yes=kyllä msg.no=ei msg.connected=yhdistetty msg.notconnected=ei yhdistetty msg.unprogrammed=Ohjelmoimaton -msg.programfail=Ohjelmointi Eponnistui +msg.programfail=Ohjelmointi Epäonnistui msg.modules=moduulit msg.na=N/A -msg.entityDeployedRocket.notGasGiant=Ei Kaasua Tll -msg.noOxygen=Varoitus: Ilmakehss ei ole happea! -msg.tooHot=Varoitus: Ilmakeh liian kuuma! +msg.entityDeployedRocket.notGasGiant=Ei Kaasua Täällä +msg.noOxygen=Varoitus: Ilmakehässä ei ole happea! +msg.tooHot=Varoitus: Ilmakehä liian kuuma! msg.tooDense=Varoitus: Ilmanpaine liian korkea! msg.muchTooDense=Varoitus: Ilmanpaine kriittisen korkea! -msg.chat.nostation1=Sin hert avaruusasemalla viipyvn tunteen kanssa, ett sinun pitkkantoinen avaruuskvely oli jonkun vanhan kettujumalan paheksuma ja ett olisis typer yritt niin uudelleen ja odottaa erilaisia tuloksia -msg.chat.nostation2=Ehk sinun pitisi ajatella ennen kuin ylitt jlleen selkesti loogisia ja absoluuttisia rajoja ja sitten ptt, ett se oli hyv idea eik sinun vikasi, jos asiat menevt pieleen -msg.chat.nostation3=Sinun tytyy olla avaruusasemalla ollaksesi tss ulottuvuudessa, ja yhtn ei ole luotu! \ No newline at end of file +msg.chat.nostation1=Sinä heräät avaruusasemalla viipyvän tunteen kanssa, että sinun pitkäkantoinen avaruuskävely oli jonkun vanhan kettujumalan paheksuma ja että olisis typerää yrittää niin uudelleen ja odottaa erilaisia tuloksia +msg.chat.nostation2=Ehkä sinun pitäisi ajatella ennen kuin ylität jälleen selkeästi loogisia ja absoluuttisia rajoja ja sitten päättää, että se oli hyvä idea eikä sinun vikasi, jos asiat menevät pieleen +msg.chat.nostation3=Sinun täytyy olla avaruusasemalla ollaksesi tässä ulottuvuudessa, ja yhtään ei ole luotu! + +jei.sb.satellitepreview=Valmis kiertoradalle! +jei.sb.copy.source=Lähde +jei.sb.copy.output=Uusi kopio +jei.sb.assemblyhint=Vähintään yksi aurinkopaneeli +jei.sb.copychiphint=Tee varmuuskopiot! From b5bd8629c9f2d32b4ff1da70014b597944ae98d5 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 10:05:31 +0200 Subject: [PATCH 011/424] Add French translations for satellite features --- src/main/resources/assets/advancedrocketry/lang/fr_FR.lang | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/fr_FR.lang b/src/main/resources/assets/advancedrocketry/lang/fr_FR.lang index f863c40f0..f06e2f69b 100644 --- a/src/main/resources/assets/advancedrocketry/lang/fr_FR.lang +++ b/src/main/resources/assets/advancedrocketry/lang/fr_FR.lang @@ -260,3 +260,10 @@ msg.spaceElevator.ascentReady=Paré pour l'ascension msg.spaceElevator.turnedOff=L'ascenseur est hors tension. msg.entityDeployedRocket.notGasGiant=Absence de gaz msg.noOxygen=Avertissement: oxygène non détecté! + +jei.sb.satellitepreview=Prêt pour l’orbite ! +jei.sb.copy.source=Source +jei.sb.copy.output=Nouvelle copie +jei.sb.assemblyhint=Au moins un panneau solaire +jei.sb.copychiphint=Faites des sauvegardes ! + From dc0a93aa0abac365b5ce0662d3ab85525425cb60 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 10:05:55 +0200 Subject: [PATCH 012/424] Update pt_br.lang --- .../resources/assets/advancedrocketry/lang/pt_br.lang | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/pt_br.lang b/src/main/resources/assets/advancedrocketry/lang/pt_br.lang index 3f63313c3..56020c67a 100644 --- a/src/main/resources/assets/advancedrocketry/lang/pt_br.lang +++ b/src/main/resources/assets/advancedrocketry/lang/pt_br.lang @@ -222,3 +222,11 @@ advancement.suitedUp.desc=Wear a full spacesuit key.controls.advancedrocketry=Advanced Rocketry key.openRocketUI=Open Rocket GUI key.toggleJetpack=Toggle Jetpack + + +jei.sb.satellitepreview=Pronto para a órbita! +jei.sb.copy.source=Fonte +jei.sb.copy.output=Nova cópia +jei.sb.assemblyhint=Pelo menos um painel solar +jei.sb.copychiphint=Faça backups! + From 2139488a55bf75d53808ba2bef5bb72a29532926 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 10:06:14 +0200 Subject: [PATCH 013/424] Add new Russian language entries for commands --- src/main/resources/assets/advancedrocketry/lang/ru_RU.lang | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/ru_RU.lang b/src/main/resources/assets/advancedrocketry/lang/ru_RU.lang index 9c25fc9d4..1f5c8ab0e 100644 --- a/src/main/resources/assets/advancedrocketry/lang/ru_RU.lang +++ b/src/main/resources/assets/advancedrocketry/lang/ru_RU.lang @@ -448,3 +448,10 @@ msg.na=Н/Д commands.weather.always_not_clear=На этой планете не бывает сухо... commands.weather.cannot_rain=Невозможно начать дождь, увы... commands.weather.cannot_thunder=Невозможно включить грозу, увы... + + +jei.sb.satellitepreview=Готово к орбите! +jei.sb.copy.source=Источник +jei.sb.copy.output=Новая копия +jei.sb.assemblyhint=Как минимум одна солнечная панель +jei.sb.copychiphint=Делайте резервные копии! From 89509a1067f340f83f0a641fa62ccc0e3774a9ac Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 10:06:32 +0200 Subject: [PATCH 014/424] Add new Ukrainian translations for satellite features --- src/main/resources/assets/advancedrocketry/lang/ua_UA.lang | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/ua_UA.lang b/src/main/resources/assets/advancedrocketry/lang/ua_UA.lang index 8c922dfd4..6321d6af0 100644 --- a/src/main/resources/assets/advancedrocketry/lang/ua_UA.lang +++ b/src/main/resources/assets/advancedrocketry/lang/ua_UA.lang @@ -159,3 +159,10 @@ mission.asteroidmining.name=Вивчення астероїдів key.controls.advancedrocketry=Advanced Rocketry key.toggleJetpack=Ввімкнути реактивний ранець + +jei.sb.satellitepreview=Готово до орбіти! +jei.sb.copy.source=Джерело +jei.sb.copy.output=Нова копія +jei.sb.assemblyhint=Щонайменше одна сонячна панель +jei.sb.copychiphint=Робіть резервні копії! + From 8311a04a2910bc9d3c336dc0d4455bdbab7441b2 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 10:06:48 +0200 Subject: [PATCH 015/424] Add new translations to zh_CN.lang --- src/main/resources/assets/advancedrocketry/lang/zh_CN.lang | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index 1f9c728f4..84ccf28ac 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -507,3 +507,9 @@ msg.chat.nostation3=你必须在空间站上才能来到这个时空,而现在 commands.weather.always_not_clear=这个星球的天气总是阴暗... commands.weather.cannot_rain=这里无法启动降雨 commands.weather.cannot_thunder=这里无法启动雷暴 + +jei.sb.satellitepreview=准备进入轨道! +jei.sb.copy.source=来源 +jei.sb.copy.output=新副本 +jei.sb.assemblyhint=至少一个太阳能电池板 +jei.sb.copychiphint=请做好备份! From 436abb2430b746e1b69acfd11d9ffc53b3f05a1b Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 10:32:22 +0200 Subject: [PATCH 016/424] Add Satellite Builder integration to JEI --- .../integration/jei/ARPlugin.java | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/ARPlugin.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/ARPlugin.java index 22a596f1d..e934a949b 100644 --- a/src/main/java/zmaster587/advancedRocketry/integration/jei/ARPlugin.java +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/ARPlugin.java @@ -41,6 +41,9 @@ import zmaster587.advancedRocketry.integration.jei.sawmill.SawMillCategory; import zmaster587.advancedRocketry.integration.jei.sawmill.SawMillRecipeHandler; import zmaster587.advancedRocketry.integration.jei.sawmill.SawMillRecipeMaker; +import zmaster587.advancedRocketry.integration.jei.satelliteBuilder.SatelliteBuilderCategory; +import zmaster587.advancedRocketry.integration.jei.satelliteBuilder.SatelliteBuilderRecipeHandler; +import zmaster587.advancedRocketry.integration.jei.satelliteBuilder.SatelliteBuilderRecipeMaker; import zmaster587.advancedRocketry.tile.multiblock.machine.*; import zmaster587.libVulpes.inventory.GuiModular; @@ -61,6 +64,7 @@ public class ARPlugin implements IModPlugin { public static final String platePresser = "zmaster587.AR.platePresser"; public static final String centrifugeUUID = "zmaster587.AR.centrifuge"; public static final String precisionLaserEngraverUUID = "zmaster587.AR.precisionlaseretcher"; + public static final String satelliteBuilderUUID = "zmaster587.AR.satelliteBuilder"; public static IJeiHelpers jeiHelpers; //AR machines can reload recipes. We still need this for JEI to be up-to-date @@ -74,17 +78,20 @@ public void registerCategories(IRecipeCategoryRegistration registry) { jeiHelpers = registry.getJeiHelpers(); IGuiHelper guiHelper = jeiHelpers.getGuiHelper(); - registry.addRecipeCategories(new RollingMachineCategory(guiHelper), - new LatheCategory(guiHelper), - new PrecisionAssemblerCategory(guiHelper), - new SawMillCategory(guiHelper), - new ChemicalReactorCategory(guiHelper), - new CrystallizerCategory(guiHelper), - new ElectrolyzerCategory(guiHelper), - new ArcFurnaceCategory(guiHelper), - new PlatePressCategory(guiHelper), - new CentrifugeCategory(guiHelper), - new PrecisionLaserEtcherCategory(guiHelper)); + registry.addRecipeCategories( + new RollingMachineCategory(guiHelper), + new LatheCategory(guiHelper), + new PrecisionAssemblerCategory(guiHelper), + new SawMillCategory(guiHelper), + new ChemicalReactorCategory(guiHelper), + new CrystallizerCategory(guiHelper), + new ElectrolyzerCategory(guiHelper), + new ArcFurnaceCategory(guiHelper), + new PlatePressCategory(guiHelper), + new CentrifugeCategory(guiHelper), + new PrecisionLaserEtcherCategory(guiHelper), + new SatelliteBuilderCategory(guiHelper) + ); } @Override @@ -128,7 +135,9 @@ public Object getIngredientUnderMouse(GuiModular guiContainer, new ArcFurnaceRecipeHandler(), new PlatePressRecipeHandler(), new CentrifugeRecipeHandler(), - new PrecisionLaserEtcherRecipeHandler()); + new PrecisionLaserEtcherRecipeHandler(), + new SatelliteBuilderRecipeHandler() + ); registry.addRecipes(RollingMachineRecipeMaker.getMachineRecipes(jeiHelpers, TileRollingMachine.class), rollingMachineUUID); registry.addRecipes(LatheRecipeMaker.getMachineRecipes(jeiHelpers, TileLathe.class), latheUUID); @@ -141,6 +150,7 @@ public Object getIngredientUnderMouse(GuiModular guiContainer, registry.addRecipes(ChemicalReactorRecipeMaker.getMachineRecipes(jeiHelpers, TileChemicalReactor.class), chemicalReactorUUID); registry.addRecipes(CentrifugeRecipeMaker.getMachineRecipes(jeiHelpers, TileCentrifuge.class), centrifugeUUID); registry.addRecipes(PrecisionLaserEtcherRecipeMaker.getMachineRecipes(jeiHelpers, TilePrecisionLaserEtcher.class), precisionLaserEngraverUUID); + registry.addRecipes(SatelliteBuilderRecipeMaker.getMachineRecipes(jeiHelpers, null), satelliteBuilderUUID); registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockRollingMachine), rollingMachineUUID); @@ -154,5 +164,6 @@ public Object getIngredientUnderMouse(GuiModular guiContainer, registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockPlatePress), platePresser); registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockCentrifuge), centrifugeUUID); registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockPrecisionLaserEngraver), precisionLaserEngraverUUID); + registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockSatelliteBuilder), satelliteBuilderUUID); } } From ae69cf0052c604c94e3feb0fca03260c684302f5 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 10:36:58 +0200 Subject: [PATCH 017/424] Add SatelliteBuilderCategory for JEI integration --- .../SatelliteBuilderCategory.java | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/integration/jei/satelliteBuilder/SatelliteBuilderCategory.java diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/satelliteBuilder/SatelliteBuilderCategory.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/satelliteBuilder/SatelliteBuilderCategory.java new file mode 100644 index 000000000..0a303e02f --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/satelliteBuilder/SatelliteBuilderCategory.java @@ -0,0 +1,152 @@ +package zmaster587.advancedRocketry.integration.jei.satelliteBuilder; + +import mezz.jei.api.IGuiHelper; +import mezz.jei.api.gui.IDrawable; +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.recipe.IRecipeCategory; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import zmaster587.advancedRocketry.integration.jei.ARPlugin; +import zmaster587.advancedRocketry.inventory.TextureResources; +import zmaster587.libVulpes.LibVulpes; + +import java.util.List; + +public class SatelliteBuilderCategory implements IRecipeCategory { + + private final IDrawable background; + private final IDrawable slotFunctionComponent; + private final IDrawable slotPowerComponent; + private final IDrawable slotIO; + private final IDrawable slotSatellite; + private final IDrawable slotIdChip; + private final IDrawable progressBar; + private final IDrawable vanillaSlot; + private final String uid; + + public SatelliteBuilderCategory(IGuiHelper guiHelper) { + // Use a blank or minimal background (176x90 is enough for the elements) + this.background = guiHelper.createBlankDrawable(176, 90); + + // Slot frames/icons from TextureResources + this.slotFunctionComponent = guiHelper.createDrawable( + new ResourceLocation("libvulpes:textures/gui/maingui.png"), + 212, 18, 18, 18); // functionComponent + + this.slotPowerComponent = guiHelper.createDrawable( + new ResourceLocation("libvulpes:textures/gui/maingui.png"), + 230, 18, 18, 18); // powercomponent + + this.slotIO = guiHelper.createDrawable( + new ResourceLocation("libvulpes:textures/gui/maingui.png"), + 212, 0, 18, 18); // ioSlot + + this.slotSatellite = guiHelper.createDrawable( + new ResourceLocation("advancedrocketry:textures/gui/progressBars/progressBars.png"), + 220, 238, 18, 18); + + this.slotIdChip = guiHelper.createDrawable( + new ResourceLocation("libvulpes:textures/gui/maingui.png"), + 230, 0, 18, 18); // idChip + + this.vanillaSlot = guiHelper.getSlotDrawable(); + + this.progressBar = guiHelper.createDrawable( + new ResourceLocation("advancedrocketry:textures/gui/progressBars/progressBars.png"), + 217, 0, 17, 17); // progressBar + + this.uid = ARPlugin.satelliteBuilderUUID; + } + + @Override + public IDrawable getBackground() { + return background; + } + + @Override + public String getTitle() { + return LibVulpes.proxy.getLocalizedString("tile.satelliteBuilder.name"); + } + + @Override + public String getModName() { + return "Advanced Rocketry"; + } + + @Override + public String getUid() { + return uid; + } + + public Class getRecipeClass() { + return SatelliteBuilderWrapper.class; + } + + + @Override + public void setRecipe(IRecipeLayout recipeLayout, SatelliteBuilderWrapper wrapper, IIngredients ingredients) { + // Place JEI slots at the same coordinates as the modules + // Slot indices: see TileSatelliteBuilder for mapping + // 0: function, 1-6: IO, 7: Output, 8: Chip, 9: Chip, 10: Chip copy 11: chassis + // Function slot 0 + recipeLayout.getItemStacks().init(0, true, 152, 10); + + // Power slots 1-2-3 + recipeLayout.getItemStacks().init(1, true, 116, 30); + recipeLayout.getItemStacks().init(2, true, 134, 30); + recipeLayout.getItemStacks().init(3, true, 152, 30); + recipeLayout.getItemStacks().init(4, true, 116, 50); + recipeLayout.getItemStacks().init(5, true, 134, 50); + recipeLayout.getItemStacks().init(6, true, 152, 50); + + // Output slot 7 + recipeLayout.getItemStacks().init(7, false, 58, 36); + + // ID chip slot 8 + recipeLayout.getItemStacks().init(8, true, 58, 16); + + // Chip copy slot 9 + recipeLayout.getItemStacks().init(9, true, 82, 16); + + // holdingslot slot 10 not used by players + //recipeLayout.getItemStacks().init(10, false, 58, 36); + + // Chassis slot 11 + recipeLayout.getItemStacks().init(11, true, 38, 16); + + recipeLayout.getItemStacks().set(ingredients); + + // Add tooltip cosmetics + wrapper.registerTooltipCallbacks(recipeLayout.getItemStacks()); + } + + @Override + public void drawExtras(Minecraft minecraft) { + FontRenderer fr = minecraft.fontRenderer; + // Draw slot frames and icons at the correct positions + slotFunctionComponent.draw(minecraft, 152, 10); // slot 0 + slotPowerComponent.draw(minecraft, 116, 30); // slot 1 + slotPowerComponent.draw(minecraft, 134, 30); // slot 2 + slotPowerComponent.draw(minecraft, 152, 30); // slot 3 + slotIO.draw(minecraft, 116, 50); // slot 4 + slotIO.draw(minecraft, 134, 50); // slot 5 + slotIO.draw(minecraft, 152, 50); // slot 6 + vanillaSlot.draw(minecraft, 58, 36); // Output slot (slot 7) + slotIdChip.draw(minecraft, 58, 16); // slot 8 + slotIdChip.draw(minecraft, 82, 16); // slot 9 + slotSatellite.draw(minecraft, 38, 16); // Chassis slot (slot 11) + + // Progress bar + progressBar.draw(minecraft, 75, 36); + + } + @Override + public java.util.List getTooltipStrings(int mouseX, int mouseY) { + return java.util.Collections.emptyList(); + } + +} From 6b66c716ace1cb796cc416e6bd9709bae807a632 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 10:37:21 +0200 Subject: [PATCH 018/424] Add SatelliteBuilderRecipeHandler for JEI integration --- .../SatelliteBuilderRecipeHandler.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/integration/jei/satelliteBuilder/SatelliteBuilderRecipeHandler.java diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/satelliteBuilder/SatelliteBuilderRecipeHandler.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/satelliteBuilder/SatelliteBuilderRecipeHandler.java new file mode 100644 index 000000000..adaa2e443 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/satelliteBuilder/SatelliteBuilderRecipeHandler.java @@ -0,0 +1,28 @@ +package zmaster587.advancedRocketry.integration.jei.satelliteBuilder; + +import mezz.jei.api.recipe.IRecipeHandler; +import mezz.jei.api.recipe.IRecipeWrapper; +import zmaster587.advancedRocketry.integration.jei.ARPlugin; + +public class SatelliteBuilderRecipeHandler implements IRecipeHandler { + + @Override + public Class getRecipeClass() { + return SatelliteBuilderWrapper.class; + } + + @Override + public String getRecipeCategoryUid(SatelliteBuilderWrapper recipe) { + return ARPlugin.satelliteBuilderUUID; + } + + @Override + public IRecipeWrapper getRecipeWrapper(SatelliteBuilderWrapper recipe) { + return recipe; + } + + @Override + public boolean isRecipeValid(SatelliteBuilderWrapper recipe) { + return recipe != null; + } +} From 5414e988c2c96cdab38bbb44efc7ea448d2121ef Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 10:37:48 +0200 Subject: [PATCH 019/424] Add SatelliteBuilderRecipeMaker class for recipe creation Implement SatelliteBuilderRecipeMaker to create recipes for satellite assembly and chip copying. --- .../SatelliteBuilderRecipeMaker.java | 168 ++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/integration/jei/satelliteBuilder/SatelliteBuilderRecipeMaker.java diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/satelliteBuilder/SatelliteBuilderRecipeMaker.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/satelliteBuilder/SatelliteBuilderRecipeMaker.java new file mode 100644 index 000000000..2827a502f --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/satelliteBuilder/SatelliteBuilderRecipeMaker.java @@ -0,0 +1,168 @@ +package zmaster587.advancedRocketry.integration.jei.satelliteBuilder; + +import mezz.jei.api.gui.ITooltipCallback; +import mezz.jei.api.IJeiHelpers; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; +import zmaster587.advancedRocketry.api.AdvancedRocketryItems; +import zmaster587.advancedRocketry.integration.jei.satelliteBuilder.SatelliteBuilderWrapper; +import zmaster587.libVulpes.api.LibVulpesItems; +import zmaster587.libVulpes.interfaces.IRecipe; + + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class SatelliteBuilderRecipeMaker { + + public static List getMachineRecipes(IJeiHelpers helpers, Class clazz) { + List recipes = new ArrayList<>(); + + // --- Satellite Assembly Example --- + // Slot mapping: + // 0: Function component (core module) + // 1-6: Module components (power, IO, etc) + // 7: Output slot + // 8: ID chip slot (input) + // 9: Chip copy slot (input) + // 10: Holding slot (ghostslot, not used by player) + // 11: Chassis slot + + + // slot 0 + List coreModules = new ArrayList<>(); + for (int i = 0; i < 7; i++) { + coreModules.add(new ItemStack(AdvancedRocketryItems.itemSatellitePrimaryFunction, 1, i)); + } // slot 0 + + // slots 1-6: power gen, battery, data units + List moduleVariants = Arrays.asList( + new ItemStack(AdvancedRocketryItems.itemSatellitePowerSource, 1, 0), + new ItemStack(AdvancedRocketryItems.itemSatellitePowerSource, 1, 1), + new ItemStack(LibVulpesItems.itemBattery, 1, 0), + new ItemStack(LibVulpesItems.itemBattery, 1, 1), + new ItemStack(AdvancedRocketryItems.itemDataUnit, 1, 0) + ); + + + + // Slot 8: controllers mapped 1:1 to primariry core modules (metas 0-6) + List satelliteControllers = Arrays.asList( + new ItemStack(AdvancedRocketryItems.itemSatelliteIdChip), // 0: Optical + new ItemStack(AdvancedRocketryItems.itemSatelliteIdChip), // 1: Composition + new ItemStack(AdvancedRocketryItems.itemSatelliteIdChip), // 2: Mass Scanner + new ItemStack(AdvancedRocketryItems.itemSatelliteIdChip), // 3: Microwave Energy + new ItemStack(AdvancedRocketryItems.itemOreScanner), // 4: Ore Mapping + new ItemStack(AdvancedRocketryItems.itemBiomeChanger), // 5: Biome Changer (remote) + new ItemStack(AdvancedRocketryItems.itemWeatherController)// 6: Weather Controller (remote) + ); + + + List output = Collections.singletonList(new ItemStack(AdvancedRocketryItems.itemSatellite)); // slot 7 (output) + List chassis = Collections.singletonList(new ItemStack(AdvancedRocketryItems.itemSatellite)); // slot 11 (empty chassis) + + List> inputs = new ArrayList<>(); + inputs.add(coreModules); // slot 0: Function component + inputs.add(moduleVariants); // slot 1: Module component + inputs.add(moduleVariants); // slot 2: Module component + inputs.add(moduleVariants); // slot 3: Module component + inputs.add(moduleVariants); // slot 4: Module component + inputs.add(moduleVariants); // slot 5: Module component + inputs.add(moduleVariants); // slot 6: Module component + //inputs.add(Collections.emptyList()); // slot 7: Output slot (not used as input) + inputs.add(satelliteControllers); // slot 8: ID chip slot + inputs.add(Collections.emptyList()); // slot 9: Chip copy slot (not used in this recipe) + //inputs.add(Collections.emptyList()); // slot 10: Holding slot (ghostslot, not used) + inputs.add(chassis); // slot 11: Chassis slot + + // Anonymous IRecipe implementation + IRecipe assemblyRecipe = new IRecipe() { + @Override + public List getOutput() { return output; } // slot 7 + @Override + public List getFluidOutputs() { return Collections.emptyList(); } + @Override + public List> getIngredients() { return inputs; } + @Override + public List getFluidIngredients() { return Collections.emptyList(); } + @Override + public int getTime() { return 200; } + @Override + public int getPower() { return 0; } + @Override + public String getOreDictString(int var1) { return ""; } + }; + + recipes.add(new SatelliteBuilderWrapper(assemblyRecipe, false)); + + // --- Chip Copy Example --- + // Slot mapping for chip copy: + // 8: Source chip (input) + // 9: Blank chip (input) + // 7: Output slot (copied chip) + + List sourceChips = Arrays.asList( + new ItemStack(AdvancedRocketryItems.itemSatelliteIdChip), + new ItemStack(AdvancedRocketryItems.itemPlanetIdChip), + new ItemStack(AdvancedRocketryItems.itemSpaceStationChip), + new ItemStack(AdvancedRocketryItems.itemOreScanner), + new ItemStack(AdvancedRocketryItems.itemBiomeChanger), + new ItemStack(AdvancedRocketryItems.itemWeatherController), + new ItemStack(AdvancedRocketryItems.itemSpaceElevatorChip) + ); + + // Mirror the source chips for blank chips + List blankChips = sourceChips; + + // The output cycling in mapped order: + List copiedOutputVariants = Arrays.asList( + new ItemStack(AdvancedRocketryItems.itemSatelliteIdChip), + new ItemStack(AdvancedRocketryItems.itemPlanetIdChip), + new ItemStack(AdvancedRocketryItems.itemSpaceStationChip), + new ItemStack(AdvancedRocketryItems.itemOreScanner), + new ItemStack(AdvancedRocketryItems.itemBiomeChanger), + new ItemStack(AdvancedRocketryItems.itemWeatherController), + new ItemStack(AdvancedRocketryItems.itemSpaceElevatorChip) + ); + + List> chipCopyInputs = new ArrayList<>(); + chipCopyInputs.add(Collections.emptyList()); // slot 0: Function component (not used) + chipCopyInputs.add(Collections.emptyList()); // slot 1: Power component (not used) + chipCopyInputs.add(Collections.emptyList()); // slot 2: Power component (not used) + chipCopyInputs.add(Collections.emptyList()); // slot 3: Power component (not used) + chipCopyInputs.add(Collections.emptyList()); // slot 4: IO component (not used) + chipCopyInputs.add(Collections.emptyList()); // slot 5: IO component (not used) + chipCopyInputs.add(Collections.emptyList()); // slot 6: IO component (not used) + //chipCopyInputs.add(Collections.emptyList()); // slot 7: Output slot + chipCopyInputs.add(sourceChips); // slot 8: Source chip + chipCopyInputs.add(blankChips); // slot 9: Blank chip + //chipCopyInputs.add(Collections.emptyList()); // slot 10: Holding slot (not used) + chipCopyInputs.add(Collections.emptyList()); // slot 11: Chassis slot (not used) + + IRecipe chipCopyRecipe = new IRecipe() { + @Override public List getOutput() { + // Could return first as a fallback; the wrapper will override with setOutputLists + return java.util.Collections.singletonList(copiedOutputVariants.get(0)); + } + @Override + public List getFluidOutputs() { return Collections.emptyList(); } + @Override + public List> getIngredients() { return chipCopyInputs; } + @Override + public List getFluidIngredients() { return Collections.emptyList(); } + @Override + public int getTime() { return 200; } + @Override + public int getPower() { return 0; } + @Override + public String getOreDictString(int var1) { return ""; } + }; + + recipes.add(new SatelliteBuilderWrapper(chipCopyRecipe, true, copiedOutputVariants)); + + return recipes; + } +} From 9bef88dfcbff58ae7d1f4121235757350a052259 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 10:38:10 +0200 Subject: [PATCH 020/424] Add SatelliteBuilderWrapper for JEI integration --- .../SatelliteBuilderWrapper.java | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/integration/jei/satelliteBuilder/SatelliteBuilderWrapper.java diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/satelliteBuilder/SatelliteBuilderWrapper.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/satelliteBuilder/SatelliteBuilderWrapper.java new file mode 100644 index 000000000..4c6943055 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/satelliteBuilder/SatelliteBuilderWrapper.java @@ -0,0 +1,147 @@ +package zmaster587.advancedRocketry.integration.jei.satelliteBuilder; + +import mezz.jei.api.gui.IGuiItemStackGroup; +import mezz.jei.api.gui.ITooltipCallback; +import mezz.jei.api.ingredients.IIngredients; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.resources.I18n; +import net.minecraft.item.ItemStack; +import net.minecraft.util.text.TextFormatting; +import zmaster587.advancedRocketry.api.AdvancedRocketryItems; +import zmaster587.advancedRocketry.integration.jei.MachineRecipe; +import zmaster587.libVulpes.LibVulpes; +import zmaster587.libVulpes.interfaces.IRecipe; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class SatelliteBuilderWrapper extends MachineRecipe { + public final boolean isCopyRecipe; + private final IRecipe baseRecipe; // keep a handle + private final List outputVariants; // for JEI cycling (copy recipe) + private static Set COPY_STRIP_STRINGS; + + public SatelliteBuilderWrapper(IRecipe rec, boolean isCopyRecipe) { + this(rec, isCopyRecipe, null); + } + + public SatelliteBuilderWrapper(IRecipe rec, boolean isCopyRecipe, List outputVariants) { + super(rec); + this.isCopyRecipe = isCopyRecipe; + this.baseRecipe = rec; + this.outputVariants = outputVariants; + } + + @Override + public void getIngredients(mezz.jei.api.ingredients.IIngredients ingredients) { + super.getIngredients(ingredients); // inputs already mapped + + if (isCopyRecipe) { + // ONE output slot cycling MANY variants + List variants = (outputVariants != null && !outputVariants.isEmpty()) + ? outputVariants + : baseRecipe.getOutput(); // fallback if you didn’t pass variants + + if (variants != null && !variants.isEmpty()) { + ingredients.setOutputLists(ItemStack.class, + java.util.Collections.singletonList(variants)); + } + } else { + // Assembly: single concrete output (first item) + List outs = baseRecipe.getOutput(); + if (outs != null && !outs.isEmpty()) { + ingredients.setOutput(ItemStack.class, outs.get(0)); + } + } + } + + + + public java.util.List getOutputVariants() { return outputVariants; } + + public void registerTooltipCallbacks(IGuiItemStackGroup stacks) { + final boolean isCopy = this.isCopyRecipe; + + stacks.addTooltipCallback(new ITooltipCallback() { + @Override + public void onTooltip(int slotIndex, boolean input, ItemStack stack, List tooltip) { + if (stack.isEmpty()) return; + + if (!isCopy) { + // === ASSEMBLY RECIPE === (only touch output slot) + if (slotIndex != 7) return; + + if (stack.getItem() == AdvancedRocketryItems.itemSatellite) { + // Remove "empty chassis" (whatever the localization) + String libEmpty = LibVulpes.proxy.getLocalizedString("msg.itemsatellite.empty"); + tooltip.removeIf(line -> { + String stripped = net.minecraft.util.text.TextFormatting.getTextWithoutFormattingCodes(line); + if (stripped == null) return false; + String s = stripped.trim(); + return s.equalsIgnoreCase(libEmpty) || s.equalsIgnoreCase("unprogrammed"); + }); + + // Add clean preview label if not already present + String label = I18n.format("jei.sb.satellitepreview"); + addIfMissing(tooltip, label); + } + return; + } + + // === CHIP-COPY RECIPE === + if (slotIndex == 7 || slotIndex == 8) { + ensureCopyStripStringsBuilt(); + + // Strip any "unprogrammed"/blank-style lines (locale + color safe) + tooltip.removeIf(line -> { + String stripped = net.minecraft.util.text.TextFormatting.getTextWithoutFormattingCodes(line); + return stripped != null && COPY_STRIP_STRINGS.contains(stripped.trim().toLowerCase()); + }); + + // Add concise labels + final String key = (slotIndex == 7) ? "jei.sb.copy.output" : "jei.sb.copy.source"; + String label = I18n.format(key); + addIfMissing(tooltip, label); + } + } + }); + } + + private static void addIfMissing(List tooltip, String label) { + for (String l : tooltip) { + String stripped = net.minecraft.util.text.TextFormatting.getTextWithoutFormattingCodes(l); + if (stripped != null && stripped.equalsIgnoreCase(label)) return; + } + tooltip.add(label); + } + + private static void ensureCopyStripStringsBuilt() { + if (COPY_STRIP_STRINGS != null) return; + COPY_STRIP_STRINGS = new HashSet<>(); + String[] keys = { + "msg.itemchip.unprogrammed", + "msg.satelliteidchip.unprogrammed", + "msg.planetidchip.unprogrammed", + "msg.stationchip.unprogrammed", + "msg.orescanner.unprogrammed", + "msg.itemsatellite.empty" + }; + for (String k : keys) { + String v1 = I18n.format(k); + if (v1 != null) COPY_STRIP_STRINGS.add(v1.trim().toLowerCase()); + String v2 = LibVulpes.proxy.getLocalizedString(k); + if (v2 != null) COPY_STRIP_STRINGS.add(v2.trim().toLowerCase()); + } + COPY_STRIP_STRINGS.add("unprogrammed"); + } + + @Override + public void drawInfo(Minecraft minecraft, int recipeWidth, int recipeHeight, int mouseX, int mouseY) { + FontRenderer fr = minecraft.fontRenderer; + String text = I18n.format(isCopyRecipe ? "jei.sb.copychiphint" : "jei.sb.assemblyhint"); + int tw = fr.getStringWidth(text); + fr.drawString(text, (recipeWidth - tw) / 2, recipeHeight - fr.FONT_HEIGHT - 4, 0x000000); + } +} From 16778040e74d4d0d3e843e434737de7e5f7de6e8 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 20:47:45 +0200 Subject: [PATCH 021/424] Add message for already assembled rocket --- src/main/resources/assets/advancedrocketry/lang/en_US.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index 502730313..3141b0a38 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -412,6 +412,7 @@ msg.rocketbuilder.acc=Acc msg.rocketbuilder.build=Build msg.rocketbuilder.scan=Scan msg.rocketbuild.combinedthrust=Fuel types cannot be combined! +msg.rocketbuilder.alreadyassembled=Rocket already assembled msg.solar.collectingEnergy=Collecting Energy: msg.solar.cannotcollectEnergy=Unable to collect Energy msg.asteroidChip.asteroid=Asteroid From 5eceb8c6664faf6cecc036a40838aa575db0630a Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 20:50:28 +0200 Subject: [PATCH 022/424] Add translation for already assembled rocket message --- src/main/resources/assets/advancedrocketry/lang/de_DE.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/de_DE.lang b/src/main/resources/assets/advancedrocketry/lang/de_DE.lang index d832ae4e5..4a6d75c7c 100644 --- a/src/main/resources/assets/advancedrocketry/lang/de_DE.lang +++ b/src/main/resources/assets/advancedrocketry/lang/de_DE.lang @@ -345,6 +345,7 @@ msg.rocketbuilder.fuel=Treibstoff msg.rocketbuilder.acc=Beschleunigung msg.rocketbuilder.build=Bauen msg.rocketbuilder.scan=Scannen +msg.rocketbuilder.alreadyassembled=Rakete bereits zusammengebaut msg.solar.collectingEnergy= Energie sammeln: msg.solar.cannotcollectEnergy=Kann keine Energie sammeln msg.asteroidChip.asteroid=Asteroid From 7c0816586d5e5f6f004f329a9f243fed4e27bf0b Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 20:51:16 +0200 Subject: [PATCH 023/424] Add Spanish translation for rocket builder message --- src/main/resources/assets/advancedrocketry/lang/es_ES.lang | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/es_ES.lang b/src/main/resources/assets/advancedrocketry/lang/es_ES.lang index 76c126f26..dee6a00a0 100644 --- a/src/main/resources/assets/advancedrocketry/lang/es_ES.lang +++ b/src/main/resources/assets/advancedrocketry/lang/es_ES.lang @@ -108,6 +108,8 @@ item.jackhammer.name=Martillo neumático item.sealDetector.name=Detector de sellado tile.orientationControl.name=Controlador de orientación +msg.rocketbuilder.alreadyassembled=Cohete ya ensamblado + material.Dilithium.name=Dilitio From 74d784231c539d5d791a359bf36b2e8c3ac0c488 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 20:52:02 +0200 Subject: [PATCH 024/424] Add translation for already assembled rocket message --- src/main/resources/assets/advancedrocketry/lang/ru_RU.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/ru_RU.lang b/src/main/resources/assets/advancedrocketry/lang/ru_RU.lang index 1f5c8ab0e..198fac170 100644 --- a/src/main/resources/assets/advancedrocketry/lang/ru_RU.lang +++ b/src/main/resources/assets/advancedrocketry/lang/ru_RU.lang @@ -376,6 +376,7 @@ msg.rocketbuilder.fuel=Топливо msg.rocketbuilder.acc=Точность msg.rocketbuilder.build=Стройка msg.rocketbuilder.scan=Сканирование +msg.rocketbuilder.alreadyassembled=Ракета вже зібрана msg.solar.collectingEnergy=Сбор энергии: msg.solar.cannotcollectEnergy=Невозможно собрать энергию msg.asteroidChip.asteroid=Астероид From 1a09c92dfe4c50258d2a7e111107a9a2ac3af02d Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 20:53:14 +0200 Subject: [PATCH 025/424] Fix translation for already assembled rocket message --- src/main/resources/assets/advancedrocketry/lang/ru_RU.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/ru_RU.lang b/src/main/resources/assets/advancedrocketry/lang/ru_RU.lang index 198fac170..5d41eca70 100644 --- a/src/main/resources/assets/advancedrocketry/lang/ru_RU.lang +++ b/src/main/resources/assets/advancedrocketry/lang/ru_RU.lang @@ -376,7 +376,7 @@ msg.rocketbuilder.fuel=Топливо msg.rocketbuilder.acc=Точность msg.rocketbuilder.build=Стройка msg.rocketbuilder.scan=Сканирование -msg.rocketbuilder.alreadyassembled=Ракета вже зібрана +msg.rocketbuilder.alreadyassembled=Ракета уже собрана msg.solar.collectingEnergy=Сбор энергии: msg.solar.cannotcollectEnergy=Невозможно собрать энергию msg.asteroidChip.asteroid=Астероид From cee2f150b1db30b4bec7667cd5e4a09ceb830421 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 20:53:43 +0200 Subject: [PATCH 026/424] Add translation for already assembled rocket message --- src/main/resources/assets/advancedrocketry/lang/zh_CN.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index 84ccf28ac..6d5379489 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -412,6 +412,7 @@ msg.rocketbuilder.acc=飞行控制中心 msg.rocketbuilder.build=建造 msg.rocketbuilder.scan=扫描 msg.rocketbuild.combinedthrust=燃料类型不能组合! +msg.rocketbuilder.alreadyassembled=火箭已组装 msg.solar.collectingEnergy=收集能量: msg.solar.cannotcollectEnergy=无法收集能量 msg.asteroidChip.asteroid=小行星 From 0ca57a68f692225f594c5d138287a747e1c38fd6 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 21:13:34 +0200 Subject: [PATCH 027/424] Rocket assembler: fixed: errormessage and translationkey Automatically updates status to unscanned if no rocket is present when the GUI is opened. Localized error message for already assembled rockets. --- .../tile/TileRocketAssemblingMachine.java | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java index aa77c094d..089d35c8d 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java @@ -812,6 +812,17 @@ else if (ErrorCodes.INCOMPLETESTRCUTURE.equals(getStatus())) @Override public List getModules(int ID, EntityPlayer player) { + + // Automatically set status to unscanned if no rocket is present when opening GUI + if (!world.isRemote && status == ErrorCodes.ALREADY_ASSEMBLED) { + AxisAlignedBB box = (bbCache != null) ? bbCache : getRocketPadBounds(world, pos); + if (box == null || world.getEntitiesWithinAABB(EntityRocket.class, box).isEmpty()) { + status = ErrorCodes.UNSCANNED; + markDirty(); + } + } + + List modules = new LinkedList<>(); modules.add(new ModulePower(160, 90, this)); @@ -1155,7 +1166,7 @@ protected enum ErrorCodes { OUTPUTBLOCKED(LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.outputblocked")), INVALIDBLOCK(LibVulpes.proxy.getLocalizedString("msg.rocketbuild.invalidblock")), COMBINEDTHRUST(LibVulpes.proxy.getLocalizedString("msg.rocketbuild.combinedthrust")), - ALREADY_ASSEMBLED("rocket already assembled"); + ALREADY_ASSEMBLED(LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.alreadyassembled")); String code; From a052e20140eb2e7443e3a042b9009c264c933bcc Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 15 Oct 2025 23:52:06 +0200 Subject: [PATCH 028/424] Add unscanned station message to lang file Added new message for unscanned station status. --- src/main/resources/assets/advancedrocketry/lang/en_US.lang | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index 3141b0a38..7a92d2177 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -397,7 +397,9 @@ msg.rocketbuilder.noseat=Missing seat or satellite bay! msg.rocketbuilder.noengines=You do not have enough thrust! msg.rocketbuilder.noguidance=Missing Guidance Computer msg.rocketbuilder.unscanned=Rocket unscanned +msg.rocketbuilder.unscanned_station=Standing by for scan msg.rocketbuilder.success_station=Ready! +msg.rocketbuilder.fail_cut=Build failed: area changed. msg.rocketbuilder.empty=Nothing here msg.rocketbuilder.finished=Build Complete! msg.rocketbuild.invalidblock=Invalid block! From 07b3319387dba044ad4fdcca65178750e4f662f3 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 16 Oct 2025 00:07:59 +0200 Subject: [PATCH 029/424] Fix failure message formatting in en_US.lang --- src/main/resources/assets/advancedrocketry/lang/en_US.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index 7a92d2177..b876edffe 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -399,7 +399,7 @@ msg.rocketbuilder.noguidance=Missing Guidance Computer msg.rocketbuilder.unscanned=Rocket unscanned msg.rocketbuilder.unscanned_station=Standing by for scan msg.rocketbuilder.success_station=Ready! -msg.rocketbuilder.fail_cut=Build failed: area changed. +msg.rocketbuilder.fail_cut=Build failed: area changed msg.rocketbuilder.empty=Nothing here msg.rocketbuilder.finished=Build Complete! msg.rocketbuild.invalidblock=Invalid block! From 45e0513554081c4b8de8be7396a7d3cc0fbb1fc4 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 16 Oct 2025 00:09:43 +0200 Subject: [PATCH 030/424] Add new error codes for rocket assembly (station assembler) --- .../advancedRocketry/tile/TileRocketAssemblingMachine.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java index 089d35c8d..6cb62ba97 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java @@ -1166,7 +1166,9 @@ protected enum ErrorCodes { OUTPUTBLOCKED(LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.outputblocked")), INVALIDBLOCK(LibVulpes.proxy.getLocalizedString("msg.rocketbuild.invalidblock")), COMBINEDTHRUST(LibVulpes.proxy.getLocalizedString("msg.rocketbuild.combinedthrust")), - ALREADY_ASSEMBLED(LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.alreadyassembled")); + ALREADY_ASSEMBLED(LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.alreadyassembled")), + UNSCANNED_STATION(LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.unscanned_station")), + FAIL_CUT(LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.fail_cut")); String code; From d0398b8cd7caec5ab0acc7e473712c5846967d28 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 16 Oct 2025 00:56:55 +0200 Subject: [PATCH 031/424] Station assembler properly communicates with player errormessages for all its operations --- .../tile/TileStationAssembler.java | 82 +++++++++++++------ 1 file changed, 55 insertions(+), 27 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileStationAssembler.java b/src/main/java/zmaster587/advancedRocketry/tile/TileStationAssembler.java index 74b2fdaaf..abc674c3c 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileStationAssembler.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileStationAssembler.java @@ -63,11 +63,13 @@ public boolean canScan() { public AxisAlignedBB scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { int actualMinX = (int) bb.maxX, - actualMinY = (int) bb.maxY, - actualMinZ = (int) bb.maxZ, - actualMaxX = (int) bb.minX, - actualMaxY = (int) bb.minY, - actualMaxZ = (int) bb.minZ; + actualMinY = (int) bb.maxY, + actualMinZ = (int) bb.maxZ, + actualMaxX = (int) bb.minX, + actualMaxY = (int) bb.minY, + actualMaxZ = (int) bb.minZ; + + boolean foundNonAir = false; for (int xCurr = (int) bb.minX; xCurr <= bb.maxX; xCurr++) { for (int zCurr = (int) bb.minZ; zCurr <= bb.maxZ; zCurr++) { @@ -76,29 +78,32 @@ public AxisAlignedBB scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { BlockPos posCurr = new BlockPos(xCurr, yCurr, zCurr); if (!world.isAirBlock(posCurr)) { - if (xCurr < actualMinX) - actualMinX = xCurr; - if (yCurr < actualMinY) - actualMinY = yCurr; - if (zCurr < actualMinZ) - actualMinZ = zCurr; - if (xCurr > actualMaxX) - actualMaxX = xCurr; - if (yCurr > actualMaxY) - actualMaxY = yCurr; - if (zCurr > actualMaxZ) - actualMaxZ = zCurr; + foundNonAir = true; + + if (xCurr < actualMinX) actualMinX = xCurr; + if (yCurr < actualMinY) actualMinY = yCurr; + if (zCurr < actualMinZ) actualMinZ = zCurr; + if (xCurr > actualMaxX) actualMaxX = xCurr; + if (yCurr > actualMaxY) actualMaxY = yCurr; + if (zCurr > actualMaxZ) actualMaxZ = zCurr; } } } } - status = ErrorCodes.SUCCESS_STATION; + // Tell the player whats up + if (!foundNonAir) { + status = ErrorCodes.EMPTY; // nothing to pack inside bb + return bb; // sanity check + } else { + status = ErrorCodes.SUCCESS_STATION; // ok to proceed with packing + } return new AxisAlignedBB(actualMinX, actualMinY, actualMinZ, actualMaxX, actualMaxY, actualMaxZ); } + @Override public void assembleRocket() { if (!world.isRemote) { @@ -113,6 +118,9 @@ public void assembleRocket() { try { storageChunk = StorageChunk.cutWorldBB(world, bbCache); } catch (NegativeArraySizeException e) { + status = ErrorCodes.FAIL_CUT; + markDirty(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); return; } @@ -152,20 +160,38 @@ public void assembleRocket() { @Override protected void updateText() { - if (!world.isRemote) { - if (getRocketPadBounds(world, pos) == null) + if (world != null && !world.isRemote) { + if (getRocketPadBounds(world, pos) == null) { setStatus(ErrorCodes.INCOMPLETESTRCUTURE.ordinal()); - else if (ErrorCodes.INCOMPLETESTRCUTURE.equals(getStatus())) - setStatus(ErrorCodes.UNSCANNED.ordinal()); + } else if (ErrorCodes.INCOMPLETESTRCUTURE.equals(getStatus())) { + setStatus(ErrorCodes.UNSCANNED_STATION.ordinal()); + } } - errorText.setText(status.getErrorCode()); + if (errorText != null) { + errorText.setText(status.getErrorCode()); + } } @Override public List getModules(int ID, EntityPlayer player) { List modules = new LinkedList<>(); + // GUI-open reset errorcode if pad is valid and we're idle + if (!world.isRemote) { + AxisAlignedBB bounds = getRocketPadBounds(world, pos); + if (bounds == null) { + setStatus(ErrorCodes.INCOMPLETESTRCUTURE.ordinal()); + } else if (!isScanning()) { + ErrorCodes s = getStatus(); + if (s == ErrorCodes.SUCCESS_STATION || s == ErrorCodes.SUCCESS || + s == ErrorCodes.FINISHED || s == ErrorCodes.EMPTY || + s == ErrorCodes.UNSCANNED) { + setStatus(ErrorCodes.UNSCANNED_STATION.ordinal()); + } + } + } + modules.add(new ModulePower(160, 30, this)); modules.add(new ModuleProgress(149, 30, 2, verticalProgressBar, this)); @@ -177,6 +203,7 @@ public List getModules(int ID, EntityPlayer player) { buttonBuild.setColor(0xFFFF2222); modules.add(errorText = new ModuleText(5, 22, "", 0xFFFFFF22)); modules.add(new ModuleSync(4, this)); + modules.add(new ModuleSync(2, this)); // sync error codes to client (on change) updateText(); @@ -190,19 +217,20 @@ public List getModules(int ID, EntityPlayer player) { @Override - public void useNetworkData(EntityPlayer player, Side side, byte id, - NBTTagCompound nbt) { + public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompound nbt) { + + super.useNetworkData(player, side, id, nbt); + // recompute AFTER super boolean isScanningFlag = !isScanning() && canScan(); - super.useNetworkData(player, side, id, nbt); if (id == 1 && isScanningFlag) { - storedId = (long) ItemStationChip.getUUID(inventory.getStackInSlot(1)); if (storedId == 0) storedId = null; } } + @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); From 6e997b4167ada636e10da040457c568b2bca80c5 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 17 Oct 2025 16:01:33 +0200 Subject: [PATCH 032/424] Perfomance fixes Enable/disable button actually means early exit. General Throttling to 20tick intervals, +phasing for multiple transcievers --- .../tile/cables/TileWirelessTransciever.java | 115 +++++++++++++----- 1 file changed, 85 insertions(+), 30 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java b/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java index 7687b9353..2ce4755c0 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java @@ -38,6 +38,10 @@ public class TileWirelessTransciever extends TileEntity implements INetworkMachine, IModularInventory, ILinkableTile, IDataHandler, ITickable, IToggleButton { + // How often to transfer data (in ticks) + private int transferIntervalTicks = 20; + // Fixed phase per tile to spread load + private int phase = -1; protected ModuleToggleSwitch toggleSwitch; boolean extractMode; @@ -53,6 +57,10 @@ public TileWirelessTransciever() { data.setMaxData(100); toggle = new ModuleToggleSwitch(50, 50, 0, LibVulpes.proxy.getLocalizedString("msg.wirelessTransciever.extract"), this, TextureResources.buttonGeneric, 64, 18, false); toggleSwitch = new ModuleToggleSwitch(160, 5, 1, "", this, zmaster587.libVulpes.inventory.TextureResources.buttonToggleImage, 11, 26, true); + + // Align internal booleans with UI defaults + extractMode = toggle.getState(); // false initially + enabled = toggleSwitch.getState(); // true initially } @@ -229,7 +237,7 @@ public NBTTagCompound writeToNBT(NBTTagCompound nbt) { nbt.setBoolean("mode", extractMode); nbt.setBoolean("enabled", enabled); nbt.setInteger("networkID", networkID); - data.writeToNBT(nbt); + data.writeToNBT(nbt); return super.writeToNBT(nbt); } @@ -248,51 +256,98 @@ public int addData(int maxAmount, DataType type, EnumFacing dir, @Override public void onLoad() { super.onLoad(); - if (!world.isRemote) { - if (!NetworkRegistry.dataNetwork.doesNetworkExist(networkID)) + // Server side only + if (world == null || world.isRemote) return; + + // Ensure sane interval before using it in modulo + if (transferIntervalTicks <= 0) transferIntervalTicks = 20; + + // Stable per-tile phase to spread work over time (no persistence needed) + phase = (int) Math.floorMod(this.pos.toLong(), transferIntervalTicks); + + // (Re)join the data network only if we’re actually linked to one + if (networkID != -1) { + if (!NetworkRegistry.dataNetwork.doesNetworkExist(networkID)) { + // Create (or re-create) this specific network id NetworkRegistry.dataNetwork.getNewNetworkID(networkID); + } + // Make sure we're not double-registered, then register with the right role NetworkRegistry.dataNetwork.getNetwork(networkID).removeFromAll(this); - if (extractMode) + if (extractMode) { NetworkRegistry.dataNetwork.getNetwork(networkID).addSource(this, EnumFacing.UP); - else + } else { NetworkRegistry.dataNetwork.getNetwork(networkID).addSink(this, EnumFacing.UP); - + } } } @Override public void update() { + // Server only + if (world.isRemote) return; - if (!world.isRemote) { - IBlockState state = world.getBlockState(getPos()); - if (state.getBlock() instanceof RotatableBlock) { - EnumFacing facing = RotatableBlock.getFront(state).getOpposite(); - - TileEntity tile = world.getTileEntity(getPos().add(facing.getFrontOffsetX(), facing.getFrontOffsetY(), facing.getFrontOffsetZ())); - - if (tile instanceof IDataHandler && !(tile instanceof TileWirelessTransciever)) { - for (DataType data : DataType.values()) { - - if (data == DataStorage.DataType.UNDEFINED) - continue; - - if (!extractMode) { - int amountCurrent = this.data.getDataAmount(data); - if (amountCurrent > 0) { - int amt = ((IDataHandler) tile).addData(amountCurrent, data, facing.getOpposite(), true); - this.data.extractData(amt, data, facing.getOpposite(), true); - } - } else { - int amt = ((IDataHandler) tile).extractData(this.data.getMaxData() - this.data.getDataAmount(data), data, facing.getOpposite(), true); - this.data.addData(amt, data, facing.getOpposite(), true); - } - } + // Respect front-panel enable switch + if (!enabled) return; + + // Guard against bad values (e.g., NBT edits) + if (transferIntervalTicks <= 0) transferIntervalTicks = 20; + + // Initialize a stable phase to spread load across ticks + if (phase < 0) { + phase = (int) Math.floorMod(this.pos.toLong(), transferIntervalTicks); + } + + // Throttle: only run on the tile's assigned tick + long now = world.getTotalWorldTime(); + if (((now + phase) % transferIntervalTicks) != 0) return; + + IBlockState state = world.getBlockState(getPos()); + if (!(state.getBlock() instanceof RotatableBlock)) return; + + // Face the block's "IO" side + EnumFacing facing = RotatableBlock.getFront(state).getOpposite(); + TileEntity neighbor = world.getTileEntity(getPos().offset(facing)); + + // Must be a data handler and not another wireless transceiver (avoid loops) + if (!(neighbor instanceof IDataHandler) || (neighbor instanceof TileWirelessTransciever)) return; + + boolean changed = false; + + for (DataStorage.DataType dataType : DataStorage.DataType.values()) { + if (dataType == DataStorage.DataType.UNDEFINED) continue; + + if (!extractMode) { + // PUSH: from this buffer -> neighbor + int have = this.data.getDataAmount(dataType); + if (have <= 0) continue; + + int moved = ((IDataHandler) neighbor).addData(have, dataType, facing.getOpposite(), true); + if (moved > 0) { + this.data.extractData(moved, dataType, facing.getOpposite(), true); + changed = true; + } + } else { + // PULL: from neighbor -> this buffer + int room = this.data.getMaxData() - this.data.getDataAmount(dataType); + if (room <= 0) continue; + + int moved = ((IDataHandler) neighbor).extractData(room, dataType, facing.getOpposite(), true); + if (moved > 0) { + this.data.addData(moved, dataType, facing.getOpposite(), true); + changed = true; } } } + + // Persist changes; a full block update isn't strictly required each tick + if (changed) { + this.markDirty(); + // If you want to sync the client meter instantly, you can uncomment: + // world.notifyBlockUpdate(pos, state, state, 3); + } } From 26b343c2c2c697bac9f1bc045c631d3ec51216ee Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 17 Oct 2025 16:08:43 +0200 Subject: [PATCH 033/424] fixed Satellite terminal no more broadcasting UI to every player in range, no more downloading data without power. --- .../tile/satellite/TileSatelliteTerminal.java | 170 +++++++++++++++--- 1 file changed, 142 insertions(+), 28 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java index 7dcfaef7f..0d42dcac5 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java @@ -17,7 +17,6 @@ import zmaster587.advancedRocketry.inventory.modules.ModuleSatellite; import zmaster587.advancedRocketry.item.ItemData; import zmaster587.advancedRocketry.item.ItemSatelliteIdentificationChip; -import zmaster587.advancedRocketry.network.PacketSatellite; import zmaster587.advancedRocketry.satellite.SatelliteData; import zmaster587.advancedRocketry.util.IDataInventory; import zmaster587.advancedRocketry.util.PlanetaryTravelHelper; @@ -36,6 +35,9 @@ public class TileSatelliteTerminal extends TileInventoriedRFConsumer implements INetworkMachine, IModularInventory, IButtonInventory, IDataInventory, IDataHandler { + // Subscribers: players who currently have this GUI open (server-side only) + private final java.util.Set subscribers = new java.util.HashSet<>(); + //private ModuleText satelliteText; private SatelliteBase satellite; @@ -121,12 +123,22 @@ public void readDataFromNetwork(ByteBuf in, byte packetId, @Override public void update() { super.update(); - - if (!world.isRemote) { - //update satellite for players nearby - if ((world.getTotalWorldTime() % 20) == 0) { - PacketHandler.sendToNearby(new PacketMachine(this, (byte) 22), world.provider.getDimension(), pos, 16); + if (world.isRemote) return; + + if ((world.getTotalWorldTime() % 20) == 0 && !subscribers.isEmpty()) { + PacketMachine pkt = new PacketMachine(this, (byte)22); + java.util.Set stale = new java.util.HashSet<>(); + + for (java.util.UUID id : subscribers) { + net.minecraft.entity.player.EntityPlayerMP mp = + (net.minecraft.entity.player.EntityPlayerMP) world.getPlayerEntityByUUID(id); + if (mp == null || !mp.isEntityAlive()) { + stale.add(id); + continue; + } + zmaster587.libVulpes.network.PacketHandler.sendToPlayer(pkt, mp); } + if (!stale.isEmpty()) subscribers.removeAll(stale); } } @@ -134,11 +146,35 @@ public void update() { public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompound nbt) { if (id == 0) { storeData(0); + } else if (id == 100) { + if (!world.isRemote) { + SatelliteBase sat = getSatelliteFromSlot(0); + + boolean inRange = false; + if (sat != null) { + int satDim = sat.getDimensionId(); + int hereDim = DimensionManager.getEffectiveDimId(world, pos).getId(); + inRange = PlanetaryTravelHelper.isTravelAnywhereInPlanetarySystem(satDim, hereDim); + } + boolean hasLink = (sat instanceof SatelliteData) && inRange; + boolean hasPower = getUniversalEnergyStored() >= getPowerPerOperation(); + + if (hasLink && hasPower) { + // perform action and pay the RF cost, just like extractData(commit=true) + sat.performAction(player, world, pos); + this.energy.extractEnergy(getPowerPerOperation(), false); + } - if (satellite != null && PlanetaryTravelHelper.isTravelAnywhereInPlanetarySystem(satellite.getDimensionId(), DimensionManager.getEffectiveDimId(world, pos).getId())) { - satellite.performAction(player, world, pos); + // Push a fresh status payload either way so the UI reflects current state + if (player instanceof net.minecraft.entity.player.EntityPlayerMP) { + zmaster587.libVulpes.network.PacketHandler.sendToPlayer( + new PacketMachine(this, (byte)22), + (net.minecraft.entity.player.EntityPlayerMP) player + ); + } } + } else if (id == 101) { onInventoryButtonPressed(id - 100); } @@ -147,25 +183,26 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompou if (world.isRemote) { // 22 should never arrive at the server int status = nbt.getInteger("status"); satellite = getSatelliteFromSlot(0); - if (moduleText != null){ - if (status != 0 && satellite != null) { - if (status == 1) - moduleText.setText(LibVulpes.proxy.getLocalizedString("msg.notenoughpower")); - - else if (status == 2) { - moduleText.setText(satellite.getName() + "\n\n" + LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.toofar")); - } else if (status == 3) { - moduleText.setText(satellite.getName() + "\n\n" + LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.info") + "\n" + - "Power gen.: "+nbt.getInteger("ppt")+"\n"+ - "Data: "+nbt.getInteger("data") +"/"+nbt.getInteger("maxdata")); + if (moduleText != null) { + if (status != 0 && satellite != null) { + if (status == 1) { + moduleText.setText(LibVulpes.proxy.getLocalizedString("msg.notenoughpower")); + } else if (status == 2) { + moduleText.setText(satellite.getName() + "\n\n" + LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.toofar")); + } else if (status == 3) { + moduleText.setText(satellite.getName() + "\n\n" + LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.info") + "\n" + + "Power gen.: " + nbt.getInteger("ppt") + "\n" + + "Data: " + nbt.getInteger("data") + "/" + nbt.getInteger("maxdata")); + } + } else { + moduleText.setText(LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.nolink")); } - } else - moduleText.setText(LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.nolink")); } } } } + @Override public void setInventorySlotContents(int slot, @Nonnull ItemStack stack) { super.setInventorySlotContents(slot, stack); @@ -191,6 +228,19 @@ public SatelliteBase getSatelliteFromSlot(int slot) { @Override public List getModules(int ID, EntityPlayer player) { + // Ensure the server registers the viewer and sends immediate state + if (!world.isRemote && player instanceof net.minecraft.entity.player.EntityPlayerMP) { + java.util.UUID uid = player.getUniqueID(); + if (!subscribers.contains(uid)) { + subscribers.add(uid); + } + // immediate payload so UI doesn’t show "no link" for up to 1s + zmaster587.libVulpes.network.PacketHandler.sendToPlayer( + new PacketMachine(this, (byte)22), + (net.minecraft.entity.player.EntityPlayerMP) player + ); + } + List modules = new LinkedList<>(); modules.add(new ModulePower(18, 20, this.energy)); modules.add(new ModuleButton(116, 70, 0, LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.connect"), this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); @@ -274,18 +324,42 @@ public void storeData(int id) { @Override public int extractData(int maxAmount, DataType type, EnumFacing dir, boolean commit) { - //TODO + SatelliteBase sat = getSatelliteFromSlot(0); + + // Link + range + power gates (same as UI) + boolean inRange = false; + if (sat != null) { + int satDim = sat.getDimensionId(); + int hereDim = DimensionManager.getEffectiveDimId(world, pos).getId(); + inRange = PlanetaryTravelHelper.isTravelAnywhereInPlanetarySystem(satDim, hereDim); + } + boolean hasLink = (sat instanceof SatelliteData) && inRange; + boolean hasPower = getUniversalEnergyStored() >= getPowerPerOperation(); - SatelliteBase satellite = getSatelliteFromSlot(0); - if (satellite instanceof SatelliteData && PlanetaryTravelHelper.isTravelAnywhereInPlanetarySystem(satellite.getDimensionId(), DimensionManager.getEffectiveDimId(world, pos).getId())) { - satellite.performAction(null, world, pos); + if (!(hasLink && hasPower)) { + return 0; } - if (type == data.getDataType() || data.getDataType() == DataType.UNDEFINED) { - return data.removeData(maxAmount, commit); + if (!commit) { + // Simulate: do NOT pull from satellite; just report current availability + if (type != data.getDataType() && data.getDataType() != DataType.UNDEFINED) return 0; + int available = data.getData(); + return Math.min(maxAmount, available); } - return 0; + // COMMIT path: first pull fresh data from the satellite into our buffer + sat.performAction(null, world, pos); + + // Now validate type and figure out how much we can remove + if (type != data.getDataType() && data.getDataType() != DataType.UNDEFINED) return 0; + + int removable = Math.min(maxAmount, data.getData()); + if (removable <= 0) return 0; + + // Consume RF only if we're actually removing data + this.energy.extractEnergy(getPowerPerOperation(), false); + + return data.removeData(removable, true); } @Override @@ -298,4 +372,44 @@ public int addData(int maxAmount, DataType type, EnumFacing dir, boolean commit) public boolean canInteractWithContainer(EntityPlayer entity) { return true; } + + + // Subscribe/unsubscribe when GUI (container) opens/closes + @Override + public void openInventory(EntityPlayer player) { + super.openInventory(player); + if (!world.isRemote && player != null) { + subscribers.add(player.getUniqueID()); + // immediate first payload so UI populates without waiting a tick + if (player instanceof net.minecraft.entity.player.EntityPlayerMP) { + zmaster587.libVulpes.network.PacketHandler.sendToPlayer(new PacketMachine(this, (byte)22), + (net.minecraft.entity.player.EntityPlayerMP) player); + } + } + } + + @Override + public void closeInventory(EntityPlayer player) { + super.closeInventory(player); + if (!world.isRemote && player != null) { + subscribers.remove(player.getUniqueID()); + } + } + + @Override + public void onChunkUnload() { + super.onChunkUnload(); + if (!world.isRemote) { + subscribers.clear(); + } + } + + @Override + public void invalidate() { + super.invalidate(); + if (!world.isRemote) { + subscribers.clear(); + } + } + } From 11a4638d6e883f460b65a17210e9351512f53b27 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 17 Oct 2025 16:09:27 +0200 Subject: [PATCH 034/424] Change 'Connect!' to 'Download' and update thrust message to fit GUI --- src/main/resources/assets/advancedrocketry/lang/en_US.lang | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index b876edffe..ef50c3f68 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -359,7 +359,7 @@ msg.satctrlcenter.toofar=Too Far msg.satctrlcenter.nolink=No Link... msg.satctrlcenter.info=Info: msg.satctrlcenter.destroysat=Destroy Satellite -msg.satctrlcenter.connect=Connect! +msg.satctrlcenter.connect=Download msg.satbuilder.writesecondchip=Write to Secondary Chip msg.dockingport.target=Target Id msg.dockingport.me=My Id @@ -394,7 +394,7 @@ msg.warpmon.artifact=Artifacts msg.rocketbuilder.success=Clear for liftoff! msg.rocketbuilder.nofuel=Not enough fuel capacity! msg.rocketbuilder.noseat=Missing seat or satellite bay! -msg.rocketbuilder.noengines=You do not have enough thrust! +msg.rocketbuilder.noengines=Not enough thrust! msg.rocketbuilder.noguidance=Missing Guidance Computer msg.rocketbuilder.unscanned=Rocket unscanned msg.rocketbuilder.unscanned_station=Standing by for scan From 416a7a71a9ef20788d5a13ff6d9311c0c3c37c77 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 18 Oct 2025 19:47:52 +0200 Subject: [PATCH 035/424] Improve event bus registration in TileRocketAssemblingMachine Refactor event registration and handling for rocket assembly. Should fix GC going crazy when idle, aswell as lower overall GC for tile --- .../tile/TileRocketAssemblingMachine.java | 97 ++++++++++++------- 1 file changed, 63 insertions(+), 34 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java index 6cb62ba97..dc08ae779 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java @@ -28,6 +28,7 @@ import zmaster587.advancedRocketry.entity.EntityRocket; import zmaster587.advancedRocketry.item.ItemPackedStructure; import zmaster587.advancedRocketry.network.PacketInvalidLocationNotify; +import zmaster587.advancedRocketry.tile.TileRocketAssemblingMachine.ErrorCodes; import zmaster587.advancedRocketry.tile.hatch.TileSatelliteHatch; import zmaster587.advancedRocketry.util.StorageChunk; import zmaster587.advancedRocketry.util.WeightEngine; @@ -91,25 +92,44 @@ public TileRocketAssemblingMachine() { stats = new StatsRocket(); building = false; prevProgress = 0; - MinecraftForge.EVENT_BUS.register(this); } + private boolean registeredBus = false; + + @Override + public void onLoad() { + // Called after world is set and NBT is loaded; safe place to register (server only) + if (!world.isRemote && !registeredBus) { + MinecraftForge.EVENT_BUS.register(this); + registeredBus = true; + } + } + @Override public void invalidate() { super.invalidate(); - MinecraftForge.EVENT_BUS.unregister(this); - for (HashedBlockPosition pos : blockPos) { - TileEntity tile = world.getTileEntity(pos.getBlockPos()); + unregisterFromBus(); - if (tile instanceof IMultiblock) - ((IMultiblock) tile).setIncomplete(); + if (world != null) + for (HashedBlockPosition pos : blockPos) { + TileEntity tile = world.getTileEntity(pos.getBlockPos()); + if (tile instanceof IMultiblock) { + ((IMultiblock) tile).setIncomplete(); + } } } @Override public void onChunkUnload() { super.onChunkUnload(); - MinecraftForge.EVENT_BUS.unregister(this); + unregisterFromBus(); + } + + private void unregisterFromBus() { + if (registeredBus) { + MinecraftForge.EVENT_BUS.unregister(this); + registeredBus = false; + } } public ErrorCodes getStatus() { @@ -1117,39 +1137,48 @@ public List getConnectedInfrastructure() { } @SubscribeEvent - public void onRocketLand(RocketLandedEvent event) { - if (event.world.isRemote) - return; - EntityRocketBase rocket = (EntityRocketBase) event.getEntity(); - - - //This apparently happens sometimes - if (world == null) { - AdvancedRocketry.logger.debug("World null for rocket builder during rocket land event @ " + this.pos); - return; + public void onRocketLand(RocketLandedEvent e) { + // Server/world guard + if (e.world.isRemote || e.world != this.world) return; + + // Ensure we have pad bounds + if (bbCache == null) bbCache = getRocketPadBounds(world, pos); + if (bbCache == null) return; + + // Make sure the event entity is a rocket + final net.minecraft.entity.Entity ent = e.getEntity(); + if (!(ent instanceof EntityRocketBase)) return; + final EntityRocketBase landed = (EntityRocketBase) ent; + + // Quick membership test with tiny epsilon + final AxisAlignedBB box = bbCache.grow(1.0E-4, 1.0E-4, 1.0E-4); + if (!landed.getEntityBoundingBox().intersects(box)) return; + + // Track rocket id and (re)link infra + lastRocketID = landed.getEntityId(); + for (IInfrastructure infra : getConnectedInfrastructure()) { + landed.linkInfrastructure(infra); } - if (getBBCache() == null) { - bbCache = getRocketPadBounds(world, pos); + // Maintain original semantics: only fast-path when exactly one rocket in the pad + List rockets = world.getEntitiesWithinAABB(EntityRocket.class, box); + if (rockets.size() == 1) { + EntityRocket r = rockets.get(0); + r.recalculateStats(); + this.stats = r.stats.copy(); + this.status = ErrorCodes.ALREADY_ASSEMBLED; + markDirty(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); + } else { + // Fallback: rescan if something odd happens + scanRocket(world, pos, bbCache); } - if (getBBCache() != null) { - double buffer = 0.0001; - AxisAlignedBB bufferedBB = bbCache.grow(buffer, buffer, buffer); - List rockets = world.getEntitiesWithinAABB(EntityRocketBase.class, bufferedBB); - - if (rockets.contains(rocket)) { - lastRocketID = rocket.getEntityId(); - for (IInfrastructure infrastructure : getConnectedInfrastructure()) { - rocket.linkInfrastructure(infrastructure); - } - scanRocket(world,pos, bbCache); // rescan on landing - - PacketHandler.sendToPlayersTrackingEntity(new PacketMachine(this, (byte) 3), rocket); - } - } + // Preserve original networking + PacketHandler.sendToPlayersTrackingEntity(new PacketMachine(this, (byte)3), landed); } + protected enum ErrorCodes { SUCCESS(LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.success")), NOFUEL(LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.nofuel")), From 807c9a4f98b82a600541f046dc474229acd4fa38 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 19 Oct 2025 18:09:48 +0200 Subject: [PATCH 036/424] Add ModuleSatelliteTerminal for satelliteterminal really fixed DDosing everyone in 16block radius with updated UI-info. --- .../modules/ModuleSatelliteTerminal.java | 224 ++++++++++++++++++ 1 file changed, 224 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleSatelliteTerminal.java diff --git a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleSatelliteTerminal.java b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleSatelliteTerminal.java new file mode 100644 index 000000000..1cc03ccdb --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleSatelliteTerminal.java @@ -0,0 +1,224 @@ +package zmaster587.advancedRocketry.inventory.modules; + +import java.util.Collections; +import java.util.List; + +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.IContainerListener; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; + +import zmaster587.advancedRocketry.tile.satellite.TileSatelliteTerminal; +import zmaster587.advancedRocketry.dimension.DimensionManager; +import zmaster587.advancedRocketry.util.PlanetaryTravelHelper; +import zmaster587.advancedRocketry.satellite.SatelliteData; +import zmaster587.advancedRocketry.api.satellite.SatelliteBase; +import zmaster587.advancedRocketry.item.ItemSatelliteIdentificationChip; + +import zmaster587.libVulpes.LibVulpes; +import zmaster587.libVulpes.inventory.modules.ModuleBase; +import zmaster587.libVulpes.inventory.modules.ModuleText; + +/** + * Per-viewer status module for the Satellite Control Center. + * Forces a sync every 0.5s (10 ticks) while the GUI is open. + * Sends 4 ints: 0=status, 1=ppt, 2=data, 3=maxdata. + */ +public class ModuleSatelliteTerminal extends ModuleBase { + + private final ModuleText text; + private final int color; + private final IInventory inv; // client: read chip name + private final TileSatelliteTerminal tile; // server: compute values + + // {status, ppt, data, max} + private final int[] vals = new int[4]; + + + // Force burst every 10 ticks + private long lastPushBucket = Long.MIN_VALUE; + private boolean burstPending = false; + + + // Add field to track current chip/satellite identity (server-side) + private long lastSatId = Long.MIN_VALUE; // or int; use -1 for "no sat" + + private static long getCurrentSatId(TileSatelliteTerminal t) { + zmaster587.advancedRocketry.api.satellite.SatelliteBase sat = t.getSatelliteFromSlot(0); + if (sat == null) return -1L; + return sat.getId(); // adjust if getId() is int; cast/convert as needed + } + + public ModuleSatelliteTerminal(int x, int y, int color) { + this(x, y, color, null, null); + } + + public ModuleSatelliteTerminal(int x, int y, int color, IInventory inv, TileSatelliteTerminal tile) { + super(x, y); + this.color = color; + this.inv = inv; + this.tile = tile; + this.text = new ModuleText(x, y, "", color); + this.text.setText(LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.nolink")); + } + + @Override + public void renderForeground(int x, int y, int mouseX, int mouseY, float zLevel, + GuiContainer gui, FontRenderer font) { + } + + @Override + public void renderBackground(GuiContainer gui, int x, int y, int mouseX, int mouseY, + FontRenderer font) { + + text.renderBackground(gui, x, y, mouseX, mouseY, font); + } + + @Override + public List getSlots(Container container) { return Collections.emptyList(); } + + @Override public int numberOfChangesToSend() { return 4; } + + // Some libVulpes builds use needsUpdate; keep it mapped to our logic. + @Override + public boolean needsUpdate(int localId) { return isUpdateRequired(localId); } + + @Override + public void sendInitialChanges(Container container, IContainerListener listener, int moduleIndex) { + if (tile != null && !tile.getWorld().isRemote) { + int[] now = computeStatusFromTile(tile); + for (int i = 0; i < 4; i++) vals[i] = now[i]; + lastSatId = getCurrentSatId(tile); + long t = tile.getWorld().getTotalWorldTime(); + lastPushBucket = t / 10L; + } + + for (int i = 0; i < 4; i++) { + listener.sendWindowProperty(container, moduleIndex + i, vals[i]); + } + burstPending = false; // reset + } + + @Override + public boolean isUpdateRequired(int relativeIdx) { + if (tile != null && !tile.getWorld().isRemote) { + final long t = tile.getWorld().getTotalWorldTime(); + final long bucket = t / 10L; + + // Detect satellite/chip change + final long curSatId = getCurrentSatId(tile); + final boolean satChanged = (curSatId != lastSatId); + if (satChanged) lastSatId = curSatId; + + // Arm a new burst on bucket edge OR sat change + if (bucket != lastPushBucket || satChanged) { + lastPushBucket = bucket; + + // Compute all four, assign immediately so all lanes read the same snapshot + final int[] now = computeStatusFromTile(tile); + System.arraycopy(now, 0, vals, 0, 4); + + // One atomic send of all lanes this tick + burstPending = true; + + } + } + + // During a burst, ALL lanes return true so container sends 0..3 in one pass. + return burstPending; + } + + @Override + public void sendChanges(Container container, IContainerListener listener, + int variableId, int relativeIdx) { + // 'variableId' IS the global property id. Do NOT add relativeIdx. + listener.sendWindowProperty(container, variableId, vals[relativeIdx]); + + // Clear the burst only after the last lane goes out + if (relativeIdx == 3) { + burstPending = false; + } + } + + + + @Override + public void onChangeRecieved(int relativeIdx, int value) { + vals[relativeIdx] = value; + rebuildClientText(); + } + + // ---- Helpers ---- + + private static int[] computeStatusFromTile(TileSatelliteTerminal t) { + int status = 0, ppt = 0, data = 0, max = 0; + + SatelliteBase sat = t.getSatelliteFromSlot(0); + + // --- Case 1: No chip or invalid satellite --- + if (!(sat instanceof SatelliteData)) { + return new int[] { 0, 0, 0, 0 }; + } + + // --- Case 2: Valid satellite --- + boolean hasPower = t.getUniversalEnergyStored() >= t.getPowerPerOperation(); + int hereDim = DimensionManager.getEffectiveDimId(t.getWorld(), t.getPos()).getId(); + boolean inRange = PlanetaryTravelHelper.isTravelAnywhereInPlanetarySystem(sat.getDimensionId(), hereDim); + + if (!hasPower) { + status = 1; // Not enough power + } else if (!inRange) { + status = 2; // Out of range + } else { + status = 3; // OK and connected + + SatelliteData s = (SatelliteData) sat; + ppt = s.getPowerPerTick(); // Power generation rate + data = s.data.getData(); // Current data amount + max = s.data.getMaxData(); // Maximum storage + } + + // --- Always return all four fields --- + return new int[] { status, ppt, data, max }; + } + + + // Client: rebuild visible text; sat name read locally from chip + private void rebuildClientText() { + final int status = vals[0]; + final int ppt = vals[1]; + final int data = vals[2]; + final int max = vals[3]; + + String satName = null; + if (inv != null && inv.getSizeInventory() > 0) { + ItemStack stack0 = inv.getStackInSlot(0); + if (!stack0.isEmpty() && stack0.getItem() instanceof ItemSatelliteIdentificationChip) { + SatelliteBase sat = ItemSatelliteIdentificationChip.getSatellite(stack0); + if (sat != null) satName = sat.getName(); + } + } + + String msg; + if (status == 0) { + msg = LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.nolink"); + } else if (status == 1) { + msg = LibVulpes.proxy.getLocalizedString("msg.notenoughpower"); + } else if (status == 2) { + msg = LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.toofar"); + } else { + msg = LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.info") + + "\nPower gen.: " + ppt + "\nData: " + data + "/" + max; + } + + if (satName != null && !satName.isEmpty()) { + msg = satName + "\n\n" + msg; + } + + text.setText(msg); + text.setColor(color); + } +} From dd697a61d3871701a683891594c92075c9078e16 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 19 Oct 2025 19:11:37 +0200 Subject: [PATCH 037/424] Refactor TileSatelliteTerminal for clarity and efficiency Refactor TileSatelliteTerminal class by removing unused code and simplifying methods. --- .../tile/satellite/TileSatelliteTerminal.java | 290 +++++------------- 1 file changed, 69 insertions(+), 221 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java index 0d42dcac5..114013040 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java @@ -20,6 +20,7 @@ import zmaster587.advancedRocketry.satellite.SatelliteData; import zmaster587.advancedRocketry.util.IDataInventory; import zmaster587.advancedRocketry.util.PlanetaryTravelHelper; + import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.inventory.modules.*; import zmaster587.libVulpes.network.PacketHandler; @@ -32,30 +33,20 @@ import java.util.LinkedList; import java.util.List; +public class TileSatelliteTerminal extends TileInventoriedRFConsumer + implements INetworkMachine, IModularInventory, IButtonInventory, IDataInventory, IDataHandler { -public class TileSatelliteTerminal extends TileInventoriedRFConsumer implements INetworkMachine, IModularInventory, IButtonInventory, IDataInventory, IDataHandler { - - // Subscribers: players who currently have this GUI open (server-side only) - private final java.util.Set subscribers = new java.util.HashSet<>(); - - - //private ModuleText satelliteText; - private SatelliteBase satellite; - private ModuleText moduleText; private DataStorage data; public TileSatelliteTerminal() { super(10000, 2); - data = new DataStorage(); data.setMaxData(1000); } @Override @Nonnull - public int[] getSlotsForFace(@Nullable EnumFacing side) { - return new int[0]; - } + public int[] getSlotsForFace(@Nullable EnumFacing side) { return new int[0]; } @Override public String getModularInventoryName() { @@ -63,9 +54,7 @@ public String getModularInventoryName() { } @Override - public boolean isItemValidForSlot(int slot, @Nonnull ItemStack stack) { - return true; - } + public boolean isItemValidForSlot(int slot, @Nonnull ItemStack stack) { return true; } @Override public boolean canPerformFunction() { @@ -73,81 +62,36 @@ public boolean canPerformFunction() { } @Override - public int getPowerPerOperation() { - return 1; - } + public int getPowerPerOperation() { return 1; } @Override public void performFunction() { - if (world.isRemote) - updateInventoryInfo(); + // No client push here anymore; module sync handles display updates. } + // Old custom packet not used anymore; keep empty to satisfy INetworkMachine @Override - public void writeDataToNetwork(ByteBuf out, byte packetId) { - if (packetId == (byte) 22) { - satellite = getSatelliteFromSlot(0); - if (satellite != null && satellite instanceof SatelliteData) { - if (getUniversalEnergyStored() < getPowerPerOperation()) { - out.writeInt(1); // no power - } else { - if (!PlanetaryTravelHelper.isTravelAnywhereInPlanetarySystem(satellite.getDimensionId(), DimensionManager.getEffectiveDimId(world, pos).getId())) { - out.writeInt(2);//out of range - } else { - out.writeInt(3); - out.writeInt(((SatelliteData) satellite).getPowerPerTick()); - out.writeInt(((SatelliteData) satellite).data.getData()); - out.writeInt(((SatelliteData) satellite).data.getMaxData()); - } - } - } else { - out.writeInt(0); // no link - } - } - } + public void writeDataToNetwork(ByteBuf out, byte packetId) { } + // Old custom packet not used anymore; keep empty to satisfy INetworkMachine @Override - public void readDataFromNetwork(ByteBuf in, byte packetId, - NBTTagCompound nbt) { - if (packetId == (byte) 22) { - int status = in.readInt(); - if (status == 3){ - nbt.setInteger("ppt", in.readInt()); - nbt.setInteger("data", in.readInt()); - nbt.setInteger("maxdata", in.readInt()); - } - nbt.setInteger("status", status); - } - } + public void readDataFromNetwork(ByteBuf in, byte packetId, NBTTagCompound nbt) { } - @Override - public void update() { - super.update(); - if (world.isRemote) return; - - if ((world.getTotalWorldTime() % 20) == 0 && !subscribers.isEmpty()) { - PacketMachine pkt = new PacketMachine(this, (byte)22); - java.util.Set stale = new java.util.HashSet<>(); - - for (java.util.UUID id : subscribers) { - net.minecraft.entity.player.EntityPlayerMP mp = - (net.minecraft.entity.player.EntityPlayerMP) world.getPlayerEntityByUUID(id); - if (mp == null || !mp.isEntityAlive()) { - stale.add(id); - continue; - } - zmaster587.libVulpes.network.PacketHandler.sendToPlayer(pkt, mp); - } - if (!stale.isEmpty()) subscribers.removeAll(stale); - } - } + // Tick: nothing needed; the module polls the tile every 9 tick while GUI is open + //@Override + //public void update() { + // super.update(); + // no status pushing needed + //} @Override public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompound nbt) { if (id == 0) { + // store data to item (server handles it inside storeData) storeData(0); } else if (id == 100) { + // "Connect" / perform action if (!world.isRemote) { SatelliteBase sat = getSatelliteFromSlot(0); @@ -161,153 +105,104 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompou boolean hasPower = getUniversalEnergyStored() >= getPowerPerOperation(); if (hasLink && hasPower) { - // perform action and pay the RF cost, just like extractData(commit=true) sat.performAction(player, world, pos); this.energy.extractEnergy(getPowerPerOperation(), false); } - - // Push a fresh status payload either way so the UI reflects current state - if (player instanceof net.minecraft.entity.player.EntityPlayerMP) { - zmaster587.libVulpes.network.PacketHandler.sendToPlayer( - new PacketMachine(this, (byte)22), - (net.minecraft.entity.player.EntityPlayerMP) player - ); - } } } else if (id == 101) { - onInventoryButtonPressed(id - 100); - } - - if (id == 22) { - if (world.isRemote) { // 22 should never arrive at the server - int status = nbt.getInteger("status"); - satellite = getSatelliteFromSlot(0); - if (moduleText != null) { - if (status != 0 && satellite != null) { - if (status == 1) { - moduleText.setText(LibVulpes.proxy.getLocalizedString("msg.notenoughpower")); - } else if (status == 2) { - moduleText.setText(satellite.getName() + "\n\n" + LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.toofar")); - } else if (status == 3) { - moduleText.setText(satellite.getName() + "\n\n" + LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.info") + "\n" + - "Power gen.: " + nbt.getInteger("ppt") + "\n" + - "Data: " + nbt.getInteger("data") + "/" + nbt.getInteger("maxdata")); - } - } else { - moduleText.setText(LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.nolink")); + if (!world.isRemote) { + ItemStack stack = getStackInSlot(0); + if (!stack.isEmpty() && stack.getItem() instanceof ItemSatelliteIdentificationChip) { + ItemSatelliteIdentificationChip idchip = (ItemSatelliteIdentificationChip) stack.getItem(); + + SatelliteBase sat = idchip.getSatellite(stack); + if (sat != null) { + DimensionManager.getInstance() + .getDimensionProperties(sat.getDimensionId()) + .removeSatellite(sat.getId()); } + + idchip.erase(stack); + // server mutates the inventory; client will get it via normal container sync + setInventorySlotContents(0, stack); } } } } - @Override public void setInventorySlotContents(int slot, @Nonnull ItemStack stack) { super.setInventorySlotContents(slot, stack); - satellite = getSatelliteFromSlot(0); - updateInventoryInfo(); } - public void updateInventoryInfo() { - - } - - public SatelliteBase getSatelliteFromSlot(int slot) { - ItemStack stack = getStackInSlot(slot); if (!stack.isEmpty() && stack.getItem() instanceof ItemSatelliteIdentificationChip) { return ItemSatelliteIdentificationChip.getSatellite(stack); } - return null; } @Override public List getModules(int ID, EntityPlayer player) { + List modules = new LinkedList<>(); - // Ensure the server registers the viewer and sends immediate state - if (!world.isRemote && player instanceof net.minecraft.entity.player.EntityPlayerMP) { - java.util.UUID uid = player.getUniqueID(); - if (!subscribers.contains(uid)) { - subscribers.add(uid); - } - // immediate payload so UI doesn’t show "no link" for up to 1s - zmaster587.libVulpes.network.PacketHandler.sendToPlayer( - new PacketMachine(this, (byte)22), - (net.minecraft.entity.player.EntityPlayerMP) player - ); - } + modules.add(new ModulePower(18, 20, this.energy) { + @Override public int numberOfChangesToSend() { return 2; } + }); - List modules = new LinkedList<>(); - modules.add(new ModulePower(18, 20, this.energy)); - modules.add(new ModuleButton(116, 70, 0, LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.connect"), this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); - modules.add(new ModuleButton(173, 3, 1, "", this, TextureResources.buttonKill, LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.destroysat"), 24, 24)); - modules.add(new ModuleData(28, 20, 1, this, data)); - ModuleSatellite moduleSatellite = new ModuleSatellite(152, 10, this, 0); - moduleSatellite.setSatellite(satellite); - modules.add(moduleSatellite); + modules.add(new ModuleButton(116, 70, 0, + LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.connect"), + this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); + + modules.add(new ModuleButton(173, 3, 1, "", + this, TextureResources.buttonKill, + LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.destroysat"), 24, 24)); - //Try to assign a satellite ASAP - //moduleSatellite.setSatellite(getSatelliteFromSlot(0)); + modules.add(new ModuleData(28, 20, 1, this, data) { + @Override public int numberOfChangesToSend() { return 2; } + }); - moduleText = new ModuleText(60, 20, LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.nolink"), 0x404040); - modules.add(moduleText); + modules.add(new ModuleSatellite(152, 10, this, 0) { + @Override public int numberOfChangesToSend() { return 0; } + }); + + // Add status module last; no need to keep a field reference + modules.add(new zmaster587.advancedRocketry.inventory.modules.ModuleSatelliteTerminal( + 60, 20, 0x404040, this, this)); - updateInventoryInfo(); return modules; } + @Override public void onInventoryButtonPressed(int buttonId) { - if (buttonId == 0) { - PacketHandler.sendToServer(new PacketMachine(this, (byte) (100 + buttonId))); - + PacketHandler.sendToServer(new PacketMachine(this, (byte) (100 + buttonId))); // id 100 } else if (buttonId == 1) { - ItemStack stack = getStackInSlot(0); - - if (!stack.isEmpty() && stack.getItem() instanceof ItemSatelliteIdentificationChip) { - ItemSatelliteIdentificationChip idchip = (ItemSatelliteIdentificationChip) stack.getItem(); - - SatelliteBase satellite = idchip.getSatellite(stack); - - //Somebody might want to erase the chip of an already existing satellite - if (satellite != null) - DimensionManager.getInstance().getDimensionProperties(satellite.getDimensionId()).removeSatellite(satellite.getId()); - - idchip.erase(stack); - setInventorySlotContents(0, stack); - PacketHandler.sendToServer(new PacketMachine(this, (byte) (100 + buttonId))); - } + PacketHandler.sendToServer(new PacketMachine(this, (byte) (100 + buttonId))); // id 101 } - } @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); - - NBTTagCompound data = new NBTTagCompound(); - - this.data.writeToNBT(data); - nbt.setTag("data", data); + NBTTagCompound dataTag = new NBTTagCompound(); + this.data.writeToNBT(dataTag); + nbt.setTag("data", dataTag); return nbt; } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); - - NBTTagCompound data = nbt.getCompoundTag("data"); - this.data.readFromNBT(data); + NBTTagCompound dataTag = nbt.getCompoundTag("data"); + this.data.readFromNBT(dataTag); } @Override - public void loadData(int id) { - } + public void loadData(int id) { } @Override public void storeData(int id) { @@ -326,7 +221,6 @@ public void storeData(int id) { public int extractData(int maxAmount, DataType type, EnumFacing dir, boolean commit) { SatelliteBase sat = getSatelliteFromSlot(0); - // Link + range + power gates (same as UI) boolean inRange = false; if (sat != null) { int satDim = sat.getDimensionId(); @@ -336,80 +230,34 @@ public int extractData(int maxAmount, DataType type, EnumFacing dir, boolean com boolean hasLink = (sat instanceof SatelliteData) && inRange; boolean hasPower = getUniversalEnergyStored() >= getPowerPerOperation(); - if (!(hasLink && hasPower)) { - return 0; - } + if (!(hasLink && hasPower)) return 0; if (!commit) { - // Simulate: do NOT pull from satellite; just report current availability if (type != data.getDataType() && data.getDataType() != DataType.UNDEFINED) return 0; int available = data.getData(); return Math.min(maxAmount, available); } - // COMMIT path: first pull fresh data from the satellite into our buffer sat.performAction(null, world, pos); - // Now validate type and figure out how much we can remove if (type != data.getDataType() && data.getDataType() != DataType.UNDEFINED) return 0; int removable = Math.min(maxAmount, data.getData()); if (removable <= 0) return 0; - // Consume RF only if we're actually removing data this.energy.extractEnergy(getPowerPerOperation(), false); + int removed = data.removeData(removable, true); - return data.removeData(removable, true); + return removed; } @Override public int addData(int maxAmount, DataType type, EnumFacing dir, boolean commit) { + int added = data.addData(maxAmount, type, commit); - return data.addData(maxAmount, type, commit); + return added; } @Override - public boolean canInteractWithContainer(EntityPlayer entity) { - return true; - } - - - // Subscribe/unsubscribe when GUI (container) opens/closes - @Override - public void openInventory(EntityPlayer player) { - super.openInventory(player); - if (!world.isRemote && player != null) { - subscribers.add(player.getUniqueID()); - // immediate first payload so UI populates without waiting a tick - if (player instanceof net.minecraft.entity.player.EntityPlayerMP) { - zmaster587.libVulpes.network.PacketHandler.sendToPlayer(new PacketMachine(this, (byte)22), - (net.minecraft.entity.player.EntityPlayerMP) player); - } - } - } - - @Override - public void closeInventory(EntityPlayer player) { - super.closeInventory(player); - if (!world.isRemote && player != null) { - subscribers.remove(player.getUniqueID()); - } - } - - @Override - public void onChunkUnload() { - super.onChunkUnload(); - if (!world.isRemote) { - subscribers.clear(); - } - } - - @Override - public void invalidate() { - super.invalidate(); - if (!world.isRemote) { - subscribers.clear(); - } - } - + public boolean canInteractWithContainer(EntityPlayer entity) { return true; } } From 9d9dbbd1c674a29770c6908177ac8299b48dc975 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 19 Oct 2025 19:12:46 +0200 Subject: [PATCH 038/424] Change sync period from 10 ticks to 9 ticks added "private static final long PERIOD_TICKS = 9L;" 9 is just enough to never see data jump up by 2, --- .../inventory/modules/ModuleSatelliteTerminal.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleSatelliteTerminal.java b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleSatelliteTerminal.java index 1cc03ccdb..c9ce27b44 100644 --- a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleSatelliteTerminal.java +++ b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleSatelliteTerminal.java @@ -24,7 +24,7 @@ /** * Per-viewer status module for the Satellite Control Center. - * Forces a sync every 0.5s (10 ticks) while the GUI is open. + * Forces a sync every 0.5s (9 ticks) while the GUI is open. * Sends 4 ints: 0=status, 1=ppt, 2=data, 3=maxdata. */ public class ModuleSatelliteTerminal extends ModuleBase { @@ -34,11 +34,12 @@ public class ModuleSatelliteTerminal extends ModuleBase { private final IInventory inv; // client: read chip name private final TileSatelliteTerminal tile; // server: compute values + private static final long PERIOD_TICKS = 9L; // {status, ppt, data, max} private final int[] vals = new int[4]; - // Force burst every 10 ticks + // Force burst every 9 ticks private long lastPushBucket = Long.MIN_VALUE; private boolean burstPending = false; @@ -93,7 +94,7 @@ public void sendInitialChanges(Container container, IContainerListener listener, for (int i = 0; i < 4; i++) vals[i] = now[i]; lastSatId = getCurrentSatId(tile); long t = tile.getWorld().getTotalWorldTime(); - lastPushBucket = t / 10L; + lastPushBucket = t / PERIOD_TICKS; } for (int i = 0; i < 4; i++) { @@ -106,7 +107,7 @@ public void sendInitialChanges(Container container, IContainerListener listener, public boolean isUpdateRequired(int relativeIdx) { if (tile != null && !tile.getWorld().isRemote) { final long t = tile.getWorld().getTotalWorldTime(); - final long bucket = t / 10L; + final long bucket = t / PERIOD_TICKS; // Detect satellite/chip change final long curSatId = getCurrentSatId(tile); From a0683cf1050b407217aef5af33d229798625c0f4 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 20 Oct 2025 08:18:47 +0200 Subject: [PATCH 039/424] Refactor extractData method in TileSatelliteTerminal fixes: wirelesstranciever can now pull from internal storage without a chip or link. moving data from satellite to terminal still gated behind "haspower" --- .../tile/satellite/TileSatelliteTerminal.java | 44 +++++++++++-------- 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java index 114013040..0c805adea 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java @@ -219,8 +219,27 @@ public void storeData(int id) { @Override public int extractData(int maxAmount, DataType type, EnumFacing dir, boolean commit) { - SatelliteBase sat = getSatelliteFromSlot(0); + // 1) Type guard (unchanged) + if (type != data.getDataType() && data.getDataType() != DataType.UNDEFINED) { + return 0; + } + + // 2) Simulation: report local only (don’t guess satellite yield) + if (!commit) { + int availableLocal = data.getData(); + return Math.min(maxAmount, availableLocal); + } + + // 3) Drain LOCAL first, chip or no chip + int availableLocal = data.getData(); + int toGive = Math.min(maxAmount, availableLocal); + int removed = 0; + if (toGive > 0) { + removed = data.removeData(toGive, true); + } + // 4) If we have link+power, auto-download to refill AFTER the pull + SatelliteBase sat = getSatelliteFromSlot(0); boolean inRange = false; if (sat != null) { int satDim = sat.getDimensionId(); @@ -230,27 +249,16 @@ public int extractData(int maxAmount, DataType type, EnumFacing dir, boolean com boolean hasLink = (sat instanceof SatelliteData) && inRange; boolean hasPower = getUniversalEnergyStored() >= getPowerPerOperation(); - if (!(hasLink && hasPower)) return 0; - - if (!commit) { - if (type != data.getDataType() && data.getDataType() != DataType.UNDEFINED) return 0; - int available = data.getData(); - return Math.min(maxAmount, available); + if (hasLink && hasPower) { + sat.performAction(null, world, pos); // same as GUI Download + this.energy.extractEnergy(getPowerPerOperation(), false); + // (No immediate extra removal here; we already served the request.) } - sat.performAction(null, world, pos); - - if (type != data.getDataType() && data.getDataType() != DataType.UNDEFINED) return 0; - - int removable = Math.min(maxAmount, data.getData()); - if (removable <= 0) return 0; - - this.energy.extractEnergy(getPowerPerOperation(), false); - int removed = data.removeData(removable, true); - - return removed; + return removed; // may be 0 if buffer empty and no link/power } + @Override public int addData(int maxAmount, DataType type, EnumFacing dir, boolean commit) { int added = data.addData(maxAmount, type, commit); From cb3d62e92626a6534571eb71c0e360c171aa4672 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 20 Oct 2025 17:04:42 +0200 Subject: [PATCH 040/424] Add insert message to wireless transceiver language file --- src/main/resources/assets/advancedrocketry/lang/en_US.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index ef50c3f68..a1e234077 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -482,6 +482,7 @@ msg.entity.rocket.clear=Clear msg.entity.rocket.rcs=RCS Mode msg.entity.rocket.none=None Selected msg.wirelessTransciever.extract=extract +msg.wirelessTransciever.insert=insert msg.powerunit.rfpertick=FE/t msg.linker.error.firstMachine=This must be the first machine to link! From acaf48717d21d37c36c017d393573c904c49259b Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 20 Oct 2025 17:15:01 +0200 Subject: [PATCH 041/424] Add up and down facing states to wirelesstransciever --- .../blockstates/wirelesstransciever.json | 28 +++++++++++-------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/blockstates/wirelesstransciever.json b/src/main/resources/assets/advancedrocketry/blockstates/wirelesstransciever.json index 72b127360..b2c7287f9 100644 --- a/src/main/resources/assets/advancedrocketry/blockstates/wirelesstransciever.json +++ b/src/main/resources/assets/advancedrocketry/blockstates/wirelesstransciever.json @@ -1,13 +1,19 @@ { - "variants": { - "facing=north,state=false": { "model": "advancedrocketry:wirelesstransciever" }, - "facing=south,state=false": { "model": "advancedrocketry:wirelesstransciever", "y": 180 }, - "facing=west,state=false": { "model": "advancedrocketry:wirelesstransciever", "y": 270 }, - "facing=east,state=false": { "model": "advancedrocketry:wirelesstransciever", "y": 90 }, - "facing=north,state=true": { "model": "advancedrocketry:wirelesstransciever" }, - "facing=south,state=true": { "model": "advancedrocketry:wirelesstransciever", "y": 180 }, - "facing=west,state=true": { "model": "advancedrocketry:wirelesstransciever", "y": 270 }, - "facing=east,state=true": { "model": "advancedrocketry:wirelesstransciever", "y": 90 }, - "inventory" : { "model": "advancedrocketry:wirelesstransciever" } - } + "variants": { + "facing=north,state=false": { "model": "advancedrocketry:wirelesstransciever" }, + "facing=south,state=false": { "model": "advancedrocketry:wirelesstransciever", "y": 180 }, + "facing=west,state=false": { "model": "advancedrocketry:wirelesstransciever", "y": 270 }, + "facing=east,state=false": { "model": "advancedrocketry:wirelesstransciever", "y": 90 }, + "facing=up,state=false": { "model": "advancedrocketry:wirelesstransciever", "x": 270 }, + "facing=down,state=false": { "model": "advancedrocketry:wirelesstransciever", "x": 90 }, + + "facing=north,state=true": { "model": "advancedrocketry:wirelesstransciever" }, + "facing=south,state=true": { "model": "advancedrocketry:wirelesstransciever", "y": 180 }, + "facing=west,state=true": { "model": "advancedrocketry:wirelesstransciever", "y": 270 }, + "facing=east,state=true": { "model": "advancedrocketry:wirelesstransciever", "y": 90 }, + "facing=up,state=true": { "model": "advancedrocketry:wirelesstransciever", "x": 270 }, + "facing=down,state=true": { "model": "advancedrocketry:wirelesstransciever", "x": 90 }, + + "inventory": { "model": "advancedrocketry:wirelesstransciever" } + } } From e2ee79b48098b849312c5c9b40d5038109134b0b Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 20 Oct 2025 17:19:11 +0200 Subject: [PATCH 042/424] Enhance TileWirelessTransciever Added network ID label and improved data handling. --- .../tile/cables/TileWirelessTransciever.java | 142 +++++++++++++----- 1 file changed, 108 insertions(+), 34 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java b/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java index 2ce4755c0..b3f5ce015 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java @@ -2,6 +2,7 @@ import io.netty.buffer.ByteBuf; import net.minecraft.block.state.IBlockState; +import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -21,11 +22,11 @@ import zmaster587.advancedRocketry.inventory.TextureResources; import zmaster587.advancedRocketry.world.util.MultiData; import zmaster587.libVulpes.LibVulpes; -import zmaster587.libVulpes.block.RotatableBlock; import zmaster587.libVulpes.interfaces.ILinkableTile; import zmaster587.libVulpes.inventory.modules.IModularInventory; import zmaster587.libVulpes.inventory.modules.IToggleButton; import zmaster587.libVulpes.inventory.modules.ModuleBase; +import zmaster587.libVulpes.inventory.modules.ModuleText; import zmaster587.libVulpes.inventory.modules.ModuleToggleSwitch; import zmaster587.libVulpes.items.ItemLinker; import zmaster587.libVulpes.network.PacketHandler; @@ -42,6 +43,15 @@ public class TileWirelessTransciever extends TileEntity implements INetworkMachi private int transferIntervalTicks = 20; // Fixed phase per tile to spread load private int phase = -1; + // Show network ID (label) + private ModuleText netIdLabel; + + // Avoid per-call allocations from DataType.values() + // needs update if DataType enum changes + private static final DataType[] TYPES = { + DataType.DISTANCE, DataType.HUMIDITY, DataType.TEMPERATURE, + DataType.COMPOSITION, DataType.ATMOSPHEREDENSITY, DataType.MASS + }; protected ModuleToggleSwitch toggleSwitch; boolean extractMode; @@ -57,12 +67,37 @@ public TileWirelessTransciever() { data.setMaxData(100); toggle = new ModuleToggleSwitch(50, 50, 0, LibVulpes.proxy.getLocalizedString("msg.wirelessTransciever.extract"), this, TextureResources.buttonGeneric, 64, 18, false); toggleSwitch = new ModuleToggleSwitch(160, 5, 1, "", this, zmaster587.libVulpes.inventory.TextureResources.buttonToggleImage, 11, 26, true); - + // Align internal booleans with UI defaults extractMode = toggle.getState(); // false initially enabled = toggleSwitch.getState(); // true initially + updateToggleLabel(); + + // Network ID label + netIdLabel = new ModuleText(40, 72, "Network: -", 0x000000); + netIdLabel.setAlwaysOnTop(true); // optional, so it renders over slots + } + + private void updateToggleLabel() { + if (toggle != null) { + String key = extractMode + ? "msg.wirelessTransciever.extract" // pulling from side → network + : "msg.wirelessTransciever.insert"; // pushing from network → side + toggle.setText(LibVulpes.proxy.getLocalizedString(key)); + } } + private EnumFacing resolveFront(IBlockState state) { + if (state == null) return EnumFacing.NORTH; + if (state.getBlock() instanceof zmaster587.advancedRocketry.block.BlockTransciever) { + return zmaster587.advancedRocketry.block.BlockTransciever.getFront(state); + } + // fallback for legacy blocks if any remain + if (state.getBlock() instanceof zmaster587.libVulpes.block.RotatableBlock) { + return zmaster587.libVulpes.block.RotatableBlock.getFront(state); + } + return EnumFacing.NORTH; + } @Override public boolean onLinkStart(@Nonnull ItemStack item, TileEntity entity, EntityPlayer player, World world) { @@ -78,6 +113,7 @@ public boolean onLinkStart(@Nonnull ItemStack item, TileEntity entity, EntityPla @Override public void onChunkUnload() { super.onChunkUnload(); + if (networkID == -1) return; if (NetworkRegistry.dataNetwork.doesNetworkExist(networkID)) NetworkRegistry.dataNetwork.getNetwork(networkID).removeFromAll(this); } @@ -85,8 +121,17 @@ public void onChunkUnload() { @Override public boolean onLinkComplete(@Nonnull ItemStack item, TileEntity entity, EntityPlayer player, World world) { BlockPos pos = ItemLinker.getMasterCoords(item); + if (pos == null) return false; // defensive + + if (pos.equals(this.pos)) { + if (world.isRemote) player.sendMessage(new TextComponentTranslation("msg.linker.sameblock")); + return false; + } + + if (!world.isBlockLoaded(pos)) return false; TileEntity tile = world.getTileEntity(pos); + if (!(tile instanceof TileWirelessTransciever)) return false; if (tile instanceof TileWirelessTransciever) { if (world.isRemote) { @@ -111,6 +156,16 @@ public boolean onLinkComplete(@Nonnull ItemStack item, TileEntity entity, Entity addToNetwork(); ((TileWirelessTransciever) tile).addToNetwork(); + + //SYNC CLIENT UI/STATE FOR BOTH TILES + this.markDirty(); + world.notifyBlockUpdate(this.pos, world.getBlockState(this.pos), world.getBlockState(this.pos), 3); + + tile.markDirty(); + world.notifyBlockUpdate(tile.getPos(), world.getBlockState(tile.getPos()), + world.getBlockState(tile.getPos()), 3); + + ItemLinker.resetPosition(item); return true; @@ -167,6 +222,7 @@ public List getModules(int id, EntityPlayer player) { list.add(toggle); list.add(toggleSwitch); + list.add(netIdLabel); return list; } @@ -197,22 +253,23 @@ public void readDataFromNetwork(ByteBuf in, byte packetId, } @Override - public void useNetworkData(EntityPlayer player, Side side, byte id, - NBTTagCompound nbt) { - - if (side.isServer()) { - if (id == 0) { - extractMode = nbt.getBoolean("state"); - if (NetworkRegistry.dataNetwork.doesNetworkExist(networkID)) { - NetworkRegistry.dataNetwork.getNetwork(networkID).removeFromAll(this); - - if (extractMode) - NetworkRegistry.dataNetwork.getNetwork(networkID).addSource(this, EnumFacing.UP); - else - NetworkRegistry.dataNetwork.getNetwork(networkID).addSink(this, EnumFacing.UP); - } - } else if (id == 1) { - enabled = nbt.getBoolean("state"); + public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompound nbt) { + if (!side.isServer()) return; + if (id == 1) { // enable/disable toggle doesn’t touch networks + enabled = nbt.getBoolean("state"); + return; + } + if (networkID == -1) return; // not linked yet; ignore network mutations + + if (id == 0) { + extractMode = nbt.getBoolean("state"); + updateToggleLabel(); + if (NetworkRegistry.dataNetwork.doesNetworkExist(networkID)) { + NetworkRegistry.dataNetwork.getNetwork(networkID).removeFromAll(this); + if (extractMode) + NetworkRegistry.dataNetwork.getNetwork(networkID).addSource(this, EnumFacing.UP); + else + NetworkRegistry.dataNetwork.getNetwork(networkID).addSink(this, EnumFacing.UP); } } } @@ -228,19 +285,26 @@ public void readFromNBT(NBTTagCompound nbt) { //addToNetwork(); toggle.setToggleState(extractMode); + updateToggleLabel(); toggleSwitch.setToggleState(enabled); + if (world != null && world.isRemote && netIdLabel != null) { + netIdLabel.setText("Network: " + networkID); + } + } @Override @Nonnull public NBTTagCompound writeToNBT(NBTTagCompound nbt) { + super.writeToNBT(nbt); // MOVE: call first nbt.setBoolean("mode", extractMode); nbt.setBoolean("enabled", enabled); nbt.setInteger("networkID", networkID); - data.writeToNBT(nbt); - return super.writeToNBT(nbt); + data.writeToNBT(nbt); + return nbt; } + @Override public int extractData(int maxAmount, DataType type, EnumFacing dir, boolean commit) { @@ -305,19 +369,17 @@ public void update() { if (((now + phase) % transferIntervalTicks) != 0) return; IBlockState state = world.getBlockState(getPos()); - if (!(state.getBlock() instanceof RotatableBlock)) return; - // Face the block's "IO" side - EnumFacing facing = RotatableBlock.getFront(state).getOpposite(); + // Resolve front for either 6-way or legacy block + EnumFacing front = resolveFront(state); + EnumFacing facing = front.getOpposite(); // keep existing IO semantics TileEntity neighbor = world.getTileEntity(getPos().offset(facing)); - - // Must be a data handler and not another wireless transceiver (avoid loops) - if (!(neighbor instanceof IDataHandler) || (neighbor instanceof TileWirelessTransciever)) return; + if (neighbor == null || neighbor instanceof TileWirelessTransciever) return; + if (!(neighbor instanceof IDataHandler)) return; boolean changed = false; - for (DataStorage.DataType dataType : DataStorage.DataType.values()) { - if (dataType == DataStorage.DataType.UNDEFINED) continue; + for (DataType dataType : TYPES) { if (!extractMode) { // PUSH: from this buffer -> neighbor @@ -342,6 +404,7 @@ public void update() { } } + // Persist changes; a full block update isn't strictly required each tick if (changed) { this.markDirty(); @@ -353,25 +416,36 @@ public void update() { @Override public void onInventoryButtonPressed(int buttonId) { - if (buttonId == 1) + if (buttonId == 1) { enabled = toggleSwitch.getState(); - else if (buttonId == 0) + } else if (buttonId == 0) { extractMode = toggle.getState(); + updateToggleLabel(); + } PacketHandler.sendToServer(new PacketMachine(this, (byte) buttonId)); } - @Override public void stateUpdated(ModuleBase module) { - if (module == toggleSwitch) + if (module == toggleSwitch) { enabled = toggleSwitch.getState(); - else if (module == toggle) + } else if (module == toggle) { extractMode = toggle.getState(); + updateToggleLabel(); + } if (!world.isRemote) { this.markDirty(); world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); } } - + @Override + public void invalidate() { + // called when the TE is removed because the block changed/broke + if (!world.isRemote && NetworkRegistry.dataNetwork.doesNetworkExist(networkID)) { + NetworkRegistry.dataNetwork.getNetwork(networkID).removeFromAll(this); + } + super.invalidate(); + } + } From 07b5a209b8b7fd1186b5f7d66fb19839367dc7c7 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 20 Oct 2025 17:21:37 +0200 Subject: [PATCH 043/424] Refactor BlockTransciever for 6way placing Placing 6 ways! Also placement sticks to the face u are look at. ->Easier to place plugs without getting annoyed. --- .../block/BlockTransciever.java | 127 ++++++++++++++++-- 1 file changed, 117 insertions(+), 10 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java b/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java index 38b59d4b7..a3cedb36f 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java @@ -1,38 +1,145 @@ package zmaster587.advancedRocketry.block; +import javax.annotation.Nonnull; + +import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockRenderLayer; // <-- correct package +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraft.block.properties.PropertyDirection; // <-- correct package +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.libVulpes.block.BlockTile; public class BlockTransciever extends BlockTile { - private static final AxisAlignedBB[] bb = {new AxisAlignedBB(.25, .25, .75, .75, .75, 1), - new AxisAlignedBB(.25, .25, 0, .75, .75, 0.25), - new AxisAlignedBB(.75, .25, .25, 1, .75, .75), - new AxisAlignedBB(0, .25, .25, 0.25, .75, .75)}; + public static final PropertyDirection FACING = PropertyDirection.create("facing"); + + private static final AxisAlignedBB AABB_N = new AxisAlignedBB(.25, .25, 0.00, .75, .75, .25); + private static final AxisAlignedBB AABB_S = new AxisAlignedBB(.25, .25, .75, .75, .75, 1.00); + private static final AxisAlignedBB AABB_W = new AxisAlignedBB(0.00, .25, .25, .25, .75, .75); + private static final AxisAlignedBB AABB_E = new AxisAlignedBB(.75, .25, .25, 1.00, .75, .75); + private static final AxisAlignedBB AABB_U = new AxisAlignedBB(.25, .75, .25, .75, 1.00, .75); + private static final AxisAlignedBB AABB_D = new AxisAlignedBB(.25, 0.00, .25, .75, .25, .75); public BlockTransciever(Class tileClass, int guiId) { super(tileClass, guiId); + this.setDefaultState( + this.blockState.getBaseState() + .withProperty(STATE, Boolean.FALSE) + .withProperty(FACING, EnumFacing.NORTH) + ); + this.setHardness(3f); + this.setResistance(10f); + this.setLightOpacity(0); } @Override - public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, - BlockPos pos) { + public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos) { + EnumFacing f = state.getValue(FACING).getOpposite(); + switch (f) { + case NORTH: return AABB_N; + case SOUTH: return AABB_S; + case WEST: return AABB_W; + case EAST: return AABB_E; + case UP: return AABB_U; + case DOWN: return AABB_D; + default: return FULL_BLOCK_AABB; + } + } + @Override public boolean isFullCube(IBlockState state) { return false; } + @Override public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos) { return false; } + @Override public boolean isOpaqueCube(IBlockState state) { return false; } - return bb[state.getValue(FACING).ordinal() - 2]; + @SideOnly(Side.CLIENT) + @Override + @Nonnull + public BlockRenderLayer getBlockLayer() { + return BlockRenderLayer.CUTOUT_MIPPED; } + // If this still errors in your mappings, rename the method to: + // public BlockRenderLayer getRenderLayer() { return BlockRenderLayer.CUTOUT_MIPPED; } @Override - public boolean isFullCube(IBlockState state) { - return false; + protected BlockStateContainer createBlockState() { + return new BlockStateContainer(this, FACING, STATE); + } + + @Override + public int getMetaFromState(IBlockState state) { + int face = state.getValue(FACING).getIndex(); // 0..5 + boolean on = state.getValue(STATE); + return face | (on ? 8 : 0); + } + + @Override + public IBlockState getStateFromMeta(int meta) { + EnumFacing f = EnumFacing.getFront(meta & 7); + boolean on = (meta & 8) != 0; + return this.getDefaultState().withProperty(FACING, f).withProperty(STATE, on); + } + + @Override + public IBlockState getActualState(IBlockState state, IBlockAccess world, BlockPos pos) { + return state; + } + + @Override + @Nonnull + public IBlockState getStateForPlacement( + World world, BlockPos pos, EnumFacing clickedFace, + float hitX, float hitY, float hitZ, int meta, + EntityLivingBase placer, EnumHand hand) { + return this.getDefaultState() + .withProperty(FACING, clickedFace) + .withProperty(STATE, Boolean.FALSE); + } + + @Override + public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, + EntityLivingBase placer, @Nonnull ItemStack stack) { + // keep orientation from getStateForPlacement } @Override - public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos) { + public boolean rotateBlock(World world, BlockPos pos, EnumFacing axis) { + IBlockState s = world.getBlockState(pos); + EnumFacing cur = s.getValue(FACING); + EnumFacing next; + + switch (axis) { + case UP: + case DOWN: + next = (cur == EnumFacing.UP || cur == EnumFacing.DOWN) ? cur : cur.rotateY(); + break; + case NORTH: + case SOUTH: + case EAST: + case WEST: + next = (cur == EnumFacing.UP || cur == EnumFacing.DOWN) ? cur : cur.rotateY(); + break; + default: + next = cur; + } + + if (next != cur) { + world.setBlockState(pos, s.withProperty(FACING, next), 2); + return true; + } return false; } + + public static EnumFacing getFront(IBlockState state) { + if (state == null || !state.getPropertyKeys().contains(FACING)) return EnumFacing.NORTH; + return state.getValue(FACING); + } } From a11783907b980d0a22aa5d5eb562ba289f7a3610 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 20 Oct 2025 17:22:07 +0200 Subject: [PATCH 044/424] Fix import statements in BlockTransciever.java --- .../zmaster587/advancedRocketry/block/BlockTransciever.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java b/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java index a3cedb36f..a83b44248 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java @@ -7,14 +7,14 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.BlockRenderLayer; // <-- correct package +import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; -import net.minecraft.block.properties.PropertyDirection; // <-- correct package +import net.minecraft.block.properties.PropertyDirection; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.libVulpes.block.BlockTile; From 009be847f6209dfdfa4a6778ac6a911c9966e871 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Tue, 21 Oct 2025 08:04:23 +0200 Subject: [PATCH 045/424] Implement scroll caching for GUI module hopefully fixed for modspaghetti-ppl --- ...oduleContainerPanYOnlyWithScrollCache.java | 124 ++++++++++++++---- 1 file changed, 101 insertions(+), 23 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleContainerPanYOnlyWithScrollCache.java b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleContainerPanYOnlyWithScrollCache.java index 229933deb..f4368e04c 100644 --- a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleContainerPanYOnlyWithScrollCache.java +++ b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleContainerPanYOnlyWithScrollCache.java @@ -2,53 +2,131 @@ import zmaster587.libVulpes.inventory.modules.ModuleContainerPanYOnly; import zmaster587.libVulpes.inventory.modules.ModuleBase; + +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.util.ResourceLocation; -import java.util.concurrent.ConcurrentHashMap; -import java.util.Map; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + import java.util.List; +import java.util.concurrent.atomic.AtomicReference; public class ModuleContainerPanYOnlyWithScrollCache extends ModuleContainerPanYOnly { /** - * Scroll position cache for the observatory asteroid list. - * - One entry (per GUI layout) per client; cleared on new scan or scroll. - * - Minimal memory use (single Integer per layout). - * - Client-side only; no multiplayer or server impact. - * - Thread-safe for typical GUI use. - * - If reused, ensure cacheKey is unique per list type / GUI layout. + * Single global scroll position cache for the client. + * Stores one Integer (legal range [-containerSizeY, 0]) for the *most recently used* pane. + * Latest write always wins (old overwrites new; there is only one slot). */ + private static final AtomicReference GLOBAL_SCROLL = new AtomicReference<>(null); + + // Lazy, one-time restore (containerSizeY may not be final at ctor time) + private boolean didRestore = false; + private Integer pendingCachedPos = null; - // Cache: only stores latest scroll position per key - private static final Map scrollCache = new ConcurrentHashMap<>(); - private final String cacheKey; + // ===== Constructors ===== + public ModuleContainerPanYOnlyWithScrollCache( + int offsetX, int offsetY, + List moduleList, List staticModules, + ResourceLocation backdrop, + int screenSizeX, int screenSizeY, + int paddingX, int paddingY, + int containerSizeX, int containerSizeY + ) { + super(offsetX, offsetY, moduleList, staticModules, backdrop, screenSizeX, screenSizeY, + paddingX, paddingY, containerSizeX, containerSizeY); - public ModuleContainerPanYOnlyWithScrollCache(int offsetX, int offsetY, List moduleList, List staticModules, ResourceLocation backdrop, int screenSizeX, int screenSizeY, int paddingX, int paddingY, int containerSizeX, int containerSizeY) { - super(offsetX, offsetY, moduleList, staticModules, backdrop, screenSizeX, screenSizeY, paddingX, paddingY, containerSizeX, containerSizeY); + // Snapshot current global scroll to restore later (after layout stabilizes) + this.pendingCachedPos = GLOBAL_SCROLL.get(); + } + + // ===== Clamping & persistence ===== + private int clampScroll(int y) { + if (y > 0) return 0; + int min = -this.containerSizeY; + return (y < min) ? min : y; + } - // Create unique cache key - this.cacheKey = "observatory_asteroid_list:" + offsetX + ":" + offsetY + ":" + screenSizeX + ":" + screenSizeY; + private void saveScrollIfChanged() { + int y = clampScroll(super.getScrollY()); + Integer prev = GLOBAL_SCROLL.get(); + if (prev != null && prev.intValue() == y) return; // no write if unchanged + GLOBAL_SCROLL.set(y); // single slot: old key always overwritten by new write + } - // Restore scroll position if available - Integer cachedPos = scrollCache.get(cacheKey); - if (cachedPos != null) { - super.setOffset2(-cachedPos); + // One-time lazy restore when bounds should be final + @Override + @SideOnly(Side.CLIENT) + public void renderBackground(GuiContainer gui, int x, int y, int mouseX, int mouseY, FontRenderer font) { + if (!didRestore) { + if (pendingCachedPos != null) { + int clamped = clampScroll(pendingCachedPos); + // Base setOffset2 sets currentPosY = -y, so pass -clamped + super.setOffset2(-clamped); + } + didRestore = true; } + super.renderBackground(gui, x, y, mouseX, mouseY, font); } + // Capture all movement paths (wheel, drag, programmatic move, close) @Override protected void moveContainerInterior(int deltaY) { super.moveContainerInterior(deltaY); - scrollCache.put(cacheKey, super.getScrollY()); + saveScrollIfChanged(); } @Override public void onScroll(int dwheel) { super.onScroll(dwheel); - scrollCache.put(cacheKey, super.getScrollY()); + saveScrollIfChanged(); + } + + @Override + @SideOnly(Side.CLIENT) + public void onMouseClickedAndDragged(int x, int y, int button, long timeSinceLastClick) { + super.onMouseClickedAndDragged(x, y, button, timeSinceLastClick); + saveScrollIfChanged(); + } + + @Override + public void setEnabled(boolean state) { + if (!state && this.isEnabled()) { + // Persist on GUI disable/close + saveScrollIfChanged(); + } + super.setEnabled(state); + } + + // Persist programmatic jumps too + @Override + protected void setOffset2(int y) { + super.setOffset2(y); + saveScrollIfChanged(); + } + + // external centralized wheel dispatcher + @SideOnly(Side.CLIENT) + public void acceptExternalScroll(int dwheel, int mouseX, int mouseY) { + if (dwheel == 0 || !this.isEnabled()) return; + if (isMouseInBoundsForThis(mouseX, mouseY)) { + super.onScroll(dwheel); + saveScrollIfChanged(); + } + } + + // Corrected bounds check (local space; include edges) + private boolean isMouseInBoundsForThis(int mouseX, int mouseY) { + int localX = mouseX - this.offsetX; + int localY = mouseY - this.offsetY; + return localX >= 0 && localX < this.screenSizeX + && localY >= 0 && localY < this.screenSizeY; } - // Public method to clear cache (for new asteroid scans) + // ===== Cache management helpers ===== + /** Clear the single cached position (e.g., on new scan). */ public static void clearScrollCache() { - scrollCache.clear(); + GLOBAL_SCROLL.set(null); } } From a65205f30f6fd1bb405f5f56d53f50e57facfcad Mon Sep 17 00:00:00 2001 From: kaduvill Date: Tue, 21 Oct 2025 16:56:48 +0200 Subject: [PATCH 046/424] Mousewheel-scrolling asteroidlist part of fixing scrollreset. --- .../tile/multiblock/TileObservatory.java | 48 +++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java index 89f59d102..b20919e5e 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java @@ -383,36 +383,56 @@ public List getModules(int ID, EntityPlayer player) { int sizeX = 52; int sizeY = 46; if (world.isRemote) { - //Border + // Border for RIGHT composition pane (unchanged) modules.add(new ModuleScaledImage(baseX - 3, baseY - 3, 3, baseY + sizeY + 6, TextureResources.verticalBar)); modules.add(new ModuleScaledImage(baseX + sizeX, baseY - 3, -3, baseY + sizeY + 6, TextureResources.verticalBar)); modules.add(new ModuleScaledImage(baseX, baseY - 3, sizeX, 3, TextureResources.horizontalBar)); modules.add(new ModuleScaledImage(baseX, 2 * baseY + sizeY, sizeX, -3, TextureResources.horizontalBar)); } - ModuleContainerPanYOnly pan2 = new ModuleContainerPanYOnly(baseX, baseY, buttonList, new LinkedList<>(), null, 40, 48, 0, 0, 0, 72); - modules.add(pan2); - - //Add borders for asteroid - baseX = 5; - baseY = 32; - sizeX = 112; - sizeY = 46; + // Preserve RIGHT pane coords before reusing baseX/baseY for the LEFT pane + final int compX = baseX; + final int compY = baseY; + final int compScreenX = 40; // same as original + final int compScreenY = 48; // same as original + + // ---- LEFT pane (asteroid list) border + baseX = 5; + baseY = 32; + sizeX = 112; + sizeY = 46; if (world.isRemote) { - //Border + // Border for LEFT asteroid list modules.add(new ModuleScaledImage(baseX - 3, baseY - 3, 3, baseY + sizeY + 6, TextureResources.verticalBar)); modules.add(new ModuleScaledImage(baseX + sizeX, baseY - 3, -3, baseY + sizeY + 6, TextureResources.verticalBar)); modules.add(new ModuleScaledImage(baseX, baseY - 3, sizeX, 3, TextureResources.horizontalBar)); modules.add(new ModuleScaledImage(baseX, 2 * baseY + sizeY, sizeX, -3, TextureResources.horizontalBar)); } - //listing of asteroids with scrollcaching + // ---- LEFT asteroid list: wheel-enabled + cached if (lastSeed != -1) { - ModuleContainerPanYOnlyWithScrollCache pan = new ModuleContainerPanYOnlyWithScrollCache( - baseX, baseY, list2, new LinkedList<>(), null, sizeX - 2, sizeY, 0, -48, 0, 72); - modules.add(pan); + ModuleContainerPanYOnlyWithScrollCache panLeft = new ModuleContainerPanYOnlyWithScrollCache( + baseX, baseY, + list2, new LinkedList<>(), + null, + sizeX - 2, sizeY, // (screen width minus 2 like original) + 0, -48, // paddingX, paddingY + 0, 72 // containerSizeX, containerSizeY + ); + modules.add(panLeft); // LEFT FIRST to consume wheel } + // ---- RIGHT composition pane: parent class (drag-only; wheel will be 0 after left consumes it) + ModuleContainerPanYOnly panRight = new ModuleContainerPanYOnly( + compX, compY, + buttonList, new LinkedList<>(), + null, + compScreenX, compScreenY, + 0, 0, + 0, 72 + ); + modules.add(panRight); + } else if (tabModule.getTab() == 0) { modules.add(new ModulePower(18, 20, getBatteries())); From a69461ca442a4a83ce297142cf23b520e8595069 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Tue, 21 Oct 2025 16:58:07 +0200 Subject: [PATCH 047/424] Improve scroll caching and scroll asteroidlist with mousewheel. Refactor scroll position caching and event handling for better performance and memory management. --- ...oduleContainerPanYOnlyWithScrollCache.java | 255 ++++++++++++++---- 1 file changed, 202 insertions(+), 53 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleContainerPanYOnlyWithScrollCache.java b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleContainerPanYOnlyWithScrollCache.java index f4368e04c..5e5265475 100644 --- a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleContainerPanYOnlyWithScrollCache.java +++ b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleContainerPanYOnlyWithScrollCache.java @@ -3,29 +3,52 @@ import zmaster587.libVulpes.inventory.modules.ModuleContainerPanYOnly; import zmaster587.libVulpes.inventory.modules.ModuleBase; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import java.io.IOException; +import java.lang.ref.WeakReference; import java.util.List; -import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicInteger; public class ModuleContainerPanYOnlyWithScrollCache extends ModuleContainerPanYOnly { - /** - * Single global scroll position cache for the client. - * Stores one Integer (legal range [-containerSizeY, 0]) for the *most recently used* pane. - * Latest write always wins (old overwrites new; there is only one slot). - */ - private static final AtomicReference GLOBAL_SCROLL = new AtomicReference<>(null); + // ===== Single-slot global cache (latest write wins; no memory growth) ===== + private static final int NO_SCROLL = Integer.MIN_VALUE; + private static final AtomicInteger GLOBAL_SCROLL = new AtomicInteger(NO_SCROLL); - // Lazy, one-time restore (containerSizeY may not be final at ctor time) + // ===== Track live instances so the event handler can find "this" without editing GuiModular ===== + @SideOnly(Side.CLIENT) + private static final CopyOnWriteArrayList> LIVE = + new CopyOnWriteArrayList<>(); + + @SideOnly(Side.CLIENT) + private WeakReference lastGui = new WeakReference<>(null); + + @SideOnly(Side.CLIENT) + private static volatile boolean EVENT_REGISTERED = false; + + // >>> Store GUI origin captured during render to avoid touching protected xSize/ySize + @SideOnly(Side.CLIENT) + private volatile int lastGuiLeft = 0, lastGuiTop = 0; + + // ===== Instance state ===== + private int lastSavedY = NO_SCROLL; private boolean didRestore = false; - private Integer pendingCachedPos = null; - // ===== Constructors ===== + // Debounce to avoid micro-stutter under heavy input + private long lastSaveNs = 0L; + private static final long SAVE_INTERVAL_NS = 30_000_000L; // 30 ms + public ModuleContainerPanYOnlyWithScrollCache( int offsetX, int offsetY, List moduleList, List staticModules, @@ -34,99 +57,225 @@ public ModuleContainerPanYOnlyWithScrollCache( int paddingX, int paddingY, int containerSizeX, int containerSizeY ) { - super(offsetX, offsetY, moduleList, staticModules, backdrop, screenSizeX, screenSizeY, - paddingX, paddingY, containerSizeX, containerSizeY); + super(offsetX, offsetY, moduleList, staticModules, backdrop, + screenSizeX, screenSizeY, paddingX, paddingY, + containerSizeX, containerSizeY); - // Snapshot current global scroll to restore later (after layout stabilizes) - this.pendingCachedPos = GLOBAL_SCROLL.get(); + // Register this instance for event routing (client-side only) + if (Minecraft.getMinecraft() != null) { + LIVE.add(new WeakReference<>(this)); + maybeRegisterEventHandler(); + } } - // ===== Clamping & persistence ===== + // Ensure we don’t leak refs if the module gets disabled/detached + @Override + public void setEnabled(boolean state) { + if (!state && this.isEnabled()) { + saveScrollIfChangedForce(); // persist last position + } + super.setEnabled(state); + // Optional: prune dead refs occasionally + pruneDeadRefs(); + } + + // Clamp to base’s legal range [-containerSizeY, 0] private int clampScroll(int y) { if (y > 0) return 0; int min = -this.containerSizeY; return (y < min) ? min : y; } + // Debounced save after movement, skipping no-op writes globally and per-instance private void saveScrollIfChanged() { - int y = clampScroll(super.getScrollY()); - Integer prev = GLOBAL_SCROLL.get(); - if (prev != null && prev.intValue() == y) return; // no write if unchanged - GLOBAL_SCROLL.set(y); // single slot: old key always overwritten by new write + final int y = clampScroll(super.getScrollY()); + + // Per-instance no-op: if we already observed y, don't do anything. + if (y == lastSavedY) return; + + // Global no-op: if the global cache already holds y, skip the write, but + // update our lastSavedY so we don't keep re-checking. + final int global = GLOBAL_SCROLL.get(); + if (global == y) { + lastSavedY = y; + return; + } + + // Keep debounce to avoid bursts during fine-grained drags. + final long now = System.nanoTime(); + if (now - lastSaveNs < SAVE_INTERVAL_NS) { + lastSavedY = y; // remember the new y even if we didn't write globally yet + return; + } + + lastSaveNs = now; + lastSavedY = y; + + // Use lazySet for cheap release write, perfectly fine for a UI cache + GLOBAL_SCROLL.lazySet(y); + + // DEBUG + //System.out.println("[SCROLLER] save y=" + y); } - // One-time lazy restore when bounds should be final + + // Force save (bypass debounce) on close or disable, still skipping no-op + private void saveScrollIfChangedForce() { + final int y = clampScroll(super.getScrollY()); + + // If both our last and the global already equal y, it's a no-op + if (y == lastSavedY && GLOBAL_SCROLL.get() == y) return; + + lastSavedY = y; + lastSaveNs = System.nanoTime(); + + GLOBAL_SCROLL.lazySet(y); + + // DEBUG + //System.out.println("[SCROLLER] force-save y=" + y); + } + + // Restore once when bounds are stable @Override @SideOnly(Side.CLIENT) public void renderBackground(GuiContainer gui, int x, int y, int mouseX, int mouseY, FontRenderer font) { + // Remember the GUI we’re rendering in so the event handler can filter by current screen + this.lastGui = new WeakReference<>(gui); + + // >>> Capture guiLeft/guiTop from the parameters + this.lastGuiLeft = x; + this.lastGuiTop = y; + if (!didRestore) { - if (pendingCachedPos != null) { - int clamped = clampScroll(pendingCachedPos); - // Base setOffset2 sets currentPosY = -y, so pass -clamped - super.setOffset2(-clamped); + int v = GLOBAL_SCROLL.get(); + if (v != NO_SCROLL) { + int clamped = clampScroll(v); + super.setOffset2(-clamped); // base uses -y + lastSavedY = clamped; + //System.out.println("[SCROLLER] restore y=" + clamped); // DEBUG } didRestore = true; } super.renderBackground(gui, x, y, mouseX, mouseY, font); } - // Capture all movement paths (wheel, drag, programmatic move, close) + + @Override + @SideOnly(Side.CLIENT) + public void renderForeground(int guiOffsetX, int guiOffsetY, int mouseX, int mouseY, float zLevel, + GuiContainer gui, FontRenderer font) { + super.renderForeground(guiOffsetX, guiOffsetY, mouseX, mouseY, zLevel, gui, font); + } + + // Single save point for any movement @Override protected void moveContainerInterior(int deltaY) { super.moveContainerInterior(deltaY); saveScrollIfChanged(); } + // Base onScroll calls moveContainerInterior; don’t double-save here @Override public void onScroll(int dwheel) { super.onScroll(dwheel); - saveScrollIfChanged(); } @Override @SideOnly(Side.CLIENT) public void onMouseClickedAndDragged(int x, int y, int button, long timeSinceLastClick) { super.onMouseClickedAndDragged(x, y, button, timeSinceLastClick); - saveScrollIfChanged(); } - @Override - public void setEnabled(boolean state) { - if (!state && this.isEnabled()) { - // Persist on GUI disable/close - saveScrollIfChanged(); - } - super.setEnabled(state); + // Public clear (e.g., on new scan) + public static void clearScrollCache() { + GLOBAL_SCROLL.set(NO_SCROLL); + //System.out.println("[SCROLLER] clear cache"); // DEBUG } - // Persist programmatic jumps too - @Override - protected void setOffset2(int y) { - super.setOffset2(y); - saveScrollIfChanged(); + // ===== Event routing (client-side only) ===== + + @SideOnly(Side.CLIENT) + private static void maybeRegisterEventHandler() { + if (!EVENT_REGISTERED) { + MinecraftForge.EVENT_BUS.register(new WheelRouter()); + EVENT_REGISTERED = true; + } } - // external centralized wheel dispatcher @SideOnly(Side.CLIENT) - public void acceptExternalScroll(int dwheel, int mouseX, int mouseY) { - if (dwheel == 0 || !this.isEnabled()) return; - if (isMouseInBoundsForThis(mouseX, mouseY)) { - super.onScroll(dwheel); - saveScrollIfChanged(); + private static void pruneDeadRefs() { + for (WeakReference ref : LIVE) { + if (ref.get() == null) LIVE.remove(ref); } } - // Corrected bounds check (local space; include edges) - private boolean isMouseInBoundsForThis(int mouseX, int mouseY) { - int localX = mouseX - this.offsetX; - int localY = mouseY - this.offsetY; + @SideOnly(Side.CLIENT) + private boolean isMouseOverThis(int relX, int relY) { + // relX/relY are GUI-relative to (guiLeft, guiTop) + int localX = relX - this.offsetX; + int localY = relY - this.offsetY; return localX >= 0 && localX < this.screenSizeX && localY >= 0 && localY < this.screenSizeY; } - // ===== Cache management helpers ===== - /** Clear the single cached position (e.g., on new scan). */ - public static void clearScrollCache() { - GLOBAL_SCROLL.set(null); + @SideOnly(Side.CLIENT) + private boolean isOnThisGui(GuiScreen current) { + GuiContainer g = lastGui.get(); + return g != null && g == current; + } + + @SideOnly(Side.CLIENT) + private static class WheelRouter { + private static int lastTickDispatched = -1; + private static int lastScreenId = 0; + private static int lastWheelSign = 0; // -1/+1 + + @SubscribeEvent + public void onMouseInputPre(GuiScreenEvent.MouseInputEvent.Pre evt) throws IOException { + GuiScreen screen = evt.getGui(); + if (!(screen instanceof GuiContainer)) return; + + int d = org.lwjgl.input.Mouse.getEventDWheel(); + if (d == 0) return; + + Minecraft mc = Minecraft.getMinecraft(); + int tick = (mc.ingameGUI != null) ? mc.ingameGUI.getUpdateCounter() : 0; + int screenId = System.identityHashCode(screen); + int sign = Integer.signum(d); + + // Coalesce: same screen + same tick + same direction => treat as duplicate + if (tick == lastTickDispatched && screenId == lastScreenId && sign == lastWheelSign) { + evt.setCanceled(true); + return; + } + + int scaledW = screen.width, scaledH = screen.height; + int mouseX = org.lwjgl.input.Mouse.getX() * scaledW / mc.displayWidth; + int mouseY = scaledH - org.lwjgl.input.Mouse.getY() * scaledH / mc.displayHeight - 1; + + boolean handled = false; + for (int i = LIVE.size() - 1; i >= 0; i--) { + WeakReference ref = LIVE.get(i); + ModuleContainerPanYOnlyWithScrollCache mod = ref.get(); + if (mod == null) { LIVE.remove(i); continue; } + if (!mod.getVisible() || !mod.isEnabled()) continue; + if (!mod.isOnThisGui(screen)) continue; + + int relX = mouseX - mod.lastGuiLeft; + int relY = mouseY - mod.lastGuiTop; + if (!mod.isMouseOverThis(relX, relY)) continue; + + mod.onScroll(d); // will call moveContainerInterior -> save + handled = true; + break; + } + + if (handled) { + lastTickDispatched = tick; + lastScreenId = screenId; + lastWheelSign = sign; + evt.setCanceled(true); + } + } } } From 937fbfbbc1635a34db3584de03552e9965556467 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Tue, 21 Oct 2025 22:29:07 +0200 Subject: [PATCH 048/424] Tooltip for ItemAsteroidChip Unique names, and Type showing in tooltip --- .../item/ItemAsteroidChip.java | 46 +++++++++++++++---- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java b/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java index 4ecc42e2f..bddbf843e 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java @@ -66,24 +66,50 @@ public void setType(@Nonnull ItemStack stack, String type) { nbt.setString(astType, type); stack.setTagCompound(nbt); } + // SplitMix64 mixer: great diffusion, tiny cost + // Make Unique ID from UUID and type (looks random, but is deterministic) + // Only for tooltip display purposes. Actual NBT untouched. + private static long mix64(long z) { + z += 0x9E3779B97F4A7C15L; + z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L; + z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL; + return z ^ (z >>> 31); + } - @Override - public void addInformation(@Nonnull ItemStack stack, World player, List list, ITooltipFlag bool) { + // Deterministic display id from UUID and type (no world dependence) + private static long makeDisplayId(Long uuid, String type) { + long base = (uuid == null) ? 0L : uuid; + long th = (type == null) ? 0L : Integer.toUnsignedLong(type.hashCode()); + return mix64(base ^ (th << 1)); // fold in type so same UUID/different types look different + } + @Override + public void addInformation(@Nonnull ItemStack stack, World world, List list, ITooltipFlag flag) { if (!stack.hasTagCompound()) { list.add(LibVulpes.proxy.getLocalizedString("msg.unprogrammed")); - } else { - if (stack.getItemDamage() == 0) { + return; + } + if (stack.getItemDamage() == 0) { + Long id = getUUID(stack); + String type = getType(stack); + + if (type != null && !type.isEmpty()) { + list.add(LibVulpes.proxy.getLocalizedString("msg.asteroidChip.type") + ": " + + ChatFormatting.AQUA + type); + } - list.add(LibVulpes.proxy.getLocalizedString("msg.asteroidChip.asteroid") + "-" + ChatFormatting.DARK_GREEN + getUUID(stack)); + // Tooltip-only, random-looking but deterministic + final long disp = makeDisplayId(id, type); + final String hex = Long.toUnsignedString(disp, 16).toUpperCase(); - super.addInformation(stack, player, list, bool); + // Fixed-length visual tag (avoid lookalikes by using N=6 chars) + final int N = 6; + final String shortHex = (hex.length() > N) ? hex.substring(hex.length() - N) : hex; - //list.add("Mass: " + unknown); - //list.add("Atmosphere Density: " + unknown); - //list.add("Distance From Star: " + unknown); + list.add(LibVulpes.proxy.getLocalizedString("msg.asteroidChip.asteroid") + ": " + + ChatFormatting.DARK_GREEN + shortHex); - } + super.addInformation(stack, world, list, flag); } } From 791e540ba119fa31b46c746f56662a24a98ae25c Mon Sep 17 00:00:00 2001 From: kaduvill Date: Tue, 21 Oct 2025 22:41:32 +0200 Subject: [PATCH 049/424] Add new observatory and asteroid chip messages --- src/main/resources/assets/advancedrocketry/lang/en_US.lang | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index a1e234077..94ca254f1 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -287,6 +287,7 @@ msg.observetory.text.composition=Composition msg.observetory.text.processdiscovery=Process discovery msg.observetory.text.observabledistance=Observable distance: msg.observetory.text.missionTime=Mission Time: +msg.observetory.req.open=Observatory must be open (night, clear sky, sky access) or be in space! msg.tooltip.data=Data msg.tooltip.asteroidselection=Asteroid Selection msg.label.name=Name @@ -418,6 +419,7 @@ msg.rocketbuilder.alreadyassembled=Rocket already assembled msg.solar.collectingEnergy=Collecting Energy: msg.solar.cannotcollectEnergy=Unable to collect Energy msg.asteroidChip.asteroid=Asteroid +msg.asteroidChip.type=Type msg.atmanal.atmtype=Atmosphere Type: msg.atmanal.canbreathe=Breathable: msg.biomechanger.scan=Scan Biome From 4ca03d3bea0432aadd9cf00da431d4a115fd3a4c Mon Sep 17 00:00:00 2001 From: kaduvill Date: Tue, 21 Oct 2025 22:53:37 +0200 Subject: [PATCH 050/424] Dynamic Process button tooltip handling tell the player why button dont work if observatory is (!open) --- .../tile/multiblock/TileObservatory.java | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java index b20919e5e..0f3619525 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java @@ -303,8 +303,30 @@ public List getModules(int ID, EntityPlayer player) { modules.add(new ModuleTexturedSlotArray(5, 120, this, 1, 2, TextureResources.idChip)); modules.add(new ModuleOutputSlotArray(45, 120, this, 2, 3)); modules.add(new ModuleProgress(25, 120, 0, new ProgressBarImage(217, 0, 17, 17, 234, 0, EnumFacing.DOWN, TextureResources.progressBars), this)); - modules.add(new ModuleButton(25, 120, 1, "", this, zmaster587.libVulpes.inventory.TextureResources.buttonNull, LibVulpes.proxy.getLocalizedString("msg.observetory.text.processdiscovery"), 17, 17)); + + ModuleButton processBtn = new ModuleButton( + 25, 120, 1, "", + this, + zmaster587.libVulpes.inventory.TextureResources.buttonNull, + // default tooltip (will be replaced conditionally below) + LibVulpes.proxy.getLocalizedString("msg.observetory.text.processdiscovery"), + 17, 17 + ); + + // `isOpen` is synchronized to client via writeNetworkData/readNetworkData, so safe to read here. + if (!isOpen) { + // Show requirements when the dome isn't open (daytime, raining, no sky, etc.) + String tooltip = LibVulpes.proxy.getLocalizedString("msg.observetory.req.open"); + processBtn.setToolTipText(tooltip); + } else { + // Keep your normal tooltip when open + processBtn.setToolTipText(LibVulpes.proxy.getLocalizedString("msg.observetory.text.processdiscovery")); + } + + // Keep it enabled so the tooltip renders (ModuleButton.isMouseOver checks enabled) + processBtn.setEnabled(true); + modules.add(processBtn); ModuleButton scanButton = new ModuleButton(100, 120, 2, LibVulpes.proxy.getLocalizedString("msg.observetory.scan.button"), this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild, LibVulpes.proxy.getLocalizedString("msg.observetory.scan.tooltip"), 64, 18); @@ -549,7 +571,7 @@ else if (id == PROCESS_CHIP && !world.isRemote) { if (inv.getStackInSlot(2).isEmpty() && isOpen && hasEnergy(500) && lastButton != -1) { ItemStack stack = inv.decrStackSize(1, 1); if (stack != ItemStack.EMPTY && stack.getItem() instanceof ItemAsteroidChip) { - ((ItemAsteroidChip) (stack.getItem())).setUUID(stack, lastSeed); + ((ItemAsteroidChip) (stack.getItem())).setUUID(stack, lastSeed + lastButton); ((ItemAsteroidChip) (stack.getItem())).setType(stack, lastType); ((ItemAsteroidChip) (stack.getItem())).setMaxData(stack, 1000); inv.setInventorySlotContents(2, stack); From 8dde7e417a14c3bf5981284c43203cade4023713 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 24 Oct 2025 15:27:47 +0200 Subject: [PATCH 051/424] Update RenderAsteroidSky.java Fixed: crossmod compat: Leaky GLstates broke entityculling e.g. Also made Asteroids glow if they are infront of a sun, and pushed them behind Disks. --- .../render/planet/RenderAsteroidSky.java | 551 ++++++++---------- 1 file changed, 244 insertions(+), 307 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderAsteroidSky.java b/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderAsteroidSky.java index 75bac2b36..ba7c44ef2 100644 --- a/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderAsteroidSky.java +++ b/src/main/java/zmaster587/advancedRocketry/client/render/planet/RenderAsteroidSky.java @@ -5,7 +5,6 @@ import net.minecraft.client.renderer.*; import net.minecraft.client.renderer.GlStateManager.DestFactor; import net.minecraft.client.renderer.GlStateManager.SourceFactor; -import net.minecraft.client.renderer.entity.Render; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; @@ -19,54 +18,70 @@ import zmaster587.advancedRocketry.api.dimension.solar.StellarBody; import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.advancedRocketry.dimension.DimensionProperties; -import zmaster587.advancedRocketry.event.RocketEventHandler; import zmaster587.advancedRocketry.inventory.TextureResources; import zmaster587.advancedRocketry.stations.SpaceObjectManager; import zmaster587.advancedRocketry.stations.SpaceStationObject; import zmaster587.advancedRocketry.util.AstronomicalBodyHelper; import zmaster587.libVulpes.util.Vector3F; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; import java.util.Random; public class RenderAsteroidSky extends IRenderHandler { - + // === Textures === public static final ResourceLocation asteroid1 = new ResourceLocation("advancedRocketry:textures/planets/asteroid_a.png"); public static final ResourceLocation asteroid2 = new ResourceLocation("advancedRocketry:textures/planets/asteroid_b.png"); public static final ResourceLocation asteroid3 = new ResourceLocation("advancedRocketry:textures/planets/asteroid_c.png"); - ResourceLocation currentlyBoundTex = null; - float celestialAngle; - Vector3F axis; - Minecraft mc = Minecraft.getMinecraft(); - private int starGLCallList; - private int glSkyList; - private int glSkyList2; - private int glSkyList3; - - //Mostly vanilla code - //TODO: make usable on other planets + + // Per-frame texture bind cache (local to this renderer) + private ResourceLocation boundTex = null; + + // Runtime / state + private float celestialAngle; + private final Vector3F axis; + private final Minecraft mc = Minecraft.getMinecraft(); + + // Display lists + private final int starGLCallList; + private final int glSkyList; + private final int glSkyList2; + private final int glSkyList3; + + // Reused scratch buffers to reduce GC + private final List childrenBuf = new ArrayList<>(8); + private final float[] shadowColorTmp = new float[3]; + + // Helpers for ring/black-hole math + private static float xrotangle = 0; // for ring rotation (kept exactly as before) + private static final float[] skycolor = {0,0,0}; // for black hole rendering (same usage as before) + private static double currentplanetphi = 0; // ring/disk angle (same) + + // === ctor === public RenderAsteroidSky() { axis = new Vector3F<>(1f, 0f, 0f); + // Build display lists once (same seeds/geometry as original) this.starGLCallList = GLAllocation.generateDisplayLists(4); + GL11.glPushMatrix(); GL11.glNewList(this.starGLCallList, GL11.GL_COMPILE); - this.renderStars(); + this.renderStars(); // stars list GL11.glEndList(); GL11.glPopMatrix(); + BufferBuilder buffer = Tessellator.getInstance().getBuffer(); + + // Sky dome slice 1 this.glSkyList = this.starGLCallList + 1; GL11.glNewList(this.glSkyList, GL11.GL_COMPILE); byte b2 = 64; int i = 256 / b2 + 2; float f = 16.0F; - int j; - int k; - for (j = -b2 * i; j <= b2 * i; j += b2) { - for (k = -b2 * i; k <= b2 * i; k += b2) { + for (int j = -b2 * i; j <= b2 * i; j += b2) { + for (int k = -b2 * i; k <= b2 * i; k += b2) { buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION); buffer.pos(j, f, k).endVertex(); buffer.pos(j + b2, f, k).endVertex(); @@ -75,35 +90,43 @@ public RenderAsteroidSky() { Tessellator.getInstance().draw(); } } - GL11.glEndList(); + + // Sky dome slice 2 this.glSkyList2 = this.starGLCallList + 2; GL11.glNewList(this.glSkyList2, GL11.GL_COMPILE); f = -16.0F; buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION); - - for (j = -b2 * i; j <= b2 * i; j += b2) { - for (k = -b2 * i; k <= b2 * i; k += b2) { + for (int j = -b2 * i; j <= b2 * i; j += b2) { + for (int k = -b2 * i; k <= b2 * i; k += b2) { buffer.pos(j, f, k).endVertex(); buffer.pos(j + b2, f, k).endVertex(); buffer.pos(j + b2, f, k + b2).endVertex(); buffer.pos(j, f, k + b2).endVertex(); } } - Tessellator.getInstance().draw(); GL11.glEndList(); + // Asteroids list this.glSkyList3 = this.starGLCallList + 3; GL11.glPushMatrix(); GL11.glNewList(this.glSkyList3, GL11.GL_COMPILE); - renderAsteroids(); + renderAsteroids(); // geometry baked with fixed seed matching original GL11.glEndList(); GL11.glPopMatrix(); } + // Efficient texture binder (skip redundant binds per frame) + private void bind(ResourceLocation tex) { + if (tex != null && tex != boundTex) { + mc.renderEngine.bindTexture(tex); + boundTex = tex; + } + } + private void renderAsteroids() { - Random random = new Random(10843L); + Random random = new Random(10843L); // same seed => identical layout to original BufferBuilder buffer = Tessellator.getInstance().getBuffer(); buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR); @@ -132,10 +155,9 @@ private void renderAsteroids() { double d15 = Math.sin(d14); double d16 = Math.cos(d14); - float r, g, b; - r = random.nextFloat() * 0.05f + .95f; - g = random.nextFloat() * 0.1f + .9f; - b = random.nextFloat() * 0.1f + .9f; + float r = random.nextFloat() * 0.05f + .95f; + float g = random.nextFloat() * 0.1f + .9f; + float b = random.nextFloat() * 0.1f + .9f; for (int j = 0; j < 4; ++j) { double d17 = 0.0D; @@ -151,13 +173,11 @@ private void renderAsteroids() { } } } - Tessellator.getInstance().draw(); - //buffer.finishDrawing(); } private void renderStars() { - Random random = new Random(10842L); + Random random = new Random(10842L); // same seed => identical layout to original BufferBuilder buffer = Tessellator.getInstance().getBuffer(); buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION); @@ -200,50 +220,38 @@ private void renderStars() { } } } - Tessellator.getInstance().draw(); - //buffer.finishDrawing(); } - private static float xrotangle = 0; // used for ring rotation because I don't want to bother changing the definitions of methods. - private static float[] skycolor = {0,0,0}; // used for black hole rendering - same reason as above - private static double currentplanetphi = 0; // used for calculating ring/disk angle - @Override public void render(float partialTicks, WorldClient world, Minecraft mc) { + // per-frame texture bind cache reset + boundTex = null; - - //TODO: properly handle this + // === Gather properties (unchanged logic) === float atmosphere; int solarOrbitalDistance, planetOrbitalDistance = 0; double myPhi = 0, myTheta = 0, myPrevOrbitalTheta = 0, myRotationalPhi = 0; - boolean hasAtmosphere = false, isMoon; - float[] shadowColorMultiplier = {0f, 0f, 0f}; - float[] parentAtmColor = new float[]{1f, 1f, 1f}; + boolean isMoon; + // shadowColorTmp reused; values set below float[] parentRingColor = new float[]{1f, 1f, 1f}; float[] ringColor = new float[]{1f, 1f, 1f}; float sunSize = 1.0f; - float starSeparation = 0f; boolean isWarp = false; - boolean isGasGiant = false; boolean hasRings = false; - boolean parentPlanetHasDecorator = true; boolean parentHasRings = false; boolean parentHasATM = false; DimensionProperties parentProperties = null; DimensionProperties properties; EnumFacing travelDirection = null; - ResourceLocation parentPlanetIcon = null; List children; StellarBody primaryStar; celestialAngle = mc.world.getCelestialAngle(partialTicks); Vec3d sunColor; - if (mc.world.provider instanceof IPlanetaryProvider) { IPlanetaryProvider planetaryProvider = (IPlanetaryProvider) mc.world.provider; - properties = (DimensionProperties) planetaryProvider.getDimensionProperties(mc.player.getPosition()); atmosphere = planetaryProvider.getAtmosphereDensityFromHeight(mc.getRenderViewEntity().posY, mc.player.getPosition()); @@ -259,15 +267,16 @@ public void render(float partialTicks, WorldClient world, Minecraft mc) { hasRings = properties.hasRings(); ringColor = properties.ringColor; - children = new LinkedList<>(); + childrenBuf.clear(); for (Integer i : properties.getChildPlanets()) { - children.add(DimensionManager.getInstance().getDimensionProperties(i)); + childrenBuf.add(DimensionManager.getInstance().getDimensionProperties(i)); } + children = childrenBuf; solarOrbitalDistance = properties.getSolarOrbitalDistance(); - - if (isMoon = properties.isMoon()) { + isMoon = properties.isMoon(); + if (isMoon) { parentProperties = properties.getParentProperties(); planetOrbitalDistance = properties.getParentOrbitalDistance(); parentHasRings = parentProperties.hasRings; @@ -277,22 +286,22 @@ public void render(float partialTicks, WorldClient world, Minecraft mc) { sunColor = planetaryProvider.getSunColor(mc.player.getPosition()); primaryStar = properties.getStar(); if (primaryStar != null) { - sunSize = properties.getStar().getSize(); - } else + sunSize = primaryStar.getSize(); + } else { primaryStar = DimensionManager.getInstance().getStar(0); + } + if (world.provider.getDimension() == ARConfiguration.getCurrentConfig().spaceDimId) { isWarp = properties.getParentPlanet() == SpaceObjectManager.WARPDIMID; if (isWarp) { SpaceStationObject station = (SpaceStationObject) SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(mc.player.getPosition()); - travelDirection = station.getForwardDirection(); + if (station != null) travelDirection = station.getForwardDirection(); } } - } - else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.getDimension())) { - + } else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.getDimension())) { properties = DimensionManager.getInstance().getDimensionProperties(mc.world.provider.getDimension()); - atmosphere = properties.getAtmosphereDensityAtHeight(mc.getRenderViewEntity().posY);//planetaryProvider.getAtmosphereDensityFromHeight(mc.getRenderViewEntity().posY, mc.player.getPosition()); + atmosphere = properties.getAtmosphereDensityAtHeight(mc.getRenderViewEntity().posY); EnumFacing dir = getRotationAxis(properties, mc.player.getPosition()); axis.x = (float) dir.getFrontOffsetX(); axis.y = (float) dir.getFrontOffsetY(); @@ -305,15 +314,16 @@ else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.get hasRings = properties.hasRings(); ringColor = properties.ringColor; - children = new LinkedList<>(); + childrenBuf.clear(); for (Integer i : properties.getChildPlanets()) { - children.add(DimensionManager.getInstance().getDimensionProperties(i)); + childrenBuf.add(DimensionManager.getInstance().getDimensionProperties(i)); } + children = childrenBuf; solarOrbitalDistance = properties.getSolarOrbitalDistance(); - - if (isMoon = properties.isMoon()) { + isMoon = properties.isMoon(); + if (isMoon) { parentProperties = properties.getParentProperties(); planetOrbitalDistance = properties.getParentOrbitalDistance(); parentHasRings = parentProperties.hasRings; @@ -322,22 +332,25 @@ else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.get } float[] sunColorFloat = properties.getSunColor(); - sunColor = new Vec3d(sunColorFloat[0], sunColorFloat[1], sunColorFloat[2]);//planetaryProvider.getSunColor(mc.player.getPosition()); + sunColor = new Vec3d(sunColorFloat[0], sunColorFloat[1], sunColorFloat[2]); primaryStar = properties.getStar(); if (primaryStar != null) { - sunSize = properties.getStar().getSize(); - } else + sunSize = primaryStar.getSize(); + } else { primaryStar = DimensionManager.getInstance().getStar(0); + } + if (world.provider.getDimension() == ARConfiguration.getCurrentConfig().spaceDimId) { isWarp = properties.getParentPlanet() == SpaceObjectManager.WARPDIMID; if (isWarp) { SpaceStationObject station = (SpaceStationObject) SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(mc.player.getPosition()); - travelDirection = station.getForwardDirection(); + if (station != null) travelDirection = station.getForwardDirection(); } } - } - else { - children = new LinkedList<>(); + } else { + // No planet provider and dimension not registered: fall back to overworld props (exactly as before) + childrenBuf.clear(); + children = childrenBuf; isMoon = false; atmosphere = DimensionManager.overworldProperties.getAtmosphereDensityAtHeight(mc.getRenderViewEntity().posY); solarOrbitalDistance = DimensionManager.overworldProperties.orbitalDist; @@ -348,6 +361,7 @@ else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.get currentplanetphi = myPhi; + // === Sky color & base dome === GlStateManager.disableTexture2D(); Vec3d vec3 = Minecraft.getMinecraft().world.getSkyColor(this.mc.getRenderViewEntity(), partialTicks); float f1 = (float) vec3.x; @@ -359,23 +373,17 @@ else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.get float f4 = (f1 * 30.0F + f2 * 59.0F + f3 * 11.0F) / 100.0F; float f5 = (f1 * 30.0F + f2 * 70.0F) / 100.0F; f6 = (f1 * 30.0F + f3 * 70.0F) / 100.0F; - f1 = f4; - f2 = f5; - f3 = f6; + f1 = f4; f2 = f5; f3 = f6; } - //Simulate atmospheric thickness, vaugely - //This is done like this to prevent problems with superbright atmospheres on low-atmosphere planets - //Plus you couldn't see stars during the day anyway + // Atmospheric brightness shaping (unchanged) int atmosphereInt = properties.getAtmosphereDensity(); -// System.out.println("before:"+f1+":"+f2+":"+f3); f1 = atmosphereInt < 1 ? 0 : (float) Math.pow(f1, Math.sqrt(Math.max(atmosphere, 0.0001))); f2 = atmosphereInt < 1 ? 0 : (float) Math.pow(f2, Math.sqrt(Math.max(atmosphere, 0.0001))); f3 = atmosphereInt < 1 ? 0 : (float) Math.pow(f3, Math.sqrt(Math.max(atmosphere, 0.0001))); - - f1*=Math.min(1,atmosphere); - f2*=Math.min(1,atmosphere); - f3*=Math.min(1,atmosphere); + f1 *= Math.min(1, atmosphere); + f2 *= Math.min(1, atmosphere); + f3 *= Math.min(1, atmosphere); skycolor[0] = f1; skycolor[1] = f2; @@ -391,12 +399,10 @@ else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.get GL11.glCallList(this.glSkyList); GlStateManager.disableFog(); GlStateManager.disableAlpha(); - RenderHelper.disableStandardItemLighting(); + net.minecraft.client.renderer.RenderHelper.disableStandardItemLighting(); + float[] afloat = mc.world.provider.calcSunriseSunsetColors(celestialAngle, partialTicks); - float f7; - float f8; - float f9; - float f10; + float f7, f8, f9, f10; if (afloat != null) { GlStateManager.disableTexture2D(); @@ -406,7 +412,6 @@ else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.get GL11.glRotatef(MathHelper.sin(mc.world.getCelestialAngleRadians(partialTicks)) < 0.0F ? 180.0F : 0.0F, 0.0F, 0.0F, 1.0F); GL11.glRotated(90.0F - myRotationalPhi, 0.0F, 0.0F, 1.0F); - //Sim atmospheric thickness f6 = afloat[0]; f7 = afloat[1]; f8 = afloat[2]; @@ -416,9 +421,7 @@ else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.get f9 = (f6 * 30.0F + f7 * 59.0F + f8 * 11.0F) / 100.0F; f10 = (f6 * 30.0F + f7 * 70.0F) / 100.0F; f11 = (f6 * 30.0F + f8 * 70.0F) / 100.0F; - f6 = f9; - f7 = f10; - f8 = f11; + f6 = f9; f7 = f10; f8 = f11; } buffer.begin(GL11.GL_TRIANGLE_FAN, DefaultVertexFormats.POSITION_COLOR); @@ -427,50 +430,49 @@ else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.get for (int j = 0; j <= b0; ++j) { f11 = (float) j * (float) Math.PI * 2.0F / (float) b0; - float f12 = MathHelper.sin(f11); - float f13 = MathHelper.cos(f11); - buffer.pos(f12 * 120.0F, f13 * 120.0F, -f13 * 40.0F * afloat[3]).color(afloat[0], afloat[1], afloat[2], 0.0F).endVertex(); + float sx = MathHelper.sin(f11); + float cx = MathHelper.cos(f11); + buffer.pos(sx * 120.0F, cx * 120.0F, -cx * 40.0F * afloat[3]).color(afloat[0], afloat[1], afloat[2], 0.0F).endVertex(); } - Tessellator.getInstance().draw(); GL11.glPopMatrix(); GlStateManager.shadeModel(GL11.GL_FLAT); } - shadowColorMultiplier = new float[]{f1, f2, f3}; + + // shadow color multiplier (reused array) + shadowColorTmp[0] = f1; + shadowColorTmp[1] = f2; + shadowColorTmp[2] = f3; GlStateManager.enableTexture2D(); GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE); GL11.glPushMatrix(); + // rain alpha handling + if (atmosphere > 0) f6 = 1.0F - (mc.world.getRainStrength(partialTicks) * (atmosphere / 100f)); + else f6 = 1f; - if (atmosphere > 0) - f6 = 1.0F - (mc.world.getRainStrength(partialTicks) * (atmosphere / 100f)); - else - f6 = 1f; - - f7 = 0.0F; - f8 = 0.0F; - f9 = 0.0F; + f7 = 0.0F; f8 = 0.0F; f9 = 0.0F; GlStateManager.color(1.0F, 1.0F, 1.0F, f6); GL11.glTranslatef(f7, f8, f9); GL11.glRotatef(-90.0F, 0.0F, 1.0F, 0.0F); - float multiplier = (2 - atmosphere) / 2f;//atmosphere > 1 ? (2-atmosphere) : 1f; - if (mc.world.isRainingAt(mc.player.getPosition().add(0, 199, 0))) + float multiplier = (2 - atmosphere) / 2f; + if (mc.world.isRainingAt(mc.player.getPosition().add(0, 199, 0))) { multiplier *= 1 - mc.world.getRainStrength(partialTicks); + } GL11.glRotatef((float) myRotationalPhi, 0f, 1f, 0f); - //Draw Rings + // Rings (unchanged visuals) if (hasRings) { GL11.glPushMatrix(); GL11.glRotatef(90f, 0f, 1f, 0f); f10 = 100; double ringDist = 0; - //mc.renderEngine.bindTexture(DimensionProperties.planetRings); - mc.renderEngine.bindTexture(DimensionProperties.planetRingsNew); + bind(DimensionProperties.planetRingsNew); GL11.glRotated(70, 1, 0, 0); GL11.glTranslated(0, -10, 0); @@ -484,148 +486,120 @@ else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.get Tessellator.getInstance().draw(); GL11.glPopMatrix(); - /* - GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA); - GL11.glPushMatrix(); - - GL11.glRotatef(90f, 0f, 1f, 0f); - GL11.glRotated(70, 1, 0, 0); - GL11.glRotatef(isWarp ? 0 : celestialAngle * 360.0F, 0, 1, 0); - GL11.glTranslated(0, -10, 0); - - mc.renderEngine.bindTexture(DimensionProperties.planetRingShadow); - GlStateManager.color(0f, 0f, 0f, multiplier); - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - buffer.pos(f10, ringDist, -f10).tex(1.0D, 0.0D).endVertex(); - buffer.pos(-f10, ringDist, -f10).tex(0.0D, 0.0D).endVertex(); - buffer.pos(-f10, ringDist, f10).tex(0.0D, 1.0D).endVertex(); - buffer.pos(f10, ringDist, f10).tex(1.0D, 1.0D).endVertex(); - Tessellator.getInstance().draw(); - GL11.glPopMatrix(); - */ - + // (Shadowed ring quad code left as in original) GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE); } GlStateManager.disableTexture2D(); - //This determines whether stars should come out regardless of thickness of atmosphere, as that is factored in later - // - it checks if the colors of the sky are so close to black that you'd see stars, or if the atmosphere is zero and so no one gives a damn - float f18 = mc.world.getStarBrightness(partialTicks) * f6;//((atmosphere == 0 || (f1 < 0.09 && f2 < 0.09 && f3 < 0.09)) ? 1 : 0);// - (atmosphere > 1 ? atmosphere - 1 : 0); + // Stars + float f18 = mc.world.getStarBrightness(partialTicks) * f6; + float starAlpha = 1 - ((1 - f18) * atmosphere); - float starAlpha = 1-((1-f18)*atmosphere); - //System.out.println(starAlpha+":"+f18+":"+atmosphere); + GlStateManager.disableDepth(); // stars always on top of sky Keep? makes asteroids glow :D - //if (f18 > 0.0F) { - if (true){ - GlStateManager.color(1, 1, 1, 1); - GL11.glPushMatrix(); - if (isWarp) { - for (int i = -3; i < 5; i++) { - GL11.glPushMatrix(); - double magnitude = i * -100 + (((System.currentTimeMillis()) + 50) % 2000) / 20f; - GL11.glTranslated(-travelDirection.getFrontOffsetZ() * magnitude, 0, travelDirection.getFrontOffsetX() * magnitude); - GL11.glCallList(this.starGLCallList); - GL11.glPopMatrix(); - } - //GL11.glTranslated(((System.currentTimeMillis()/10) + 50) % 100, 0, 0); - - } else { - GL11.glColor4f(1,1,1,starAlpha); + GlStateManager.color(1, 1, 1, 1); + GL11.glPushMatrix(); + if (isWarp && travelDirection != null) { + for (int n = -3; n < 5; n++) { + GL11.glPushMatrix(); + double magnitude = n * -100 + (((System.currentTimeMillis()) + 50) % 2000) / 20f; + GL11.glTranslated(-travelDirection.getFrontOffsetZ() * magnitude, 0, travelDirection.getFrontOffsetX() * magnitude); GL11.glCallList(this.starGLCallList); - //Extra stars for low ATM - if (atmosphere < 0.5) { - GL11.glColor4f(1,1,1,starAlpha/2); - GL11.glPushMatrix(); - GL11.glRotatef(-90, 0, 1, 0); - GL11.glCallList(this.starGLCallList); - GL11.glPopMatrix(); - } - if (atmosphere < 0.25) { - GL11.glColor4f(1,1,1,starAlpha/4); - GL11.glPushMatrix(); - GL11.glRotatef(90, 0, 1, 0); - GL11.glCallList(this.starGLCallList); - GL11.glPopMatrix(); - } - GlStateManager.color(1, 1, 1, 1); + GL11.glPopMatrix(); + } + } else { + GL11.glColor4f(1, 1, 1, starAlpha); + GL11.glCallList(this.starGLCallList); + if (atmosphere < 0.5f) { + GL11.glColor4f(1, 1, 1, starAlpha / 2f); + GL11.glPushMatrix(); + GL11.glRotatef(-90, 0, 1, 0); + GL11.glCallList(this.starGLCallList); + GL11.glPopMatrix(); } - GL11.glPopMatrix(); + if (atmosphere < 0.25f) { + GL11.glColor4f(1, 1, 1, starAlpha / 4f); + GL11.glPushMatrix(); + GL11.glRotatef(90, 0, 1, 0); + GL11.glCallList(this.starGLCallList); + GL11.glPopMatrix(); + } + GlStateManager.color(1, 1, 1, 1); } + GL11.glPopMatrix(); + GlStateManager.enableTexture2D(); + GlStateManager.enableDepth(); // keep? - mc.renderEngine.bindTexture(TextureResources.locationSunPng); + // Sun & sub-stars + bind(TextureResources.locationSunPng); - //--------------------------- Draw the suns -------------------- if (!isWarp) { if (parentProperties == null || !parentProperties.isStar()) { - xrotangle = ((float) (properties.getSolarTheta() * 180f / Math.PI) % 360f); // for black hole disk - //System.out.println(xrotangle+":"+properties.getSolarTheta()); + xrotangle = ((float) (properties.getSolarTheta() * 180f / Math.PI) % 360f); // used in black hole path drawStarAndSubStars(buffer, primaryStar, properties, solarOrbitalDistance, sunSize, sunColor, multiplier); xrotangle = 0; } } + // Moons/parent planets (unchanged logic) + if (DimensionProperties.AtmosphereTypes.SUPERHIGHPRESSURE.denserThan( + DimensionProperties.AtmosphereTypes.getAtmosphereTypeFromValue((int) (100 * atmosphere)))) { - //For these parts only render if the atmosphere is below a certain threshold (SHP atmosphere) - if (DimensionProperties.AtmosphereTypes.SUPERHIGHPRESSURE.denserThan(DimensionProperties.AtmosphereTypes.getAtmosphereTypeFromValue((int) (100 * atmosphere)))) { - //Render the parent planet - if (isMoon) { + if (isMoon && parentProperties != null) { GL11.glPushMatrix(); - //Do a whole lotta math to figure out where the parent planet is supposed to be - //That 0.3054325f is there because we need to do adjustments for some ^$%^$% reason and it's consistently off by 17.5 degrees - float planetPositionTheta = AstronomicalBodyHelper.getParentPlanetThetaFromMoon(properties.rotationalPeriod, properties.orbitalDist, parentProperties.gravitationalMultiplier, myTheta, properties.baseOrbitTheta); + float planetPositionTheta = AstronomicalBodyHelper.getParentPlanetThetaFromMoon( + properties.rotationalPeriod, properties.orbitalDist, parentProperties.gravitationalMultiplier, + myTheta, properties.baseOrbitTheta); GL11.glRotatef((float) myPhi, 0f, 0f, 1f); GL11.glRotatef(planetPositionTheta, 1f, 0f, 0f); - float phiAngle = (float) ((myPhi) * Math.PI / 180f); - - //Close enough approximation, I missed something but seems to off by no more than 30* - //Nobody will look + float phiAngle = (float) (myPhi * Math.PI / 180f); double x = MathHelper.sin(phiAngle) * MathHelper.cos((float) myTheta); double y = -MathHelper.sin((float) myTheta); double rotation = -Math.PI / 2f + Math.atan2(x, y) - (myTheta - Math.PI) * MathHelper.sin(phiAngle); if (parentHasRings) { - //Semihacky rotation stuff to keep rings synced to a different rotation than planet in the sky xrotangle = -planetPositionTheta + ((float) (myTheta * 180f / Math.PI) % 360f); - //System.out.println("r:"+xrotangle); } - shadowColorMultiplier = new float[]{f1, f2, f3}; + shadowColorTmp[0] = f1; + shadowColorTmp[1] = f2; + shadowColorTmp[2] = f3; - //System.out.println("draw moon (renderplanet"); - renderPlanet(buffer, parentProperties, planetOrbitalDistance, multiplier, rotation, false, parentHasRings, (float) Math.pow(parentProperties.getGravitationalMultiplier(), 0.4), shadowColorMultiplier, 1); + renderPlanet(buffer, parentProperties, planetOrbitalDistance, multiplier, rotation, false, parentHasRings, + (float) Math.pow(parentProperties.getGravitationalMultiplier(), 0.4), shadowColorTmp, 1); xrotangle = 0; GL11.glPopMatrix(); } - //This needs to exist specifically for init purposes - //The overworld literally breaks without it - shadowColorMultiplier[0] = 1.000001f * shadowColorMultiplier[0]; + // init quirk kept as-is + shadowColorTmp[0] = 1.000001f * shadowColorTmp[0]; for (DimensionProperties moons : children) { GL11.glPushMatrix(); float planetPositionTheta = (float) ((partialTicks * moons.orbitTheta + ((1 - partialTicks) * moons.prevOrbitalTheta)) * 180F / Math.PI); - float flippedPlanetPositionTheta = 360 - planetPositionTheta; GL11.glRotatef((float) moons.orbitalPhi, 0f, 0f, 1f); GL11.glRotated(planetPositionTheta, 1f, 0f, 0f); - //Close enough approximation, I missed something but seems to off by no more than 30* - //Nobody will look - float phiAngle = (float) ((moons.orbitalPhi) * Math.PI / 180f); + float phiAngle = (float) (moons.orbitalPhi * Math.PI / 180f); double x = -MathHelper.sin(phiAngle) * MathHelper.cos((float) moons.orbitTheta); double y = MathHelper.sin((float) moons.orbitTheta); double rotation = (-Math.PI / 2f + Math.atan2(x, y) - (moons.orbitTheta - Math.PI) * MathHelper.sin(phiAngle)) + Math.PI; - shadowColorMultiplier = new float[]{f1, f2, f3}; - renderPlanet(buffer, moons, moons.getParentOrbitalDistance(), multiplier, rotation, moons.hasAtmosphere(), moons.hasRings, (float) Math.pow(moons.gravitationalMultiplier, 0.4), shadowColorMultiplier, 1); + shadowColorTmp[0] = f1; + shadowColorTmp[1] = f2; + shadowColorTmp[2] = f3; + + renderPlanet(buffer, moons, moons.getParentOrbitalDistance(), multiplier, rotation, moons.hasAtmosphere(), + moons.hasRings, (float) Math.pow(moons.gravitationalMultiplier, 0.4), shadowColorTmp, 1); GL11.glPopMatrix(); } } @@ -635,35 +609,48 @@ else if (DimensionManager.getInstance().isDimensionCreated(mc.world.provider.get GlStateManager.disableBlend(); GlStateManager.enableAlpha(); - GL11.glPopMatrix(); + GL11.glPopMatrix(); // matching the big push before rings/stars/sun + // === Asteroid billboards === GlStateManager.enableTexture2D(); - - mc.renderEngine.bindTexture(asteroid1); GlStateManager.color(1, 1, 1); + GlStateManager.depthMask(false); + GlStateManager.enableBlend(); // additive star style keeps them in "sky" + GlStateManager.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE); + + GlStateManager.disableDepth(); // keep? + + bind(asteroid1); GL11.glCallList(this.glSkyList3); GL11.glPushMatrix(); GL11.glRotatef(90, 0.2f, 0.8f, 0); - mc.renderEngine.bindTexture(asteroid2); + bind(asteroid2); GL11.glCallList(this.glSkyList3); GL11.glRotatef(90, 0.2f, 0.8f, 0); - mc.renderEngine.bindTexture(asteroid3); + bind(asteroid3); GL11.glCallList(this.glSkyList3); GL11.glPopMatrix(); - GL11.glDepthMask(true); + GlStateManager.enableDepth(); // keep? - - //RocketEventHandler.onPostWorldRender(partialTicks); - //Fix player/items going transparent + // === PROPER GL STATE RESET === + // Keep depth mask on, but DO NOT clear depth here + GlStateManager.depthMask(true); + GlStateManager.disableBlend(); OpenGlHelper.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 0, 0); + GlStateManager.shadeModel(GL11.GL_FLAT); + GlStateManager.enableTexture2D(); + GlStateManager.enableAlpha(); + GlStateManager.alphaFunc(GL11.GL_GREATER, 0.1f); + GlStateManager.color(1f, 1f, 1f, 1f); + GlStateManager.enableCull(); } + protected void drawStarAndSubStars(BufferBuilder buffer, StellarBody sun, DimensionProperties properties, int solarOrbitalDistance, float sunSize, Vec3d sunColor, float multiplier) { drawStar(buffer, sun, properties, solarOrbitalDistance, sunSize, sunColor, multiplier); List subStars = sun.getSubStars(); - if (subStars != null && !subStars.isEmpty()) { GL11.glPushMatrix(); float phaseInc = 360f / subStars.size(); @@ -674,12 +661,14 @@ protected void drawStarAndSubStars(BufferBuilder buffer, StellarBody sun, Dimens GL11.glRotatef(subStar.getStarSeparation() * AstronomicalBodyHelper.getBodySizeMultiplier(solarOrbitalDistance), 1, 0, 0); float[] color = subStar.getColor(); - drawStar(buffer, subStar, properties, solarOrbitalDistance, subStar.getSize(), new Vec3d(color[0], color[1], color[2]), multiplier); + drawStar(buffer, subStar, properties, solarOrbitalDistance, subStar.getSize(), + new Vec3d(color[0], color[1], color[2]), multiplier); GL11.glPopMatrix(); } GL11.glPopMatrix(); } } + protected ResourceLocation getTextureForPlanet(DimensionProperties properties) { return properties.getPlanetIcon(); } @@ -692,7 +681,6 @@ protected EnumFacing getRotationAxis(DimensionProperties properties, BlockPos po return EnumFacing.EAST; } - protected void renderPlanet(BufferBuilder buffer, DimensionProperties properties, float planetOrbitalDistance, float alphaMultiplier, double shadowAngle, boolean hasAtmosphere, boolean hasRing, float gravitationalMultiplier, float[] shadowColorMultiplier, float alphaMultiplier2) { renderPlanet2(buffer, properties, 20f * AstronomicalBodyHelper.getBodySizeMultiplier(planetOrbitalDistance) * gravitationalMultiplier, alphaMultiplier, shadowAngle, hasRing, shadowColorMultiplier, alphaMultiplier2); } @@ -704,9 +692,15 @@ protected void renderPlanet2(BufferBuilder buffer, DimensionProperties propertie boolean gasGiant = properties.isGasGiant(); float[] skyColor = properties.skyColor; float[] ringColor = properties.ringColor; - RenderPlanetarySky. renderPlanetPubHelper(buffer, icon, 0, 0, -20, size * 0.2f, alphaMultiplier, shadowAngle, hasAtmosphere, skyColor, ringColor, gasGiant, hasRing, properties.ringAngle, hasDecorators, shadowColorMultiplier, alphaMultiplier2); - } + // Keep external call identical + RenderPlanetarySky.renderPlanetPubHelper( + buffer, icon, 0, 0, -20, + size * 0.2f, alphaMultiplier, shadowAngle, + hasAtmosphere, skyColor, ringColor, gasGiant, hasRing, properties.ringAngle, + hasDecorators, shadowColorMultiplier, alphaMultiplier2 + ); + } protected Vector3F getRotateAxis() { return axis; @@ -718,12 +712,12 @@ public void renderSphere(double x, double y, double z, float radius, int slices, bufferBuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - for(int i = 0; i < slices; i++) { - for(int j = 0; j < stacks; j++) { - double firstLong = 2 * Math.PI * (i / (double)slices); - double secondLong = 2 * Math.PI * ((i + 1) / (double)slices); - double firstLat = Math.PI * (j / (double)stacks) - Math.PI / 2; - double secondLat = Math.PI * ((j + 1) / (double)stacks) - Math.PI / 2; + for (int i = 0; i < slices; i++) { + for (int j = 0; j < stacks; j++) { + double firstLong = 2 * Math.PI * (i / (double) slices); + double secondLong = 2 * Math.PI * ((i + 1) / (double) slices); + double firstLat = Math.PI * (j / (double) stacks) - Math.PI / 2; + double secondLat = Math.PI * ((j + 1) / (double) stacks) - Math.PI / 2; bufferBuilder.pos(x + radius * Math.cos(firstLat) * Math.cos(firstLong), y + radius * Math.sin(firstLat), z + radius * Math.cos(firstLat) * Math.sin(firstLong)).tex(0.0D, 0.0D).endVertex(); bufferBuilder.pos(x + radius * Math.cos(secondLat) * Math.cos(firstLong), y + radius * Math.sin(secondLat), z + radius * Math.cos(secondLat) * Math.sin(firstLong)).tex(1.0D, 0.0D).endVertex(); @@ -731,9 +725,9 @@ public void renderSphere(double x, double y, double z, float radius, int slices, bufferBuilder.pos(x + radius * Math.cos(firstLat) * Math.cos(secondLong), y + radius * Math.sin(firstLat), z + radius * Math.cos(firstLat) * Math.sin(secondLong)).tex(0.0D, 1.0D).endVertex(); } } - tessellator.draw(); } + protected void drawStar(BufferBuilder buffer, StellarBody sun, DimensionProperties properties, int solarOrbitalDistance, float sunSize, Vec3d sunColor, float multiplier) { if (sun != null && sun.isBlackHole()) { GlStateManager.enableAlpha(); @@ -742,86 +736,38 @@ protected void drawStar(BufferBuilder buffer, StellarBody sun, DimensionProperti GL11.glPushMatrix(); GL11.glTranslatef(0, 30, 0); - GL11.glDisable(GL11.GL_BLEND); GlStateManager.depthMask(true); + // Black hole sphere GL11.glPushMatrix(); GL11.glTranslatef(0, 100, 0); f10 = sunSize * 2f * AstronomicalBodyHelper.getBodySizeMultiplier(solarOrbitalDistance); - - mc.renderEngine.bindTexture(TextureResources.locationWhitePng); + bind(TextureResources.locationWhitePng); GlStateManager.disableCull(); - GlStateManager.color(skycolor[0], skycolor[1], skycolor[2]); // Set the color - renderSphere(0, 0, 0, f10, 16, 16); // Draw the sphere + GlStateManager.color(skycolor[0], skycolor[1], skycolor[2]); + renderSphere(0, 0, 0, f10, 16, 16); GlStateManager.enableCull(); GL11.glEnable(GL11.GL_BLEND); GL11.glDepthMask(false); GL11.glPopMatrix(); -/* - GL11.glPushMatrix(); - mc.renderEngine.bindTexture(TextureResources.locationBlackHole); - GL11.glTranslatef(0, 100, 0); - f10 = sunSize * 2f * AstronomicalBodyHelper.getBodySizeMultiplier(solarOrbitalDistance); - //float scale = 1 ; - //GL11.glRotatef(phase, 0, 1, 0); - //GL11.glScaled(scale, scale, scale); - GlStateManager.color((float) 1, (float) .5, (float) .4, 1f); - - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - //multiplier = 2; - buffer.pos(-f10, 0.0D, -f10).tex(0.0D, 0.0D).endVertex(); - buffer.pos(f10, 0.0D, -f10).tex(1.0D, 0.0D).endVertex(); - buffer.pos(f10, 0.0D, f10).tex(1.0D, 1.0D).endVertex(); - buffer.pos(-f10, 0.0D, f10).tex(0.0D, 1.0D).endVertex(); - Tessellator.getInstance().draw(); - GL11.glPopMatrix(); - - - GL11.glEnable(GL11.GL_BLEND); - GL11.glDepthMask(false); - - GL11.glPushMatrix(); - mc.renderEngine.bindTexture(TextureResources.locationBlackHoleBorder); - GL11.glTranslatef( 0, 99.8F, 0); - //GL11.glRotatef(phase, 0, 1, 0); - float scale = 1.1F; - GL11.glScaled(scale, scale, scale); - GlStateManager.color((float) 1, (float) .5, (float) .4, 1f); - buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); - //multiplier = 2; - buffer.pos(-f10, 0.0D, -f10).tex(0.0D, 0.0D).endVertex(); - buffer.pos(f10, 0.0D, -f10).tex(1.0D, 0.0D).endVertex(); - buffer.pos(f10, 0.0D, f10).tex(1.0D, 1.0D).endVertex(); - buffer.pos(-f10, 0.0D, f10).tex(0.0D, 1.0D).endVertex(); - Tessellator.getInstance().draw(); - GL11.glPopMatrix(); -*/ float diskangle = sun.diskAngle; - float m = -xrotangle; - while (m > 360) - m-=360; - while (m < 0) - m+=360; - //Render accretion disk - mc.renderEngine.bindTexture(TextureResources.locationAccretionDiskDense); - GlStateManager.depthMask(false); + while (m > 360) m -= 360; + while (m < 0) m += 360; - float speedMult = 5; + // Dense inner disk - ORIGINAL ROTATIONS + bind(TextureResources.locationAccretionDiskDense); + GlStateManager.depthMask(false); GlStateManager.disableCull(); - GL11.glPushMatrix(); GL11.glTranslatef(0, 100, 0); GL11.glRotatef(90, 0f, 1f, 0f); - //GL11.glRotatef(m, 1f, 0f, 0f); - //GL11.glRotatef(diskangle, 0, 0, 1); - //GL11.glRotatef(90, 1, 0, 0); - GL11.glRotatef((System.currentTimeMillis() % (int) (360 * 360 * speedMult)) / (360f * speedMult), 0, 1, 0); - - GlStateManager.color((float) 1, (float) .7, (float) .55, 1f); + // Original rotation with speedMult = 5 + GL11.glRotatef((System.currentTimeMillis() % (int) (360 * 360 * 5)) / (360f * 5), 0, 1, 0); + GlStateManager.color(1f, .7f, .55f, 1f); buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); f10 = sunSize * 6.5f * AstronomicalBodyHelper.getBodySizeMultiplier(solarOrbitalDistance); buffer.pos(-f10, 0.0D, -f10).tex(0.0D, 0.0D).endVertex(); @@ -831,23 +777,23 @@ protected void drawStar(BufferBuilder buffer, StellarBody sun, DimensionProperti Tessellator.getInstance().draw(); GL11.glPopMatrix(); - - mc.renderEngine.bindTexture(TextureResources.locationAccretionDisk); - + // Outer translucent disks - COMPLEX ORIGINAL LOGIC + bind(TextureResources.locationAccretionDisk); for (int i = 0; i < 3; i++) { - speedMult = ((0) * 1.01f + 1)/0.1F; + float speedMult = 10.0f; // ORIGINAL CALCULATION: ((0) * 1.01f + 1)/0.1F + + // First layer - 100.01f GL11.glPushMatrix(); GL11.glTranslatef(0, 100.01f, 0); + // RESTORE ALL ORIGINAL ROTATIONS: GL11.glRotatef((float) currentplanetphi, 0f, 1f, 0f); GL11.glRotatef(m, 1f, 0f, 0f); GL11.glRotatef(diskangle, 0, 0, 1); GL11.glRotatef((System.currentTimeMillis() % (int) (speedMult * 36000)) / (100f * speedMult), 0, 1, 0); - - // make every disks angle slightly different - GL11.glRotatef(120*i, 0, 1, 0); + GL11.glRotatef(120 * i, 0, 1, 0); GL11.glRotatef(0.5f, 1, 0, 0); - GlStateManager.color((float) 1, (float) .5, (float) .4, 0.3f); + GlStateManager.color(1f, .5f, .4f, 0.3f); buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); f10 = sunSize * 40f * AstronomicalBodyHelper.getBodySizeMultiplier(solarOrbitalDistance); buffer.pos(-f10, 0.0D, -f10).tex(0.0D, 0.0D).endVertex(); @@ -857,22 +803,19 @@ protected void drawStar(BufferBuilder buffer, StellarBody sun, DimensionProperti Tessellator.getInstance().draw(); GL11.glPopMatrix(); - + // Second layer - 100f GL11.glPushMatrix(); - GL11.glTranslatef(0, 100f, 0); GL11.glRotatef((float) currentplanetphi, 0f, 1f, 0f); GL11.glRotatef(m, 1f, 0f, 0f); GL11.glRotatef(diskangle, 0, 0, 1); GL11.glRotatef((System.currentTimeMillis() % (int) (speedMult * 360 * 50)) / (50f * speedMult), 0, 1, 0); - // make every disks angle slightly different - GL11.glRotatef(120*i, 0, 1, 0); + GL11.glRotatef(120 * i, 0, 1, 0); GL11.glRotatef(0.5f, 1, 0, 0); - GlStateManager.color((float) 0.8, (float) .7, (float) .4, 0.3f); + GlStateManager.color(0.8f, .7f, .4f, 0.3f); buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); f10 = sunSize * 30f * AstronomicalBodyHelper.getBodySizeMultiplier(solarOrbitalDistance); - //multiplier = 2; buffer.pos(-f10, 0.0D, -f10).tex(0.0D, 0.0D).endVertex(); buffer.pos(f10, 0.0D, -f10).tex(1.0D, 0.0D).endVertex(); buffer.pos(f10, 0.0D, f10).tex(1.0D, 1.0D).endVertex(); @@ -880,47 +823,41 @@ protected void drawStar(BufferBuilder buffer, StellarBody sun, DimensionProperti Tessellator.getInstance().draw(); GL11.glPopMatrix(); + // Third layer - 99.99f GL11.glPushMatrix(); - GL11.glTranslatef(0, 99.99f, 0); GL11.glRotatef((float) currentplanetphi, 0f, 1f, 0f); GL11.glRotatef(m, 1f, 0f, 0f); GL11.glRotatef(diskangle, 0, 0, 1); GL11.glRotatef((System.currentTimeMillis() % (int) (speedMult * 360 * 25)) / (25f * speedMult), 0, 1, 0); - // make every disks angle slightly different - GL11.glRotatef(120*i, 0, 1, 0); + GL11.glRotatef(120 * i, 0, 1, 0); GL11.glRotatef(0.5f, 1, 0, 0); - GlStateManager.color((float) 0.2, (float) .4, (float) 1, 0.3f); + GlStateManager.color(0.2f, .4f, 1f, 0.3f); buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); f10 = sunSize * 15f * AstronomicalBodyHelper.getBodySizeMultiplier(solarOrbitalDistance); - //multiplier = 2; buffer.pos(-f10, 0.0D, -f10).tex(0.0D, 0.0D).endVertex(); buffer.pos(f10, 0.0D, -f10).tex(1.0D, 0.0D).endVertex(); buffer.pos(f10, 0.0D, f10).tex(1.0D, 1.0D).endVertex(); buffer.pos(-f10, 0.0D, f10).tex(0.0D, 1.0D).endVertex(); Tessellator.getInstance().draw(); GL11.glPopMatrix(); - - - - } + // ORIGINAL DEPTH MANAGEMENT GlStateManager.depthMask(true); GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT); GlStateManager.depthMask(false); + GL11.glPopMatrix(); GlStateManager.enableCull(); - - + //GlStateManager.depthMask(true); // keep ? } else { - mc.renderEngine.bindTexture(TextureResources.locationSunPng); - //Set sun color and distance + // Regular star (quad) path + bind(TextureResources.locationSunPng); GlStateManager.color((float) sunColor.x, (float) sunColor.y, (float) sunColor.z, Math.min((multiplier) * 2f, 1f)); buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); float f10 = sunSize * 15f * AstronomicalBodyHelper.getBodySizeMultiplier(solarOrbitalDistance); - //multiplier = 2; buffer.pos(-f10, 120.0D, -f10).tex(0.0D, 0.0D).endVertex(); buffer.pos(f10, 120.0D, -f10).tex(1.0D, 0.0D).endVertex(); buffer.pos(f10, 120.0D, f10).tex(1.0D, 1.0D).endVertex(); From 3c1cf60e56b6e58805be3d4eb66fd99419d13d17 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 24 Oct 2025 16:02:42 +0200 Subject: [PATCH 052/424] Fixing rocketmonitor tickspam Implement neighbor change handling for redstone power updates. Add neighborChanged method for block updates. --- .../block/BlockTileNeighborUpdate.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockTileNeighborUpdate.java b/src/main/java/zmaster587/advancedRocketry/block/BlockTileNeighborUpdate.java index a39b6b5c3..4ee00b0d3 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockTileNeighborUpdate.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockTileNeighborUpdate.java @@ -15,6 +15,21 @@ public BlockTileNeighborUpdate(Class tileClass, int guiId) super(tileClass, guiId); } + // redstone power uses neighbor change to update redstone power + @Override + public void neighborChanged(net.minecraft.block.state.IBlockState state, + net.minecraft.world.World world, + net.minecraft.util.math.BlockPos pos, + net.minecraft.block.Block blockIn, + net.minecraft.util.math.BlockPos fromPos) { + super.neighborChanged(state, world, pos, blockIn, fromPos); + TileEntity te = world.getTileEntity(pos); + if (te instanceof zmaster587.libVulpes.util.IAdjBlockUpdate) { + ((zmaster587.libVulpes.util.IAdjBlockUpdate) te).onAdjacentBlockUpdated(); + } + } + + @Override public void onNeighborChange(IBlockAccess world, BlockPos pos, BlockPos neighbor) { super.onNeighborChange(world, pos, neighbor); From 788a9f820e6a22023a1be94f7eabd8c10f3962fd Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 24 Oct 2025 16:08:21 +0200 Subject: [PATCH 053/424] Enhance TileRocketMonitoringStation functionality Added redstone power caching on neigbourchange, no more polling for redstonechanges 20 times per second. Improved event handling for rocket launch preparation. Updated fuel and height snapshots with tick throttles for performance. UX: subscribe to rocketevents to make GUI feel alive. Launchbutton will listen for Rocketevents like "prelaunch, launch, reached orbit, landed" --- .../TileRocketMonitoringStation.java | 389 +++++++++++++----- 1 file changed, 285 insertions(+), 104 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java index 9ab6b6334..07bd0793b 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java @@ -5,21 +5,29 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.NetworkManager; +import net.minecraft.network.play.server.SPacketUpdateTileEntity; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.ITickable; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.eventhandler.EventPriority; + import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.EntityRocketBase; import zmaster587.advancedRocketry.api.IInfrastructure; import zmaster587.advancedRocketry.api.IMission; +import zmaster587.advancedRocketry.api.RocketEvent; import zmaster587.advancedRocketry.api.fuel.FuelRegistry; import zmaster587.advancedRocketry.api.satellite.SatelliteBase; import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.advancedRocketry.entity.EntityRocket; import zmaster587.advancedRocketry.inventory.TextureResources; + import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.client.util.IndicatorBarImage; import zmaster587.libVulpes.client.util.ProgressBarImage; @@ -31,7 +39,6 @@ import zmaster587.libVulpes.tile.IComparatorOverride; import zmaster587.libVulpes.util.IAdjBlockUpdate; import zmaster587.libVulpes.util.INetworkMachine; -import zmaster587.libVulpes.util.ZUtils.RedstoneState; import javax.annotation.Nonnull; import java.util.LinkedList; @@ -39,28 +46,80 @@ public class TileRocketMonitoringStation extends TileEntity implements IModularInventory, ITickable, IAdjBlockUpdate, IInfrastructure, ILinkableTile, INetworkMachine, IButtonInventory, IProgressBar, IComparatorOverride { + // ==== TUNABLE TICK THROTTLES ==== + // 2–3 ticks for height/vel feels live; 5–10 ticks is fine for fuel. + private static final int T_HEIGHTVEL_TICKS = 3; // ~6.7 Hz + private static final int T_FUEL_TICKS = 10; // ~2 Hz + private static final int T_COMPARATOR_TICKS = 3; // match height cadence + // ================================= + EntityRocketBase linkedRocket; IMission mission; ModuleText missionText; - //RedstoneState state; - //ModuleRedstoneOutputButton redstoneControl; + + // Cached redstone state from neighbor callbacks (don’t poll every tick) + private boolean isPoweredCached = false, initPower = false; + + // Throttles + private int heightVelTick = 0, fuelTick = 0, comparatorTick = 0; + + // Comparator cache (change-only) + private int lastComparator = -1; + + // Server snapshots (served via ModuleProgress polling) + private int snapHeight = 0, snapVel = 0; + private int snapFuel = 0, snapFuelCap = 0; // active fuel (id=2 semantics) + private int snapOx = 0, snapOxCap = 0; // oxidizer (id=6 semantics) + + // GUI cached fields (client) boolean was_powered = false; int rocketHeight; int velocity; int fuelLevel, maxFuelLevel; int oxidizerFuelLevel; + // === GUI event status (server -> client via TE update) === + // 0=idle, 1=prelaunch, 2=launching, 3=orbit, 4=landed, 5=aborted + private int uiStatus = 0; + private transient ModuleText launchStatus; // client-only widget + private transient int lastUiStatusShown = -1; // client change-detect + + // Event bus registration flag + private boolean registeredBus = false; + public TileRocketMonitoringStation() { mission = null; missionText = new ModuleText(20, 90, LibVulpes.proxy.getLocalizedString("msg.monitoringStation.missionProgressNA"), 0x2b2b2b); - //redstoneControl = new ModuleRedstoneOutputButton(174, 4, -1, "", this); - //state = RedstoneState.ON; } + // --- Lifecycle / bus registration --- + + @Override + public void onLoad() { + if (!world.isRemote && !registeredBus) { + MinecraftForge.EVENT_BUS.register(this); + registeredBus = true; + } + if (!world.isRemote && !initPower) { + boolean now = world.isBlockIndirectlyGettingPowered(pos) > 0; + isPoweredCached = now; + was_powered = now; // <- important: no phantom rising edge later + initPower = true; + } + } + + @Override public void invalidate() { super.invalidate(); + // Unregister bus + if (!world.isRemote && registeredBus) { + MinecraftForge.EVENT_BUS.unregister(this); + registeredBus = false; + } + + // Preserve original unlink-on-destroy semantics if (linkedRocket != null) { linkedRocket.unlinkInfrastructure(this); unlinkRocket(); @@ -71,49 +130,178 @@ public void invalidate() { } } - public boolean getEquivalentPower() { - //if (state == RedstoneState.OFF) - // return false; + @Override + public void onChunkUnload() { + super.onChunkUnload(); + // IMPORTANT: do NOT unlink here — preserve original behavior: + // this tile remains linked across unload/reload and during flight/space. + if (!world.isRemote && registeredBus) { + MinecraftForge.EVENT_BUS.unregister(this); + registeredBus = false; + } + } - boolean state2 = world.isBlockIndirectlyGettingPowered(pos) > 0; + // --- Redstone power caching via block neighbor callbacks --- - //if (state == RedstoneState.INVERTED) - // state2 = !state2; - return state2; + @Deprecated + public boolean getEquivalentPower() { + return world.isBlockIndirectlyGettingPowered(pos) > 0; } @Override public void onAdjacentBlockUpdated() { + if (world == null || world.isRemote) return; + + boolean now = world.isBlockIndirectlyGettingPowered(pos) > 0; + boolean rising = now && !isPoweredCached; + + // Update cache first so it stays correct even with no rocket linked + isPoweredCached = now; + was_powered = now; // optional if you surface this elsewhere + if (rising && linkedRocket != null) { + linkedRocket.prepareLaunch(); // only on true 0->1 edge + markDirty(); + } } + + + // --- IInfrastructure --- + @Override public int getMaxLinkDistance() { return 300000; } + @Override + public boolean disconnectOnLiftOff() { + return false; + } + + @Override + public boolean linkRocket(EntityRocketBase rocket) { + this.linkedRocket = rocket; + this.lastComparator = -1; // ensure first comparator notify fires if needed + return true; + } + + @Override + public void unlinkRocket() { + linkedRocket = null; + + // Reset snapshots so viewers don't see stale values + snapHeight = 0; snapVel = 0; + snapFuel = 0; snapFuelCap = 0; + snapOx = 0; snapOxCap = 0; + + // Server-only: force comparator to 0 and notify once + if (world != null && !world.isRemote) { + lastComparator = 0; + world.updateComparatorOutputLevel(pos, world.getBlockState(pos).getBlock()); + } + } + + // --- Ticking --- + @Override public void update() { - if (!world.isRemote) { - if (linkedRocket instanceof EntityRocket) { - if ((int) (15 * ((EntityRocket) linkedRocket).getRelativeHeightFraction()) != (int) (15 * ((EntityRocket) linkedRocket).getPreviousRelativeHeightFraction())) { - markDirty(); - } - if (getEquivalentPower() && linkedRocket != null) { - if (!was_powered) { - System.out.println("prepare launch (redstone powered)"); - linkedRocket.prepareLaunch(); - //System.out.println("launching..."); - was_powered = true; + if (world.isRemote) return; + + // One-time prime (in case no neighbor event has fired yet) + if (!initPower) { + isPoweredCached = world.isBlockIndirectlyGettingPowered(pos) > 0; + initPower = true; + } + + // Runs infrequently to recover from any missed neighbor events. + if ( (world.getTotalWorldTime() & 100) == 0 ) { // every 100 ticks + boolean polled = world.isBlockIndirectlyGettingPowered(pos) > 0; + isPoweredCached = polled; // DO NOT trigger launch here; just reconcile the cache + } + // Idle fast-exit + if (linkedRocket == null) { return; } + + // ---- height + velocity snapshots, every T_HEIGHTVEL_TICKS ---- + if (++heightVelTick >= Math.max(1, T_HEIGHTVEL_TICKS)) { + heightVelTick = 0; + + snapHeight = (int) linkedRocket.posY; + snapVel = (int) (linkedRocket.motionY * 100); + + // comparator (0–15) change-only, every T_COMPARATOR_TICKS + if (++comparatorTick >= Math.max(1, T_COMPARATOR_TICKS)) { + comparatorTick = 0; + if (linkedRocket instanceof EntityRocket) { + int comp = (int)(15 * ((EntityRocket) linkedRocket).getRelativeHeightFraction()); + if (comp != lastComparator) { + lastComparator = comp; + world.updateComparatorOutputLevel(pos, world.getBlockState(pos).getBlock()); } } } - if(!getEquivalentPower()){ - was_powered = false; // - } + } + + // ---- fuel snapshots, every T_FUEL_TICKS ---- + if (++fuelTick >= Math.max(1, T_FUEL_TICKS)) { + fuelTick = 0; + + // Original semantics: + // - id=2 shows the *active* rocket fuel + // - id=6 shows oxidizer independently + final FuelRegistry.FuelType active = linkedRocket.getRocketFuelType(); + snapFuel = linkedRocket.getFuelAmount(active); + snapFuelCap = linkedRocket.getFuelCapacity(active); + + snapOx = linkedRocket.getFuelAmount(FuelRegistry.FuelType.LIQUID_OXIDIZER); + snapOxCap = linkedRocket.getFuelCapacity(FuelRegistry.FuelType.LIQUID_OXIDIZER); + } + } + + // --- Forge Rocket Events -> authorititative UI status (server -> client via TE update) --- + + @SubscribeEvent(priority = EventPriority.LOWEST) // see final canceled state + public void onPreLaunch(RocketEvent.RocketPreLaunchEvent e) { + if (world == null || world.isRemote) return; + if (linkedRocket != null && e.getEntity() == linkedRocket) { + // At LOWEST, if someone canceled it, isCanceled() will be true now. + uiStatus = e.isCanceled() ? 5 : 1; // aborted or prelaunch + markDirty(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); } } + @SubscribeEvent + public void onLaunch(RocketEvent.RocketLaunchEvent e) { + if (world == null || world.isRemote) return; + if (linkedRocket != null && e.getEntity() == linkedRocket) { + uiStatus = 2; // launching! + markDirty(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); + } + } + + @SubscribeEvent + public void onOrbit(RocketEvent.RocketReachesOrbitEvent e) { + if (world == null || world.isRemote) return; + if (linkedRocket != null && e.getEntity() == linkedRocket) { + uiStatus = 3; // reached orbit + markDirty(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); + } + } + + @SubscribeEvent + public void onLanded(RocketEvent.RocketLandedEvent e) { + if (world == null || world.isRemote) return; + if (linkedRocket != null && e.getEntity() == linkedRocket) { + uiStatus = 4; // landed + markDirty(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); + } + } + + // --- Linker flow --- @Override public boolean onLinkStart(@Nonnull ItemStack item, TileEntity entity, EntityPlayer player, World world) { @@ -128,7 +316,10 @@ public boolean onLinkStart(@Nonnull ItemStack item, TileEntity entity, EntityPla } if (player.world.isRemote) - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentTranslation("%s %s", new TextComponentTranslation("msg.monitoringStation.link"), ": " + getPos().getX() + " " + getPos().getY() + " " + getPos().getZ())); + Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage( + new TextComponentTranslation("%s %s", + new TextComponentTranslation("msg.monitoringStation.link"), + ": " + getPos().getX() + " " + getPos().getY() + " " + getPos().getZ())); return true; } @@ -139,69 +330,62 @@ public boolean onLinkComplete(@Nonnull ItemStack item, TileEntity entity, Entity return false; } - @Override - public void unlinkRocket() { - linkedRocket = null; - } + // --- NBT / TE sync --- @Override - public boolean disconnectOnLiftOff() { - return false; + public NBTTagCompound getUpdateTag() { + return writeToNBT(new NBTTagCompound()); } @Override - public boolean linkRocket(EntityRocketBase rocket) { - this.linkedRocket = rocket; - return true; + public SPacketUpdateTileEntity getUpdatePacket() { + NBTTagCompound tag = new NBTTagCompound(); + writeToNBT(tag); + return new SPacketUpdateTileEntity(pos, 0, tag); } @Override - public NBTTagCompound getUpdateTag() { - return writeToNBT(new NBTTagCompound()); + public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) { + readFromNBT(pkt.getNbtCompound()); } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); - - //state = RedstoneState.values()[nbt.getByte("redstoneState")]; - //redstoneControl.setRedstoneState(state); was_powered = nbt.getBoolean("was_powered"); if (nbt.hasKey("missionID")) { long id = nbt.getLong("missionID"); - int dimid = nbt.getInteger("missionDimId"); - SatelliteBase sat = DimensionManager.getInstance().getSatellite(id); - - if (sat instanceof IMission) + if (sat instanceof IMission) { mission = (IMission) sat; + } } + uiStatus = nbt.getInteger("uiStatus"); } @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); - //nbt.setByte("redstoneState", (byte) state.ordinal()); nbt.setBoolean("was_powered", was_powered); if (mission != null) { nbt.setLong("missionID", mission.getMissionId()); nbt.setInteger("missionDimId", mission.getOriginatingDimension()); } + nbt.setInteger("uiStatus", uiStatus); return nbt; } + // --- LibVulpes network bridge --- + @Override public void writeDataToNetwork(ByteBuf out, byte id) { if (id == 1) out.writeLong(mission == null ? -1 : mission.getMissionId()); - //else if (id == 2) - //out.writeByte(state.ordinal()); } @Override - public void readDataFromNetwork(ByteBuf in, byte packetId, - NBTTagCompound nbt) { + public void readDataFromNetwork(ByteBuf in, byte packetId, NBTTagCompound nbt) { if (packetId == 1) { nbt.setLong("id", in.readLong()); } else if (packetId == 2) { @@ -210,8 +394,7 @@ public void readDataFromNetwork(ByteBuf in, byte packetId, } @Override - public void useNetworkData(EntityPlayer player, Side side, byte id, - NBTTagCompound nbt) { + public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompound nbt) { if (id == 1) { long idNum = nbt.getLong("id"); if (idNum == -1) { @@ -219,15 +402,13 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, setMissionText(); } else { SatelliteBase base = DimensionManager.getInstance().getSatellite(idNum); - if (base instanceof IMission) { mission = (IMission) base; setMissionText(); } } } else if (id == 2) { - //state = RedstoneState.values()[nbt.getByte("state")]; - //redstoneControl.setRedstoneState(state); + // redstone control path was commented in original; preserved } if (id == 100) { if (linkedRocket != null) @@ -235,20 +416,26 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, } } + // --- GUI / Modules --- + @Override public List getModules(int ID, EntityPlayer player) { - LinkedList modules = new LinkedList<>(); modules.add(new ModuleButton(20, 40, 0, "Launch!", this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); + + // Status line for rocket events (client only) + if (world.isRemote) { + launchStatus = new ModuleText(10, 30, "", 0xFFFFFF22); + modules.add(launchStatus); + } + modules.add(new ModuleProgress(98, 4, 0, new IndicatorBarImage(2, 7, 12, 81, 17, 0, 6, 6, 1, 0, EnumFacing.UP, TextureResources.rocketHud), this)); modules.add(new ModuleProgress(120, 14, 1, new IndicatorBarImage(2, 95, 12, 71, 17, 0, 6, 6, 1, 0, EnumFacing.UP, TextureResources.rocketHud), this)); modules.add(new ModuleProgress(142, 14, 2, new ProgressBarImage(2, 173, 12, 71, 17, 6, 3, 69, 1, 1, EnumFacing.UP, TextureResources.rocketHud), this)); modules.add(new ModuleProgress(148, 14, 6, new ProgressBarImage(2, 173, 12, 71, 17, 75, 3, 69, 1, 1, EnumFacing.UP, TextureResources.rocketHud), this)); - //modules.add(redstoneControl); setMissionText(); - modules.add(missionText); modules.add(new ModuleProgress(30, 110, 3, TextureResources.progressToMission, this)); modules.add(new ModuleProgress(30, 120, 4, TextureResources.workMission, this)); @@ -268,19 +455,23 @@ private void setMissionText() { int minutes = (time / 60) % 60; int hours = time / 3600; - missionText.setText(((SatelliteBase) mission).getName() + LibVulpes.proxy.getLocalizedString("msg.monitoringStation.progress") + String.format("\n%02dhr:%02dm:%02ds", hours, minutes, seconds)); - } else + String name = (mission instanceof SatelliteBase) + ? ((SatelliteBase) mission).getName() + : LibVulpes.proxy.getLocalizedString("msg.monitoringStation.mission"); + + missionText.setText(name + LibVulpes.proxy.getLocalizedString("msg.monitoringStation.progress") + + String.format("\n%02dhr:%02dm:%02ds", hours, minutes, seconds)); + } else { missionText.setText(LibVulpes.proxy.getLocalizedString("msg.monitoringStation.missionProgressNA")); + } } @Override public void onInventoryButtonPressed(int buttonId) { if (buttonId != -1) PacketHandler.sendToServer(new PacketMachine(this, (byte) (buttonId + 100))); - else { - //state = redstoneControl.getState(); + else PacketHandler.sendToServer(new PacketMachine(this, (byte) 2)); - } } @Override @@ -306,7 +497,22 @@ public float getNormallizedProgress(int id) { return (float) Math.min(Math.max(3f * (mission.getProgress(this.world) - 0.666f), 0f), 1f); } - //keep text updated + // Client: reflect server-driven rocket event status in the GUI text + if (world.isRemote && launchStatus != null && uiStatus != lastUiStatusShown) { + lastUiStatusShown = uiStatus; + String msg; + switch (uiStatus) { + case 1: msg = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.prelaunch"); break; // "Pre-launch checks…" + case 2: msg = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.launching"); break; // "Launching!" + case 3: msg = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.orbit"); break; // "Reached orbit" + case 4: msg = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.landed"); break; // "Landed" + case 5: msg = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.aborted"); break; // "Launch aborted" + default: msg = ""; break; + } + launchStatus.setText(msg); + } + + // Keep mission text updated on client if (world.isRemote && mission != null) setMissionText(); @@ -327,31 +533,20 @@ else if (id == 6) @Override public int getProgress(int id) { - //Try to keep client synced with server, this also allows us to put the monitor on a different world altogether - if (world.isRemote) - if (mission != null && id == 0) - return getTotalProgress(id); - else if (id == 0) - return rocketHeight; - else if (id == 1) - return velocity; - else if (id == 2) - return fuelLevel; - else if (id == 6) - return oxidizerFuelLevel; - - if (linkedRocket == null) + // Client: use client-side cached fields (preserve original mission/height quirk) + if (world.isRemote) { + if (mission != null && id == 0) return getTotalProgress(id); // original oddity preserved + if (id == 0) return rocketHeight; + if (id == 1) return velocity; + if (id == 2) return fuelLevel; + if (id == 6) return oxidizerFuelLevel; return 0; - - if (id == 0) - return (int) linkedRocket.posY; - else if (id == 1) - return (int) (linkedRocket.motionY * 100); - else if (id == 2) - return linkedRocket.getFuelAmount(linkedRocket.getRocketFuelType()); - else if (id == 6) - return linkedRocket.getFuelAmount(FuelRegistry.FuelType.LIQUID_OXIDIZER); - + } + // Server: return snapshots only (cheap) + if (id == 0) return snapHeight; + if (id == 1) return snapVel; + if (id == 2) return snapFuel; // active fuel amount + if (id == 6) return snapOx; // oxidizer amount return 0; } @@ -362,23 +557,9 @@ public int getTotalProgress(int id) { else if (id == 1) return 1000; else if (id == 2) - if (world.isRemote) - return maxFuelLevel; - else if (linkedRocket == null) - return 0; - else - return linkedRocket.getFuelCapacity(linkedRocket.getRocketFuelType()); - + return world.isRemote ? maxFuelLevel : snapFuelCap; else if (id == 6) - if (world.isRemote) - return maxFuelLevel; - else if (linkedRocket == null) - return 0; - else - return linkedRocket.getFuelCapacity(FuelRegistry.FuelType.LIQUID_OXIDIZER); - - - + return world.isRemote ? maxFuelLevel : snapOxCap; return 1; } From 1203b91ca67c50adb7ff501d0933a0d720c890c4 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 24 Oct 2025 16:10:22 +0200 Subject: [PATCH 054/424] Add monitoring station status messages Added monitoring station messages for prelaunch, launching, orbit, landed, and aborted states. --- src/main/resources/assets/advancedrocketry/lang/en_US.lang | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index 94ca254f1..865ad4a84 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -314,6 +314,11 @@ msg.fuelingStation.link=You program the linker with the fueling station at msg.monitoringStation.missionProgressNA=Mission Progress: N/A msg.monitoringStation.link=You program the linker with the monitoring station at msg.monitoringStation.progress= Progress: +msg.monitoringStation.prelaunch=Initiating... +msg.monitoringStation.launching=Launching! +msg.monitoringStation.orbit=Reached orbit +msg.monitoringStation.landed=Landed +msg.monitoringStation.aborted=Aborted msg.guidanceComputerHatch.loadingState=Loading State: msg.guidanceComputerHatch.ejectonlanding=Auto Eject Upon Landing msg.guidanceComputerHatch.ejectonsatlanding=Allow Ejection of Satellite Chips From e149f8bdaa3e14ad6616e6dd01be8c8137a89a59 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 27 Oct 2025 15:59:59 +0100 Subject: [PATCH 055/424] Implement fuel rate recomputation in EntityRocket Added a method to recompute fuel consumption rates based on fuel types and their capacities. HardFix 0 burnrate --- .../advancedRocketry/entity/EntityRocket.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java b/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java index 96a725916..e5566c6d7 100644 --- a/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java +++ b/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java @@ -177,6 +177,32 @@ public EntityRocket(World world, StorageChunk storage, StatsRocket stats, double landingPadDisplayText.setColor(0x00ff00); } + private void recomputeFuelRates() { + for (FuelRegistry.FuelType t : new FuelRegistry.FuelType[]{ + FuelRegistry.FuelType.LIQUID_MONOPROPELLANT, + FuelRegistry.FuelType.LIQUID_BIPROPELLANT, + FuelRegistry.FuelType.LIQUID_OXIDIZER, + FuelRegistry.FuelType.NUCLEAR_WORKING_FLUID}) { + + if (getFuelCapacity(t) <= 0) continue; + + String name = (t == FuelRegistry.FuelType.LIQUID_OXIDIZER) ? stats.getOxidizerFluid() + : (t == FuelRegistry.FuelType.NUCLEAR_WORKING_FLUID) ? stats.getWorkingFluid() + : stats.getFuelFluid(); + if ("null".equals(name)) continue; + + Fluid f = FluidRegistry.getFluid(name); + if (f == null) continue; + + int base = stats.getBaseFuelRate(t); + if (base <= 0) continue; + + int rate = (int)(FuelRegistry.instance.getMultiplier(t, f) * base); + if (rate > 0) setFuelConsumptionRate(t, rate); + } + } + + /** * @param blockState the blockstate to damage * @return the blockstate that the input blockstate turns into @@ -1747,6 +1773,7 @@ public void explode() { public void recalculateStats(){ this.storage.recalculateStats(this.stats); + recomputeFuelRates(); } /** @@ -1764,6 +1791,7 @@ public void launch() { boolean allowLaunch = false; this.storage.recalculateStats(this.stats); + recalculateStats(); NBTTagCompound nbtdata = new NBTTagCompound(); writeToNBT(nbtdata); @@ -2039,6 +2067,7 @@ protected void readEntityFromNBT(NBTTagCompound nbt) { } spacePosition.readFromNBT(nbt); + recomputeFuelRates(); } protected void writeNetworkableNBT(NBTTagCompound nbt) { From 6177518c34d9aca8687297fd529e37f35d23eed2 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 27 Oct 2025 16:06:47 +0100 Subject: [PATCH 056/424] Refactor BlockTileRedstoneEmitter methods Refactor methods for clarity and efficiency, ensuring server-only updates to block state. Reducing redstone spam --- .../block/BlockTileRedstoneEmitter.java | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockTileRedstoneEmitter.java b/src/main/java/zmaster587/advancedRocketry/block/BlockTileRedstoneEmitter.java index fefcbe482..b59042f81 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockTileRedstoneEmitter.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockTileRedstoneEmitter.java @@ -8,17 +8,21 @@ import net.minecraft.world.World; import zmaster587.libVulpes.block.BlockTile; +// Fueling Station block public class BlockTileRedstoneEmitter extends BlockTile { - public BlockTileRedstoneEmitter(Class tileClass, - int guiId) { + public BlockTileRedstoneEmitter(Class tileClass, int guiId) { super(tileClass, guiId); } @Override - public int getWeakPower(IBlockState blockState, IBlockAccess blockAccess, - BlockPos pos, EnumFacing side) { - return blockState.getValue(STATE) ? 15 : 0; + public int getWeakPower(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side) { + return state.getValue(STATE) ? 15 : 0; + } + + @Override + public int getStrongPower(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing side) { + return getWeakPower(state, world, pos, side); } @Override @@ -26,11 +30,23 @@ public boolean canProvidePower(IBlockState state) { return true; } - public void setRedstoneState(World world, IBlockState state, BlockPos pos, boolean newState) { - if (world.getBlockState(pos).getBlock() != this) - return; + public void setRedstoneState(World world, IBlockState _ignored, BlockPos pos, boolean newState) { + // Server-only to avoid client mutations + if (world.isRemote) return; + + // skip if chunk isn't loaded + if (!world.isBlockLoaded(pos)) return; + + // Read the current state from the world to avoid acting on a stale IBlockState + IBlockState curState = world.getBlockState(pos); + if (curState.getBlock() != this) return; + + boolean current = curState.getValue(STATE); + if (current == newState) return; // no-op if unchanged + + IBlockState updated = curState.withProperty(STATE, newState); - world.setBlockState(pos, state.withProperty(STATE, newState)); - world.notifyBlockUpdate(pos, state, state, 3); + // 3 = neighbors notified (1) + clients updated (2) + world.setBlockState(pos, updated, 3); } } From 2c4e13642554be69d391978fc1c03e7a4b7a9f12 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 27 Oct 2025 19:05:02 +0100 Subject: [PATCH 057/424] Enhance fluid management and redstone control in TileFuelingStation Improve fluid handling and redstone state management. Removed most of per-tick-behavior, lookups and redstonespam. Fixed BUG that allowed u to fill hydrogen/oxygen into monoproptanks, and getting 0 burnrate forever on ur rocket Huge Permormance update. --- .../infrastructure/TileFuelingStation.java | 503 ++++++++++++++---- 1 file changed, 394 insertions(+), 109 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java index 70a77e210..0f17f956c 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java @@ -17,6 +17,8 @@ import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidTankProperties; import net.minecraftforge.fml.relauncher.Side; import zmaster587.advancedRocketry.api.*; import zmaster587.advancedRocketry.api.fuel.FuelRegistry; @@ -41,13 +43,28 @@ import javax.annotation.Nonnull; import java.util.ArrayList; import java.util.List; +import java.util.Objects; public class TileFuelingStation extends TileInventoriedRFConsumerTank implements IModularInventory, IMultiblock, IInfrastructure, ILinkableTile, INetworkMachine, IButtonInventory { + private EntityRocketBase linkedRocket; private HashedBlockPosition masterBlock; private ModuleRedstoneOutputButton redstoneControl; private RedstoneState state; + // Tune cadence: Ticks between operations + private static final int OP_THROTTLE_TICKS = 5; + + // Stop polling after full for current link/fluid + private boolean fuelingActive = false; + + // Cache last emitted redstone to avoid duplicate updates + private Boolean lastRs = null; + + // Small perf win: cache resolved fluids from rocket stats + private String lastFuelStr = null, lastOxStr = null, lastWorkStr = null; + private Fluid cachedFuelFluid = null, cachedOxFluid = null, cachedWorkFluid = null; + public TileFuelingStation() { super(1000, 3, 5000); masterBlock = new HashedBlockPosition(0, -1, 0); @@ -55,68 +72,254 @@ public TileFuelingStation() { state = RedstoneState.ON; } - @Override - public int getMaxLinkDistance() { - return 10; + private void syncTE() { + markDirty(); + net.minecraft.block.state.IBlockState s = world.getBlockState(pos); + world.notifyBlockUpdate(pos, s, s, 3); } + @Override + public int getMaxLinkDistance() { return 10; } + + // ---- redstone emission with duplicate suppression ---- private void setRedstoneState(boolean condition) { - if (state == RedstoneState.INVERTED) - condition = !condition; - else if (state == RedstoneState.OFF) - condition = false; - ((BlockTileRedstoneEmitter) AdvancedRocketryBlocks.blockFuelingStation).setRedstoneState(world, world.getBlockState(pos), pos, condition); + if (world == null || world.isRemote) return; + + if (state == RedstoneState.INVERTED) condition = !condition; + else if (state == RedstoneState.OFF) condition = false; + if (lastRs != null && lastRs == condition) return; + lastRs = condition; + + net.minecraft.block.state.IBlockState s = world.getBlockState(pos); + if (AdvancedRocketryBlocks.blockFuelingStation instanceof BlockTileRedstoneEmitter) { + ((BlockTileRedstoneEmitter) AdvancedRocketryBlocks.blockFuelingStation) + .setRedstoneState(world, s, pos, condition); + } + markDirty(); + } + + + // ---- small cache to avoid repeated FluidRegistry lookups per tick ---- + private void refreshFluidCachesIfNeeded() { + if (linkedRocket == null || linkedRocket.stats == null) return; + String f = linkedRocket.stats.getFuelFluid(); + String o = linkedRocket.stats.getOxidizerFluid(); + String w = linkedRocket.stats.getWorkingFluid(); + + if (!Objects.equals(f, lastFuelStr)) { + lastFuelStr = f; + cachedFuelFluid = (f == null || "null".equals(f)) ? null : FluidRegistry.getFluid(f); + } + if (!Objects.equals(o, lastOxStr)) { + lastOxStr = o; + cachedOxFluid = (o == null || "null".equals(o)) ? null : FluidRegistry.getFluid(o); + } + if (!Objects.equals(w, lastWorkStr)) { + lastWorkStr = w; + cachedWorkFluid = (w == null || "null".equals(w)) ? null : FluidRegistry.getFluid(w); + } } + private boolean isStationFluidForThisRocket(Fluid current) { + refreshFluidCachesIfNeeded(); + if (current == null || linkedRocket == null) return false; + + // If a specific fluid was already chosen, match directly. + if (current == cachedFuelFluid || current == cachedOxFluid || current == cachedWorkFluid) { + return true; + } + + // Allow first-time lock-in when rocket hasn't chosen a fluid yet, + // but DOES have capacity for the corresponding tank and "current" is valid for that type. + if ("null".equals(linkedRocket.stats.getFuelFluid())) { + if ((linkedRocket.getFuelCapacity(FuelType.LIQUID_MONOPROPELLANT) > 0 && + FuelRegistry.instance.isFuel(FuelType.LIQUID_MONOPROPELLANT, current)) || + (linkedRocket.getFuelCapacity(FuelType.LIQUID_BIPROPELLANT) > 0 && + FuelRegistry.instance.isFuel(FuelType.LIQUID_BIPROPELLANT, current))) { + return true; + } + } + + if ("null".equals(linkedRocket.stats.getOxidizerFluid())) { + if (linkedRocket.getFuelCapacity(FuelType.LIQUID_OXIDIZER) > 0 && + FuelRegistry.instance.isFuel(FuelType.LIQUID_OXIDIZER, current)) { + return true; + } + } + + if ("null".equals(linkedRocket.stats.getWorkingFluid())) { + if (linkedRocket.getFuelCapacity(FuelType.NUCLEAR_WORKING_FLUID) > 0 && + FuelRegistry.instance.isFuel(FuelType.NUCLEAR_WORKING_FLUID, current)) { + return true; + } + } + + return false; + } + + + @Override + public void update() { + if (world.isRemote) return; + + // Lightweight bucket poll every 10 ticks (automation/hoppers) + if ((world.getTotalWorldTime() % 10L) == 0L) { + ItemStack in = inventory.getStackInSlot(0); + if (!in.isEmpty() && useBucket(0, in)) { + syncTE(); // only when something actually changed + } + } + + super.update(); // IMPORTANT: preserve parent RF/ticking pipeline + } + + @Override public void performFunction() { - if (!world.isRemote) { - //Lock rocket to a specific fluid so that it has only one oxidizer/bipropellant/monopropellant/etc - FluidStack currentFluidStack = tank.getFluid(); - if (currentFluidStack != null) { - Fluid currentFluid = currentFluidStack.getFluid(); - - //Check to see if we should set the rocket fuel - if (linkedRocket.stats.getFuelFluid().equals("null")) { - if ((FuelRegistry.instance.isFuel(FuelType.LIQUID_MONOPROPELLANT, currentFluid) && linkedRocket.getFuelCapacity(FuelType.LIQUID_MONOPROPELLANT) > 0) || (FuelRegistry.instance.isFuel(FuelType.LIQUID_BIPROPELLANT, currentFluid) && linkedRocket.getFuelCapacity(FuelType.LIQUID_BIPROPELLANT) > 0)) - linkedRocket.stats.setFuelFluid(currentFluid.getName()); - } - if (linkedRocket.stats.getOxidizerFluid().equals("null")) { - if (FuelRegistry.instance.isFuel(FuelType.LIQUID_OXIDIZER, currentFluid)) - linkedRocket.stats.setOxidizerFluid(currentFluid.getName()); - } - if (linkedRocket.stats.getWorkingFluid().equals("null")) { - if (FuelRegistry.instance.isFuel(FuelType.NUCLEAR_WORKING_FLUID, currentFluid)) - linkedRocket.stats.setWorkingFluid(currentFluid.getName()); - } + if (world.isRemote) return; // server-only + + if (!fuelingActive) { + FluidStack fs = tank.getFluid(); + boolean relevant = false, room = false; + + if (linkedRocket != null && fs != null) { + Fluid f = fs.getFluid(); + // relevant if this fluid matches what this rocket can actually use + relevant = isStationFluidForThisRocket(f); + // room if the matching logical tank has capacity + room = relevant && canRocketFitFluid(f); + } - //Actually fill the fuel if that is the case - if (currentFluid == FluidRegistry.getFluid(linkedRocket.stats.getFuelFluid()) || currentFluid == FluidRegistry.getFluid(linkedRocket.stats.getOxidizerFluid()) || currentFluid == FluidRegistry.getFluid(linkedRocket.stats.getWorkingFluid())) { - if (linkedRocket.getRocketFuelType() == FuelType.LIQUID_BIPROPELLANT && FuelRegistry.instance.isFuel(FuelType.LIQUID_OXIDIZER, currentFluid)) { - int fuelRate = (int) (FuelRegistry.instance.getMultiplier(FuelType.LIQUID_OXIDIZER, currentFluid) * linkedRocket.stats.getBaseFuelRate(FuelType.LIQUID_OXIDIZER)); - tank.drain(linkedRocket.addFuelAmount(FuelType.LIQUID_OXIDIZER, ARConfiguration.getCurrentConfig().fuelPointsPer10Mb), true); - linkedRocket.setFuelConsumptionRate(FuelType.LIQUID_OXIDIZER, fuelRate); - } else { - int fuelRate = (int) (FuelRegistry.instance.getMultiplier(linkedRocket.getRocketFuelType(), currentFluid) * linkedRocket.stats.getBaseFuelRate(linkedRocket.getRocketFuelType())); - tank.drain(linkedRocket.addFuelAmount(linkedRocket.getRocketFuelType(), ARConfiguration.getCurrentConfig().fuelPointsPer10Mb), true); - linkedRocket.setFuelConsumptionRate(linkedRocket.getRocketFuelType(), fuelRate); - } + setRedstoneState(relevant && !room); // emit when relevant but full + fuelingActive = room; // arm when relevant and there’s room + if (!fuelingActive) return; + } - } + // from here: only do rocket-facing work when it's worth it... + if (linkedRocket == null) { + fuelingActive = false; + setRedstoneState(false); + return; + } + + // Stop all work once full (until unlink/relink) + if (!fuelingActive) { + FluidStack fs = tank.getFluid(); + if (fs != null && canRocketFitFluid(fs.getFluid())) { + fuelingActive = true; // resume fueling after reload + // don’t run expensive work this tick; we’ll catch it on the next throttled pass + } else { + // already full or no relevant fluid — keep RS accurate + setRedstoneState(fs != null && isStationFluidForThisRocket(fs.getFluid()) && !canRocketFitFluid(fs.getFluid())); + } + return; + } + + // Throttle only the expensive fueling/redstone path + if ((world.getTotalWorldTime() % OP_THROTTLE_TICKS) != 0L) return; + + FluidStack currentFluidStack = tank.getFluid(); + if (currentFluidStack == null) { + // No fluid to offer; keep fuelingActive so we’ll retry when fluid arrives + setRedstoneState(false); + return; + } + + final Fluid currentFluid = currentFluidStack.getFluid(); + + // Lock rocket to specific fluids if unset + if ("null".equals(linkedRocket.stats.getFuelFluid())) { + if ((FuelRegistry.instance.isFuel(FuelType.LIQUID_MONOPROPELLANT, currentFluid) && linkedRocket.getFuelCapacity(FuelType.LIQUID_MONOPROPELLANT) > 0) + || (FuelRegistry.instance.isFuel(FuelType.LIQUID_BIPROPELLANT, currentFluid) && linkedRocket.getFuelCapacity(FuelType.LIQUID_BIPROPELLANT) > 0)) { + linkedRocket.stats.setFuelFluid(currentFluid.getName()); + } + } + if ("null".equals(linkedRocket.stats.getOxidizerFluid())) { + if (FuelRegistry.instance.isFuel(FuelType.LIQUID_OXIDIZER, currentFluid)) { + linkedRocket.stats.setOxidizerFluid(currentFluid.getName()); + } + } + if ("null".equals(linkedRocket.stats.getWorkingFluid())) { + if (FuelRegistry.instance.isFuel(FuelType.NUCLEAR_WORKING_FLUID, currentFluid)) { + linkedRocket.stats.setWorkingFluid(currentFluid.getName()); + } + } + + // Update caches after potential stat change + refreshFluidCachesIfNeeded(); + + // If station fluid isn't relevant for this rocket, we can't help + if (!isStationFluidForThisRocket(currentFluid)) { + setRedstoneState(false); + fuelingActive = false; // go fully idle if station fluid not relevant + return; + } + + if (!canRocketFitFluid(currentFluid)) { + setRedstoneState(true); + fuelingActive = false; // early-return above- next pass + markDirty(); + return; + } - //If the rocket is full then emit redstone - setRedstoneState(!canRocketFitFluid(currentFluid)); + // Determine which tank to fill + final FuelType typeToFill; + if (FuelRegistry.instance.isFuel(FuelType.LIQUID_OXIDIZER, currentFluid) + && linkedRocket.getFuelCapacity(FuelType.LIQUID_OXIDIZER) > linkedRocket.getFuelAmount(FuelType.LIQUID_OXIDIZER)) { + typeToFill = FuelType.LIQUID_OXIDIZER; + + } else if (FuelRegistry.instance.isFuel(FuelType.LIQUID_BIPROPELLANT, currentFluid) + && linkedRocket.getFuelCapacity(FuelType.LIQUID_BIPROPELLANT) > linkedRocket.getFuelAmount(FuelType.LIQUID_BIPROPELLANT)) { + typeToFill = FuelType.LIQUID_BIPROPELLANT; + + } else if (FuelRegistry.instance.isFuel(FuelType.LIQUID_MONOPROPELLANT, currentFluid) + && linkedRocket.getFuelCapacity(FuelType.LIQUID_MONOPROPELLANT) > linkedRocket.getFuelAmount(FuelType.LIQUID_MONOPROPELLANT)) { + typeToFill = FuelType.LIQUID_MONOPROPELLANT; + + } else if (FuelRegistry.instance.isFuel(FuelType.NUCLEAR_WORKING_FLUID, currentFluid) + && linkedRocket.getFuelCapacity(FuelType.NUCLEAR_WORKING_FLUID) > linkedRocket.getFuelAmount(FuelType.NUCLEAR_WORKING_FLUID)) { + typeToFill = FuelType.NUCLEAR_WORKING_FLUID; + + } else { + // not relevant or no room + setRedstoneState(false); + fuelingActive = false; + return; + } + // Bounded transfer scaled by throttle; drain exactly what was accepted + int step = ARConfiguration.getCurrentConfig().fuelPointsPer10Mb; + int toOffer = Math.min(step * OP_THROTTLE_TICKS, tank.getFluidAmount()); + if (toOffer > 0) { + int accepted = linkedRocket.addFuelAmount(typeToFill, toOffer); // assumes returns actual mB accepted + if (accepted > 0) { + tank.drain(accepted, true); + int baseRate = linkedRocket.stats.getBaseFuelRate(typeToFill); + if (baseRate > 0) { + int multRate = (int)(FuelRegistry.instance.getMultiplier(typeToFill, currentFluid) * baseRate); + if (multRate > 0) { + linkedRocket.setFuelConsumptionRate(typeToFill, multRate); + } + } } } - useBucket(0, inventory.getStackInSlot(0)); + + // Re-evaluate full; if full now, stop within this link + boolean fullNow = !canRocketFitFluid(currentFluid); + setRedstoneState(fullNow); + if (fullNow) { + fuelingActive = false; + markDirty(); + } } @Override public int getPowerPerOperation() { - return 30; + // same average RF/mb as before, just throttled + return 30 * OP_THROTTLE_TICKS; } + @Override public SPacketUpdateTileEntity getUpdatePacket() { return new SPacketUpdateTileEntity(pos, getBlockMetadata(), getUpdateTag()); @@ -132,45 +335,74 @@ public NBTTagCompound getUpdateTag() { return writeToNBT(new NBTTagCompound()); } - @Override public boolean canPerformFunction() { - boolean v = linkedRocket != null && (tank.getFluid() != null && tank.getFluidAmount() > 9 && canRocketFitFluid(tank.getFluid().getFluid())); - //System.out.println(v); - return v; + if (world.isRemote) return false; + if (linkedRocket == null) return false; + + FluidStack fs = tank.getFluid(); + if (fs == null || fs.amount <= 9) return false; + + // only if the rocket can fit this fluid + if (!canRocketFitFluid(fs.getFluid())) return false; + + // Consume RF only on the throttled ticks + return (world.getTotalWorldTime() % OP_THROTTLE_TICKS) == 0L; } @Override public boolean canFill(Fluid fluid) { - return FuelRegistry.instance.isFuel(FuelType.LIQUID_MONOPROPELLANT, fluid) || FuelRegistry.instance.isFuel(FuelType.NUCLEAR_WORKING_FLUID, fluid) || FuelRegistry.instance.isFuel(FuelType.LIQUID_BIPROPELLANT, fluid) || FuelRegistry.instance.isFuel(FuelType.LIQUID_OXIDIZER, fluid); + if (fluid == null) return false; + return FuelRegistry.instance.isFuel(FuelType.LIQUID_MONOPROPELLANT, fluid) + || FuelRegistry.instance.isFuel(FuelType.NUCLEAR_WORKING_FLUID, fluid) + || FuelRegistry.instance.isFuel(FuelType.LIQUID_BIPROPELLANT, fluid) + || FuelRegistry.instance.isFuel(FuelType.LIQUID_OXIDIZER, fluid); } - /** * @param fluid the fluid to check whether the rocket has space for it * @return boolean on whether the rocket can accept the fluid */ - public boolean canRocketFitFluid(Fluid fluid) { - return canFill(fluid) && ((linkedRocket.getRocketFuelType() == FuelType.LIQUID_BIPROPELLANT && FuelRegistry.instance.isFuel(FuelType.LIQUID_OXIDIZER, fluid)) ? linkedRocket.getFuelCapacity(FuelType.LIQUID_OXIDIZER) > linkedRocket.getFuelAmount(FuelType.LIQUID_OXIDIZER) : linkedRocket.getFuelCapacity(linkedRocket.getRocketFuelType()) > linkedRocket.getFuelAmount(linkedRocket.getRocketFuelType())); - } + private boolean canRocketFitFluid(Fluid f) { + if (f == null || linkedRocket == null) return false; + if (FuelRegistry.instance.isFuel(FuelType.LIQUID_OXIDIZER, f)) { + return linkedRocket.getFuelAmount(FuelType.LIQUID_OXIDIZER) < linkedRocket.getFuelCapacity(FuelType.LIQUID_OXIDIZER); + } + if (FuelRegistry.instance.isFuel(FuelType.LIQUID_BIPROPELLANT, f)) { + return linkedRocket.getFuelAmount(FuelType.LIQUID_BIPROPELLANT) < linkedRocket.getFuelCapacity(FuelType.LIQUID_BIPROPELLANT); + } + if (FuelRegistry.instance.isFuel(FuelType.LIQUID_MONOPROPELLANT, f)) { + return linkedRocket.getFuelAmount(FuelType.LIQUID_MONOPROPELLANT) < linkedRocket.getFuelCapacity(FuelType.LIQUID_MONOPROPELLANT); + } + if (FuelRegistry.instance.isFuel(FuelType.NUCLEAR_WORKING_FLUID, f)) { + return linkedRocket.getFuelAmount(FuelType.NUCLEAR_WORKING_FLUID) < linkedRocket.getFuelCapacity(FuelType.NUCLEAR_WORKING_FLUID); + } + return false; + } @Override public String getModularInventoryName() { return AdvancedRocketryBlocks.blockFuelingStation.getLocalizedName(); } + // keep original claim of custom name, but return non-null to avoid GUI NPEs @Override - public boolean hasCustomName() { - return true; + public boolean hasCustomName() { return true; } + + @Override + public String getName() { + return AdvancedRocketryBlocks.blockFuelingStation.getLocalizedName(); } @Override public void setInventorySlotContents(int slot, @Nonnull ItemStack stack) { - super.setInventorySlotContents(slot, stack); - while (useBucket(0, getStackInSlot(0))) ; - + if (!world.isRemote) { + boolean changed = false; + while (useBucket(0, getStackInSlot(0))) changed = true; // drain all at once + if (changed) syncTE(); // one sync if anything changed + } } /** @@ -184,32 +416,52 @@ private boolean useBucket(int slot, @Nonnull ItemStack stack) { return FluidUtils.attemptDrainContainerIInv(inventory, tank, stack, 0, 1); } + @Override public boolean isItemValidForSlot(int slot, @Nonnull ItemStack stack) { - if (stack.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, EnumFacing.UP)) { - FluidStack fstack = stack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, EnumFacing.UP).getTankProperties()[0].getContents(); - return fstack != null && canFill(fstack.getFluid()); - } - return false; + if (!stack.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, EnumFacing.UP)) return false; + IFluidHandler cap = stack.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, EnumFacing.UP); + if (cap == null) return false; + IFluidTankProperties[] props = cap.getTankProperties(); + if (props == null || props.length == 0) return false; + FluidStack fstack = props[0].getContents(); + return fstack != null && canFill(fstack.getFluid()); } @Override public void unlinkRocket() { this.linkedRocket = null; - ((BlockTileRedstoneEmitter) AdvancedRocketryBlocks.blockFuelingStation).setRedstoneState(world, world.getBlockState(pos), pos, false); - + this.fuelingActive = false; + this.lastRs = null; + ((BlockTileRedstoneEmitter) AdvancedRocketryBlocks.blockFuelingStation) + .setRedstoneState(world, world.getBlockState(pos), pos, false); + markDirty(); } @Override - public boolean disconnectOnLiftOff() { - return true; - } + public boolean disconnectOnLiftOff() { return true; } @Override public boolean linkRocket(EntityRocketBase rocket) { this.linkedRocket = rocket; - if (tank.getFluid() != null) - setRedstoneState(!canRocketFitFluid(tank.getFluid().getFluid())); + this.lastRs = null; + refreshFluidCachesIfNeeded(); + + boolean room = false; + + if (tank.getFluid() != null) { + Fluid f = tank.getFluid().getFluid(); + boolean relevant = isStationFluidForThisRocket(f); + room = relevant && canRocketFitFluid(f); + setRedstoneState(relevant && !room); + } else { + setRedstoneState(false); + } + + // Arm fueling only if there’s actually room for the current fluid + this.fuelingActive = room; + + syncTE(); return true; } @@ -225,7 +477,9 @@ public boolean onLinkStart(@Nonnull ItemStack item, TileEntity entity, } if (player.world.isRemote) - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage((new TextComponentString(LibVulpes.proxy.getLocalizedString("msg.fuelingStation.link") + ": " + this.pos.getX() + " " + this.pos.getY() + " " + this.pos.getZ()))); + Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage( + new TextComponentString(LibVulpes.proxy.getLocalizedString("msg.fuelingStation.link") + + ": " + this.pos.getX() + " " + this.pos.getY() + " " + this.pos.getZ())); return true; } @@ -233,18 +487,29 @@ public boolean onLinkStart(@Nonnull ItemStack item, TileEntity entity, public void invalidate() { super.invalidate(); if (getMasterBlock() instanceof TileRocketAssemblingMachine) - ((TileRocketAssemblingMachine) getMasterBlock()).removeConnectedInfrastructure(this); + ((TileRocketAssemblingMachine)getMasterBlock()).removeConnectedInfrastructure(this); - //Mostly for client rendering stuff if (linkedRocket != null) linkedRocket.unlinkInfrastructure(this); + + // Hard-off to avoid stale output when chunk unload order is weird + lastRs = null; + fuelingActive = false; + + if (world != null && AdvancedRocketryBlocks.blockFuelingStation instanceof BlockTileRedstoneEmitter) { + ((BlockTileRedstoneEmitter) AdvancedRocketryBlocks.blockFuelingStation) + .setRedstoneState(world, world.getBlockState(pos), pos, false); + } + + markDirty(); } @Override public boolean onLinkComplete(@Nonnull ItemStack item, TileEntity entity, EntityPlayer player, World world) { if (player.world.isRemote) - Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(new TextComponentTranslation("msg.linker.error.firstMachine")); + Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage( + new TextComponentTranslation("msg.linker.error.firstMachine")); return false; } @@ -273,23 +538,13 @@ public List getModules(int ID, EntityPlayer player) { } @Override - public String getName() { - return null; - } + public boolean canInteractWithContainer(EntityPlayer entity) { return true; } @Override - public boolean canInteractWithContainer(EntityPlayer entity) { - return true; - } - - @Override - public boolean linkMission(IMission mission) { - return false; - } + public boolean linkMission(IMission mission) { return false; } @Override - public void unlinkMission() { - } + public void unlinkMission() { } @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { @@ -298,6 +553,7 @@ public NBTTagCompound writeToNBT(NBTTagCompound nbt) { if (hasMaster()) { nbt.setIntArray("masterPos", new int[]{masterBlock.x, masterBlock.y, masterBlock.z}); } + // fuelingActive not persisted on purpose to match original continuous behavior after reload return nbt; } @@ -311,12 +567,11 @@ public void readFromNBT(NBTTagCompound nbt) { int[] pos = nbt.getIntArray("masterPos"); setMasterBlock(new BlockPos(pos[0], pos[1], pos[2])); } + // lastRs/fuelingActive intentionally not restored; link events will reset as needed } @Override - public boolean hasMaster() { - return masterBlock.y > -1; - } + public boolean hasMaster() { return masterBlock.y > -1; } @Override public TileEntity getMasterBlock() { @@ -324,23 +579,15 @@ public TileEntity getMasterBlock() { } @Override - public void setMasterBlock(BlockPos pos) { - masterBlock = new HashedBlockPosition(pos); - } + public void setMasterBlock(BlockPos pos) { masterBlock = new HashedBlockPosition(pos); } @Override - public void setComplete(BlockPos pos) { - - } + public void setComplete(BlockPos pos) { } @Override - public void setIncomplete() { - masterBlock.y = -1; - } + public void setIncomplete() { masterBlock.y = -1; } - public boolean canRenderConnection() { - return true; - } + public boolean canRenderConnection() { return true; } @Override public void onInventoryButtonPressed(int buttonId) { @@ -354,22 +601,60 @@ public void writeDataToNetwork(ByteBuf out, byte id) { } @Override - public void readDataFromNetwork(ByteBuf in, byte packetId, - NBTTagCompound nbt) { + public void readDataFromNetwork(ByteBuf in, byte packetId, NBTTagCompound nbt) { nbt.setByte("state", in.readByte()); } @Override - public void useNetworkData(EntityPlayer player, Side side, byte id, - NBTTagCompound nbt) { + public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompound nbt) { state = RedstoneState.values()[nbt.getByte("state")]; + markDirty(); + if (side == Side.SERVER && linkedRocket != null) { + FluidStack fs = tank.getFluid(); + if (fs == null) { setRedstoneState(false); return; } + Fluid f = fs.getFluid(); + boolean relevant = isStationFluidForThisRocket(f); + boolean room = relevant && canRocketFitFluid(f); + setRedstoneState(relevant && !room); + } + } - if (linkedRocket != null && tank.getFluid() != null) - setRedstoneState(!canRocketFitFluid(tank.getFluid().getFluid())); + + @Override + public void onLoad() { + if (world.isRemote) return; + lastRs = null; // allow first emit + refreshFluidCachesIfNeeded(); + + boolean emit = false; + if (linkedRocket != null) { + FluidStack fs = tank.getFluid(); + if (fs != null) { + Fluid f = fs.getFluid(); + emit = isStationFluidForThisRocket(f) && !canRocketFitFluid(f); + // also re-arm fueling if we actually can fit + if (!emit && isStationFluidForThisRocket(f) && canRocketFitFluid(f)) { + fuelingActive = true; + } + } + } + setRedstoneState(emit); } @Override - public boolean isEmpty() { - return inventory.isEmpty(); + public void onChunkUnload() { + super.onChunkUnload(); + if (world == null || world.isRemote) return; + + lastRs = null; + fuelingActive = false; + if (AdvancedRocketryBlocks.blockFuelingStation instanceof BlockTileRedstoneEmitter) { + ((BlockTileRedstoneEmitter) AdvancedRocketryBlocks.blockFuelingStation) + .setRedstoneState(world, world.getBlockState(pos), pos, false); + } + markDirty(); } + + @Override + public boolean isEmpty() { return inventory.isEmpty(); } } From ca6aa6b5bdb779e3198842ca0ca0d18ede016424 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 27 Oct 2025 23:15:24 +0100 Subject: [PATCH 058/424] fixed status updates fixed stale statuses, and properly show status on guiReload --- .../TileRocketMonitoringStation.java | 93 ++++++++++++++----- 1 file changed, 69 insertions(+), 24 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java index 07bd0793b..4f07181fc 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java @@ -83,9 +83,25 @@ public class TileRocketMonitoringStation extends TileEntity implements IModularI private int uiStatus = 0; private transient ModuleText launchStatus; // client-only widget private transient int lastUiStatusShown = -1; // client change-detect + // How long a status is considered fresh after the last event (in ticks) + private static final long STATUS_STALE_TICKS = 400L; // over 20 seconds is outdated + private long lastStatusTick = 0L; // server-only; persisted // Event bus registration flag private boolean registeredBus = false; + + private void pushState() { + if (world != null && !world.isRemote) { + markDirty(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); + } + } + + private void clearUiStatus() { + uiStatus = 0; + lastUiStatusShown = -1; // force client label to refresh to empty + pushState(); + } public TileRocketMonitoringStation() { mission = null; @@ -103,9 +119,23 @@ public void onLoad() { if (!world.isRemote && !initPower) { boolean now = world.isBlockIndirectlyGettingPowered(pos) > 0; isPoweredCached = now; - was_powered = now; // <- important: no phantom rising edge later + was_powered = now; initPower = true; } + + if (!world.isRemote) { + boolean stale = lastStatusTick == 0L || + (world.getTotalWorldTime() - lastStatusTick) > STATUS_STALE_TICKS; + + if (stale || linkedRocket == null) { + clearUiStatus(); + lastStatusTick = 0L; // reset tick + } else { + pushState(); // keep fresh status visible + } + } + + } @@ -182,26 +212,34 @@ public boolean disconnectOnLiftOff() { @Override public boolean linkRocket(EntityRocketBase rocket) { this.linkedRocket = rocket; - this.lastComparator = -1; // ensure first comparator notify fires if needed + this.lastComparator = -1; + + if (!world.isRemote) { + clearUiStatus(); + lastStatusTick = 0L; // reset tick + } return true; } + @Override public void unlinkRocket() { linkedRocket = null; - // Reset snapshots so viewers don't see stale values - snapHeight = 0; snapVel = 0; - snapFuel = 0; snapFuelCap = 0; - snapOx = 0; snapOxCap = 0; + // reset snapshots + snapHeight = snapVel = 0; + snapFuel = snapFuelCap = 0; + snapOx = snapOxCap = 0; - // Server-only: force comparator to 0 and notify once - if (world != null && !world.isRemote) { + if (!world.isRemote) { lastComparator = 0; world.updateComparatorOutputLevel(pos, world.getBlockState(pos).getBlock()); + clearUiStatus(); + lastStatusTick = 0L; // reset tick } } + // --- Ticking --- @Override @@ -215,7 +253,7 @@ public void update() { } // Runs infrequently to recover from any missed neighbor events. - if ( (world.getTotalWorldTime() & 100) == 0 ) { // every 100 ticks + if (world.getTotalWorldTime() % 100 == 0) { // every 100 ticks boolean polled = world.isBlockIndirectlyGettingPowered(pos) > 0; isPoweredCached = polled; // DO NOT trigger launch here; just reconcile the cache } @@ -260,14 +298,13 @@ public void update() { // --- Forge Rocket Events -> authorititative UI status (server -> client via TE update) --- - @SubscribeEvent(priority = EventPriority.LOWEST) // see final canceled state + @SubscribeEvent(priority = EventPriority.LOWEST) public void onPreLaunch(RocketEvent.RocketPreLaunchEvent e) { if (world == null || world.isRemote) return; if (linkedRocket != null && e.getEntity() == linkedRocket) { - // At LOWEST, if someone canceled it, isCanceled() will be true now. - uiStatus = e.isCanceled() ? 5 : 1; // aborted or prelaunch - markDirty(); - world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); + uiStatus = e.isCanceled() ? 5 : 1; // aborted or prelaunch + lastStatusTick = world.getTotalWorldTime(); + pushState(); // single place to mark+notify } } @@ -275,9 +312,9 @@ public void onPreLaunch(RocketEvent.RocketPreLaunchEvent e) { public void onLaunch(RocketEvent.RocketLaunchEvent e) { if (world == null || world.isRemote) return; if (linkedRocket != null && e.getEntity() == linkedRocket) { - uiStatus = 2; // launching! - markDirty(); - world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); + uiStatus = 2; + lastStatusTick = world.getTotalWorldTime(); + pushState(); } } @@ -285,9 +322,9 @@ public void onLaunch(RocketEvent.RocketLaunchEvent e) { public void onOrbit(RocketEvent.RocketReachesOrbitEvent e) { if (world == null || world.isRemote) return; if (linkedRocket != null && e.getEntity() == linkedRocket) { - uiStatus = 3; // reached orbit - markDirty(); - world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); + uiStatus = 3; + lastStatusTick = world.getTotalWorldTime(); + pushState(); } } @@ -295,12 +332,13 @@ public void onOrbit(RocketEvent.RocketReachesOrbitEvent e) { public void onLanded(RocketEvent.RocketLandedEvent e) { if (world == null || world.isRemote) return; if (linkedRocket != null && e.getEntity() == linkedRocket) { - uiStatus = 4; // landed - markDirty(); - world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); + uiStatus = 4; + lastStatusTick = world.getTotalWorldTime(); + pushState(); } } + // --- Linker flow --- @Override @@ -362,6 +400,7 @@ public void readFromNBT(NBTTagCompound nbt) { } } uiStatus = nbt.getInteger("uiStatus"); + lastStatusTick = nbt.getLong("lastStatusTick"); } @Override @@ -373,6 +412,7 @@ public NBTTagCompound writeToNBT(NBTTagCompound nbt) { nbt.setInteger("missionDimId", mission.getOriginatingDimension()); } nbt.setInteger("uiStatus", uiStatus); + nbt.setLong("lastStatusTick", lastStatusTick); return nbt; } @@ -428,8 +468,12 @@ public List getModules(int ID, EntityPlayer player) { if (world.isRemote) { launchStatus = new ModuleText(10, 30, "", 0xFFFFFF22); modules.add(launchStatus); + + // Force the label to refresh on this GUI open + lastUiStatusShown = -1; } + modules.add(new ModuleProgress(98, 4, 0, new IndicatorBarImage(2, 7, 12, 81, 17, 0, 6, 6, 1, 0, EnumFacing.UP, TextureResources.rocketHud), this)); modules.add(new ModuleProgress(120, 14, 1, new IndicatorBarImage(2, 95, 12, 71, 17, 0, 6, 6, 1, 0, EnumFacing.UP, TextureResources.rocketHud), this)); modules.add(new ModuleProgress(142, 14, 2, new ProgressBarImage(2, 173, 12, 71, 17, 6, 3, 69, 1, 1, EnumFacing.UP, TextureResources.rocketHud), this)); @@ -442,7 +486,8 @@ public List getModules(int ID, EntityPlayer player) { modules.add(new ModuleProgress(30, 130, 5, TextureResources.progressFromMission, this)); if (!world.isRemote) { - PacketHandler.sendToPlayer(new PacketMachine(this, (byte) 1), player); + PacketHandler.sendToPlayer(new PacketMachine(this, (byte) 1), player); // mission sync + pushState(); // TE sync (includes cleared/derived uiStatus) } return modules; From b95ff89cd005097d6623e3595003e4d26fb962b4 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Tue, 28 Oct 2025 01:01:02 +0100 Subject: [PATCH 059/424] Refactor fuel rates and implement chunk preloading Fuel rate computation on launch, hardFixing cheating Add chunk preloading for rocket launch if we are changing dims, holding force chunload 3x3 for 60 from launch event --- .../advancedRocketry/entity/EntityRocket.java | 163 ++++++++++++++---- 1 file changed, 130 insertions(+), 33 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java b/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java index e5566c6d7..8310fcf3f 100644 --- a/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java +++ b/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java @@ -25,6 +25,7 @@ import net.minecraft.util.SoundCategory; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentString; @@ -33,6 +34,9 @@ import net.minecraft.world.WorldServer; import net.minecraft.world.chunk.Chunk; import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.ForgeChunkManager; +import net.minecraftforge.common.ForgeChunkManager.Ticket; +import net.minecraftforge.common.ForgeChunkManager.Type; import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTank; @@ -90,6 +94,8 @@ import javax.annotation.Nullable; import java.util.*; + + public class EntityRocket extends EntityRocketBase implements INetworkEntity, IModularInventory, IProgressBar, IButtonInventory, ISelectionNotify, IPlanetDefiner { // set to 2 seconds because keyboard event is not sent to server @@ -140,6 +146,18 @@ public class EntityRocket extends EntityRocketBase implements INetworkEntity, IM private int rcs_mode_counter = 0; //Used to most of the logic, determining if in RCS mode or not private boolean rcs_mode = false; + + // Preload ticket for destination chunks on launch event should be enough time to get a warm dimension + private Ticket destPreloadTicket = null; + private int destPreloadDim = Integer.MIN_VALUE; + private long destPreloadExpire = Long.MIN_VALUE; // world time when we auto-release + + // Only show an oxidizer bar when the rocket actually provides oxidizer capacity. + public boolean shouldShowOxBar() { + return getFuelCapacity(FuelRegistry.FuelType.LIQUID_OXIDIZER) > 0; + } + + public EntityRocket(World p_i1582_1_) { super(p_i1582_1_); @@ -177,32 +195,6 @@ public EntityRocket(World world, StorageChunk storage, StatsRocket stats, double landingPadDisplayText.setColor(0x00ff00); } - private void recomputeFuelRates() { - for (FuelRegistry.FuelType t : new FuelRegistry.FuelType[]{ - FuelRegistry.FuelType.LIQUID_MONOPROPELLANT, - FuelRegistry.FuelType.LIQUID_BIPROPELLANT, - FuelRegistry.FuelType.LIQUID_OXIDIZER, - FuelRegistry.FuelType.NUCLEAR_WORKING_FLUID}) { - - if (getFuelCapacity(t) <= 0) continue; - - String name = (t == FuelRegistry.FuelType.LIQUID_OXIDIZER) ? stats.getOxidizerFluid() - : (t == FuelRegistry.FuelType.NUCLEAR_WORKING_FLUID) ? stats.getWorkingFluid() - : stats.getFuelFluid(); - if ("null".equals(name)) continue; - - Fluid f = FluidRegistry.getFluid(name); - if (f == null) continue; - - int base = stats.getBaseFuelRate(t); - if (base <= 0) continue; - - int rate = (int)(FuelRegistry.instance.getMultiplier(t, f) * base); - if (rate > 0) setFuelConsumptionRate(t, rate); - } - } - - /** * @param blockState the blockstate to damage * @return the blockstate that the input blockstate turns into @@ -235,6 +227,50 @@ private static IBlockState getDamagedBlock(IBlockState blockState) { return null; } + private void preloadDestinationChunks(int dimId, double x, double z, int radiusChunks, int holdSeconds) { + if (world.isRemote) return; + + // Clean any previous + releaseDestinationPreload(); + + MinecraftServer server = this.getServer(); + if (server == null) return; + + WorldServer target = server.getWorld(dimId); + if (target == null) return; // dimension not available + + // Request a NORMAL ticket in the DESTINATION world (not bound to this entity) + destPreloadTicket = ForgeChunkManager.requestTicket(AdvancedRocketry.instance, target, Type.NORMAL); + if (destPreloadTicket == null) { + AdvancedRocketry.logger.warn("[EntityRocket] Could not acquire destination preload ticket for dim {}", dimId); + return; + } + + int cx = ((int)Math.floor(x)) >> 4; + int cz = ((int)Math.floor(z)) >> 4; + for (int dx = -radiusChunks; dx <= radiusChunks; dx++) { + for (int dz = -radiusChunks; dz <= radiusChunks; dz++) { + ForgeChunkManager.forceChunk(destPreloadTicket, new ChunkPos(cx + dx, cz + dz)); + } + } + + destPreloadDim = dimId; + // use *server* time base; holdSeconds should be enough to cover ascent (~6s) + destPreloadExpire = world.getTotalWorldTime() + holdSeconds * 20L; + AdvancedRocketry.logger.debug("[EntityRocket] Preloaded 3x3 chunks at dim {} around {},{} for ~{}s", + dimId, (cx<<4), (cz<<4), holdSeconds); + } + + private void releaseDestinationPreload() { + if (destPreloadTicket != null) { + ForgeChunkManager.releaseTicket(destPreloadTicket); + destPreloadTicket = null; + destPreloadDim = Integer.MIN_VALUE; + destPreloadExpire = Long.MIN_VALUE; + } + } + + public void toggleRCS() { if (DimensionManager.getInstance().getDimensionProperties(this.world.provider.getDimension()).isAsteroid()) { rcs_mode = !rcs_mode; @@ -1110,6 +1146,11 @@ else if (!getRCS() && rcs_mode_counter > 0) { entity.fallDistance = 0; } this.fallDistance = 0; + + // Auto-release destination preload after timeout + if (destPreloadTicket != null && world.getTotalWorldTime() >= destPreloadExpire) { + releaseDestinationPreload(); + } } // When flying around in space @@ -1314,6 +1355,7 @@ else if (distanceSq > this.spacePosition.world.getRenderSizePlanetView() * this. this.motionY = 0; this.setInFlight(false); this.setInOrbit(false); + releaseDestinationPreload(); } @@ -1773,7 +1815,6 @@ public void explode() { public void recalculateStats(){ this.storage.recalculateStats(this.stats); - recomputeFuelRates(); } /** @@ -1791,7 +1832,6 @@ public void launch() { boolean allowLaunch = false; this.storage.recalculateStats(this.stats); - recalculateStats(); NBTTagCompound nbtdata = new NBTTagCompound(); writeToNBT(nbtdata); @@ -1874,12 +1914,37 @@ public void launch() { //TODO: Clean this logic a bit? - if (allowLaunch || !stats.hasSeat() || ((DimensionManager.getInstance().isDimensionCreated(destinationDimId)) || destinationDimId == ARConfiguration.getCurrentConfig().spaceDimId || destinationDimId == 0)) { //Abort if destination is invalid + if (allowLaunch || !stats.hasSeat() || ((DimensionManager.getInstance().isDimensionCreated(destinationDimId)) || destinationDimId == ARConfiguration.getCurrentConfig().spaceDimId || destinationDimId == 0)) { setInFlight(true); Iterator connectedTiles = connectedInfrastructure.iterator(); MinecraftForge.EVENT_BUS.post(new RocketLaunchEvent(this)); + // ---- PRELOAD DESTINATION 3x3 (server only) ---- + if (!world.isRemote) { + boolean willTeleportAtAscent = + !(ARConfiguration.getCurrentConfig().experimentalSpaceFlight && storage.getGuidanceComputer().isEmpty()); + + // Only preload when we know we’ll teleport off this world soon + if (willTeleportAtAscent) { + int dimId = destinationDimId; + + boolean canLoad = + DimensionManager.getInstance().isDimensionCreated(dimId) || + dimId == ARConfiguration.getCurrentConfig().spaceDimId; + + if (canLoad) { + Vector3F destVec = (storage != null) ? storage.getDestinationCoordinates(dimId, true) : null; + double dx = (destVec != null) ? destVec.x : this.posX; + double dz = (destVec != null) ? destVec.z : this.posZ; + + preloadDestinationChunks(dimId, dx, dz, /*radiusChunks*/ 1, /*holdSeconds*/ 60); + } + } + } + // ----------------------------------------------- + + //Disconnect things linked to the rocket on liftoff while (connectedTiles.hasNext()) { @@ -1939,6 +2004,7 @@ public void deconstructRocket() { @Override public void setDead() { super.setDead(); + releaseDestinationPreload(); if (storage != null && storage.world.displayListIndex != -1) GLAllocation.deleteDisplayLists(storage.world.displayListIndex); @@ -2067,7 +2133,6 @@ protected void readEntityFromNBT(NBTTagCompound nbt) { } spacePosition.readFromNBT(nbt); - recomputeFuelRates(); } protected void writeNetworkableNBT(NBTTagCompound nbt) { @@ -2285,6 +2350,7 @@ else if (id == PacketType.RECIEVENBT.ordinal()) { this.turningDownforWhat = nbt.getBoolean("down"); } else if (id == PacketType.ABORTLAUNCH.ordinal()) { this.dataManager.set(LAUNCH_COUNTER, -1); + releaseDestinationPreload(); } else if (id == PacketType.SENDSPACEPOS.ordinal()) { this.spacePosition.readFromNBT(nbt); } else if (id >= STATION_LOC_OFFSET + BUTTON_ID_OFFSET) { @@ -2415,6 +2481,15 @@ public List getModules(int ID, EntityPlayer player) { //Fuel modules.add(new ModuleProgress(192, 7, 0, new ProgressBarImage(2, 173, 12, 71, 17, 6, 3, 69, 1, 1, EnumFacing.UP, TextureResources.rocketHud), this)); + // Conditional oxidizer bar + if (shouldShowOxBar()) { + // Add a second, distinct bar for oxidizer (reuse the monitoring station’s UVs) + modules.add(new ModuleProgress( + 198, 7, 6, // position offset to avoid overlap; ID=6 matches monitoring station semantics + new ProgressBarImage(2, 173, 12, 71, 17, 75, 3, 69, 1, 1, EnumFacing.UP, TextureResources.rocketHud), + this + )); + } //Add buttons @@ -2489,14 +2564,23 @@ public float getNormallizedProgress(int id) { case LIQUID_BIPROPELLANT: case LIQUID_MONOPROPELLANT: case NUCLEAR_WORKING_FLUID: - return getFuelAmount(fuelType) / (float) getFuelCapacity(fuelType); + int amt = getFuelAmount(fuelType); + int cap = getFuelCapacity(fuelType); + return (cap > 0) ? (amt / (float) cap) : 0f; } } + // oxidizer bar matches monitoring station’s ID=6 semantics + if (id == 6) { + int oxAmt = getFuelAmount(FuelType.LIQUID_OXIDIZER); + int oxCap = getFuelCapacity(FuelType.LIQUID_OXIDIZER); + return (oxCap > 0) ? (oxAmt / (float) oxCap) : 0f; + } - return 0; + return 0f; } + public double getRelativeHeightFraction() { return (posY - getTopBlock(getPosition()).getY()) / (getEntryHeight(dimension) - getTopBlock(getPosition()).getY()); } @@ -2512,12 +2596,25 @@ public void setProgress(int id, int progress) { @Override public int getProgress(int id) { + if (id == 0) { + FuelType ft = getRocketFuelType(); + return (ft != null) ? getFuelAmount(ft) : 0; + } else if (id == 6) { + return getFuelAmount(FuelType.LIQUID_OXIDIZER); + } return 0; } @Override public int getTotalProgress(int id) { - return 0; + if (id == 0) { + FuelType ft = getRocketFuelType(); + return (ft != null) ? getFuelCapacity(ft) : 1; // never 0 + } else if (id == 6) { + int cap = getFuelCapacity(FuelType.LIQUID_OXIDIZER); + return (cap > 0) ? cap : 1; // never 0 + } + return 1; } @Override From 2448947599f026dbd164df547ec1a57ece7327d0 Mon Sep 17 00:00:00 2001 From: Marvin Eckhardt Date: Tue, 28 Oct 2025 12:02:15 +0100 Subject: [PATCH 060/424] Update gradle.properties --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index f80f2cd54..474210579 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ org.gradle.daemon=false # Project mcVersion=1.12.2 forgeVersion=14.23.5.2860 -modVersion=2.1.10 +modVersion=2.2.0 archiveBase=AdvancedRocketry startGitRev=8e676bd From ae446a9f077edf633907f7bef294d8fff69bd8e4 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 29 Oct 2025 11:37:14 +0100 Subject: [PATCH 061/424] Improved tooltip information display Will show preview of current build instead of "Error in weight calculation" --- .../advancedRocketry/item/ItemSatellite.java | 138 ++++++++++++++---- 1 file changed, 106 insertions(+), 32 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java b/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java index c26b9d0c5..9ca3d49c2 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java @@ -8,6 +8,7 @@ import zmaster587.advancedRocketry.api.SatelliteRegistry; import zmaster587.advancedRocketry.api.satellite.SatelliteBase; import zmaster587.advancedRocketry.api.satellite.SatelliteProperties; +import zmaster587.advancedRocketry.item.ItemSatellite.SatelliteModuleInventory; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.util.EmbeddedInventory; import zmaster587.libVulpes.util.ZUtils; @@ -17,6 +18,10 @@ public class ItemSatellite extends ItemIdWithName { + private static final int CORE_SLOT = 0; + private static final int FIRST_MOD_SLOT = 1; + private static final int LAST_MOD_SLOT = 6; + //Guarding inventory to ensure only valid items are placed in slots. public static class SatelliteModuleInventory extends EmbeddedInventory { public SatelliteModuleInventory() { super(7); } // slots 0-6 embedded from chassis @@ -25,26 +30,23 @@ public static class SatelliteModuleInventory extends EmbeddedInventory { public boolean isItemValidForSlot(int slot, @Nonnull ItemStack stack) { if (stack.isEmpty()) return false; - // Registry-driven: only accept items that have SatelliteProperties SatelliteProperties p = SatelliteRegistry.getSatelliteProperty(stack); if (p == null) return false; int f = p.getPropertyFlag(); - - // Slot 0: ONLY primary function meta 0-6 - if (slot == 0) { + // only allow appropriate items in appropriate slots + if (slot == CORE_SLOT) { return SatelliteProperties.Property.MAIN.isOfType(f); } - // Slots 1–6: power gen, battery, or data modules - if (slot >= 1 && slot <= 6) { + if (slot >= FIRST_MOD_SLOT && slot <= LAST_MOD_SLOT) { return SatelliteProperties.Property.POWER_GEN.isOfType(f) || SatelliteProperties.Property.BATTERY.isOfType(f) || SatelliteProperties.Property.DATA.isOfType(f); } - return false; } + @Override public void setInventorySlotContents(int index, ItemStack stack) { if (!stack.isEmpty() && !isItemValidForSlot(index, stack)) return; @@ -95,47 +97,119 @@ public void setSatellite(@Nonnull ItemStack stack, SatelliteProperties propertie } - @Override - public void addInformation(@Nonnull ItemStack stack, World player, List list, ITooltipFlag bool) { - if (stack.getItem() instanceof ItemSatellite && SatelliteRegistry.getSatelliteProperties(stack) != null) { - SatelliteProperties properties = SatelliteRegistry.getSatelliteProperties(stack); + public void addInformation(@Nonnull ItemStack stack, World world, List list, ITooltipFlag flag) { + // Assembled = has properties AND a real ID (>0) + SatelliteProperties props = SatelliteRegistry.getSatelliteProperties(stack); + final boolean isAssembled = (props != null && props.getId() > 0); + if (isAssembled) { int dataStorage, powerGeneration, powerStorage; float weight; list.add(getName(stack)); - list.add("ID: " + properties.getId()); + list.add("ID: " + props.getId()); - if (SatelliteProperties.Property.BATTERY.isOfType(properties.getPropertyFlag())) { - if ((powerStorage = properties.getPowerStorage()) > 0) - list.add(LibVulpes.proxy.getLocalizedString("msg.itemsatellite.pwr") + powerStorage); - else - list.add(ChatFormatting.RED + LibVulpes.proxy.getLocalizedString("msg.itemsatellite.nopwr")); + if (SatelliteProperties.Property.BATTERY.isOfType(props.getPropertyFlag())) { + powerStorage = props.getPowerStorage(); + list.add((powerStorage > 0) + ? LibVulpes.proxy.getLocalizedString("msg.itemsatellite.pwr") + powerStorage + : ChatFormatting.RED + LibVulpes.proxy.getLocalizedString("msg.itemsatellite.nopwr")); } - if (SatelliteProperties.Property.POWER_GEN.isOfType(properties.getPropertyFlag())) { - if ((powerGeneration = properties.getPowerGeneration()) > 0) - list.add(LibVulpes.proxy.getLocalizedString("msg.itemsatellite.pwrgen") + powerGeneration); - else - list.add(ChatFormatting.RED + LibVulpes.proxy.getLocalizedString("msg.itemsatellite.nopwrgen")); + if (SatelliteProperties.Property.POWER_GEN.isOfType(props.getPropertyFlag())) { + powerGeneration = props.getPowerGeneration(); + list.add((powerGeneration > 0) + ? LibVulpes.proxy.getLocalizedString("msg.itemsatellite.pwrgen") + powerGeneration + : ChatFormatting.RED + LibVulpes.proxy.getLocalizedString("msg.itemsatellite.nopwrgen")); } - if (SatelliteProperties.Property.DATA.isOfType(properties.getPropertyFlag())) { - if ((dataStorage = properties.getMaxDataStorage()) > 0) - list.add(LibVulpes.proxy.getLocalizedString("msg.itemsatellite.data") + ZUtils.formatNumber(dataStorage)); - else - list.add(ChatFormatting.YELLOW + LibVulpes.proxy.getLocalizedString("msg.itemsatellite.nodata")); + if (SatelliteProperties.Property.DATA.isOfType(props.getPropertyFlag())) { + dataStorage = props.getMaxDataStorage(); + list.add((dataStorage > 0) + ? LibVulpes.proxy.getLocalizedString("msg.itemsatellite.data") + ZUtils.formatNumber(dataStorage) + : ChatFormatting.YELLOW + LibVulpes.proxy.getLocalizedString("msg.itemsatellite.nodata")); } - if ((weight = properties.getWeight()) > 0) - list.add(LibVulpes.proxy.getLocalizedString("msg.itemsatellite.weight") + weight); - else - list.add(ChatFormatting.YELLOW + LibVulpes.proxy.getLocalizedString("msg.itemsatellite.noweight")); + weight = props.getWeight(); + list.add((weight > 0f) + ? LibVulpes.proxy.getLocalizedString("msg.itemsatellite.weight") + weight + : ChatFormatting.YELLOW + LibVulpes.proxy.getLocalizedString("msg.itemsatellite.noweight")); + return; + } + + // --- Preview for unassembled chassis --- + EmbeddedInventory inv = readInvFromNBT(stack); - } else { + boolean hasParts = false; + for (int i = CORE_SLOT; i <= LAST_MOD_SLOT; i++) { + if (!inv.getStackInSlot(i).isEmpty()) { hasParts = true; break; } + } + if (!hasParts) { list.add(ChatFormatting.RED + LibVulpes.proxy.getLocalizedString("msg.itemsatellite.empty")); + return; } + int flags = 0; + int powerGen = 0, powerStor = 0, dataMax = 0; + float weight = 0f; + + // Core first: flags + preview type name (no weight from core) + ItemStack core = inv.getStackInSlot(CORE_SLOT); + if (!core.isEmpty()) { + SatelliteProperties cp = SatelliteRegistry.getSatelliteProperty(core); + if (cp != null) { + flags |= cp.getPropertyFlag(); + String satType = cp.getSatelliteType(); + SatelliteBase satBase = SatelliteRegistry.getNewSatellite(satType); + if (satBase != null) { + // Show same display name users will see after assembly + list.add(satBase.getName()); + } + } + } + + // Modules: stats + weight + for (int i = FIRST_MOD_SLOT; i <= LAST_MOD_SLOT; i++) { + ItemStack s = inv.getStackInSlot(i); + if (s.isEmpty()) continue; + + SatelliteProperties p = SatelliteRegistry.getSatelliteProperty(s); + if (p != null) { + flags |= p.getPropertyFlag(); + int f = p.getPropertyFlag(); + if (f == SatelliteProperties.Property.POWER_GEN.getFlag()) + powerGen += p.getPowerGeneration(); + else if (f == SatelliteProperties.Property.BATTERY.getFlag()) + powerStor += p.getPowerStorage(); + else if (f == SatelliteProperties.Property.DATA.getFlag()) + dataMax += p.getMaxDataStorage(); + } + weight += zmaster587.advancedRocketry.util.WeightEngine.INSTANCE.getWeight(s); + } + + // Match assembly semantics: base buffer is always present + powerStor += 720; + + // Always show power storage in preview (even if no battery modules are installed) + list.add(LibVulpes.proxy.getLocalizedString("msg.itemsatellite.pwr") + powerStor); + + if (SatelliteProperties.Property.POWER_GEN.isOfType(flags)) { + list.add((powerGen > 0) + ? LibVulpes.proxy.getLocalizedString("msg.itemsatellite.pwrgen") + powerGen + : ChatFormatting.RED + LibVulpes.proxy.getLocalizedString("msg.itemsatellite.nopwrgen")); + } + if (SatelliteProperties.Property.DATA.isOfType(flags)) { + list.add((dataMax > 0) + ? LibVulpes.proxy.getLocalizedString("msg.itemsatellite.data") + ZUtils.formatNumber(dataMax) + : ChatFormatting.YELLOW + LibVulpes.proxy.getLocalizedString("msg.itemsatellite.nodata")); + } + if (weight > 0f) { + list.add(LibVulpes.proxy.getLocalizedString("msg.itemsatellite.weight") + weight); + } + + // Footer LAST + list.add(ChatFormatting.RED + LibVulpes.proxy.getLocalizedString("msg.itemsatellite.unassembled")); } + } From fa2f5e98a0225de2999a82548636118557d5b76a Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 29 Oct 2025 11:39:06 +0100 Subject: [PATCH 062/424] Update weight message for satellite tooltip --- src/main/resources/assets/advancedrocketry/lang/en_US.lang | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index 865ad4a84..f899e02d0 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -458,8 +458,10 @@ msg.itemsatellite.microwavestatus=Collecting Power msg.itemsatellite.data=Data Storage: msg.itemsatellite.nodata=No Data Storage! msg.itemsatellite.empty=Empty Chassis -msg.itemsatellite.weight=Chassis weight: +msg.itemsatellite.weight=Chassis weight: msg.itemsatellite.noweight=Error in weight calculation +msg.itemsatellite.unassembled=Not assembled (preview) + msg.brokenstage.text=Destruction stage @@ -524,4 +526,3 @@ jei.sb.copy.source=Source jei.sb.copy.output=New Copy jei.sb.assemblyhint=Atleast one solar panel jei.sb.copychiphint=Make backups! - From c9a24ea33b0c67ce5adc22e3d5dba1805de989d8 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 29 Oct 2025 14:12:28 +0100 Subject: [PATCH 063/424] Remove unused import for SatelliteModuleInventory --- .../java/zmaster587/advancedRocketry/item/ItemSatellite.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java b/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java index 9ca3d49c2..ba705ca14 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java @@ -8,7 +8,6 @@ import zmaster587.advancedRocketry.api.SatelliteRegistry; import zmaster587.advancedRocketry.api.satellite.SatelliteBase; import zmaster587.advancedRocketry.api.satellite.SatelliteProperties; -import zmaster587.advancedRocketry.item.ItemSatellite.SatelliteModuleInventory; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.util.EmbeddedInventory; import zmaster587.libVulpes.util.ZUtils; From 00be1dd55930ab3c66f771828414668cba5646e5 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 29 Oct 2025 14:13:14 +0100 Subject: [PATCH 064/424] Fixed --- .../java/zmaster587/advancedRocketry/item/ItemSatellite.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java b/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java index ba705ca14..78fb03ce7 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java @@ -192,7 +192,7 @@ else if (f == SatelliteProperties.Property.DATA.getFlag()) // Always show power storage in preview (even if no battery modules are installed) list.add(LibVulpes.proxy.getLocalizedString("msg.itemsatellite.pwr") + powerStor); - + if (SatelliteProperties.Property.POWER_GEN.isOfType(flags)) { list.add((powerGen > 0) ? LibVulpes.proxy.getLocalizedString("msg.itemsatellite.pwrgen") + powerGen From b18977049e8dcc03c74abc8694dc27ffc4e74e47 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 30 Oct 2025 00:04:10 +0100 Subject: [PATCH 065/424] Remove super.init() to optimize world initialization // Removed super.init(): it recreates per-world managers (loot/adv/scoreboard/functions) will be reloaded per dimension, slow and breaks custom data. --- .../advancedRocketry/world/WorldServerNotMulti.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/world/WorldServerNotMulti.java b/src/main/java/zmaster587/advancedRocketry/world/WorldServerNotMulti.java index cf3f46408..3614f1737 100644 --- a/src/main/java/zmaster587/advancedRocketry/world/WorldServerNotMulti.java +++ b/src/main/java/zmaster587/advancedRocketry/world/WorldServerNotMulti.java @@ -56,7 +56,9 @@ protected void saveLevel() throws MinecraftException { } public World init() { - super.init(); + // Removed super.init(): it recreates per-world managers (loot/adv/scoreboard/functions) + // will be reloaded per dimension, slow and breaks custom data. + // load weather data from NBT WorldInfoSavedData wi = (WorldInfoSavedData) perWorldStorage.getOrLoadData(WorldInfoSavedData.class, "WorldInfoSavedData"); if (wi == null) { From f593ad400d2e85e00f1330869f6ebe79f14e5845 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 30 Oct 2025 11:59:53 +0100 Subject: [PATCH 066/424] Enhance data type handling in DataStorage Refactor data handling in DataStorage class to improve type management and data addition logic. --- .../advancedRocketry/api/DataStorage.java | 63 +++++++++++++++---- 1 file changed, 51 insertions(+), 12 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/api/DataStorage.java b/src/main/java/zmaster587/advancedRocketry/api/DataStorage.java index 5cb5dc963..ac53852fc 100644 --- a/src/main/java/zmaster587/advancedRocketry/api/DataStorage.java +++ b/src/main/java/zmaster587/advancedRocketry/api/DataStorage.java @@ -20,16 +20,25 @@ public DataStorage(DataType data) { } public boolean setData(int data, DataType dataType) { - if (this.dataType == DataStorage.DataType.UNDEFINED) + // If empty/typeless, allow adopting the provided type (unless locked) + if (this.dataType == DataStorage.DataType.UNDEFINED && !this.locked) { this.dataType = dataType; + } if (dataType == DataStorage.DataType.UNDEFINED || dataType == this.dataType) { this.data = Math.min(data, maxData); + + // If we just became empty and are not locked, clear type + if (!this.locked && this.data == 0) { + this.dataType = DataType.UNDEFINED; + } return true; } return false; } + + public int getData() { return data; } @@ -78,20 +87,46 @@ public boolean isLocked() { * @param dataType type to add * @return data amount added */ - public int addData(int data, DataType dataType, boolean commit) { - if ((!this.locked && (dataType == DataStorage.DataType.UNDEFINED)) || dataType == this.dataType || this.dataType == DataStorage.DataType.UNDEFINED) { + public int addData(int data, DataType incomingType, boolean commit) { + // Snapshot + final boolean empty = (this.data == 0); + DataType current = this.dataType; + + // Compute effective type without mutating state on simulation + DataType effective = current; + if (!this.locked && empty) { + effective = (incomingType != DataType.UNDEFINED) ? incomingType : DataType.UNDEFINED; + } + + // Accept if: unlocked+UNDEFINED (wildcard), same type, or typeless + boolean accepts = + (!this.locked && incomingType == DataType.UNDEFINED) || + (incomingType == effective) || + (!this.locked && effective == DataType.UNDEFINED); + + + if (!accepts) return 0; - if (this.dataType == DataStorage.DataType.UNDEFINED) - this.dataType = dataType; + int amountToAdd = Math.min(data, this.maxData - this.data); + if (amountToAdd <= 0) return 0; - int amountToAdd = Math.min(data, this.maxData - this.data); - if (commit) - this.data += amountToAdd; - return amountToAdd; + if (commit) { + // Finalize adoption only on real add + if (!this.locked && this.data == 0) { + this.dataType = (incomingType != DataType.UNDEFINED) ? incomingType : DataType.UNDEFINED; + } + this.data += amountToAdd; + + // If still UNDEFINED but we added concrete data (edge case), solidify + if (this.dataType == DataType.UNDEFINED && incomingType != DataType.UNDEFINED) { + this.dataType = incomingType; + } } - return 0; + return amountToAdd; } + + /** * @param data max amount of data to remove * @return amount of data removed @@ -122,14 +157,18 @@ public void readFromNBT(NBTTagCompound nbt) { dataType = DataType.UNDEFINED; } - - ///TODO: dev compat if (nbt.hasKey("locked")) locked = nbt.getBoolean("locked"); else locked = false; + + // >>> ADD: heal stale type on empty <<< + if (!locked && data == 0) { + dataType = DataType.UNDEFINED; + } } + public enum DataType { UNDEFINED, DISTANCE, From 50c2c2274121de48c3352da0835cd3691436f84a Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 30 Oct 2025 12:01:51 +0100 Subject: [PATCH 067/424] Add ModuleWirelessBufferBar for wireless Tranciever This class provides a minimal, read-only data bar for the wireless transceiver's internal buffer, displaying current data, max data, and data type with appropriate rendering. Avoids confusion about voided data --- .../modules/ModuleWirelessBufferBar.java | 138 ++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleWirelessBufferBar.java diff --git a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleWirelessBufferBar.java b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleWirelessBufferBar.java new file mode 100644 index 000000000..3ec7c6e66 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleWirelessBufferBar.java @@ -0,0 +1,138 @@ +package zmaster587.advancedRocketry.inventory.modules; + +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.resources.I18n; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import zmaster587.advancedRocketry.api.DataStorage; +import zmaster587.advancedRocketry.api.DataStorage.DataType; +import zmaster587.libVulpes.gui.CommonResources; +import zmaster587.libVulpes.inventory.modules.ModuleBase; + +import java.util.LinkedList; +import java.util.List; + +/** + * Minimal, read-only data bar for the wireless transceiver's internal buffer. + * - No buttons + * - No slots + * - Server-authoritative: syncs amount, max, and type via tiny window properties. + */ +public class ModuleWirelessBufferBar extends ModuleBase { + + // Reuse same visuals as ModuleData so it looks consistent + static final int BAR_Y_SIZE = 38; + static final int BAR_X_SIZE = 6; + static final int TEX_OFFSET_X = 0; + static final int TEX_OFFSET_Y = 215; + + private final DataStorage data; // points to your uiBuffer + private int prevAmount = -1; + private int prevMax = -1; + private int prevTypeOrdinal = -1; + + public ModuleWirelessBufferBar(int offsetX, int offsetY, DataStorage data) { + super(offsetX, offsetY); + this.data = data; + this.sizeX = 10; // hitbox-ish; not used for layout + this.sizeY = BAR_Y_SIZE + 12; + } + + @Override + public int numberOfChangesToSend() { + // amount, max, type + return 3; + } + + @Override + public boolean needsUpdate(int localId) { + switch (localId) { + case 0: return data.getData() != prevAmount; + case 1: return data.getMaxData() != prevMax; + case 2: return data.getDataType().ordinal() != prevTypeOrdinal; + default: return false; + } + } + + @Override + protected void updatePreviousState(int localId) { + if (localId == 0) prevAmount = data.getData(); + else if (localId == 1) prevMax = data.getMaxData(); + else if (localId == 2) prevTypeOrdinal = data.getDataType().ordinal(); + } + + @Override + public void sendChanges(net.minecraft.inventory.Container container, + net.minecraft.inventory.IContainerListener crafter, + int variableId, int localId) { + int v; + if (localId == 0) v = data.getData(); + else if (localId == 1) v = data.getMaxData(); + else /* localId == 2 */ v = data.getDataType().ordinal(); + crafter.sendWindowProperty(container, variableId, v); + } + + @Override + public void onChangeRecieved(int slot, int value) { + if (slot == 0) { + // amount (type set below or left unchanged) + data.setData(value, DataType.UNDEFINED); + } else if (slot == 1) { + data.setMaxData(value); + } else if (slot == 2) { + DataType t = DataType.values()[Math.max(0, Math.min(DataType.values().length - 1, value))]; + data.setDataType(t); + } + } + + @SideOnly(Side.CLIENT) + @Override + public void renderForeground(int guiOffsetX, int guiOffsetY, int mouseX, int mouseY, float zLevel, + GuiContainer gui, FontRenderer font) { + int relX = mouseX - offsetX; + int relY = mouseY - offsetY; + if (relX >= 0 && relX < BAR_X_SIZE && relY >= 0 && relY < BAR_Y_SIZE) { + List tt = new LinkedList<>(); + // "Data" + tt.add(net.minecraft.client.resources.I18n.format( + "msg.tooltip.data") + " " + data.getData() + " / " + data.getMaxData()); + + // "Type: %s" with translated type + String typeName = net.minecraft.client.resources.I18n.format(data.getDataType().toString()); + tt.add(net.minecraft.client.resources.I18n.format("msg.wirelessTransciever.type", typeName)); + + + this.drawTooltip(gui, tt, mouseX, mouseY, zLevel, font); + } + } + + + @SideOnly(Side.CLIENT) + @Override + public void renderBackground(GuiContainer gui, int x, int y, int mouseX, int mouseY, FontRenderer font) { + // Bind the correct texture (same sheet as ModuleData) + gui.mc.getTextureManager().bindTexture(CommonResources.genericBackground); + + // Draw only the bar frame (8x40 at UV 176,18) + gui.drawTexturedModalRect(offsetX + x, offsetY + y, 176, 18, 8, 40); + + // Compute fill amount + int max = Math.max(1, data.getMaxData()); + float percent = Math.min(1f, Math.max(0f, data.getData() / (float) max)); + int filled = (int) (percent * BAR_Y_SIZE); + + // Draw the green fill (6 x filled) from UV (0, 215 + (BAR_Y_SIZE - filled)) + // Fill grows upward inside the frame + if (filled > 0) { + gui.drawTexturedModalRect( + offsetX + x + 1, + offsetY + y + 1 + (BAR_Y_SIZE - filled), + 0, + 215 + (BAR_Y_SIZE - filled), + BAR_X_SIZE, + filled + ); + } + } +} From 9aebe12fcb7f879332766ac640712b072be5b746 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 30 Oct 2025 12:36:52 +0100 Subject: [PATCH 068/424] Implement auto-download with exponential backoff Added auto-download functionality with exponential backoff and improved satellite handling. Wireless Transciever opens up for autodownload --- .../tile/satellite/TileSatelliteTerminal.java | 206 ++++++++++++++---- 1 file changed, 166 insertions(+), 40 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java index 0c805adea..9346726cc 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java @@ -4,6 +4,8 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.EnumFacing; import net.minecraftforge.fml.relauncher.Side; import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; @@ -30,7 +32,8 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; -import java.util.LinkedList; + +import java.util.ArrayList; import java.util.List; public class TileSatelliteTerminal extends TileInventoriedRFConsumer @@ -38,15 +41,121 @@ public class TileSatelliteTerminal extends TileInventoriedRFConsumer private DataStorage data; + // Auto-download polling with exponential backoff + private static final int AUTO_DL_BASE_INTERVAL_TICKS = 64; // min interval + private static final int AUTO_DL_MAX_INTERVAL_TICKS = 512; // cap + private int autoDlInterval = AUTO_DL_BASE_INTERVAL_TICKS; // current interval + private long nextAutoDlTick = 0L; // worldTime gate + + public TileSatelliteTerminal() { super(10000, 2); data = new DataStorage(); data.setMaxData(1000); } + private final BlockPos.MutableBlockPos mpos = new BlockPos.MutableBlockPos(); + + private boolean hasExtractPlugAdjacent() { + if (world == null) return false; + for (EnumFacing f : EnumFacing.values()) { + mpos.setPos(pos.getX() + f.getFrontOffsetX(), + pos.getY() + f.getFrontOffsetY(), + pos.getZ() + f.getFrontOffsetZ()); + if (!world.isBlockLoaded(mpos)) continue; + + TileEntity te = world.getTileEntity(mpos); + if (te instanceof zmaster587.advancedRocketry.tile.cables.TileWirelessTransciever) { + zmaster587.advancedRocketry.tile.cables.TileWirelessTransciever w = + (zmaster587.advancedRocketry.tile.cables.TileWirelessTransciever) te; + if (w.isEnabledWireless() && w.isExtractModeWireless()) return true; + } + } + return false; + } + + + + // Link+power check using an already-looked-up satellite + private boolean hasLinkAndPower(@Nonnull SatelliteBase sat) { + // must be a data satellite + if (!(sat instanceof zmaster587.advancedRocketry.satellite.SatelliteData)) return false; + + // check range + final int hereDim = zmaster587.advancedRocketry.dimension.DimensionManager + .getEffectiveDimId(world, pos).getId(); + final int satDim = sat.getDimensionId(); + + final boolean inRange = zmaster587.advancedRocketry.util.PlanetaryTravelHelper + .isTravelAnywhereInPlanetarySystem(satDim, hereDim); + if (!inRange) return false; + + // check power + return getUniversalEnergyStored() >= getPowerPerOperation(); + } + + // Keep convenience overload + private void maybeAutoDownloadFromSatellite() { + maybeAutoDownloadFromSatellite(false); + } + + private void maybeAutoDownloadFromSatellite(boolean force) { + if (world == null || world.isRemote) return; + + final long now = world.getTotalWorldTime(); + + if (force) { + autoDlInterval = AUTO_DL_BASE_INTERVAL_TICKS; + nextAutoDlTick = now + autoDlInterval; // avoid same-tick multi-pulls + } else if (now < nextAutoDlTick) { + return; + } + + // Buffer full → just schedule next check + if (data.getData() >= data.getMaxData()) { + nextAutoDlTick = now + autoDlInterval; + return; + } + + // No eligible plug → back off (unless forced) + if (!hasExtractPlugAdjacent()) { + if (!force) autoDlInterval = Math.min(autoDlInterval << 1, AUTO_DL_MAX_INTERVAL_TICKS); + nextAutoDlTick = now + autoDlInterval; + return; + } + + // Hoist satellite once + final SatelliteBase sat = getCachedSatellite(); + if (sat == null) { + if (!force) autoDlInterval = Math.min(autoDlInterval << 1, AUTO_DL_MAX_INTERVAL_TICKS); + nextAutoDlTick = now + autoDlInterval; + return; + } + + + + // No link or power → back off (unless forced) + if (!hasLinkAndPower(sat)) { + if (!force) autoDlInterval = Math.min(autoDlInterval << 1, AUTO_DL_MAX_INTERVAL_TICKS); + nextAutoDlTick = now + autoDlInterval; + return; + } + + // Do the pull + sat.performAction(null, world, pos); + this.energy.extractEnergy(getPowerPerOperation(), false); + + // Success → reset interval + autoDlInterval = AUTO_DL_BASE_INTERVAL_TICKS; + nextAutoDlTick = now + autoDlInterval; + } + + + private static final int[] NO_SLOTS = new int[0]; + @Override @Nonnull - public int[] getSlotsForFace(@Nullable EnumFacing side) { return new int[0]; } + public int[] getSlotsForFace(@Nullable EnumFacing side) { return NO_SLOTS; } @Override public String getModularInventoryName() { @@ -58,7 +167,9 @@ public String getModularInventoryName() { @Override public boolean canPerformFunction() { - return world.getTotalWorldTime() % 16 == 0 && getSatelliteFromSlot(0) != null; + if (world == null) return false; + final long now = world.getTotalWorldTime(); + return (now % 16 == 0) && (now >= nextAutoDlTick); } @Override @@ -66,9 +177,12 @@ public boolean canPerformFunction() { @Override public void performFunction() { - // No client push here anymore; module sync handles display updates. + if (world == null || world.isRemote) return; + maybeAutoDownloadFromSatellite(false); } + + // Old custom packet not used anymore; keep empty to satisfy INetworkMachine @Override public void writeDataToNetwork(ByteBuf out, byte packetId) { } @@ -131,11 +245,21 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompou } } + @Nullable private SatelliteBase cachedSat = null; + @Override public void setInventorySlotContents(int slot, @Nonnull ItemStack stack) { super.setInventorySlotContents(slot, stack); + if (!world.isRemote && slot == 0) { + cachedSat = (!stack.isEmpty() && stack.getItem() instanceof ItemSatelliteIdentificationChip) + ? ItemSatelliteIdentificationChip.getSatellite(stack) + : null; + maybeAutoDownloadFromSatellite(true); // force reset to base + } } + private @Nullable SatelliteBase getCachedSatellite() { return cachedSat; } + public SatelliteBase getSatelliteFromSlot(int slot) { ItemStack stack = getStackInSlot(slot); if (!stack.isEmpty() && stack.getItem() instanceof ItemSatelliteIdentificationChip) { @@ -146,15 +270,20 @@ public SatelliteBase getSatelliteFromSlot(int slot) { @Override public List getModules(int ID, EntityPlayer player) { - List modules = new LinkedList<>(); + List modules = new ArrayList<>(6); modules.add(new ModulePower(18, 20, this.energy) { @Override public int numberOfChangesToSend() { return 2; } }); - modules.add(new ModuleButton(116, 70, 0, + modules.add(new ModuleButton( + 116, 70, 0, LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.connect"), - this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); + this, + zmaster587.libVulpes.inventory.TextureResources.buttonBuild, + LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.autodl_hint") // tooltip + )); + modules.add(new ModuleButton(173, 3, 1, "", this, TextureResources.buttonKill, @@ -219,43 +348,21 @@ public void storeData(int id) { @Override public int extractData(int maxAmount, DataType type, EnumFacing dir, boolean commit) { - // 1) Type guard (unchanged) - if (type != data.getDataType() && data.getDataType() != DataType.UNDEFINED) { - return 0; - } + // 1) Type guard + if (type != data.getDataType() && data.getDataType() != DataType.UNDEFINED) return 0; - // 2) Simulation: report local only (don’t guess satellite yield) - if (!commit) { - int availableLocal = data.getData(); - return Math.min(maxAmount, availableLocal); - } - - // 3) Drain LOCAL first, chip or no chip - int availableLocal = data.getData(); - int toGive = Math.min(maxAmount, availableLocal); - int removed = 0; - if (toGive > 0) { - removed = data.removeData(toGive, true); - } + // 2) Simulation + if (!commit) return Math.min(maxAmount, data.getData()); - // 4) If we have link+power, auto-download to refill AFTER the pull - SatelliteBase sat = getSatelliteFromSlot(0); - boolean inRange = false; - if (sat != null) { - int satDim = sat.getDimensionId(); - int hereDim = DimensionManager.getEffectiveDimId(world, pos).getId(); - inRange = PlanetaryTravelHelper.isTravelAnywhereInPlanetarySystem(satDim, hereDim); - } - boolean hasLink = (sat instanceof SatelliteData) && inRange; - boolean hasPower = getUniversalEnergyStored() >= getPowerPerOperation(); + // 3) Drain LOCAL once + int toGive = Math.min(maxAmount, data.getData()); + int removed = (toGive > 0) ? data.removeData(toGive, true) : 0; - if (hasLink && hasPower) { - sat.performAction(null, world, pos); // same as GUI Download - this.energy.extractEnergy(getPowerPerOperation(), false); - // (No immediate extra removal here; we already served the request.) + // 4) Opportunistic refill (cheap guard inside function) + if (removed > 0) { + maybeAutoDownloadFromSatellite(true); } - - return removed; // may be 0 if buffer empty and no link/power + return removed; } @@ -266,6 +373,25 @@ public int addData(int maxAmount, DataType type, EnumFacing dir, boolean commit) return added; } + @Override + public void onLoad() { + super.onLoad(); + if (!world.isRemote) { + // Rebuild cache from current slot-0 + ItemStack s0 = getStackInSlot(0); + cachedSat = (!s0.isEmpty() && s0.getItem() instanceof ItemSatelliteIdentificationChip) + ? ItemSatelliteIdentificationChip.getSatellite(s0) + : null; + + autoDlInterval = AUTO_DL_BASE_INTERVAL_TICKS; + nextAutoDlTick = Math.min(nextAutoDlTick, world.getTotalWorldTime() + AUTO_DL_MAX_INTERVAL_TICKS); + maybeAutoDownloadFromSatellite(false); + } + } + + + + @Override public boolean canInteractWithContainer(EntityPlayer entity) { return true; } } From 0c363b1ce5b95812cd4e436f3c36dce0c8b2a8c6 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 30 Oct 2025 12:38:38 +0100 Subject: [PATCH 069/424] Refactor TileWirelessTransciever code structure added databar and langkeys to GUI --- .../tile/cables/TileWirelessTransciever.java | 128 ++++++++++++++---- 1 file changed, 99 insertions(+), 29 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java b/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java index b3f5ce015..1f8c9187a 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java @@ -2,7 +2,6 @@ import io.netty.buffer.ByteBuf; import net.minecraft.block.state.IBlockState; -import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; @@ -28,24 +27,28 @@ import zmaster587.libVulpes.inventory.modules.ModuleBase; import zmaster587.libVulpes.inventory.modules.ModuleText; import zmaster587.libVulpes.inventory.modules.ModuleToggleSwitch; +import zmaster587.advancedRocketry.inventory.modules.ModuleWirelessBufferBar; import zmaster587.libVulpes.items.ItemLinker; import zmaster587.libVulpes.network.PacketHandler; import zmaster587.libVulpes.network.PacketMachine; import zmaster587.libVulpes.util.INetworkMachine; + + import javax.annotation.Nonnull; import java.util.LinkedList; import java.util.List; public class TileWirelessTransciever extends TileEntity implements INetworkMachine, IModularInventory, ILinkableTile, IDataHandler, ITickable, IToggleButton { - // How often to transfer data (in ticks) - private int transferIntervalTicks = 20; - // Fixed phase per tile to spread load - private int phase = -1; - // Show network ID (label) - private ModuleText netIdLabel; - + + private int transferIntervalTicks = 20; // How often to transfer data (in ticks) + private int phase = -1; // Fixed phase per tile to spread load + private ModuleText netIdLabel; // Show network ID (label) + private final DataStorage uiBuffer = new DataStorage(); // UI-only, never used for logic + + + // Avoid per-call allocations from DataType.values() // needs update if DataType enum changes private static final DataType[] TYPES = { @@ -65,6 +68,9 @@ public TileWirelessTransciever() { networkID = -1; data = new MultiData(); data.setMaxData(100); + uiBuffer.setMaxData(data.getMaxData()); // UI mirror max should match MultiData max + uiBuffer.setData(0, DataType.UNDEFINED); + syncUiBufferFromMultiData(); toggle = new ModuleToggleSwitch(50, 50, 0, LibVulpes.proxy.getLocalizedString("msg.wirelessTransciever.extract"), this, TextureResources.buttonGeneric, 64, 18, false); toggleSwitch = new ModuleToggleSwitch(160, 5, 1, "", this, zmaster587.libVulpes.inventory.TextureResources.buttonToggleImage, 11, 26, true); @@ -74,8 +80,45 @@ public TileWirelessTransciever() { updateToggleLabel(); // Network ID label - netIdLabel = new ModuleText(40, 72, "Network: -", 0x000000); - netIdLabel.setAlwaysOnTop(true); // optional, so it renders over slots + String initial = LibVulpes.proxy.getLocalizedString("msg.wirelessTransciever.network") + " -"; + netIdLabel = new ModuleText(40, 72, initial, 0x000000); + netIdLabel.setAlwaysOnTop(true); + + } + + // Helpers for other terminals to query state + public boolean isEnabledWireless() { + return this.enabled; + } + public boolean isExtractModeWireless() { + return this.extractMode; + } + + // helper for syncing UI buffer from multiData + private void syncUiBufferFromMultiData() { + int total = 0; + int max = data.getMaxData(); + + int nonZero = 0; + DataType lastTypeWithData = DataType.UNDEFINED; + + for (DataType t : TYPES) { + int amt = data.getDataAmount(t); + if (amt > 0) { + nonZero++; + lastTypeWithData = t; + total += amt; + } + } + + if (total < 0) total = 0; + if (total > max) total = max; + + final DataType displayType = (nonZero == 1) ? lastTypeWithData : DataType.UNDEFINED; + + // Mirror into UI-only storage (server-authoritative; GUI module will poll this) + uiBuffer.setMaxData(max); + uiBuffer.setData(total, displayType); } private void updateToggleLabel() { @@ -222,11 +265,15 @@ public List getModules(int id, EntityPlayer player) { list.add(toggle); list.add(toggleSwitch); - list.add(netIdLabel); + list.add(netIdLabel); + + // Bar-only UI (no buttons/slots). Place it where you want it. + list.add(new ModuleWirelessBufferBar(14, 22, uiBuffer)); return list; } + @Override public String getModularInventoryName() { return "tile.wirelessTransciever.name"; @@ -255,25 +302,31 @@ public void readDataFromNetwork(ByteBuf in, byte packetId, @Override public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompound nbt) { if (!side.isServer()) return; - if (id == 1) { // enable/disable toggle doesn’t touch networks + + if (id == 1) { // enable/disable toggle — always allowed enabled = nbt.getBoolean("state"); return; } - if (networkID == -1) return; // not linked yet; ignore network mutations - if (id == 0) { + if (id == 0) { // extract/insert toggle + // Always update local state so neighbors (like the terminal) can see it extractMode = nbt.getBoolean("state"); updateToggleLabel(); - if (NetworkRegistry.dataNetwork.doesNetworkExist(networkID)) { + + // Only touch the network if we are actually linked + if (networkID != -1 && NetworkRegistry.dataNetwork.doesNetworkExist(networkID)) { NetworkRegistry.dataNetwork.getNetwork(networkID).removeFromAll(this); - if (extractMode) + if (extractMode) { NetworkRegistry.dataNetwork.getNetwork(networkID).addSource(this, EnumFacing.UP); - else + } else { NetworkRegistry.dataNetwork.getNetwork(networkID).addSink(this, EnumFacing.UP); + } } + return; } } + @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); @@ -282,21 +335,25 @@ public void readFromNBT(NBTTagCompound nbt) { enabled = nbt.getBoolean("enabled"); networkID = nbt.getInteger("networkID"); data.readFromNBT(nbt); + syncUiBufferFromMultiData(); //addToNetwork(); toggle.setToggleState(extractMode); updateToggleLabel(); toggleSwitch.setToggleState(enabled); if (world != null && world.isRemote && netIdLabel != null) { - netIdLabel.setText("Network: " + networkID); + String idStr = (networkID == -1) + ? net.minecraft.client.resources.I18n.format("msg.wirelessTransciever.network.unlinked") + : Integer.toString(networkID); + String label = LibVulpes.proxy.getLocalizedString("msg.wirelessTransciever.network"); + netIdLabel.setText(label + idStr); } - } - + @Override @Nonnull public NBTTagCompound writeToNBT(NBTTagCompound nbt) { - super.writeToNBT(nbt); // MOVE: call first + super.writeToNBT(nbt); nbt.setBoolean("mode", extractMode); nbt.setBoolean("enabled", enabled); nbt.setInteger("networkID", networkID); @@ -306,21 +363,35 @@ public NBTTagCompound writeToNBT(NBTTagCompound nbt) { @Override - public int extractData(int maxAmount, DataType type, EnumFacing dir, - boolean commit) { - return enabled ? data.extractData(maxAmount, type, dir, commit) : 0; + public int extractData(int maxAmount, DataType type, EnumFacing dir, boolean commit) { + int out = enabled ? data.extractData(maxAmount, type, dir, commit) : 0; + if (commit && out > 0) { + syncUiBufferFromMultiData(); + } + return out; } @Override - public int addData(int maxAmount, DataType type, EnumFacing dir, - boolean commit) { - return enabled ? data.addData(maxAmount, type, dir, commit) : 0; + public int addData(int maxAmount, DataType type, EnumFacing dir, boolean commit) { + int in = enabled ? data.addData(maxAmount, type, dir, commit) : 0; + if (commit && in > 0) { + syncUiBufferFromMultiData(); + } + return in; } + @Override public void onLoad() { super.onLoad(); + if (!world.isRemote) { + syncUiBufferFromMultiData(); // ensures server-side mirror matches after load + // Ensure booleans reflect current UI widgets on server after load/place + extractMode = toggle.getState(); + enabled = toggleSwitch.getState(); + } + // Server side only if (world == null || world.isRemote) return; @@ -408,8 +479,7 @@ public void update() { // Persist changes; a full block update isn't strictly required each tick if (changed) { this.markDirty(); - // If you want to sync the client meter instantly, you can uncomment: - // world.notifyBlockUpdate(pos, state, state, 3); + syncUiBufferFromMultiData(); } } From 609ecdef7e24d11d779856ac0480072c530b2db5 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 30 Oct 2025 13:00:59 +0100 Subject: [PATCH 070/424] Prevent duplicate chipwrites for same seed and button Added functionality to prevent duplicate chipwrites for the same seed and button in TileObservatory. --- .../tile/multiblock/TileObservatory.java | 84 ++++++++++++++++--- 1 file changed, 74 insertions(+), 10 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java index 0f3619525..9fa3a02db 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java @@ -49,6 +49,10 @@ public class TileObservatory extends TileMultiPowerConsumer implements IModularInventory, IDataInventory, IGuiCallback { + // Dont allow duplicate chipwrites for the same seed + button + private java.util.HashSet printedButtonsThisSeed = new java.util.HashSet<>(); + private long printedSetSeed = -1; // track which seed the set belongs to + final static int openTime = 100; final static int observationTime = 1000; private static final Block[] lens = {AdvancedRocketryBlocks.blockLens, Blocks.GLASS}; @@ -234,35 +238,56 @@ protected void writeNetworkData(NBTTagCompound nbt) { nbt.setInteger("lastButton", lastButton); if (lastType != null && !lastType.isEmpty()) nbt.setString("lastType", lastType); + + nbt.setLong("printedSetSeed", printedSetSeed); + if (!printedButtonsThisSeed.isEmpty()) { + int[] arr = printedButtonsThisSeed.stream().mapToInt(Integer::intValue).toArray(); + nbt.setIntArray("printedButtons", arr); + } } @Override protected void readNetworkData(NBTTagCompound nbt) { super.readNetworkData(nbt); openProgress = nbt.getInteger("openProgress"); - isOpen = nbt.getBoolean("isOpen"); - viewDistance = nbt.getInteger("viewableDist"); lastSeed = nbt.getLong("lastSeed"); lastButton = nbt.getInteger("lastButton"); lastType = nbt.getString("lastType"); + + printedSetSeed = nbt.getLong("printedSetSeed"); + printedButtonsThisSeed.clear(); + int[] arr = nbt.getIntArray("printedButtons"); + if (arr != null) for (int v : arr) printedButtonsThisSeed.add(v); } + @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); inv.writeToNBT(nbt); + + nbt.setLong("printedSetSeed", printedSetSeed); + if (!printedButtonsThisSeed.isEmpty()) { + int[] arr = printedButtonsThisSeed.stream().mapToInt(Integer::intValue).toArray(); + nbt.setIntArray("printedButtons", arr); + } return nbt; } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); - inv.readFromNBT(nbt); + + printedSetSeed = nbt.getLong("printedSetSeed"); + printedButtonsThisSeed.clear(); + int[] arr = nbt.getIntArray("printedButtons"); + if (arr != null) for (int v : arr) printedButtonsThisSeed.add(v); } + public LinkedList getDataBus() { return dataCables; } @@ -314,15 +339,20 @@ public List getModules(int ID, EntityPlayer player) { ); // `isOpen` is synchronized to client via writeNetworkData/readNetworkData, so safe to read here. + boolean alreadyPrinted = (lastButton != -1) && printedButtonsThisSeed.contains(lastButton); + if (!isOpen) { - // Show requirements when the dome isn't open (daytime, raining, no sky, etc.) - String tooltip = LibVulpes.proxy.getLocalizedString("msg.observetory.req.open"); - processBtn.setToolTipText(tooltip); + processBtn.setToolTipText(LibVulpes.proxy.getLocalizedString("msg.observetory.req.open")); + processBtn.setEnabled(true); + } else if (alreadyPrinted) { + processBtn.setToolTipText(LibVulpes.proxy.getLocalizedString("msg.observetory.print.already")); + processBtn.setEnabled(false); // <-- } else { - // Keep your normal tooltip when open processBtn.setToolTipText(LibVulpes.proxy.getLocalizedString("msg.observetory.text.processdiscovery")); + processBtn.setEnabled(true); } + // Keep it enabled so the tooltip renders (ModuleButton.isMouseOver checks enabled) processBtn.setEnabled(true); @@ -557,6 +587,9 @@ else if (id == SEED_CHANGE) { lastButton = -1; lastType = ""; + printedButtonsThisSeed.clear(); + printedSetSeed = lastSeed; + // Clear scroll cache when scanning new data ModuleContainerPanYOnlyWithScrollCache.clearScrollCache(); @@ -568,20 +601,51 @@ else if (id == SEED_CHANGE) { } else if (id == PROCESS_CHIP && !world.isRemote) { + // Keep printed set aligned with current seed (covers edge cases like load) + if (printedSetSeed != lastSeed) { + printedButtonsThisSeed.clear(); + printedSetSeed = lastSeed; + } + + // Hard block duplicates for this scan/selection + if (lastButton != -1 && printedButtonsThisSeed.contains(lastButton)) { + // No status message; just refresh UI so tooltip updates + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); + markDirty(); + if (player != null) { + player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), + getWorld(), pos.getX(), pos.getY(), pos.getZ()); + } + return; + } + if (inv.getStackInSlot(2).isEmpty() && isOpen && hasEnergy(500) && lastButton != -1) { ItemStack stack = inv.decrStackSize(1, 1); if (stack != ItemStack.EMPTY && stack.getItem() instanceof ItemAsteroidChip) { - ((ItemAsteroidChip) (stack.getItem())).setUUID(stack, lastSeed + lastButton); - ((ItemAsteroidChip) (stack.getItem())).setType(stack, lastType); - ((ItemAsteroidChip) (stack.getItem())).setMaxData(stack, 1000); + ((ItemAsteroidChip)(stack.getItem())).setUUID(stack, lastSeed + lastButton); + ((ItemAsteroidChip)(stack.getItem())).setType(stack, lastType); + ((ItemAsteroidChip)(stack.getItem())).setMaxData(stack, 1000); inv.setInventorySlotContents(2, stack); extractData(1000, DataType.COMPOSITION, EnumFacing.UP, true); extractData(1000, DataType.MASS, EnumFacing.UP, true); useEnergy(500); + + // Mark this selection as consumed for this seed + printedButtonsThisSeed.add(lastButton); + + // Sync + rebuild GUI so tooltip and button state update immediately + markDirty(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); + if (player != null) { + player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), + getWorld(), pos.getX(), pos.getY(), pos.getZ()); + } } } } + + } @Override From 28a9feae12b5d42d9a8f6df41d04aadbe7263650 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 30 Oct 2025 13:46:13 +0100 Subject: [PATCH 071/424] Update modVersion to 2.2.1 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 474210579..b16343f8a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ org.gradle.daemon=false # Project mcVersion=1.12.2 forgeVersion=14.23.5.2860 -modVersion=2.2.0 +modVersion=2.2.1 archiveBase=AdvancedRocketry startGitRev=8e676bd From 815567120b13cfa84595ee4307dae1decb535af5 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 1 Nov 2025 14:08:45 +0100 Subject: [PATCH 072/424] Optimize data extraction in TileObservatory Removed redundant data extraction calls for composition and mass. --- .../advancedRocketry/tile/multiblock/TileObservatory.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java index 9fa3a02db..3f1e3dcc4 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java @@ -627,8 +627,6 @@ else if (id == PROCESS_CHIP && !world.isRemote) { ((ItemAsteroidChip)(stack.getItem())).setMaxData(stack, 1000); inv.setInventorySlotContents(2, stack); - extractData(1000, DataType.COMPOSITION, EnumFacing.UP, true); - extractData(1000, DataType.MASS, EnumFacing.UP, true); useEnergy(500); // Mark this selection as consumed for this seed From a0a6b44d974cbcfea8c142b44db546c38fcab996 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 1 Nov 2025 14:09:47 +0100 Subject: [PATCH 073/424] Fix missing newline at end of ItemSatellite.java Added missing newline at the end of the file. From 9f53a714e17f62c91969843b473f044b06d5bc7e Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 2 Nov 2025 10:36:07 +0100 Subject: [PATCH 074/424] removed useless GUI calculation when player arent even looking MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit originally recomputed and updated the GUI text every tick so the ModuleTexts were always “fresh,” even when no GUI was open. --- .../station/TileStationGravityController.java | 153 +++++++++++++----- 1 file changed, 114 insertions(+), 39 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationGravityController.java b/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationGravityController.java index 51446c235..e1f863c37 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationGravityController.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationGravityController.java @@ -1,6 +1,8 @@ package zmaster587.advancedRocketry.tile.station; import io.netty.buffer.ByteBuf; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.NetworkManager; @@ -54,14 +56,95 @@ public static int getMinGravity() { public List getModules(int id, EntityPlayer player) { List modules = new LinkedList<>(); modules.add(moduleGrav); - //modules.add(numThrusters); modules.add(maxGravBuildSpeed); modules.add(redstoneControl); modules.add(targetGrav); modules.add(new ModuleSlider(6, 60, 0, TextureResources.doubleWarningSideBarIndicator, this)); - updateText(); + // inline updater that runs only while GUI is open + modules.add(new ModuleBase(0, 0) { + // --- Caches (live only for GUI lifetime) --- + private SpaceStationObject cached; // strong ref during GUI life + private int cachedId = Integer.MIN_VALUE; // station id for validation + + // last *displayed* keys (so we only update text when the user can see a change) + private int lastGravKey = Integer.MIN_VALUE; // 2dp: round(grav*100) + private int lastRateKey = Integer.MIN_VALUE; // 1dp: round(rate*10) + private int lastTgtKey = Integer.MIN_VALUE; // int + + // localized prefixes + private final String prefixGrav = LibVulpes.proxy.getLocalizedString("msg.stationgravctrl.alt"); + private final String prefixMax = LibVulpes.proxy.getLocalizedString("msg.stationgravctrl.maxaltrate"); + private final String prefixTgt = LibVulpes.proxy.getLocalizedString("msg.stationgravctrl.tgtalt"); + + // tiny formatters (no String.format churn) --- + private String twoDpFromKey(int key) { // key = round(value * 100) + int abs = Math.abs(key), whole = abs / 100, frac = abs % 100; + String s = whole + "." + (frac < 10 ? "0" : "") + frac; + return key < 0 ? "-" + s : s; + } + private String oneDpFromKey(int key) { // key = round(value * 10) + int abs = Math.abs(key), whole = abs / 10, frac = abs % 10; + String s = whole + "." + frac; + return key < 0 ? "-" + s : s; + } + + // Resolve or revalidate the cached station safely. + private boolean ensureStation() { + // Resolve if no cache yet + if (cached == null) { + ISpaceObject so = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); + if (!(so instanceof SpaceStationObject)) return false; + cached = (SpaceStationObject) so; + cachedId = so.getId(); + return true; + } + // Revalidate in case manager swapped instances + ISpaceObject current = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); + if (!(current instanceof SpaceStationObject)) { cached = null; cachedId = Integer.MIN_VALUE; return false; } + if (current.getId() != cachedId) { // instance swapped or different station under pos + cached = (SpaceStationObject) current; + cachedId = current.getId(); + } + return true; + } + + @Override + public void renderBackground(GuiContainer gui, int x, int y, int mouseX, int mouseY, FontRenderer font) { + // Only runs while GUI is visible → zero idle cost when closed. + if (!ensureStation()) return; + + // Pull current (client-synced) values + float grav = cached.getProperties().getGravitationalMultiplier(); // e.g. 0.57 + double maxRate = 7200D * cached.getMaxRotationalAcceleration(); // e.g. 144.0 + int tgt = cached.targetGravity; // 10..100 + + // Compute compare keys at display precision + int gravKey = Math.round(grav * 100f); // 2dp + int rateKey = (int)Math.round(maxRate * 10d); // 1dp + int tgtKey = tgt; // int + + // Only touch ModuleText when the visible value actually changes + if (gravKey != lastGravKey) { + moduleGrav.setText(prefixGrav + twoDpFromKey(gravKey)); + lastGravKey = gravKey; + } + if (rateKey != lastRateKey) { + maxGravBuildSpeed.setText(prefixMax + oneDpFromKey(rateKey)); + lastRateKey = rateKey; + } + if (tgtKey != lastTgtKey) { + targetGrav.setText(prefixTgt + tgtKey); + lastTgtKey = tgtKey; + } + } + + @Override public int getSizeX() { return 0; } // no visual footprint + @Override public int getSizeY() { return 0; } + }); + + return modules; } @@ -103,49 +186,41 @@ private void updateText() { @Override public void update() { + if (!(this.world.provider instanceof WorldProviderSpace)) return; - if (this.world.provider instanceof WorldProviderSpace) { + if (!world.isRemote) { + ISpaceObject spaceObject = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); + if (spaceObject == null) return; - if (!world.isRemote) { - ISpaceObject spaceObject = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); + if (redstoneControl.getState() == RedstoneState.ON) { + ((SpaceStationObject) spaceObject).targetGravity = (world.getStrongPower(pos) * 6) + 10; + } else if (redstoneControl.getState() == RedstoneState.INVERTED) { + ((SpaceStationObject) spaceObject).targetGravity = Math.abs(15 - world.getStrongPower(pos)) * 6 + 10; + } - if (spaceObject != null) { - if (redstoneControl.getState() == RedstoneState.ON) - ((SpaceStationObject) spaceObject).targetGravity = (world.getStrongPower(pos) * 6) + 10; - else if (redstoneControl.getState() == RedstoneState.INVERTED) - ((SpaceStationObject) spaceObject).targetGravity = Math.abs(15 - world.getStrongPower(pos)) * 6 + 10; - - progress = ((SpaceStationObject) spaceObject).targetGravity - minGravity; - - int targetMultiplier = (ARConfiguration.getCurrentConfig().allowZeroGSpacestations) ? ((SpaceStationObject) spaceObject).targetGravity : Math.max(10, ((SpaceStationObject) spaceObject).targetGravity); - double targetGravity = targetMultiplier / 100D; - double angVel = spaceObject.getProperties().getGravitationalMultiplier(); - double acc = 0.001; - - double difference = targetGravity - angVel; - - if (Math.abs(difference) >= 0.001) { - double finalVel = angVel; - if (difference < 0) { - finalVel = angVel + Math.max(difference, -acc); - } else if (difference > 0) { - finalVel = angVel + Math.min(difference, acc); - } - - spaceObject.getProperties().setGravitationalMultiplier((float) finalVel); - if (!world.isRemote) { - //PacketHandler.sendToNearby(new PacketStationUpdate(spaceObject, PacketStationUpdate.Type.ROTANGLE_UPDATE), this.worldObj.provider.dimensionId, this.xCoord, this.yCoord, this.zCoord, 1024); - PacketHandler.sendToAll(new PacketStationUpdate(spaceObject, PacketStationUpdate.Type.DIM_PROPERTY_UPDATE)); - markDirty(); - } else - updateText(); - } - } - } else - updateText(); + progress = ((SpaceStationObject) spaceObject).targetGravity - minGravity; + + int targetMultiplier = ARConfiguration.getCurrentConfig().allowZeroGSpacestations + ? ((SpaceStationObject) spaceObject).targetGravity + : Math.max(10, ((SpaceStationObject) spaceObject).targetGravity); + + double targetGravity = targetMultiplier / 100D; + double angVel = spaceObject.getProperties().getGravitationalMultiplier(); + double acc = 0.001; + + double difference = targetGravity - angVel; + if (Math.abs(difference) >= 0.001) { + double finalVel = angVel + (difference < 0 ? Math.max(difference, -acc) : Math.min(difference, acc)); + spaceObject.getProperties().setGravitationalMultiplier((float) finalVel); + + // networking unchanged + PacketHandler.sendToAll(new PacketStationUpdate(spaceObject, PacketStationUpdate.Type.DIM_PROPERTY_UPDATE)); + markDirty(); + } } } + @Override public String getModularInventoryName() { return AdvancedRocketryBlocks.blockGravityController.getLocalizedName(); From cf0c0b6548ef6232ca15f43f4263458cdcec9bb8 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 2 Nov 2025 11:43:23 +0100 Subject: [PATCH 075/424] shaving the spam even more. (sendtoall) changed from 20times/s to 4times/sec. reducing packets, and making this really lightweight. old worstcase: 1000packets to all players over 45sec. new: 200packets over 45sec, no noticable change for players --- .../tile/station/TileStationGravityController.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationGravityController.java b/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationGravityController.java index e1f863c37..34d5e4bcb 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationGravityController.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationGravityController.java @@ -36,6 +36,7 @@ public class TileStationGravityController extends TileEntity implements IModular private RedstoneState state = RedstoneState.OFF; private ModuleText moduleGrav, maxGravBuildSpeed, targetGrav; private ModuleRedstoneOutputButton redstoneControl; + private long lastDimPropSyncTick = -5; public TileStationGravityController() { moduleGrav = new ModuleText(6, 15, LibVulpes.proxy.getLocalizedString("msg.stationgravctrl.alt"), 0xaa2020); @@ -213,8 +214,13 @@ public void update() { double finalVel = angVel + (difference < 0 ? Math.max(difference, -acc) : Math.min(difference, acc)); spaceObject.getProperties().setGravitationalMultiplier((float) finalVel); - // networking unchanged - PacketHandler.sendToAll(new PacketStationUpdate(spaceObject, PacketStationUpdate.Type.DIM_PROPERTY_UPDATE)); + long wt = world.getTotalWorldTime(); + + if ((wt - lastDimPropSyncTick) >= 5) { // every 5 ticks ≈ 4 Hz + PacketHandler.sendToAll(new PacketStationUpdate(spaceObject, PacketStationUpdate.Type.DIM_PROPERTY_UPDATE)); + lastDimPropSyncTick = wt; + } + markDirty(); } } From b0340c74390d5ddccfec957c0088c41596d4db74 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Tue, 4 Nov 2025 00:57:42 +0100 Subject: [PATCH 076/424] Enhance TileFluidTank with fluid handling features Added fluid handling capabilities and improved fluid transfer logic. Tower configuration + dropping correct fillevel --- .../advancedRocketry/tile/TileFluidTank.java | 233 ++++++++++++++++-- 1 file changed, 208 insertions(+), 25 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileFluidTank.java b/src/main/java/zmaster587/advancedRocketry/tile/TileFluidTank.java index faddcb90f..8cde1f94f 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileFluidTank.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileFluidTank.java @@ -8,11 +8,13 @@ import net.minecraft.util.EnumFacing; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fluids.capability.IFluidTankProperties; import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; import zmaster587.advancedRocketry.world.util.WorldDummy; import zmaster587.libVulpes.tile.multiblock.hatch.TileFluidHatch; import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class TileFluidTank extends TileFluidHatch { @@ -20,6 +22,11 @@ public class TileFluidTank extends TileFluidHatch { private long lastUpdateTime; private boolean fluidChanged; + private boolean removing = false; + private boolean inColumnOp = false; + + public void setRemoving(boolean removing) { this.removing = removing; } + public TileFluidTank() { super(); fluidChanged = false; @@ -30,15 +37,56 @@ public TileFluidTank(int i) { fluidChanged = false; } + // Single, reusable delegating handler (column-aware) + private final net.minecraftforge.fluids.capability.IFluidHandler selfHandler = + new net.minecraftforge.fluids.capability.IFluidHandler() { + @Override public int fill(FluidStack r, boolean doFill) { return TileFluidTank.this.fill(r, doFill); } + @Override public FluidStack drain(FluidStack r, boolean doDrain) { return TileFluidTank.this.drain(r, doDrain); } + @Override public FluidStack drain(int max, boolean doDrain) { return TileFluidTank.this.drain(max, doDrain); } + @Override public IFluidTankProperties[] getTankProperties() { return TileFluidTank.this.getTankProperties(); } + }; + + @Override + public boolean hasCapability(net.minecraftforge.common.capabilities.Capability cap, + @Nullable EnumFacing side) { + if (cap == net.minecraftforge.fluids.capability.CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { + return true; // expose our own handler for fluids, all sides + } + return super.hasCapability(cap, side); // items and anything else come from the parent + } + + + @Override + @SuppressWarnings("unchecked") + public T getCapability(net.minecraftforge.common.capabilities.Capability cap, + @Nullable EnumFacing side) { + if (cap == net.minecraftforge.fluids.capability.CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { + return (T) selfHandler; // never fall back to parent for fluids + } + return super.getCapability(cap, side); // items etc. still via TileFluidHatch (EmbeddedInventory) + } + + + + private void checkForUpdate() { - if (fluidChanged && world instanceof WorldDummy || world.getTotalWorldTime() - lastUpdateTime > MAX_UPDATE) { - this.markDirty(); + if (world == null) return; + if (fluidChanged && (world instanceof WorldDummy || world.getTotalWorldTime() - lastUpdateTime > MAX_UPDATE)) { + markDirty(); world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); lastUpdateTime = world.getTotalWorldTime(); fluidChanged = false; } } + private boolean enterColumnOp() { + if (inColumnOp) return false; + inColumnOp = true; + return true; + } + private void exitColumnOp() { inColumnOp = false; } + + @Override public SPacketUpdateTileEntity getUpdatePacket() { return new SPacketUpdateTileEntity(getPos(), getBlockMetadata(), getUpdateTag()); @@ -49,12 +97,24 @@ public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) { readFromNBT(pkt.getNbtCompound()); } + @Override + public NBTTagCompound getUpdateTag() { + return writeToNBT(new NBTTagCompound()); + } + + @Override + public void handleUpdateTag(NBTTagCompound tag) { + readFromNBT(tag); + } + @Override public int fill(FluidStack resource, boolean doFill) { if (resource == null) return 0; + if (world == null || world.isRemote || removing) return 0; + TileFluidTank handler2 = this.getFluidTankInDirection(EnumFacing.UP); //Move up, check if we can fill there, do top down @@ -79,9 +139,10 @@ private int fillInternal2(FluidStack resource, boolean doFill) { if (resource2.amount > 0) amt += super.fill(resource2, doFill); - if (amt > 0 && doFill) + if (amt > 0 && doFill) { fluidChanged = true; - + markDirty(); + } checkForUpdate(); return amt; @@ -92,16 +153,28 @@ public String getModularInventoryName() { return AdvancedRocketryBlocks.blockPressureTank.getLocalizedName(); } + @Nullable + public FluidStack getOwnContentsCopy() { + FluidStack f = fluidTank.getFluid(); + return f == null ? null : f.copy(); + } + + @Override public FluidStack drain(int maxDrain, boolean doDrain) { + if (world == null || world.isRemote || removing) return null; + IFluidHandler handler = this.getFluidTankInDirection(EnumFacing.UP); FluidStack fStack = null; - if (handler != null && handler.getTankProperties()[0].getContents() != null && - fluidTank.getFluid() != null && fluidTank.getFluid().getFluid() == - handler.getTankProperties()[0].getContents().getFluid()) { - - fStack = handler.drain(maxDrain, doDrain); + if (handler != null) { + IFluidTankProperties[] props = handler.getTankProperties(); + FluidStack contents = (props != null && props.length > 0) ? props[0].getContents() : null; + if (contents != null && + fluidTank.getFluid() != null && + fluidTank.getFluid().getFluid() == contents.getFluid()) { + fStack = handler.drain(maxDrain, doDrain); + } } if (fStack != null) return fStack; @@ -110,6 +183,7 @@ public FluidStack drain(int maxDrain, boolean doDrain) { if (fStack2 != null && doDrain) { fluidChanged = true; + markDirty(); } checkForUpdate(); @@ -118,8 +192,8 @@ public FluidStack drain(int maxDrain, boolean doDrain) { } @Override - public FluidStack drain(FluidStack resource, - boolean doDrain) { + public FluidStack drain(FluidStack resource, boolean doDrain) { + if (world == null || world.isRemote || removing || resource == null) return null; if (this.fluidTank.getFluid() == null || resource.getFluid() != this.fluidTank.getFluid().getFluid()) return null; @@ -127,6 +201,7 @@ public FluidStack drain(FluidStack resource, } public TileFluidTank getFluidTankInDirection(EnumFacing direction) { + if (world == null) return null; TileEntity tile = world.getTileEntity(pos.offset(direction)); if (tile instanceof TileFluidTank) { @@ -161,30 +236,138 @@ protected boolean useBucket(int slot, @Nonnull ItemStack stack) { if (bucketUsed) { IFluidHandler handler = getFluidTankInDirection(EnumFacing.DOWN); if (handler != null) { - FluidStack othertank = handler.getTankProperties()[0].getContents(); - if (othertank == null || (othertank.amount < handler.getTankProperties()[0].getCapacity())) - fluidTank.drain(handler.fill(fluidTank.getFluid(), true), true); + IFluidTankProperties[] props = handler.getTankProperties(); + FluidStack contents = (props != null && props.length > 0) ? props[0].getContents() : null; + int capacity = (props != null && props.length > 0) ? props[0].getCapacity() : 0; + + // If the tank below is empty or has room, push fluid down + if (contents == null || (capacity > 0 && contents.amount < capacity)) { + FluidStack ours = fluidTank.getFluid(); + if (ours != null && ours.amount > 0) { + int canMove = handler.fill(new FluidStack(ours.getFluid(), ours.amount), false); + if (canMove > 0) { + FluidStack drained = fluidTank.drain(canMove, true); + int filled = handler.fill(drained, true); + if (filled < drained.amount) { + fluidTank.fill(new FluidStack(drained.getFluid(), drained.amount - filled), true); + } + fluidChanged = true; + markDirty(); + checkForUpdate(); + } + } + } } } return bucketUsed; } - public void onAdjacentBlockUpdated(EnumFacing dir) { - if (dir != EnumFacing.DOWN) - return; + @Override + public void invalidate() { + removing = true; + super.invalidate(); + } - TileFluidTank tank = getFluidTankInDirection(EnumFacing.UP); + @Override + public void onChunkUnload() { + removing = true; + super.onChunkUnload(); + } - if (tank != null && tank.getTankProperties()[0].getContents() != null) { - if (fluidTank.getFluid() == null) { - fluidTank.fill(tank.fluidTank.drain(fluidTank.getCapacity(), true), true); - } else if (tank.getTankProperties()[0].getContents().getFluid() == fluidTank.getFluid().getFluid()) { - fluidTank.fill(tank.drain(fluidTank.getCapacity() - fluidTank.getFluidAmount(), true), true); - tank.fluidTank.drain(fluidTank.getCapacity() - fluidTank.getFluidAmount(), true); + public void onAdjacentBlockUpdated(EnumFacing dir) { + if (world == null || world.isRemote || removing) return; + if (!enterColumnOp()) return; + try { + // If the block BELOW changed, push our fluid down into it and cascade. + if (dir == EnumFacing.DOWN) { + TileFluidTank down = getFluidTankInDirection(EnumFacing.DOWN); + if (down != null) { + FluidStack ours = fluidTank.getFluid(); + if (ours != null && ours.amount > 0) { + IFluidTankProperties[] props = down.getTankProperties(); + FluidStack below = (props != null && props.length > 0) ? props[0].getContents() : null; + boolean compatible = (below == null) || (below.getFluid() == ours.getFluid()); + + if (compatible) { + int room = down.fluidTank.getCapacity() - down.fluidTank.getFluidAmount(); + if (room > 0) { + int toMove = Math.min(room, ours.amount); + + // Use capability: simulate then commit + IFluidHandler downH = down.getCapability( + net.minecraftforge.fluids.capability.CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + EnumFacing.UP + ); + if (downH != null) { + int canFill = downH.fill(new FluidStack(ours.getFluid(), toMove), false); + if (canFill > 0) { + FluidStack drained = fluidTank.drain(canFill, true); + int filled = downH.fill(drained, true); + if (filled < drained.amount) { + // Put any remainder back to avoid loss + fluidTank.fill(new FluidStack(drained.getFluid(), drained.amount - filled), true); + } + fluidChanged = true; + markDirty(); + checkForUpdate(); + down.markDirty(); + down.checkForUpdate(); + + // Cascade to the next tank down + down.onAdjacentBlockUpdated(EnumFacing.DOWN); + } + } + } + } + } + } + } + // If the block ABOVE changed, pull fluid from the tank above into THIS tank (column-aware). + else if (dir == EnumFacing.UP) { + TileFluidTank up = getFluidTankInDirection(EnumFacing.UP); + if (up != null) { + IFluidTankProperties[] props = up.getTankProperties(); + FluidStack above = (props != null && props.length > 0) ? props[0].getContents() : null; + + if (above != null) { + if (fluidTank.getFluid() == null) { + // We're empty: pull directly from the upper tank's internal store + FluidStack moved = up.drain(fluidTank.getCapacity(), true); + if (moved != null && moved.amount > 0) { + fluidTank.fill(moved, true); + fluidChanged = true; + markDirty(); + checkForUpdate(); + } + } else if (above.getFluid() == fluidTank.getFluid().getFluid()) { + // Same fluid: do a column-aware pull from the upper tank + int room = fluidTank.getCapacity() - fluidTank.getFluidAmount(); + if (room > 0) { + FluidStack moved = up.drain(room, true); + if (moved != null && moved.amount > 0) { + fluidTank.fill(moved, true); + fluidChanged = true; + markDirty(); + checkForUpdate(); + } + } + } + } + } } - this.markDirty(); + // Final safety: ensure any state change is persisted/sent + if (fluidChanged) { + this.markDirty(); + checkForUpdate(); + } + } finally { + exitColumnOp(); } } + + + + } From 8384bdf6ef8a5b6076341be989adeab95011aff0 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Tue, 4 Nov 2025 00:58:13 +0100 Subject: [PATCH 077/424] Refactor ItemBlockFluidTank to improve fluid handling --- .../item/ItemBlockFluidTank.java | 74 ++++++++++++------- 1 file changed, 48 insertions(+), 26 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java b/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java index 614a958ae..f034a86ad 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java @@ -2,6 +2,7 @@ import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemBlock; @@ -10,6 +11,7 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTank; @@ -18,6 +20,9 @@ import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.tile.TileFluidTank; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; @@ -29,48 +34,65 @@ public ItemBlockFluidTank(Block block) { super(block); } + /** Capacity of the item tank in mB, using the same base as the block (64_000 mB), + * preserving fractional multipliers and clamping to int range. */ + private static int getCapMb() { + // Math.round(double) -> long; keep it in long, then clamp to int range + long computed = Math.round(64000d * ARConfiguration.getCurrentConfig().blockTankCapacity); + return (int) Math.min(Integer.MAX_VALUE, Math.max(0L, computed)); + } + @Override + @SideOnly(Side.CLIENT) @ParametersAreNonnullByDefault - public void addInformation(@Nonnull ItemStack stack, @Nullable World world, List list, ITooltipFlag bool) { - super.addInformation(stack, world, list, bool); + public void addInformation(@Nonnull ItemStack stack, @Nullable World world, List list, ITooltipFlag flag) { + super.addInformation(stack, world, list, flag); - FluidStack fluidStack = getFluid(stack); + final int capMb = getCapMb(); + final FluidStack fs = getFluid(stack); - if (fluidStack == null) { - list.add("Empty"); - } else { - list.add(fluidStack.getLocalizedName() + ": " + fluidStack.amount/1000 + "/"+64* ARConfiguration.getCurrentConfig().blockTankCapacity+"b"); - } + final String fluidName = (fs != null && fs.getFluid() != null) ? fs.getLocalizedName() : "Empty"; + final int amount = (fs != null) ? fs.amount : 0; + + list.add("Fluid: " + fluidName); + list.add("Level: " + amount + "/" + capMb + " mB"); } @Override @ParametersAreNonnullByDefault - public boolean placeBlockAt(@Nonnull ItemStack stack, EntityPlayer player, World world, BlockPos pos, EnumFacing side, float hitX, float hitY, float hitZ, IBlockState newState) { - super.placeBlockAt(stack, player, world, pos, side, hitX, hitY, hitZ, newState); - + public boolean placeBlockAt(@Nonnull ItemStack stack, EntityPlayer player, World world, BlockPos pos, + EnumFacing side, float hitX, float hitY, float hitZ, IBlockState newState) { + if (!super.placeBlockAt(stack, player, world, pos, side, hitX, hitY, hitZ, newState)) { + return false; + } TileEntity tile = world.getTileEntity(pos); - if (tile instanceof TileFluidTank) { IFluidHandler handler = tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, EnumFacing.DOWN); - ItemStack stack2 = stack.copy(); - stack2.setCount(1); - handler.fill(drain(stack2, Integer.MAX_VALUE), true); + if (handler != null) { + ItemStack one = stack.copy(); + one.setCount(1); + FluidStack drained = drain(one, Integer.MAX_VALUE); + if (drained != null && drained.amount > 0) { // <- guard + handler.fill(drained, true); + } + } } - return true; } - public void fill(@Nonnull ItemStack stack, FluidStack fluid) { + public void fill(@Nonnull ItemStack stack, FluidStack fluid) { NBTTagCompound nbt; - FluidTank tank = new FluidTank((int) (640000* ARConfiguration.getCurrentConfig().blockTankCapacity)); + FluidTank tank = new FluidTank(getCapMb()); if (stack.hasTagCompound()) { nbt = stack.getTagCompound(); tank.readFromNBT(nbt); - } else + } else { nbt = new NBTTagCompound(); + } - tank.fill(fluid, true); + if (fluid != null) {tank.fill(fluid, true); + } tank.writeToNBT(nbt); stack.setTagCompound(nbt); @@ -78,29 +100,29 @@ public void fill(@Nonnull ItemStack stack, FluidStack fluid) { public FluidStack drain(@Nonnull ItemStack stack, int amt) { NBTTagCompound nbt; - FluidTank tank = new FluidTank((int) (640000* ARConfiguration.getCurrentConfig().blockTankCapacity)); + FluidTank tank = new FluidTank(getCapMb()); if (stack.hasTagCompound()) { nbt = stack.getTagCompound(); tank.readFromNBT(nbt); - } else + } else { nbt = new NBTTagCompound(); + } - FluidStack stack2 = tank.drain(amt, true); + FluidStack drained = tank.drain(amt, true); tank.writeToNBT(nbt); stack.setTagCompound(nbt); - return stack2; + return drained; } public FluidStack getFluid(@Nonnull ItemStack stack) { NBTTagCompound nbt; - FluidTank tank = new FluidTank((int) (640000* ARConfiguration.getCurrentConfig().blockTankCapacity)); + FluidTank tank = new FluidTank(getCapMb()); if (stack.hasTagCompound()) { nbt = stack.getTagCompound(); tank.readFromNBT(nbt); } - return tank.getFluid(); } } From 333b45768c9b737c31ae60610eb6d6279e18fc13 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Tue, 4 Nov 2025 00:58:42 +0100 Subject: [PATCH 078/424] Refactor BlockPressurizedFluidTank interactions and methods --- .../block/BlockPressurizedFluidTank.java | 179 ++++++++++++++---- 1 file changed, 139 insertions(+), 40 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockPressurizedFluidTank.java b/src/main/java/zmaster587/advancedRocketry/block/BlockPressurizedFluidTank.java index cd6dffcfa..ed15835d6 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockPressurizedFluidTank.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockPressurizedFluidTank.java @@ -15,7 +15,6 @@ import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import net.minecraftforge.fluids.FluidUtil; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; @@ -48,66 +47,139 @@ public boolean hasTileEntity(IBlockState state) { } @Override - public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, EnumFacing side, float hitX, float hitY, float hitZ) { - TileEntity tile = world.getTileEntity(pos); - - //Do some fancy fluid stuff - if (FluidUtils.containsFluid(player.getHeldItem(hand))) { - FluidUtil.interactWithFluidHandler(player, hand, ((TileFluidHatch) tile).getFluidTank()); - } else if (!world.isRemote) - player.openGui(LibVulpes.instance, guiId.MODULAR.ordinal(), world, pos.getX(), pos.getY(), pos.getZ()); + public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, EntityPlayer player, EnumHand hand, + EnumFacing side, float hitX, float hitY, float hitZ) { + TileEntity te = world.getTileEntity(pos); + if (!(te instanceof TileFluidTank)) return false; + + // Client: consume the click (let server do the actual transfer) + if (world.isRemote) return true; + + // Try to interact via the tile's FLUID CAPABILITY (column-aware path), + // NOT the raw internal tank. + IFluidHandler handler = te.getCapability( + net.minecraftforge.fluids.capability.CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + side + ); + if (handler == null) { + handler = te.getCapability( + net.minecraftforge.fluids.capability.CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, + null + ); + } + + boolean acted = false; + if (handler != null) { + // Server-side inventory mutation + acted = net.minecraftforge.fluids.FluidUtil.interactWithFluidHandler(player, hand, handler); + if (acted) { + TileFluidTank tank = (TileFluidTank) te; + // Persist + sync + tank.markDirty(); + tank.onAdjacentBlockUpdated(EnumFacing.DOWN); + tank.onAdjacentBlockUpdated(EnumFacing.UP); + } + } + + // If we didn't perform a fluid interaction, open the GUI + if (!acted) { + player.openGui(zmaster587.libVulpes.LibVulpes.instance, + zmaster587.libVulpes.inventory.GuiHandler.guiId.MODULAR.ordinal(), + world, pos.getX(), pos.getY(), pos.getZ()); + } return true; } + + + @Override + public void onBlockAdded(World world, BlockPos pos, IBlockState state) { + super.onBlockAdded(world, pos, state); + if (world.isRemote) return; // <- add this + TileEntity teAbove = world.getTileEntity(pos.up()); + if (teAbove instanceof TileFluidTank) { + ((TileFluidTank) teAbove).onAdjacentBlockUpdated(EnumFacing.DOWN); + } + } + + @Override @ParametersAreNullableByDefault public TileEntity createTileEntity(World world, IBlockState state) { - return new TileFluidTank((int) (64000 * ARConfiguration.getCurrentConfig().blockTankCapacity)); + long computed = Math.round(64000d * ARConfiguration.getCurrentConfig().blockTankCapacity); + int capMb = (int) Math.min(Integer.MAX_VALUE, Math.max(0L, computed)); + return new TileFluidTank(capMb); } @Override @Nonnull @ParametersAreNullableByDefault - public List getDrops(IBlockAccess world, BlockPos pos, - IBlockState state, int fortune) { - return new LinkedList<>(); - } + public List getDrops(IBlockAccess world, BlockPos pos, IBlockState state, int fortune) { + List drops = new LinkedList<>(); + TileEntity te = world.getTileEntity(pos); - @Override - @ParametersAreNonnullByDefault - public void harvestBlock(World world, EntityPlayer player, BlockPos pos, IBlockState state, @Nullable TileEntity te, @Nonnull ItemStack stack) { + ItemStack out = new ItemStack(AdvancedRocketryBlocks.blockPressureTank); if (te instanceof TileFluidTank) { - IFluidHandler fluid = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, EnumFacing.DOWN); + net.minecraftforge.fluids.FluidStack own = ((TileFluidTank) te).getOwnContentsCopy(); + // 1.12: FluidStack has no isEmpty(); guard on null and amount > 0 + if (own != null && own.amount > 0) { + ((ItemBlockFluidTank) out.getItem()).fill(out, own); + } + } + drops.add(out); + return drops; + } - ItemStack itemstack = new ItemStack(AdvancedRocketryBlocks.blockPressureTank); - ((ItemBlockFluidTank) itemstack.getItem()).fill(itemstack, fluid.drain(Integer.MAX_VALUE, false)); + @Override + public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest) { + if (!world.isRemote) { + TileEntity te = world.getTileEntity(pos); + if (te instanceof TileFluidTank) { + ((TileFluidTank) te).setRemoving(true); // <- you’ll add this setter in the tile + } + } + // Let vanilla handle removal; we’ll control drops in harvestBlock + return super.removedByPlayer(state, world, pos, player, willHarvest); + } - EntityItem entityitem; + @Override + public void harvestBlock(World world, EntityPlayer player, BlockPos pos, IBlockState state, + @Nullable TileEntity te, @Nonnull ItemStack tool) { + if (world.isRemote) return; - int j1 = world.rand.nextInt(21) + 10; - float f = world.rand.nextFloat() * 0.8F + 0.1F; - float f1 = world.rand.nextFloat() * 0.8F + 0.1F; - float f2 = world.rand.nextFloat() * 0.8F + 0.1F; + // Creative: no drop, just remove + if (player.capabilities.isCreativeMode) { + world.setBlockToAir(pos); + return; + } - itemstack.setCount(1); - entityitem = new EntityItem(world, (float) pos.getX() + f, (float) pos.getY() + f1, (float) pos.getZ() + f2, new ItemStack(itemstack.getItem(), 1, 0)); - float f3 = 0.05F; - entityitem.motionX = (float) world.rand.nextGaussian() * f3; - entityitem.motionY = (float) world.rand.nextGaussian() * f3 + 0.2F; - entityitem.motionZ = (float) world.rand.nextGaussian() * f3; + // Build ONE drop item from the authoritative server tile we received + ItemStack drop = new ItemStack(AdvancedRocketryBlocks.blockPressureTank); + if (te instanceof TileFluidTank) { + // Make sure the tile knows it's in teardown; block cross-tile moves + ((TileFluidTank) te).setRemoving(true); - if (itemstack.hasTagCompound()) { - entityitem.getItem().setTagCompound(itemstack.getTagCompound().copy()); + net.minecraftforge.fluids.FluidStack own = ((TileFluidTank) te).getOwnContentsCopy(); + if (own != null && own.amount > 0) { + ((ItemBlockFluidTank) drop.getItem()).fill(drop, own); } - world.spawnEntity(entityitem); } - super.harvestBlock(world, player, pos, state, te, stack); + // Spawn our single, correct drop + EntityItem ei = new EntityItem(world, + pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, drop); + world.spawnEntity(ei); + + // Finally remove the block (this will call breakBlock and clear TE) + world.setBlockToAir(pos); } + + + @Override @ParametersAreNonnullByDefault public boolean shouldSideBeRendered(IBlockState blockState, @@ -133,12 +205,39 @@ public boolean isFullCube(IBlockState state) { return false; } + private void notifyTankOfNeighborChange(World world, BlockPos pos, BlockPos fromPos) { + // Only act for strictly adjacent vertical neighbors (no diagonals, no sides) + int dx = fromPos.getX() - pos.getX(); + int dy = fromPos.getY() - pos.getY(); + int dz = fromPos.getZ() - pos.getZ(); + + // Must be exactly one block away on Y, and same X/Z + if (dx != 0 || dz != 0) return; + if (dy != 1 && dy != -1) return; + + TileEntity te = world.getTileEntity(pos); + if (!(te instanceof zmaster587.advancedRocketry.tile.TileFluidTank)) return; + + EnumFacing dir = (dy == 1) ? EnumFacing.UP : EnumFacing.DOWN; + ((zmaster587.advancedRocketry.tile.TileFluidTank) te).onAdjacentBlockUpdated(dir); + } + + + + // Reliable for block state changes (place/break) + @Override + public void neighborChanged(IBlockState state, World world, BlockPos pos, Block blockIn, BlockPos fromPos) { + super.neighborChanged(state, world, pos, blockIn, fromPos); + if (!world.isRemote) notifyTankOfNeighborChange(world, pos, fromPos); + } + + // TE-only neighbor updates (no block state change) @Override - public void onNeighborChange(IBlockAccess world, BlockPos pos, - BlockPos neighbor) { - TileEntity tile = world.getTileEntity(pos); - if (tile instanceof TileFluidTank) - ((TileFluidTank) tile).onAdjacentBlockUpdated(EnumFacing.getFacingFromVector(neighbor.getX() - pos.getX(), neighbor.getY() - pos.getY(), neighbor.getZ() - pos.getZ())); + public void onNeighborChange(IBlockAccess world, BlockPos pos, BlockPos neighbor) { + if (world instanceof World) { + World w = (World) world; + if (!w.isRemote) notifyTankOfNeighborChange(w, pos, neighbor); + } } @Override From 31b926ac5f9fe8813301d11490379c0f925cd4c9 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Tue, 4 Nov 2025 01:27:14 +0100 Subject: [PATCH 079/424] Update language file with new and corrected entries --- .../assets/advancedrocketry/lang/en_US.lang | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index f899e02d0..45a2887da 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -11,6 +11,7 @@ death.attack.Heat=%1$s died due to overheating death.attack.Heat.player=%1$s died due to overheating entity.advancedRocketry.rocket.name=Rocket entity.rocket.name=Rocket +entity.deployedRocket.name=Rocket entity.hovercraft.name=Hovercraft tile.landingPad.name=Landing Pad @@ -288,6 +289,7 @@ msg.observetory.text.processdiscovery=Process discovery msg.observetory.text.observabledistance=Observable distance: msg.observetory.text.missionTime=Mission Time: msg.observetory.req.open=Observatory must be open (night, clear sky, sky access) or be in space! +msg.observetory.print.already=You already have a chip for this asteroid! msg.tooltip.data=Data msg.tooltip.asteroidselection=Asteroid Selection msg.label.name=Name @@ -366,6 +368,7 @@ msg.satctrlcenter.nolink=No Link... msg.satctrlcenter.info=Info: msg.satctrlcenter.destroysat=Destroy Satellite msg.satctrlcenter.connect=Download +msg.satctrlcenter.autodl_hint=Automatic with Wireless Tranciever (Extract) msg.satbuilder.writesecondchip=Write to Secondary Chip msg.dockingport.target=Target Id msg.dockingport.me=My Id @@ -375,7 +378,7 @@ msg.stationaltctrl.tgtalt=Target Altitude: msg.stationaltctrl.alt=Altitude: msg.stationgravctrl.maxaltrate=Max Gravity Change Rate: msg.stationgravctrl.tgtalt=Target Gravity: -msg.stationgravctrl.alt=Artifical Gravity: +msg.stationgravctrl.alt=Artificial Gravity: msg.stationorientctrl.alt=Angular Velocity: msg.stationorientctrl.tgtalt=Target Ang Vel: msg.warpmon.tab.warp=Warp Selection @@ -421,10 +424,12 @@ msg.rocketbuilder.build=Build msg.rocketbuilder.scan=Scan msg.rocketbuild.combinedthrust=Fuel types cannot be combined! msg.rocketbuilder.alreadyassembled=Rocket already assembled +msg.rocketbuilder.nointake=Missing Gas Intake! +msg.rocketbuilder.notank=Missing Fluidtank! msg.solar.collectingEnergy=Collecting Energy: msg.solar.cannotcollectEnergy=Unable to collect Energy msg.asteroidChip.asteroid=Asteroid -msg.asteroidChip.type=Type +msg.asteroidChip.type=Type: msg.atmanal.atmtype=Atmosphere Type: msg.atmanal.canbreathe=Breathable: msg.biomechanger.scan=Scan Biome @@ -485,13 +490,16 @@ msg.entity.rocket.launch=Launch in T- msg.entity.rocket.launch2=Press [Space] to abort msg.entity.rocket.station=Station msg.entity.rocket.pad=Pad: -msg.entity.rocket.disass=Dissassemble +msg.entity.rocket.disass=Disassemble msg.entity.rocket.seldst=Select Dst msg.entity.rocket.clear=Clear msg.entity.rocket.rcs=RCS Mode msg.entity.rocket.none=None Selected msg.wirelessTransciever.extract=extract msg.wirelessTransciever.insert=insert +msg.wirelessTransciever.type=Type: %s +msg.wirelessTransciever.network=Network: +msg.wirelessTransciever.network.unlinked=Unlinked msg.powerunit.rfpertick=FE/t msg.linker.error.firstMachine=This must be the first machine to link! From 165ea2d95df296d873d9f502ca502b23cb4f2991 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 5 Nov 2025 13:58:19 +0100 Subject: [PATCH 080/424] Using same calculation, safety and performance as parent (rocketassembler) Using same calculation, safety and performance as parent (rocketassembler) allows for all enginetypes/tanks. --- .../tile/TileUnmannedVehicleAssembler.java | 364 ++++++++++++------ 1 file changed, 243 insertions(+), 121 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileUnmannedVehicleAssembler.java b/src/main/java/zmaster587/advancedRocketry/tile/TileUnmannedVehicleAssembler.java index 6869bb1ee..2091c4a2c 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileUnmannedVehicleAssembler.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileUnmannedVehicleAssembler.java @@ -18,6 +18,7 @@ import zmaster587.advancedRocketry.entity.EntityStationDeployedRocket; import zmaster587.advancedRocketry.network.PacketInvalidLocationNotify; import zmaster587.advancedRocketry.util.StorageChunk; +import zmaster587.advancedRocketry.util.WeightEngine; import zmaster587.libVulpes.block.BlockFullyRotatable; import zmaster587.libVulpes.block.RotatableBlock; import zmaster587.libVulpes.network.PacketEntity; @@ -99,64 +100,102 @@ public AxisAlignedBB getRocketPadBounds(World world, BlockPos pos2) { return new AxisAlignedBB(xMin, yCurrent, zMin, xMax, yCurrent + yMax - 1, zMax); } + @Override public void assembleRocket() { - if (bbCache == null || world.isRemote) - return; - //Need to scan again b/c something may have changed - scanRocket(world, getPos(), bbCache); + if (bbCache == null || world.isRemote) return; - if (status != ErrorCodes.SUCCESS) - return; - StorageChunk storageChunk; + // 1) Rescan like the parent (may update stats/status and tighten AABB) + AxisAlignedBB rocketBB = scanRocket(world, getPos(), bbCache); + if (status != ErrorCodes.SUCCESS || rocketBB == null) return; - //Breaks if nothing is there + // 2) Remove replaceable/blacklisted blocks before cutting (uses parent’s helper) + removeReplaceableBlocks(bbCache); + + // 3) Cut the world into a storage chunk + final StorageChunk storageChunk; try { storageChunk = StorageChunk.cutWorldBB(world, bbCache); } catch (NegativeArraySizeException e) { return; } + // 4) Spawn the SD rocket, centered from the *rescanned* bbox + final double cx = rocketBB.minX + (rocketBB.maxX - rocketBB.minX) / 2f + 0.5f; + final double cz = rocketBB.minZ + (rocketBB.maxZ - rocketBB.minZ) / 2f + 0.5f; + final double cy = this.getPos().getY(); - EntityStationDeployedRocket rocket = new EntityStationDeployedRocket(world, storageChunk, stats.copy(), bbCache.minX + (bbCache.maxX - bbCache.minX) / 2f + .5f, getPos().getY(), bbCache.minZ + (bbCache.maxZ - bbCache.minZ) / 2f + .5f); + EntityStationDeployedRocket rocket = + new EntityStationDeployedRocket(world, storageChunk, stats.copy(), cx, cy, cz); - //TODO: setRocketDirection + // Orientations for SD rockets rocket.forwardDirection = RotatableBlock.getFront(world.getBlockState(getPos())).getOpposite(); rocket.launchDirection = EnumFacing.DOWN; - //Change engine direction + // 5) Rotate *all* engine types to match forwardDirection (defensive: only if block supports FACING) for (int x = 0; x < storageChunk.getSizeX(); x++) { for (int y = 0; y < storageChunk.getSizeY(); y++) { for (int z = 0; z < storageChunk.getSizeZ(); z++) { + BlockPos bp = new BlockPos(x, y, z); + IBlockState st = storageChunk.getBlockState(bp); + Block b = st.getBlock(); + + boolean isEngine = (b instanceof BlockRocketMotor) + || (b instanceof BlockBipropellantRocketMotor) + || (b instanceof BlockNuclearRocketMotor); - BlockPos pos3 = new BlockPos(x, y, z); - if (storageChunk.getBlockState(pos3).getBlock() instanceof BlockRocketMotor) { - storageChunk.setBlockState(pos3, storageChunk.getBlockState(pos3).withProperty(BlockFullyRotatable.FACING, rocket.forwardDirection)); + if (isEngine && st.getPropertyKeys().contains(BlockFullyRotatable.FACING)) { + storageChunk.setBlockState(bp, st.withProperty(BlockFullyRotatable.FACING, rocket.forwardDirection)); } } } } + // 6) Spawn + sync world.spawnEntity(rocket); - NBTTagCompound nbtdata = new NBTTagCompound(); - - rocket.writeToNBT(nbtdata); - PacketHandler.sendToNearby(new PacketEntity(rocket, (byte) 0, nbtdata), rocket.world.provider.getDimension(), this.pos, 64); - - stats.reset(); - this.status = ErrorCodes.UNSCANNED; - this.markDirty(); + NBTTagCompound nbt = new NBTTagCompound(); + rocket.writeToNBT(nbt); + PacketHandler.sendToNearby(new PacketEntity(rocket, (byte) 0, nbt), + rocket.world.provider.getDimension(), this.pos, 64); + // Link existing infrastructure (same order as parent) for (IInfrastructure infrastructure : getConnectedInfrastructure()) { rocket.linkInfrastructure(infrastructure); } + + // 7) Directly stamp tile stats from the entity we just created + rocket.recalculateStats(); + this.stats = rocket.stats.copy(); + + // Now finish up — and DO NOT reset after this + this.status = ErrorCodes.FINISHED; + this.markDirty(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); + + // Rescan to immediately show fresh stats after build + scanRocket(world, getPos(), bbCache); } - //TODO get direction of rocket + @Override public AxisAlignedBB scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { - // TODO Refactor! Duplicated with TileRocketAssemblingMachine + + // fast-path: rocket entity already present? + if (getBBCache() == null) bbCache = getRocketPadBounds(world, getPos()); + if (bbCache != null) { + final AxisAlignedBB buffered = bbCache.grow(1.0e-4, 1.0e-4, 1.0e-4); + + java.util.List sdr = + world.getEntitiesWithinAABB(EntityStationDeployedRocket.class, buffered); + if (sdr.size() == 1) { + EntityStationDeployedRocket r = sdr.get(0); + r.recalculateStats(); + this.stats = r.stats.copy(); + this.status = ErrorCodes.ALREADY_ASSEMBLED; + return null; + } + } int thrustMonopropellant = 0; int thrustBipropellant = 0; int thrustNuclearNozzleLimit = 0; @@ -169,45 +208,36 @@ public AxisAlignedBB scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { int fuelCapacityBipropellant = 0; int fuelCapacityOxidizer = 0; int fuelCapacityNuclearWorkingFluid = 0; - int numBlocks = 0; - float drillPower = 0f; + float weight = 0f; + stats.reset(); int actualMinX = (int) bb.maxX, - actualMinY = (int) bb.maxY, - actualMinZ = (int) bb.maxZ, - actualMaxX = (int) bb.minX, - actualMaxY = (int) bb.minY, - actualMaxZ = (int) bb.minZ; - + actualMinY = (int) bb.maxY, + actualMinZ = (int) bb.maxZ, + actualMaxX = (int) bb.minX, + actualMaxY = (int) bb.minY, + actualMaxZ = (int) bb.minZ; + // tighten AABB to non-air for (int xCurr = (int) bb.minX; xCurr <= bb.maxX; xCurr++) { for (int zCurr = (int) bb.minZ; zCurr <= bb.maxZ; zCurr++) { for (int yCurr = (int) bb.minY; yCurr <= bb.maxY; yCurr++) { - - BlockPos currPos = new BlockPos(xCurr, yCurr, zCurr); - - if (!world.isAirBlock(currPos)) { - if (xCurr < actualMinX) - actualMinX = xCurr; - if (yCurr < actualMinY) - actualMinY = yCurr; - if (zCurr < actualMinZ) - actualMinZ = zCurr; - if (xCurr > actualMaxX) - actualMaxX = xCurr; - if (yCurr > actualMaxY) - actualMaxY = yCurr; - if (zCurr > actualMaxZ) - actualMaxZ = zCurr; + BlockPos p = new BlockPos(xCurr, yCurr, zCurr); + if (!world.isAirBlock(p)) { + if (xCurr < actualMinX) actualMinX = xCurr; + if (yCurr < actualMinY) actualMinY = yCurr; + if (zCurr < actualMinZ) actualMinZ = zCurr; + if (xCurr > actualMaxX) actualMaxX = xCurr; + if (yCurr > actualMaxY) actualMaxY = yCurr; + if (zCurr > actualMaxZ) actualMaxZ = zCurr; } } } } - boolean hasSatellite = false; - boolean hasGuidance = false; boolean invalidBlock = false; + boolean foundFluidTank = false; int fluidCapacity = 0; if (verifyScan(bb, world)) { @@ -216,124 +246,216 @@ public AxisAlignedBB scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { for (int zCurr = (int) bb.minZ; zCurr <= bb.maxZ; zCurr++) { BlockPos currPos = new BlockPos(xCurr, yCurr, zCurr); - if (!world.isAirBlock(currPos)) { - IBlockState state = world.getBlockState(currPos); - Block block = state.getBlock(); - - if (ARConfiguration.getCurrentConfig().blackListRocketBlocks.contains(block)) { - if (!block.isReplaceable(world, currPos)) { - invalidBlock = true; - if (!world.isRemote) - PacketHandler.sendToNearby(new PacketInvalidLocationNotify(new HashedBlockPosition(xCurr, yCurr, zCurr)), world.provider.getDimension(), getPos(), 64); + if (world.isAirBlock(currPos)) continue; + + IBlockState state = world.getBlockState(currPos); + Block block = state.getBlock(); + + // blacklist guard + if (ARConfiguration.getCurrentConfig().blackListRocketBlocks.contains(block)) { + if (!block.isReplaceable(world, currPos)) { + invalidBlock = true; + if (!world.isRemote) { + PacketHandler.sendToNearby( + new PacketInvalidLocationNotify(new HashedBlockPosition(xCurr, yCurr, zCurr)), + world.provider.getDimension(), getPos(), 64 + ); } - continue; } + continue; + } - numBlocks++; - - //If rocketEngine increaseThrust - if (block instanceof IRocketEngine) { - if (block instanceof BlockNuclearRocketMotor) { - nuclearWorkingFluidUseMax += ((IRocketEngine) block).getFuelConsumptionRate(world, xCurr, yCurr, zCurr); - thrustNuclearNozzleLimit += ((IRocketEngine) block).getThrust(world, currPos); - } else if (block instanceof BlockBipropellantRocketMotor) { - bipropellantfuelUse += ((IRocketEngine) block).getFuelConsumptionRate(world, xCurr, yCurr, zCurr); - thrustBipropellant += ((IRocketEngine) block).getThrust(world, currPos); - } else if (block instanceof BlockRocketMotor) { - monopropellantfuelUse += ((IRocketEngine) block).getFuelConsumptionRate(world, xCurr, yCurr, zCurr); - thrustMonopropellant += ((IRocketEngine) block).getThrust(world, currPos); - } + if (ARConfiguration.getCurrentConfig().advancedWeightSystem) { + weight += WeightEngine.INSTANCE.getWeight(world, currPos); + } else { + weight += 1f; // fallback: count blocks + } - stats.addEngineLocation(xCurr - actualMinX - ((float) (actualMaxX - actualMinX) / 2f), yCurr - actualMinY, zCurr - actualMinZ - ((float) (actualMaxZ - actualMinZ) / 2f)); - //stats.addEngineLocation(xCurr - actualMinX, yCurr - actualMinY, zCurr - actualMinZ); + // Engines + thrust/fuel use + if (block instanceof IRocketEngine) { + if (block instanceof BlockNuclearRocketMotor) { + nuclearWorkingFluidUseMax += ((IRocketEngine) block).getFuelConsumptionRate(world, xCurr, yCurr, zCurr); + thrustNuclearNozzleLimit += ((IRocketEngine) block).getThrust(world, currPos); + } else if (block instanceof BlockBipropellantRocketMotor) { + bipropellantfuelUse += ((IRocketEngine) block).getFuelConsumptionRate(world, xCurr, yCurr, zCurr); + thrustBipropellant += ((IRocketEngine) block).getThrust(world, currPos); + } else if (block instanceof BlockRocketMotor) { + monopropellantfuelUse += ((IRocketEngine) block).getFuelConsumptionRate(world, xCurr, yCurr, zCurr); + thrustMonopropellant += ((IRocketEngine) block).getThrust(world, currPos); } - if (block instanceof IFuelTank) { - if (block instanceof BlockFuelTank) { - fuelCapacityMonopropellant += (((IFuelTank) block).getMaxFill(world, currPos, state) * ARConfiguration.getCurrentConfig().fuelCapacityMultiplier); - } else if (block instanceof BlockBipropellantFuelTank) { - fuelCapacityBipropellant += (((IFuelTank) block).getMaxFill(world, currPos, state) * ARConfiguration.getCurrentConfig().fuelCapacityMultiplier); - } else if (block instanceof BlockOxidizerFuelTank) { - fuelCapacityOxidizer += (((IFuelTank) block).getMaxFill(world, currPos, state) * ARConfiguration.getCurrentConfig().fuelCapacityMultiplier); - } else if (block instanceof BlockNuclearFuelTank) { - fuelCapacityNuclearWorkingFluid += (((IFuelTank) block).getMaxFill(world, currPos, state) * ARConfiguration.getCurrentConfig().fuelCapacityMultiplier); - } - } + // center engine location for UI/particles + final float halfX = (actualMaxX - actualMinX + 1) / 2f; + final float halfZ = (actualMaxZ - actualMinZ + 1) / 2f; - if (block instanceof IRocketNuclearCore) { - thrustNuclearReactorLimit += ((IRocketNuclearCore) block).getMaxThrust(world, currPos); - } + final float ex = (xCurr - actualMinX + 0.5f) - halfX; + final float ez = (zCurr - actualMinZ + 0.5f) - halfZ; + final float ey = (yCurr - actualMinY); // <- no +0.5 here + + stats.addEngineLocation(ex, ey, ez); + } - if (block instanceof IIntake) { - stats.setStatTag("intakePower", (int) stats.getStatTag("intakePower") + ((IIntake) block).getIntakeAmt(state)); + // Fuel tanks (family-specific capacities) + if (block instanceof IFuelTank) { + if (block instanceof BlockBipropellantFuelTank) { + fuelCapacityBipropellant += ((IFuelTank) block).getMaxFill(world, currPos, state) * ARConfiguration.getCurrentConfig().fuelCapacityMultiplier; + } else if (block instanceof BlockOxidizerFuelTank) { + fuelCapacityOxidizer += ((IFuelTank) block).getMaxFill(world, currPos, state) * ARConfiguration.getCurrentConfig().fuelCapacityMultiplier; + } else if (block instanceof BlockNuclearFuelTank) { + fuelCapacityNuclearWorkingFluid += ((IFuelTank) block).getMaxFill(world, currPos, state) * ARConfiguration.getCurrentConfig().fuelCapacityMultiplier; + } else if (block instanceof BlockFuelTank) { + fuelCapacityMonopropellant += ((IFuelTank) block).getMaxFill(world, currPos, state) * ARConfiguration.getCurrentConfig().fuelCapacityMultiplier; } + } - TileEntity tile = world.getTileEntity(currPos); - IFluidHandler handler; + // Nuclear core limits + if (block instanceof IRocketNuclearCore) { + thrustNuclearReactorLimit += ((IRocketNuclearCore) block).getMaxThrust(world, currPos); + } - if (tile != null && (handler = tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null)) != null) { - for (IFluidTankProperties info : handler.getTankProperties()) + // Intakes + if (block instanceof IIntake) { + stats.setStatTag("intakePower", + (int) stats.getStatTag("intakePower") + ((IIntake) block).getIntakeAmt(state)); + } + + // Generic fluid capability presence + capacity + TileEntity tile = world.getTileEntity(currPos); + if (tile != null) { + IFluidHandler handler = tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); + if (handler != null) { + for (IFluidTankProperties info : handler.getTankProperties()) { + if (info == null) continue; + if (!foundFluidTank && info.getCapacity() > 0) foundFluidTank = true; fluidCapacity += info.getCapacity(); + } } } } } } + // --- Nuclear working fluid scaling (guarded) --- int nuclearWorkingFluidUse = 0; if (thrustNuclearNozzleLimit > 0) { - //Only run the number of engines our cores can support - we can't throttle these effectively because they're small, so they shut off if they don't get full power thrustNuclearTotalLimit = Math.min(thrustNuclearNozzleLimit, thrustNuclearReactorLimit); - nuclearWorkingFluidUse = (int) (nuclearWorkingFluidUseMax * (thrustNuclearTotalLimit / (float) thrustNuclearNozzleLimit)); - thrustNuclearTotalLimit = (nuclearWorkingFluidUse * thrustNuclearNozzleLimit) / nuclearWorkingFluidUseMax; + if (nuclearWorkingFluidUseMax > 0) { + nuclearWorkingFluidUse = (int) (nuclearWorkingFluidUseMax * (thrustNuclearTotalLimit / (float) thrustNuclearNozzleLimit)); + thrustNuclearTotalLimit = (nuclearWorkingFluidUse * thrustNuclearNozzleLimit) / nuclearWorkingFluidUseMax; + } else { + nuclearWorkingFluidUse = 0; + thrustNuclearTotalLimit = 0; + } } - //Set fuel stats - //Thrust depending on rocket type + // Write stats stats.setBaseFuelRate(FuelType.LIQUID_MONOPROPELLANT, monopropellantfuelUse); - stats.setBaseFuelRate(FuelType.LIQUID_BIPROPELLANT, bipropellantfuelUse); - stats.setBaseFuelRate(FuelType.LIQUID_OXIDIZER, bipropellantfuelUse); + stats.setBaseFuelRate(FuelType.LIQUID_BIPROPELLANT, bipropellantfuelUse); + stats.setBaseFuelRate(FuelType.LIQUID_OXIDIZER, bipropellantfuelUse); stats.setBaseFuelRate(FuelType.NUCLEAR_WORKING_FLUID, nuclearWorkingFluidUse); - //Fuel storage depending on rocket type + + stats.setFuelRate(FuelType.LIQUID_MONOPROPELLANT, monopropellantfuelUse); + stats.setFuelRate(FuelType.LIQUID_BIPROPELLANT, bipropellantfuelUse); + stats.setFuelRate(FuelType.LIQUID_OXIDIZER, bipropellantfuelUse); + stats.setFuelRate(FuelType.NUCLEAR_WORKING_FLUID, nuclearWorkingFluidUse); + stats.setFuelCapacity(FuelType.LIQUID_MONOPROPELLANT, fuelCapacityMonopropellant); - stats.setFuelCapacity(FuelType.LIQUID_BIPROPELLANT, fuelCapacityBipropellant); - stats.setFuelCapacity(FuelType.LIQUID_OXIDIZER, fuelCapacityOxidizer); - stats.setFuelCapacity(FuelType.NUCLEAR_WORKING_FLUID, thrustNuclearTotalLimit); + stats.setFuelCapacity(FuelType.LIQUID_BIPROPELLANT, fuelCapacityBipropellant); + stats.setFuelCapacity(FuelType.LIQUID_OXIDIZER, fuelCapacityOxidizer); + stats.setFuelCapacity(FuelType.NUCLEAR_WORKING_FLUID, fuelCapacityNuclearWorkingFluid); - //Non-fuel stats - stats.setThrust(Math.max(thrustMonopropellant, thrustBipropellant)); - stats.setWeight(numBlocks); + stats.setThrust(Math.max(Math.max(thrustMonopropellant, thrustBipropellant), thrustNuclearTotalLimit)); + stats.setWeight(weight); stats.setStatTag("liquidCapacity", fluidCapacity); - //Total stats, used to check if the user has tried to apply two or more types of thrust/fuel - int totalFuel = fuelCapacityBipropellant + fuelCapacityNuclearWorkingFluid + fuelCapacityMonopropellant; + // Cross-family checks + int totalFuel = fuelCapacityBipropellant + fuelCapacityNuclearWorkingFluid + fuelCapacityMonopropellant; int totalFuelUse = bipropellantfuelUse + nuclearWorkingFluidUse + monopropellantfuelUse; - //Set status - if (invalidBlock) + if (invalidBlock) { status = ErrorCodes.INVALIDBLOCK; - else if (((fuelCapacityBipropellant > 0 && totalFuel > fuelCapacityBipropellant) || (fuelCapacityMonopropellant > 0 && totalFuel > fuelCapacityMonopropellant) || (fuelCapacityNuclearWorkingFluid > 0 && totalFuel > fuelCapacityNuclearWorkingFluid)) || ((thrustBipropellant > 0 && totalFuelUse > bipropellantfuelUse) || (thrustMonopropellant > 0 && totalFuelUse > monopropellantfuelUse) || (thrustNuclearTotalLimit > 0 && totalFuelUse > nuclearWorkingFluidUse))) + } else if (((fuelCapacityBipropellant > 0 && totalFuel > fuelCapacityBipropellant) + || (fuelCapacityMonopropellant > 0 && totalFuel > fuelCapacityMonopropellant) + || (fuelCapacityNuclearWorkingFluid > 0 && totalFuel > fuelCapacityNuclearWorkingFluid)) + || + ((thrustBipropellant > 0 && totalFuelUse > bipropellantfuelUse) + || (thrustMonopropellant > 0 && totalFuelUse > monopropellantfuelUse) + || (thrustNuclearTotalLimit > 0 && totalFuelUse > nuclearWorkingFluidUse))) { status = ErrorCodes.COMBINEDTHRUST; - else if (getThrust() < getNeededThrust()) + } else if (getThrust() <= getNeededThrust()) { status = ErrorCodes.NOENGINES; - else if (((thrustBipropellant > 0) && getFuel(FuelType.LIQUID_BIPROPELLANT) < getNeededFuel(FuelType.LIQUID_BIPROPELLANT)) || ((thrustMonopropellant > 0) && getFuel(FuelType.LIQUID_MONOPROPELLANT) < getNeededFuel(FuelType.LIQUID_MONOPROPELLANT)) || ((thrustNuclearTotalLimit > 0) && getFuel(FuelType.NUCLEAR_WORKING_FLUID) < getNeededFuel(FuelType.NUCLEAR_WORKING_FLUID))) + } else if (((int) stats.getStatTag("intakePower")) <= 0) { + status = ErrorCodes.NOINTAKE; + } else if (!foundFluidTank) { + status = ErrorCodes.NOTANK; + } else if (thrustBipropellant > 0 && (fuelCapacityBipropellant <= 0 || fuelCapacityOxidizer <= 0)) { + status = ErrorCodes.NOFUEL; // missing one of the required tanks + } else if (((thrustBipropellant > 0) && !hasEnoughFuelUnmanned(FuelType.LIQUID_BIPROPELLANT)) + || ((thrustMonopropellant > 0) && !hasEnoughFuelUnmanned(FuelType.LIQUID_MONOPROPELLANT)) + || ((thrustNuclearTotalLimit > 0) && !hasEnoughFuelUnmanned(FuelType.NUCLEAR_WORKING_FLUID))) { status = ErrorCodes.NOFUEL; - else + } else { status = ErrorCodes.SUCCESS; + } } return new AxisAlignedBB(actualMinX, actualMinY, actualMinZ, actualMaxX, actualMaxY, actualMaxZ); } - public float getNeededFuel(@Nonnull FuelType fuelType) { - return 1; + private boolean hasEnoughFuelUnmanned(@Nonnull FuelType family) { + // SD flight: acceleration in entity code is ≈ 0.005 blocks/tick^2 + final float a_station = 0.005f; + final float targetS = 128f; // SD rocket switches to orbit after ~128 blocks + + float t; // seconds (ticks) we can sustain full burn + + switch (family) { + case LIQUID_MONOPROPELLANT: { + final int cap = stats.getFuelCapacity(FuelType.LIQUID_MONOPROPELLANT); + final int rate = stats.getBaseFuelRate(FuelType.LIQUID_MONOPROPELLANT); + if (cap <= 0 || rate <= 0) return false; + t = cap / (float) rate; + break; + } + + case LIQUID_BIPROPELLANT: { + // Both streams must exist; consume in lockstep at their own rates. + final int capFuel = stats.getFuelCapacity(FuelType.LIQUID_BIPROPELLANT); + final int capOx = stats.getFuelCapacity(FuelType.LIQUID_OXIDIZER); + final int rateFuel= stats.getBaseFuelRate(FuelType.LIQUID_BIPROPELLANT); + final int rateOx = stats.getBaseFuelRate(FuelType.LIQUID_OXIDIZER); + if (capFuel <= 0 || capOx <= 0 || rateFuel <= 0 || rateOx <= 0) return false; + + final float tFuel = capFuel / (float) rateFuel; + final float tOx = capOx / (float) rateOx; + t = Math.min(tFuel, tOx); // limiting stream dictates burn time + break; + } + + case NUCLEAR_WORKING_FLUID: { + final int cap = stats.getFuelCapacity(FuelType.NUCLEAR_WORKING_FLUID); + final int rate = stats.getBaseFuelRate(FuelType.NUCLEAR_WORKING_FLUID); + if (cap <= 0 || rate <= 0) return false; + t = cap / (float) rate; + break; + } + + default: + return false; + } + + // distance under constant accel: s = 0.5 * a * t^2 + final float sCan = 0.5f * a_station * t * t; + return sCan >= targetS; } + + //No additional scanning is needed @Override protected boolean verifyScan(AxisAlignedBB bb, World world) { return true; } -} \ No newline at end of file +} From a5db4c9b8b832887138225caf359afd30bca8ac9 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 5 Nov 2025 13:58:58 +0100 Subject: [PATCH 081/424] Change intake amount from 10 to 1 part of a larger rewrite to gasmission timings --- .../java/zmaster587/advancedRocketry/block/BlockIntake.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockIntake.java b/src/main/java/zmaster587/advancedRocketry/block/BlockIntake.java index 706f2f883..33a7260fe 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockIntake.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockIntake.java @@ -13,7 +13,7 @@ public BlockIntake(Material material) { @Override public int getIntakeAmt(IBlockState state) { - return 10; + return 1; } } From 45c0bacd57af84dc4356504289291400c71ac30d Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 5 Nov 2025 14:00:22 +0100 Subject: [PATCH 082/424] Add gas harvest amount multiplier and infinite option Added configuration options for gas harvesting. --- .../advancedRocketry/api/ARConfiguration.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/api/ARConfiguration.java b/src/main/java/zmaster587/advancedRocketry/api/ARConfiguration.java index 617d27f1f..9051d7528 100644 --- a/src/main/java/zmaster587/advancedRocketry/api/ARConfiguration.java +++ b/src/main/java/zmaster587/advancedRocketry/api/ARConfiguration.java @@ -165,6 +165,10 @@ public class ARConfiguration { @ConfigProperty(needsSync = true) public double gasCollectionMult; @ConfigProperty(needsSync = true) + public double gasHarvestAmountMultiplier; + @ConfigProperty(needsSync = true) + public boolean gasHarvestInfinite; + @ConfigProperty(needsSync = true) public double terraformSpeed; @ConfigProperty public boolean terraformRequiresFluid; @@ -412,6 +416,16 @@ public static void loadPreInit() { arConfig.gasCollectionMult = config.get(MISSION, "gasMissionMultiplier", 1.0, "Multiplier for the amount of time gas collection missions take").getDouble(); harvestableGasses = config.getStringList("harvestableGasses", MISSION, new String[]{}, "list of fluid names that can be harvested as Gas from any gas giant"); spawnableGasses = config.getStringList("spawnableGasses", MISSION, new String[]{"hydrogen;125;1600;1.0", "helium;125;1600;0.9", "helium3;175;1600;0.2", "oxygen;0;124;1.0", "nitrogen;0;124;1.0", "ammonia;0;124;0.75", "methane;0;124;0.25"}, "list of fluid names that can be spawned as a gas giant. Format is fluid;minGravity;maxGravity;chance"); + arConfig.gasHarvestAmountMultiplier = config.get( + MISSION, "gasHarvestAmountMultiplier", 1.0, + "Per-mission harvest cap = 64,000 mB × multiplier. Actual yield = min(cap, total free tank space at launch). Ignored if gasHarvestInfinite=true." + ).getDouble(); + + arConfig.gasHarvestInfinite = config.get( + MISSION, "gasHarvestInfinite", false, + "Fill all attached tanks up to their total free space at launch, capped at 2,147,483,647 mB per mission." + ).getBoolean(); + //Energy Production arConfig.solarGeneratorMult = config.get(ENERGY, "solarGeneratorMultiplier", 1, "Amount of power per tick the solar generator should produce").getInt(); From 3b003f763a2e1690cffddf6c081aaf67381a664e Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 5 Nov 2025 14:01:49 +0100 Subject: [PATCH 083/424] part of update for child (concerning gas missions) --- .../tile/TileRocketAssemblingMachine.java | 71 +++++++++++++------ 1 file changed, 51 insertions(+), 20 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java index dc08ae779..1b05536af 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java @@ -282,7 +282,7 @@ public AxisAlignedBB scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { double buffer = 0.0001; AxisAlignedBB bufferedBB = bbCache.grow(buffer, buffer, buffer); List rockets = world.getEntitiesWithinAABB(EntityRocket.class, bufferedBB); - if (rockets.size() == 1){ // only if axactly one rocket is here + if (rockets.size() == 1){ // only if exactly one rocket is here rockets.get(0).recalculateStats(); this.stats = rockets.get(0).stats; status = ErrorCodes.ALREADY_ASSEMBLED; // to prevent assembly @@ -443,17 +443,23 @@ public AxisAlignedBB scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { thrustNuclearTotalLimit = (nuclearWorkingFluidUse * thrustNuclearNozzleLimit) / nuclearWorkingFluidUseMax; } - //Set fuel stats - //Thrust depending on rocket type + // Set fuel stats + // Thrust depending on rocket type stats.setBaseFuelRate(FuelType.LIQUID_MONOPROPELLANT, monopropellantfuelUse); - stats.setBaseFuelRate(FuelType.LIQUID_BIPROPELLANT, bipropellantfuelUse); - stats.setBaseFuelRate(FuelType.LIQUID_OXIDIZER, bipropellantfuelUse); + stats.setBaseFuelRate(FuelType.LIQUID_BIPROPELLANT, bipropellantfuelUse); + stats.setBaseFuelRate(FuelType.LIQUID_OXIDIZER, bipropellantfuelUse); stats.setBaseFuelRate(FuelType.NUCLEAR_WORKING_FLUID, nuclearWorkingFluidUse); - //Fuel storage depending on rocket type - stats.setFuelCapacity(FuelType.LIQUID_MONOPROPELLANT, fuelCapacityMonopropellant); - stats.setFuelCapacity(FuelType.LIQUID_BIPROPELLANT, fuelCapacityBipropellant); - stats.setFuelCapacity(FuelType.LIQUID_OXIDIZER, fuelCapacityOxidizer); - stats.setFuelCapacity(FuelType.NUCLEAR_WORKING_FLUID, fuelCapacityNuclearWorkingFluid); + + stats.setFuelRate(FuelType.LIQUID_MONOPROPELLANT, monopropellantfuelUse); + stats.setFuelRate(FuelType.LIQUID_BIPROPELLANT, bipropellantfuelUse); + stats.setFuelRate(FuelType.LIQUID_OXIDIZER, bipropellantfuelUse); + stats.setFuelRate(FuelType.NUCLEAR_WORKING_FLUID, nuclearWorkingFluidUse); + + // Fuel storage depending on rocket type + stats.setFuelCapacity(FuelType.LIQUID_MONOPROPELLANT, fuelCapacityMonopropellant); + stats.setFuelCapacity(FuelType.LIQUID_BIPROPELLANT, fuelCapacityBipropellant); + stats.setFuelCapacity(FuelType.LIQUID_OXIDIZER, fuelCapacityOxidizer); + stats.setFuelCapacity(FuelType.NUCLEAR_WORKING_FLUID, fuelCapacityNuclearWorkingFluid); //Non-fuel stats stats.setWeight(weight); @@ -465,27 +471,50 @@ public AxisAlignedBB scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { int totalFuelUse = bipropellantfuelUse + nuclearWorkingFluidUse + monopropellantfuelUse; //System.out.println("rocket fuel use:"+totalFuelUse); + // --- Biprop requirement: if any bipropellant thrust exists, require both tanks --- + if (thrustBipropellant > 0) { + if (fuelCapacityBipropellant <= 0 || fuelCapacityOxidizer <= 0) { + status = ErrorCodes.NOFUEL; // or a dedicated error if you add one + return new AxisAlignedBB(actualMinX, actualMinY, actualMinZ, actualMaxX, actualMaxY, actualMaxZ); + } + } + //Set status - if (invalidBlock) + if (invalidBlock) { status = ErrorCodes.INVALIDBLOCK; - else if (((fuelCapacityBipropellant > 0 && totalFuel > fuelCapacityBipropellant) || (fuelCapacityMonopropellant > 0 && totalFuel > fuelCapacityMonopropellant) || (fuelCapacityNuclearWorkingFluid > 0 && totalFuel > fuelCapacityNuclearWorkingFluid)) + + } else if (((fuelCapacityBipropellant > 0 && totalFuel > fuelCapacityBipropellant) + || (fuelCapacityMonopropellant > 0 && totalFuel > fuelCapacityMonopropellant) + || (fuelCapacityNuclearWorkingFluid > 0 && totalFuel > fuelCapacityNuclearWorkingFluid)) || - ((thrustBipropellant > 0 && totalFuelUse > bipropellantfuelUse) || (thrustMonopropellant > 0 && totalFuelUse > monopropellantfuelUse) || (thrustNuclearTotalLimit > 0 && totalFuelUse > nuclearWorkingFluidUse))) + ((thrustBipropellant > 0 && totalFuelUse > bipropellantfuelUse) + || (thrustMonopropellant > 0 && totalFuelUse > monopropellantfuelUse) + || (thrustNuclearTotalLimit > 0 && totalFuelUse > nuclearWorkingFluidUse))) { status = ErrorCodes.COMBINEDTHRUST; - else if (!hasGuidance && !hasSatellite) + + } else if (!hasGuidance && !hasSatellite) { status = ErrorCodes.NOGUIDANCE; - else if (getThrust() <= getNeededThrust()) + + } else if (getThrust() <= getNeededThrust()) { status = ErrorCodes.NOENGINES; - else if (((thrustBipropellant > 0) && !hasEnoughFuel(FuelType.LIQUID_BIPROPELLANT)) || ((thrustMonopropellant > 0) && !hasEnoughFuel(FuelType.LIQUID_MONOPROPELLANT)) || ((thrustNuclearTotalLimit > 0) && !hasEnoughFuel(FuelType.NUCLEAR_WORKING_FLUID))) + + } else if (thrustBipropellant > 0 && (fuelCapacityBipropellant <= 0 || fuelCapacityOxidizer <= 0)) { + // Biprop engines require BOTH bipropellant AND oxidizer capacity + status = ErrorCodes.NOFUEL; + + } else if (((thrustBipropellant > 0) && !hasEnoughFuel(FuelType.LIQUID_BIPROPELLANT)) + || ((thrustMonopropellant > 0) && !hasEnoughFuel(FuelType.LIQUID_MONOPROPELLANT)) + || ((thrustNuclearTotalLimit > 0) && !hasEnoughFuel(FuelType.NUCLEAR_WORKING_FLUID))) { status = ErrorCodes.NOFUEL; - else + + } else { status = ErrorCodes.SUCCESS; + } } - return new AxisAlignedBB(actualMinX, actualMinY, actualMinZ, actualMaxX, actualMaxY, actualMaxZ); } - private void removeReplaceableBlocks(AxisAlignedBB bb) { + protected void removeReplaceableBlocks(AxisAlignedBB bb) { for (int yCurr = (int) bb.minY; yCurr <= bb.maxY; yCurr++) { for (int xCurr = (int) bb.minX; xCurr <= bb.maxX; xCurr++) { for (int zCurr = (int) bb.minZ; zCurr <= bb.maxZ; zCurr++) { @@ -1197,7 +1226,9 @@ protected enum ErrorCodes { COMBINEDTHRUST(LibVulpes.proxy.getLocalizedString("msg.rocketbuild.combinedthrust")), ALREADY_ASSEMBLED(LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.alreadyassembled")), UNSCANNED_STATION(LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.unscanned_station")), - FAIL_CUT(LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.fail_cut")); + FAIL_CUT(LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.fail_cut")), + NOINTAKE(LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.nointake")), + NOTANK(LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.notank")); String code; From 691eb289fa55b7a04fd9b23747d0a9b460b308e9 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 5 Nov 2025 14:02:48 +0100 Subject: [PATCH 084/424] Enhance gas collection and fuel consumption logic Added plannedHarvestMb to track gas collection capacity and updated fuel consumption logic for ascent. Allows all enginetypes and tanks like normal rocket. reused logic from parent --- .../entity/EntityStationDeployedRocket.java | 175 +++++++++++++++++- 1 file changed, 167 insertions(+), 8 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/entity/EntityStationDeployedRocket.java b/src/main/java/zmaster587/advancedRocketry/entity/EntityStationDeployedRocket.java index 228d593d5..0f6f48d83 100644 --- a/src/main/java/zmaster587/advancedRocketry/entity/EntityStationDeployedRocket.java +++ b/src/main/java/zmaster587/advancedRocketry/entity/EntityStationDeployedRocket.java @@ -26,14 +26,13 @@ import zmaster587.advancedRocketry.api.RocketEvent.RocketLaunchEvent; import zmaster587.advancedRocketry.api.RocketEvent.RocketPreLaunchEvent; import zmaster587.advancedRocketry.api.StatsRocket; -import zmaster587.advancedRocketry.api.atmosphere.AtmosphereRegister; +import zmaster587.advancedRocketry.api.fuel.FuelRegistry; import zmaster587.advancedRocketry.api.stations.ISpaceObject; import zmaster587.advancedRocketry.client.SoundRocketEngine; import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.advancedRocketry.dimension.DimensionProperties; import zmaster587.advancedRocketry.mission.MissionGasCollection; import zmaster587.advancedRocketry.network.PacketSatellite; -import zmaster587.advancedRocketry.network.PacketSatellitesUpdate; import zmaster587.advancedRocketry.stations.SpaceObjectManager; import zmaster587.advancedRocketry.util.AudioRegistry; import zmaster587.advancedRocketry.util.StorageChunk; @@ -62,6 +61,7 @@ public class EntityStationDeployedRocket extends EntityRocket { private ModuleText atmText; private short gasId; private Ticket ticket; + private long plannedHarvestMb = 0L; // planned total mB to attempt this mission public EntityStationDeployedRocket(World world) { super(world); @@ -121,8 +121,21 @@ public void launch() { setInFlight(true); return; } - if (getFuelAmount(getRocketFuelType()) < getFuelCapacity(getRocketFuelType())) - return; + + if (storage != null) { + storage.recalculateStats(this.stats); // keeps everything else in sync + } + + + FuelRegistry.FuelType rt = getRocketFuelType(); + if (rt != null && ARConfiguration.getCurrentConfig().rocketRequireFuel) { + if (getFuelAmount(rt) < getFuelCapacity(rt)) return; + + if (rt == FuelRegistry.FuelType.LIQUID_BIPROPELLANT) { + if (getFuelAmount(FuelRegistry.FuelType.LIQUID_OXIDIZER) + < getFuelCapacity(FuelRegistry.FuelType.LIQUID_OXIDIZER)) return; + } + } ISpaceObject spaceObj; if (world.provider.getDimension() == ARConfiguration.getCurrentConfig().spaceDimId && @@ -281,7 +294,12 @@ public void onUpdate() { motionX += acc * forwardDirection.getFrontOffsetX(); motionY += acc * forwardDirection.getFrontOffsetY(); motionZ += acc * forwardDirection.getFrontOffsetZ(); - setFuelAmount(getRocketFuelType(), getFuelAmount(getRocketFuelType()) - 1); + + // server-side fuel consumption for thrust ticks + if (!world.isRemote && burningFuel) { + // only consume if we actually need to (respect config + biprop pairing) + tryConsumeAscentFuel(); + } } if (!world.isRemote && this.getDistance(actualLaunchLocation.x, actualLaunchLocation.y, actualLaunchLocation.z) > 128) { @@ -402,14 +420,64 @@ public void onOrbitReached() { return; } - //one intake with a 1 bucket tank should take 100 seconds - float intakePower = (Integer) stats.getStatTag("intakePower"); + // --- Plan harvest & cap duration by what we can actually get --- + final net.minecraftforge.fluids.Fluid targetFluid = + properties.getHarvestableGasses().get(gasId); + + // (1) config harvest cap (mB) + final boolean infinite = ARConfiguration.getCurrentConfig().gasHarvestInfinite; + final double mult = Math.max(0.0, ARConfiguration.getCurrentConfig().gasHarvestAmountMultiplier); + final long base64k = 64_000L; + final int harvestCapMb = infinite + ? Integer.MAX_VALUE + : (int) Math.min(Integer.MAX_VALUE, Math.round(base64k * mult)); + + // (2) free capacity for this gas across all rocket tanks (simulate) + int freeMb = 0; + for (TileEntity tile : this.storage.getFluidTiles()) { + net.minecraftforge.fluids.capability.IFluidHandler h = + tile.getCapability(net.minecraftforge.fluids.capability.CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); + if (h == null) continue; + int couldTake = h.fill(new net.minecraftforge.fluids.FluidStack(targetFluid, Integer.MAX_VALUE), false); + if (couldTake > 0) { + freeMb = (int) Math.min((long) Integer.MAX_VALUE, (long) freeMb + (long) couldTake); + } + } + + // (3) final planned harvest for this mission + this.plannedHarvestMb = Math.max(0, Math.min(harvestCapMb, freeMb)); + + // (4) duration = min( baseCurveTime(capForTiming), ceil(plannedHarvest / rate) ) + // Keep your curve and denominator 25 + final int liquidCapacity = safeTagInt(stats, "liquidCapacity"); + final int intake = safeTagInt(stats, "intakePower"); + final long rate = DENOM_PER_INTAKE * (long) Math.max(1, intake); // mB/s + + final long durationSeconds; + if (intake <= 0 || this.plannedHarvestMb <= 0) { + durationSeconds = 360L; // safety default + } else { + // IMPORTANT: cap the capacity used by the curve to the harvest cap, + // so durations match the table when harvest is smaller than tank size. + final int capForTiming = infinite ? liquidCapacity : Math.min(liquidCapacity, harvestCapMb); + + double effCapMb = computeEffectiveCapacityMb(capForTiming); + long baseSeconds = (long) Math.floor(effCapMb / (double) rate); + long capSeconds = (long) Math.ceil((double) this.plannedHarvestMb / (double) rate); + + durationSeconds = Math.max(1L, Math.min(baseSeconds, capSeconds)); + } + final long durationTicks = Math.max(1L, durationSeconds * 20L); + + + MissionGasCollection miningMission = + new MissionGasCollection(durationTicks, this, connectedInfrastructure, targetFluid); - MissionGasCollection miningMission = new MissionGasCollection(intakePower == 0 ? 360 : (long) (2 * ((int) stats.getStatTag("liquidCapacity") / intakePower)), this, connectedInfrastructure, properties.getHarvestableGasses().get(gasId)); miningMission.setDimensionId(properties.getId()); properties.addSatellite(miningMission); + // broadcast if (!world.isRemote) { PacketHandler.sendToAll(new PacketSatellite(miningMission)); } @@ -495,8 +563,99 @@ public void writeMissionPersistentNBT(NBTTagCompound nbt) { nbt.setShort("gas", gasId); + nbt.setLong("plannedHarvestMb", Math.max(0L, this.plannedHarvestMb)); + } + + // handle possible bad data gracefully + private static int safeTagInt(StatsRocket s, String key) { + Object v = s.getStatTag(key); + return (v instanceof Number) ? Math.max(0, ((Number) v).intValue()) : 0; + } + + // --- Nonlinear gas mission timing (alpha = 0.2) --- + // effectiveCapacity = BASE_CAP * (liquidCapacity / BASE_CAP)^ALPHA + // baseSeconds = floor( effectiveCapacity / (DENOM_PER_INTAKE * intakePower) ) + // finalSeconds = min(baseSeconds, ceil(plannedHarvestMb / (DENOM_PER_INTAKE * intakePower))) + private static final long BASE_CAP = 64_000L; // 64,000 mB (64 buckets) + private static final double ALPHA = 0.2d; // gentle sublinear scaling + private static final long DENOM_PER_INTAKE = 25L; // you picked "25 * intakePower" + + // Returns the effective capacity (mB) from your nonlinear curve. + private static double computeEffectiveCapacityMb(int liquidCapacity) { + double ratio = Math.max(1.0d, ((double) liquidCapacity) / (double) BASE_CAP); + return (double) BASE_CAP * Math.pow(ratio, ALPHA); } + private static long computeMissionDurationSeconds(int liquidCapacity, int intakePower) { + // default fallback if bad data + if (intakePower <= 0) return 360L; // 6 minutes safety default + + // scale in double to avoid precision loss, clamp ratio >= 1 to avoid shrinking below base + double ratio = Math.max(1.0d, ((double) liquidCapacity) / (double) BASE_CAP); + double effectiveCapacity = (double) BASE_CAP * Math.pow(ratio, ALPHA); + + long denom = DENOM_PER_INTAKE * (long) Math.max(1, intakePower); + long secs = (long) Math.floor(effectiveCapacity / (double) denom); + + return Math.max(1L, secs); // never zero + } + + // Consume ascent fuel exactly like the parent rocket does. + // Returns true if fuel was consumed this tick (or fuel is not required by config). + private boolean tryConsumeAscentFuel() { + if (!ARConfiguration.getCurrentConfig().rocketRequireFuel) + return true; + + final FuelRegistry.FuelType rt = getRocketFuelType(); + if (rt == null) + return false; + + // current amounts + int main = getFuelAmount(rt); + final int mainRate = Math.max(1, getFuelConsumptionRate(rt)); // defensive + + if (rt == FuelRegistry.FuelType.LIQUID_BIPROPELLANT) { + int ox = getFuelAmount(FuelRegistry.FuelType.LIQUID_OXIDIZER); + final int oxRate = Math.max(1, getFuelConsumptionRate(FuelRegistry.FuelType.LIQUID_OXIDIZER)); + + // both-or-nothing + if (main >= mainRate && ox >= oxRate) { + setFuelAmount(rt, main - mainRate); + setFuelAmount(FuelRegistry.FuelType.LIQUID_OXIDIZER, ox - oxRate); + } else { + return false; // not enough of one stream + } + + // normalize + clear fluid names when empty + setFuelAmount(rt, Math.max(0, getFuelAmount(rt))); + setFuelAmount(FuelRegistry.FuelType.LIQUID_OXIDIZER, Math.max(0, getFuelAmount(FuelRegistry.FuelType.LIQUID_OXIDIZER))); + + if (getFuelAmount(rt) == 0) { + stats.setFuelFluid("null"); + stats.setWorkingFluid("null"); + } + if (getFuelAmount(FuelRegistry.FuelType.LIQUID_OXIDIZER) == 0) { + stats.setOxidizerFluid("null"); + } + return true; + } else { + if (main >= mainRate) { + setFuelAmount(rt, main - mainRate); + } else { + return false; + } + + // normalize + clear when empty + setFuelAmount(rt, Math.max(0, getFuelAmount(rt))); + if (getFuelAmount(rt) == 0) { + stats.setFuelFluid("null"); + stats.setWorkingFluid("null"); + } + return true; + } + } + + @Override public void readMissionPersistentNBT(NBTTagCompound nbt) { super.readMissionPersistentNBT(nbt); From 9228b33aceba0b4728837b609547ab290f1d09b1 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 5 Nov 2025 14:03:31 +0100 Subject: [PATCH 085/424] Add intake power calculation and refine liquid capacity Refactor StorageChunk to include intake power calculation and improve liquid capacity handling. --- .../advancedRocketry/util/StorageChunk.java | 54 +++++++++++++------ 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/util/StorageChunk.java b/src/main/java/zmaster587/advancedRocketry/util/StorageChunk.java index 48dd09f56..b61cbc90e 100644 --- a/src/main/java/zmaster587/advancedRocketry/util/StorageChunk.java +++ b/src/main/java/zmaster587/advancedRocketry/util/StorageChunk.java @@ -168,7 +168,7 @@ public void recalculateStats(StatsRocket stats) { int fuelCapacityBipropellant = 0; int fuelCapacityOxidizer = 0; int fuelCapacityNuclearWorkingFluid = 0; - + int intakePower = 0; float drillPower = 0f; //stats.reset_no_fuel(); stats.reset_no_fuel();// Oh Quarter... you can not keep adding engine and seat locations every launch @@ -230,24 +230,14 @@ public void recalculateStats(StatsRocket stats) { if (block instanceof IMiningDrill) { drillPower += ((IMiningDrill) block).getMiningSpeed(world, currBlockPos); } + if (block instanceof IIntake) { + intakePower += ((IIntake) block).getIntakeAmt(state); + } if (block.getUnlocalizedName().contains("servicemonitor")) { hasServiceMonitor = true; } - - TileEntity tile = world.getTileEntity(currBlockPos); - if (tile instanceof TileSatelliteHatch) { - if (ARConfiguration.getCurrentConfig().advancedWeightSystem) { - TileSatelliteHatch hatch = (TileSatelliteHatch) tile; - if (hatch.getSatellite() != null) { - weight += hatch.getSatellite().getProperties().getWeight(); - } else if (hatch.getStackInSlot(0).getItem() instanceof ItemPackedStructure) { - ItemPackedStructure struct = (ItemPackedStructure) hatch.getStackInSlot(0).getItem(); - weight += struct.getStructure(hatch.getStackInSlot(0)).getWeight(); - } - } - } - } + } } } } @@ -272,10 +262,42 @@ public void recalculateStats(StatsRocket stats) { stats.setFuelCapacity(FuelRegistry.FuelType.LIQUID_OXIDIZER, fuelCapacityOxidizer); stats.setFuelCapacity(FuelRegistry.FuelType.NUCLEAR_WORKING_FLUID, fuelCapacityNuclearWorkingFluid); - //Non-fuel stats + // SAFE liquid capacity sum (saturating at Integer.MAX_VALUE) + long liquidCapacitySum = 0L; + + outer: + for (TileEntity te : this.getFluidTiles()) { + net.minecraftforge.fluids.capability.IFluidHandler fh = + te.getCapability(net.minecraftforge.fluids.capability.CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); + if (fh == null) continue; + + net.minecraftforge.fluids.capability.IFluidTankProperties[] props = fh.getTankProperties(); + if (props == null) continue; + + for (net.minecraftforge.fluids.capability.IFluidTankProperties p : props) { + if (p == null) continue; + long cap = Math.max(0L, (long) p.getCapacity()); // guard negatives + if (cap == 0L) continue; + + long next = liquidCapacitySum + cap; // saturating add + if (next >= (long) Integer.MAX_VALUE) { + liquidCapacitySum = (long) Integer.MAX_VALUE; + break outer; // early exit once saturated + } + liquidCapacitySum = next; + } + } + + int liquidCapacitySafe = (int) Math.max(0L, Math.min(liquidCapacitySum, (long) Integer.MAX_VALUE)); + stats.setStatTag("liquidCapacity", liquidCapacitySafe); + + + //Non-fuel stats (keep these after the capacity/tag work) stats.setWeight(weight); stats.setThrust(Math.max(Math.max(thrustMonopropellant, thrustBipropellant), thrustNuclearTotalLimit)); stats.setDrillingPower(drillPower); + stats.setStatTag("intakePower", intakePower); + // (liquidCapacity already set above) } public void addTileEntity(TileEntity te) { From 26403d47d9ee56f725f05db82d8f522aa75d2889 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 5 Nov 2025 14:06:09 +0100 Subject: [PATCH 086/424] Simplify power per operation smoother powerdraw (broken in last update) --- .../tile/infrastructure/TileFuelingStation.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java index 0f17f956c..06aa2a755 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java @@ -315,8 +315,7 @@ public void performFunction() { @Override public int getPowerPerOperation() { - // same average RF/mb as before, just throttled - return 30 * OP_THROTTLE_TICKS; + return 30; } @@ -343,11 +342,8 @@ public boolean canPerformFunction() { FluidStack fs = tank.getFluid(); if (fs == null || fs.amount <= 9) return false; - // only if the rocket can fit this fluid - if (!canRocketFitFluid(fs.getFluid())) return false; - - // Consume RF only on the throttled ticks - return (world.getTotalWorldTime() % OP_THROTTLE_TICKS) == 0L; + // Only draw power when the rocket can actually take this fluid + return canRocketFitFluid(fs.getFluid()); } @Override From 93a4cd434d245f67575cac95b1759e3663a16aa9 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 5 Nov 2025 14:07:39 +0100 Subject: [PATCH 087/424] Refactor gas collection logic in MissionGasCollection Safer handling, 2 new config entries: infinitemode and harvest multiplier. both of these are per mission. --- .../mission/MissionGasCollection.java | 51 ++++++++++++++++--- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/mission/MissionGasCollection.java b/src/main/java/zmaster587/advancedRocketry/mission/MissionGasCollection.java index 6c94b3d21..7e48311e5 100644 --- a/src/main/java/zmaster587/advancedRocketry/mission/MissionGasCollection.java +++ b/src/main/java/zmaster587/advancedRocketry/mission/MissionGasCollection.java @@ -22,7 +22,6 @@ public class MissionGasCollection extends MissionResourceCollection { - private Fluid gasFluid; public MissionGasCollection() { @@ -42,14 +41,49 @@ public String getName() { @Override public void onMissionComplete() { + Object ipObj = rocketStats.getStatTag("intakePower"); + int ip = (ipObj instanceof Number) ? Math.max(0, ((Number) ipObj).intValue()) : 0; + + if (ip > 0 && gasFluid != null) { + final Fluid type = gasFluid; + + // Planned harvest written by the rocket at launch + final boolean hasPlanned = missionPersistantNBT.hasKey("plannedHarvestMb"); + final long planned = hasPlanned ? Math.max(0L, missionPersistantNBT.getLong("plannedHarvestMb")) : -1L; + + // Config + final boolean infinite = ARConfiguration.getCurrentConfig().gasHarvestInfinite; + final double mult = Math.max(0.0, ARConfiguration.getCurrentConfig().gasHarvestAmountMultiplier); + final long basePerMission = 64_000L; // mB + + long remaining; + if (hasPlanned) { + remaining = Math.min(Integer.MAX_VALUE, planned); + } else { + remaining = infinite + ? Integer.MAX_VALUE + : Math.min(Integer.MAX_VALUE, Math.round(basePerMission * mult)); + } + + - if ((int) rocketStats.getStatTag("intakePower") > 0 && gasFluid != null) { - Fluid type = gasFluid;//FluidRegistry.getFluid("hydrogen"); - //Fill gas tanks for (TileEntity tile : this.rocketStorage.getFluidTiles()) { - tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null).fill(new FluidStack(type, 64000), true); + net.minecraftforge.fluids.capability.IFluidHandler handler = + tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); + if (handler == null) continue; + + if (remaining <= 0) break; + + int want = (int)Math.min(Integer.MAX_VALUE, remaining); + int couldTake = handler.fill(new FluidStack(type, want), false); // simulate + if (couldTake > 0) { + int filled = handler.fill(new FluidStack(type, couldTake), true); + remaining -= Math.max(0, filled); + } } } + + World world = DimensionManager.getWorld(launchDimension); if (world == null) { @@ -89,12 +123,15 @@ public void onMissionComplete() { @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); - nbt.setString("gas", gasFluid.getName()); + if (gasFluid != null) { + nbt.setString("gas", gasFluid.getName()); + } } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); - gasFluid = FluidRegistry.getFluid(nbt.getString("gas")); + String name = nbt.getString("gas"); + gasFluid = name != null && !name.isEmpty() ? FluidRegistry.getFluid(name) : null; } } From 42670ab6229c9589bbc984e9ec89952d45a37d3c Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 5 Nov 2025 16:27:46 +0100 Subject: [PATCH 088/424] Fix typo in copy chip hint message From c7017b9bf3d8e0306b51908e8b6efbb506653747 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 5 Nov 2025 16:29:55 +0100 Subject: [PATCH 089/424] PerformanceTweaks --- .../TileStationAltitudeController.java | 148 ++++++++++++------ 1 file changed, 97 insertions(+), 51 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationAltitudeController.java b/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationAltitudeController.java index 6ed4760ab..205fb7f5b 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationAltitudeController.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationAltitudeController.java @@ -1,6 +1,8 @@ package zmaster587.advancedRocketry.tile.station; import io.netty.buffer.ByteBuf; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.NetworkManager; @@ -30,10 +32,10 @@ public class TileStationAltitudeController extends TileEntity implements IModula int progress; private RedstoneState state = RedstoneState.OFF; - + private long lastAltSyncTick = -10; private ModuleText moduleGrav, numGravPylons, maxGravBuildSpeed, targetGrav; private ModuleRedstoneOutputButton redstoneControl; - + private boolean wasChanging = false; public TileStationAltitudeController() { moduleGrav = new ModuleText(6, 15, "Altitude: ", 0xaa2020); //numGravPylons = new ModuleText(10, 25, "Number Of Thrusters: ", 0xaa2020); @@ -54,7 +56,63 @@ public List getModules(int id, EntityPlayer player) { modules.add(new ModuleSlider(6, 60, 0, TextureResources.doubleWarningSideBarIndicator, this)); modules.add(redstoneControl); - updateText(); + // inline updater that runs only while GUI is open + modules.add(new ModuleBase(0, 0) { + private SpaceStationObject cached; + private int cachedId = Integer.MIN_VALUE; + + // last shown keys (ints in Km) + private int lastAltKm = Integer.MIN_VALUE; + private int lastTgtKm = Integer.MIN_VALUE; + + // localized prefixes (cache per GUI session) + private final String prefixAlt = LibVulpes.proxy.getLocalizedString("msg.stationaltctrl.alt"); + private final String prefixTgt = LibVulpes.proxy.getLocalizedString("msg.stationaltctrl.tgtalt"); + + private boolean ensureStation() { + if (cached == null) { + ISpaceObject so = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); + if (!(so instanceof SpaceStationObject)) return false; + cached = (SpaceStationObject) so; + cachedId = so.getId(); + return true; + } + ISpaceObject current = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); + if (!(current instanceof SpaceStationObject)) { cached = null; cachedId = Integer.MIN_VALUE; return false; } + if (current.getId() != cachedId) { + cached = (SpaceStationObject) current; + cachedId = current.getId(); + } + return true; + } + + @Override + public void renderBackground(GuiContainer gui, int x, int y, int mouseX, int mouseY, FontRenderer font) { + // Only runs while the GUI is visible → zero idle cost when closed. + if (!ensureStation()) return; + + // Compute display keys (Km as ints) + int curAltKm = (int)Math.round(cached.getOrbitalDistance() * 200.0 + 100.0); + int tgtAltKm = cached.targetOrbitalDistance * 200 + 100; + + // Update only when the visible value changes + if (curAltKm != lastAltKm) { + // "Altitude: XXXKm" + moduleGrav.setText(prefixAlt + " " + curAltKm + "Km"); + lastAltKm = curAltKm; + } + if (tgtAltKm != lastTgtKm) { + // "Target Altitude: YYY" + targetGrav.setText(prefixTgt + " " + tgtAltKm); + lastTgtKm = tgtAltKm; + } + } + + @Override public int getSizeX() { return 0; } + @Override public int getSizeY() { return 0; } + }); + + return modules; } @@ -83,62 +141,50 @@ public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) { readFromNBT(pkt.getNbtCompound()); } - private void updateText() { - if (world.isRemote) { - ISpaceObject spaceObject = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); - if (spaceObject != null) { - moduleGrav.setText(String.format("%s %.0fKm", LibVulpes.proxy.getLocalizedString("msg.stationaltctrl.alt"), spaceObject.getOrbitalDistance() * 200 + 100)); - //maxGravBuildSpeed.setText(String.format("%s%.1f", LibVulpes.proxy.getLocalizedString("msg.stationaltctrl.maxaltrate"), 7200D * spaceObject.getMaxRotationalAcceleration())); - targetGrav.setText(String.format("%s %d", LibVulpes.proxy.getLocalizedString("msg.stationaltctrl.tgtalt"), ((SpaceStationObject) spaceObject).targetOrbitalDistance * 200 + 100)); - } + @Override + public void update() { + if (!(world.provider instanceof WorldProviderSpace) || world.isRemote) return; + + ISpaceObject so = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); + if (so == null) return; + SpaceStationObject sso = (SpaceStationObject) so; - //numThrusters.setText("Number Of Thrusters: 0"); + // Redstone → target + if (redstoneControl.getState() == RedstoneState.ON) { + sso.targetOrbitalDistance = Math.max((world.getStrongPower(pos) * 13) + 4, 190); + } else if (redstoneControl.getState() == RedstoneState.INVERTED) { + sso.targetOrbitalDistance = Math.max(Math.abs(15 - world.getStrongPower(pos)) * 13 + 4, 190); } - } - @Override - public void update() { - if (this.world.provider instanceof WorldProviderSpace) { + progress = sso.targetOrbitalDistance; - if (!world.isRemote) { - ISpaceObject spaceObject = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); + // Converge with epsilon + double target = sso.targetOrbitalDistance; + double current = so.getOrbitalDistance(); + double diff = target - current; + double acc = 0.02D; + boolean changing = Math.abs(diff) >= 0.001D; - if (spaceObject != null) { - if (redstoneControl.getState() == RedstoneState.ON) - ((SpaceStationObject) spaceObject).targetOrbitalDistance = Math.max((world.getStrongPower(pos) * 13) + 4, 190); - else if (redstoneControl.getState() == RedstoneState.INVERTED) - ((SpaceStationObject) spaceObject).targetOrbitalDistance = Math.max(Math.abs(15 - world.getStrongPower(pos)) * 13 + 4, 190); - - progress = ((SpaceStationObject) spaceObject).targetOrbitalDistance; - - double targetGravity = ((SpaceStationObject) spaceObject).targetOrbitalDistance; - double angVel = spaceObject.getOrbitalDistance(); - double acc = 0.02;//0.1 * (getTotalProgress(0) - angVel + 1) / (float) getTotalProgress(0); - - double difference = targetGravity - angVel; - - if (difference != 0) { - double finalVel = angVel; - if (difference < 0) { - finalVel = angVel + Math.max(difference, -acc); - } else if (difference > 0) { - finalVel = angVel + Math.min(difference, acc); - } - - spaceObject.setOrbitalDistance((float) finalVel); - if (!world.isRemote) { - //PacketHandler.sendToNearby(new PacketStationUpdate(spaceObject, PacketStationUpdate.Type.ROTANGLE_UPDATE), this.worldObj.provider.dimensionId, this.xCoord, this.yCoord, this.zCoord, 1024); - PacketHandler.sendToAll(new PacketStationUpdate(spaceObject, PacketStationUpdate.Type.ALTITUDE_UPDATE)); - markDirty(); - } else - updateText(); - } - } - } else - updateText(); + if (changing) { + double next = current + (diff < 0 ? Math.max(diff, -acc) : Math.min(diff, acc)); + so.setOrbitalDistance((float) next); + + long wt = world.getTotalWorldTime(); + if (wt - lastAltSyncTick >= 10L) { // ~4 Hz while changing + PacketHandler.sendToAll(new PacketStationUpdate(so, PacketStationUpdate.Type.ALTITUDE_UPDATE)); + lastAltSyncTick = wt; + } + markDirty(); + } else if (wasChanging) { + // final flush on settle so clients end exactly on the last value + PacketHandler.sendToAll(new PacketStationUpdate(so, PacketStationUpdate.Type.ALTITUDE_UPDATE)); + markDirty(); } + + wasChanging = changing; } + @Override public String getModularInventoryName() { return AdvancedRocketryBlocks.blockAltitudeController.getLocalizedName(); From fea1fae07e426b408ab680c736231b318ab35390 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 5 Nov 2025 16:41:49 +0100 Subject: [PATCH 090/424] Improve rotation update handling in PacketStationUpdate Refactor ROTANGLE_UPDATE case to handle rotation updates more smoothly by checking proximity to server snapshot and adjusting velocities accordingly. --- .../network/PacketStationUpdate.java | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/network/PacketStationUpdate.java b/src/main/java/zmaster587/advancedRocketry/network/PacketStationUpdate.java index 21eb199fd..50ca374b1 100644 --- a/src/main/java/zmaster587/advancedRocketry/network/PacketStationUpdate.java +++ b/src/main/java/zmaster587/advancedRocketry/network/PacketStationUpdate.java @@ -75,6 +75,7 @@ public void write(ByteBuf out) { Logger.getLogger("advancedRocketry").warning("Dimension " + stationNumber + " has thrown an exception trying to write NBT, deleting!"); DimensionManager.getInstance().deleteDimension(stationNumber); } + break; default: } } @@ -128,7 +129,8 @@ public void read(ByteBuf in) { @Override public void executeClient(EntityPlayer thePlayer) { spaceObject = SpaceObjectManager.getSpaceManager().getSpaceStation(stationNumber); - + if (spaceObject == null) return; + switch (type) { case DEST_ORBIT_UPDATE: spaceObject.setDestOrbitingBody(destOrbitingBody); @@ -140,14 +142,32 @@ public void executeClient(EntityPlayer thePlayer) { if (spaceObject instanceof SpaceStationObject) ((SpaceStationObject) spaceObject).setFuelAmount(fuel); break; - case ROTANGLE_UPDATE: - spaceObject.setRotation(rx, EnumFacing.EAST); - spaceObject.setRotation(ry, EnumFacing.UP); - spaceObject.setRotation(rz, EnumFacing.NORTH); - spaceObject.setDeltaRotation(drx, EnumFacing.EAST); - spaceObject.setDeltaRotation(dry, EnumFacing.UP); - spaceObject.setDeltaRotation(drz, EnumFacing.NORTH); + case ROTANGLE_UPDATE: { + SpaceStationObject sso = (SpaceStationObject) spaceObject; + + // Current client-predicted angles + double crx = sso.getRotation(EnumFacing.EAST); + double cry = sso.getRotation(EnumFacing.UP); + double crz = sso.getRotation(EnumFacing.NORTH); + + // If we're close to server snapshot, avoid snapping: just update angular velocities + final double SNAP_DEG = 2.0; // small tolerance; tune 1–3° + boolean close = + Math.abs(crx - rx) < SNAP_DEG && + Math.abs(cry - ry) < SNAP_DEG && + Math.abs(crz - rz) < SNAP_DEG; + + if (close) { + // keep current pose, just update velocities (smooth, no blink) + sso.setDeltaRotation(drx, EnumFacing.EAST); + sso.setDeltaRotation(dry, EnumFacing.UP); + sso.setDeltaRotation(drz, EnumFacing.NORTH); + } else { + // we're far off: do a one-time snap + reset baseline + sso.applyRemoteRotationState(rx, ry, rz, drx, dry, drz); + } break; + } case SIGNAL_WHITE_BURST: PlanetEventHandler.runBurst(Minecraft.getMinecraft().world.getTotalWorldTime() + 20, 20); break; From 49670460de64faa74016d45678a07de991b33830 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 5 Nov 2025 16:42:23 +0100 Subject: [PATCH 091/424] Refactor GUI update logic in TileStationOrientationController Refactor TileStationOrientationController to improve GUI updates and synchronization with space station state. --- .../TileStationOrientationController.java | 156 +++++++++++------- 1 file changed, 100 insertions(+), 56 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationOrientationController.java b/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationOrientationController.java index d3ed36055..11eaa29ed 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationOrientationController.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationOrientationController.java @@ -1,6 +1,8 @@ package zmaster587.advancedRocketry.tile.station; import io.netty.buffer.ByteBuf; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; @@ -26,6 +28,7 @@ public class TileStationOrientationController extends TileEntity implements ITickable, IModularInventory, INetworkMachine, ISliderBar, IButtonInventory { private int[] progress; + private long lastRotSyncTick = -5; private ModuleText moduleAngularVelocity, numThrusters, maxAngularAcceleration, targetRotations; @@ -56,70 +59,111 @@ public List getModules(int id, EntityPlayer player) { modules.add(new ModuleButton(25, 35, 2, LibVulpes.proxy.getLocalizedString("msg.spacelaser.reset"), this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild, 36, 15)); //modules.add(new ModuleSlider(24, 35, 2, TextureResources.doubleWarningSideBarIndicator, (ISliderBar)this)); - updateText(); - return modules; - } + // inline updater that runs only while GUI is open + modules.add(new ModuleBase(0, 0) { + private SpaceStationObject cached; + private int cachedId = Integer.MIN_VALUE; - private void updateText() { - if (world.isRemote) { - ISpaceObject spaceObject = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); - if (spaceObject != null) { - moduleAngularVelocity.setText(String.format("%s%.1f %.1f %.1f", LibVulpes.proxy.getLocalizedString("msg.stationorientctrl.alt"), 72000D * spaceObject.getDeltaRotation(EnumFacing.EAST), 72000D * spaceObject.getDeltaRotation(EnumFacing.UP), 7200D * spaceObject.getDeltaRotation(EnumFacing.NORTH))); - //maxAngularAcceleration.setText(String.format("Maximum Angular Acceleration: %.1f", 7200D*object.getMaxRotationalAcceleration())); + private int lastVelX = Integer.MIN_VALUE, lastVelY = Integer.MIN_VALUE, lastVelZ = Integer.MIN_VALUE; + private int lastTgtX = Integer.MIN_VALUE, lastTgtY = Integer.MIN_VALUE, lastTgtZ = Integer.MIN_VALUE; - //numThrusters.setText("Number Of Thrusters: 0"); - int[] targetRotationsPerHour = ((SpaceStationObject) spaceObject).targetRotationsPerHour; - targetRotations.setText(String.format("%s%d %d %d", LibVulpes.proxy.getLocalizedString("msg.stationorientctrl.tgtalt"), targetRotationsPerHour[0], targetRotationsPerHour[1], targetRotationsPerHour[2])); + private final String prefixVel = LibVulpes.proxy.getLocalizedString("msg.stationorientctrl.alt"); + private final String prefixTgt = LibVulpes.proxy.getLocalizedString("msg.stationorientctrl.tgtalt"); + + private String oneDp(int key) { + int abs = Math.abs(key), whole = abs / 10, frac = abs % 10; + String s = whole + "." + frac; + return key < 0 ? "-" + s : s; } - } + + private boolean ensureStation() { + if (cached == null) { + ISpaceObject so = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); + if (!(so instanceof SpaceStationObject)) return false; + cached = (SpaceStationObject) so; + cachedId = so.getId(); + return true; + } + ISpaceObject current = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); + if (!(current instanceof SpaceStationObject)) { cached = null; cachedId = Integer.MIN_VALUE; return false; } + if (current.getId() != cachedId) { + cached = (SpaceStationObject) current; + cachedId = current.getId(); + } + return true; + } + + @Override + public void renderBackground(GuiContainer gui, int x, int y, int mouseX, int mouseY, FontRenderer font) { + if (!ensureStation()) return; + + double dX = cached.getDeltaRotation(EnumFacing.EAST); + double dY = cached.getDeltaRotation(EnumFacing.UP); + double dZ = cached.getDeltaRotation(EnumFacing.NORTH); + int[] tgt = cached.targetRotationsPerHour; + + int velX = (int)Math.round(72000D * dX * 10D); + int velY = (int)Math.round(72000D * dY * 10D); + int velZ = (int)Math.round( 7200D * dZ * 10D); + + if (velX != lastVelX || velY != lastVelY || velZ != lastVelZ) { + moduleAngularVelocity.setText(prefixVel + oneDp(velX) + " " + oneDp(velY) + " " + oneDp(velZ)); + lastVelX = velX; lastVelY = velY; lastVelZ = velZ; + } + + if (tgt[0] != lastTgtX || tgt[1] != lastTgtY || tgt[2] != lastTgtZ) { + targetRotations.setText(prefixTgt + tgt[0] + " " + tgt[1] + " " + tgt[2]); + lastTgtX = tgt[0]; lastTgtY = tgt[1]; lastTgtZ = tgt[2]; + } + } + + @Override public int getSizeX() { return 0; } + @Override public int getSizeY() { return 0; } + }); + + + return modules; } @Override public void update() { + // Only relevant in space + if (!(world.provider instanceof WorldProviderSpace)) return; + // Server-side only + if (world.isRemote) return; + + ISpaceObject spaceObject = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); + if (spaceObject == null) return; + + EnumFacing[] dirs = { EnumFacing.EAST, EnumFacing.UP, EnumFacing.NORTH }; + int[] targetRotationsPerHour = ((SpaceStationObject) spaceObject).targetRotationsPerHour; + + // keep sliders in sync with server state + for (int i = 0; i < 3; i++) { + setProgress(i, targetRotationsPerHour[i] + (getTotalProgress(i) / 2)); + } - if (this.world.provider instanceof WorldProviderSpace) { - if (!world.isRemote) { - ISpaceObject spaceObject = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); - boolean update = false; - - if (spaceObject != null) { - - EnumFacing[] dirs = {EnumFacing.EAST, EnumFacing.UP, EnumFacing.NORTH}; - int[] targetRotationsPerHour = ((SpaceStationObject) spaceObject).targetRotationsPerHour; - for (int i = 0; i < 3; i++) { - setProgress(i, targetRotationsPerHour[i] + (getTotalProgress(i) / 2)); - } - - - for (int i = 0; i < 3; i++) { - - double targetAngularVelocity = targetRotationsPerHour[i] / 72000D; - double angVel = spaceObject.getDeltaRotation(dirs[i]); - double acc = spaceObject.getMaxRotationalAcceleration(); - - double difference = targetAngularVelocity - angVel; - - if (difference != 0) { - double finalVel = angVel; - if (difference < 0) { - finalVel = angVel + Math.max(difference, -acc); - } else if (difference > 0) { - finalVel = angVel + Math.min(difference, acc); - } - - spaceObject.setDeltaRotation(finalVel, dirs[i]); - update = true; - } - } - - if (!world.isRemote && update) { - //PacketHandler.sendToNearby(new PacketStationUpdate(spaceObject, PacketStationUpdate.Type.ROTANGLE_UPDATE), this.worldObj.provider.dimensionId, this.xCoord, this.yCoord, this.zCoord, 1024); - PacketHandler.sendToAll(new PacketStationUpdate(spaceObject, PacketStationUpdate.Type.ROTANGLE_UPDATE)); - } - } else - updateText(); - } else - updateText(); + boolean updated = false; + + for (int i = 0; i < 3; i++) { + double targetAngularVelocity = targetRotationsPerHour[i] / 72000D; + double angVel = spaceObject.getDeltaRotation(dirs[i]); + double acc = spaceObject.getMaxRotationalAcceleration(); + + double difference = targetAngularVelocity - angVel; + if (difference != 0) { + double finalVel = angVel + (difference < 0 ? Math.max(difference, -acc) : Math.min(difference, acc)); + spaceObject.setDeltaRotation(finalVel, dirs[i]); + updated = true; + } + } + + if (updated) { + long t = world.getTotalWorldTime(); + if (t - lastRotSyncTick >= 5) { // ~4 Hz + PacketHandler.sendToAll(new PacketStationUpdate(spaceObject, PacketStationUpdate.Type.ROTANGLE_UPDATE)); + lastRotSyncTick = t; + } } } From b6e94459e74476349e5189d8734918848162c7f3 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 5 Nov 2025 16:44:49 +0100 Subject: [PATCH 092/424] Fix formatting issue in TileUnmannedVehicleAssembler From b98253c1a86b6fd9ac08743e13261b55a00e1482 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 5 Nov 2025 17:06:27 +0100 Subject: [PATCH 093/424] Refactor rotation and time modification handling fixes snaps and laggy resyncs when changing rotationvelocities in controller --- .../stations/SpaceStationObject.java | 48 ++++++++++++++----- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/stations/SpaceStationObject.java b/src/main/java/zmaster587/advancedRocketry/stations/SpaceStationObject.java index 10340153f..fc6b65544 100644 --- a/src/main/java/zmaster587/advancedRocketry/stations/SpaceStationObject.java +++ b/src/main/java/zmaster587/advancedRocketry/stations/SpaceStationObject.java @@ -57,9 +57,10 @@ public class SpaceStationObject implements ISpaceObject, IPlanetDefiner { private boolean isAnchored = false; private double[] rotation; private double[] angularVelocity; - private long lastTimeModification = 0; + private final long[] lastTimeModification = new long[3]; // one per axis private DimensionProperties properties; + public SpaceStationObject() { properties = (DimensionProperties) zmaster587.advancedRocketry.dimension.DimensionManager.defaultSpaceDimensionProperties.clone(); orbitalDistance = 50.0f; @@ -75,8 +76,12 @@ public SpaceStationObject() { knownPlanetList = new HashSet<>(); angularVelocity = new double[3]; rotation = new double[3]; - } - + long now = getWorldTime(); + lastTimeModification[0] = now; + lastTimeModification[1] = now; + lastTimeModification[2] = now; + } + public Set getKnownPlanetList() { return knownPlanetList; } @@ -110,6 +115,17 @@ public void discoverPlanet(int pid) { PacketHandler.sendToAll(new PacketSpaceStationInfo(getId(), this)); } + public void applyRemoteRotationState(double rx, double ry, double rz, + double drx, double dry, double drz) { + rotation[0] = rx; rotation[1] = ry; rotation[2] = rz; + angularVelocity[0] = drx; angularVelocity[1] = dry; angularVelocity[2] = drz; + long now = getWorldTime(); + lastTimeModification[0] = now; + lastTimeModification[1] = now; + lastTimeModification[2] = now; + } + + /** * @return id of the space object (NOT the DIMID) */ @@ -209,8 +225,12 @@ public int getAltitude() { * @return rotation of the station in degrees */ public double getRotation(EnumFacing dir) { - - return (rotation[getIDFromDir(dir)] + getDeltaRotation(dir) * (getWorldTime() - lastTimeModification)) % (360D); + int idx = getIDFromDir(dir); + long dt = getWorldTime() - lastTimeModification[idx]; + double a = rotation[idx] + angularVelocity[idx] * dt; + // keep modulo stable + a = ((a % 360D) + 360D) % 360D; + return a; } /** @@ -241,8 +261,10 @@ else if (facing == EnumFacing.UP) /** * @param rotation rotation of the station in degrees */ - public void setRotation(double rotation, EnumFacing facing) { - this.rotation[getIDFromDir(facing)] = rotation; + public void setRotation(double rotDeg, EnumFacing facing) { + int idx = getIDFromDir(facing); + rotation[idx] = rotDeg; + lastTimeModification[idx] = getWorldTime(); } /** @@ -255,15 +277,17 @@ public double getDeltaRotation(EnumFacing facing) { /** * @param rotation anglarVelocity of the station in degrees per tick */ - public void setDeltaRotation(double rotation, EnumFacing facing) { + public void setDeltaRotation(double newVel, EnumFacing facing) { if (!isAnchored()) { - this.rotation[getIDFromDir(facing)] = getRotation(facing); - this.lastTimeModification = getWorldTime(); - - this.angularVelocity[getIDFromDir(facing)] = rotation; + int idx = getIDFromDir(facing); + // capture current integrated angle as the new snapshot + rotation[idx] = getRotation(facing); + lastTimeModification[idx] = getWorldTime(); + angularVelocity[idx] = newVel; } } + public double getMaxRotationalAcceleration() { return 0.02D; } From 7097b9cd23325d347b05115849417829bceb3b4c Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 5 Nov 2025 17:07:16 +0100 Subject: [PATCH 094/424] Simplify rotation state application for space stations fixing snappy resyncs laggy stuff when changing rotationangles --- .../network/PacketStationUpdate.java | 26 +++---------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/network/PacketStationUpdate.java b/src/main/java/zmaster587/advancedRocketry/network/PacketStationUpdate.java index 50ca374b1..28182d281 100644 --- a/src/main/java/zmaster587/advancedRocketry/network/PacketStationUpdate.java +++ b/src/main/java/zmaster587/advancedRocketry/network/PacketStationUpdate.java @@ -143,29 +143,9 @@ public void executeClient(EntityPlayer thePlayer) { ((SpaceStationObject) spaceObject).setFuelAmount(fuel); break; case ROTANGLE_UPDATE: { - SpaceStationObject sso = (SpaceStationObject) spaceObject; - - // Current client-predicted angles - double crx = sso.getRotation(EnumFacing.EAST); - double cry = sso.getRotation(EnumFacing.UP); - double crz = sso.getRotation(EnumFacing.NORTH); - - // If we're close to server snapshot, avoid snapping: just update angular velocities - final double SNAP_DEG = 2.0; // small tolerance; tune 1–3° - boolean close = - Math.abs(crx - rx) < SNAP_DEG && - Math.abs(cry - ry) < SNAP_DEG && - Math.abs(crz - rz) < SNAP_DEG; - - if (close) { - // keep current pose, just update velocities (smooth, no blink) - sso.setDeltaRotation(drx, EnumFacing.EAST); - sso.setDeltaRotation(dry, EnumFacing.UP); - sso.setDeltaRotation(drz, EnumFacing.NORTH); - } else { - // we're far off: do a one-time snap + reset baseline - sso.applyRemoteRotationState(rx, ry, rz, drx, dry, drz); - } + ((SpaceStationObject) spaceObject).applyRemoteRotationState( + rx, ry, rz, drx, dry, drz + ); break; } case SIGNAL_WHITE_BURST: From fadb21261207a343b14e03259ef8c2c5f4c22170 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 6 Nov 2025 10:39:36 +0100 Subject: [PATCH 095/424] Add handling for nuclear working fluid in EntityRocket --- .../zmaster587/advancedRocketry/entity/EntityRocket.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java b/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java index 8310fcf3f..af41de4a1 100644 --- a/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java +++ b/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java @@ -752,6 +752,11 @@ public boolean canRocketFitFluid(FluidStack fluidStack) { if (stats.getOxidizerFluid().equals("null") && isCorrectFluid) stats.setOxidizerFluid(fluidStack.getFluid().getName()); return isCorrectFluid; + } else if (FuelRegistry.instance.isFuel(FuelType.NUCLEAR_WORKING_FLUID, fluidStack.getFluid())) { + boolean isCorrectFluid = stats.getWorkingFluid().equals("null") || fluidStack.getFluid() == FluidRegistry.getFluid(stats.getWorkingFluid()); + if (stats.getWorkingFluid().equals("null") && isCorrectFluid) + stats.setWorkingFluid(fluidStack.getFluid().getName()); + return isCorrectFluid; } return false; } From 3b35f5f0dc56c12798344112dc41f2dff2bcd7eb Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 6 Nov 2025 10:41:21 +0100 Subject: [PATCH 096/424] Fix nuclear working fluid --- .../infrastructure/TileFuelingStation.java | 56 ++++++++++++++----- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java index 06aa2a755..0ca2b7021 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java @@ -20,6 +20,7 @@ import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fluids.capability.IFluidTankProperties; import net.minecraftforge.fml.relauncher.Side; +import zmaster587.advancedRocketry.AdvancedRocketry; import zmaster587.advancedRocketry.api.*; import zmaster587.advancedRocketry.api.fuel.FuelRegistry; import zmaster587.advancedRocketry.api.fuel.FuelRegistry.FuelType; @@ -109,15 +110,15 @@ private void refreshFluidCachesIfNeeded() { if (!Objects.equals(f, lastFuelStr)) { lastFuelStr = f; - cachedFuelFluid = (f == null || "null".equals(f)) ? null : FluidRegistry.getFluid(f); + cachedFuelFluid = (f == null || "null".equals(f) || f.isEmpty()) ? null : FluidRegistry.getFluid(f); } if (!Objects.equals(o, lastOxStr)) { lastOxStr = o; - cachedOxFluid = (o == null || "null".equals(o)) ? null : FluidRegistry.getFluid(o); + cachedOxFluid = (o == null || "null".equals(o) || o.isEmpty()) ? null : FluidRegistry.getFluid(o); } if (!Objects.equals(w, lastWorkStr)) { lastWorkStr = w; - cachedWorkFluid = (w == null || "null".equals(w)) ? null : FluidRegistry.getFluid(w); + cachedWorkFluid = (w == null || "null".equals(w) || w.isEmpty()) ? null : FluidRegistry.getFluid(w); } } @@ -125,8 +126,17 @@ private boolean isStationFluidForThisRocket(Fluid current) { refreshFluidCachesIfNeeded(); if (current == null || linkedRocket == null) return false; - // If a specific fluid was already chosen, match directly. - if (current == cachedFuelFluid || current == cachedOxFluid || current == cachedWorkFluid) { + // --- compare by fluid name, not by instance --- + final String currentName = current.getName(); + + // If a specific fluid was already chosen, match directly by name. + if (lastFuelStr != null && !"null".equals(lastFuelStr) && !lastFuelStr.isEmpty() && currentName.equals(lastFuelStr)) { + return true; + } + if (lastOxStr != null && !"null".equals(lastOxStr) && !lastOxStr.isEmpty() && currentName.equals(lastOxStr)) { + return true; + } + if (lastWorkStr != null && !"null".equals(lastWorkStr) && !lastWorkStr.isEmpty() && currentName.equals(lastWorkStr)) { return true; } @@ -287,13 +297,26 @@ public void performFunction() { fuelingActive = false; return; } - // Bounded transfer scaled by throttle; drain exactly what was accepted + + // Bounded transfer scaled by throttle; drain exactly the delta that actually landed int step = ARConfiguration.getCurrentConfig().fuelPointsPer10Mb; int toOffer = Math.min(step * OP_THROTTLE_TICKS, tank.getFluidAmount()); if (toOffer > 0) { - int accepted = linkedRocket.addFuelAmount(typeToFill, toOffer); // assumes returns actual mB accepted - if (accepted > 0) { - tank.drain(accepted, true); + final int before = linkedRocket.getFuelAmount(typeToFill); + final int ret = linkedRocket.addFuelAmount(typeToFill, toOffer); + + // Be robust to either contract: + // - if ret == new total -> delta = ret - before + // - if ret == accepted -> delta = ret (clamped to toOffer) + int delta = Math.max(0, ret - before); + if (delta == 0) { + // Assume ret is "accepted amount" + delta = Math.min(toOffer, Math.max(0, ret)); + } + + if (delta > 0) { + tank.drain(delta, true); + int baseRate = linkedRocket.stats.getBaseFuelRate(typeToFill); if (baseRate > 0) { int multRate = (int)(FuelRegistry.instance.getMultiplier(typeToFill, currentFluid) * baseRate); @@ -304,6 +327,7 @@ public void performFunction() { } } + // Re-evaluate full; if full now, stop within this link boolean fullNow = !canRocketFitFluid(currentFluid); setRedstoneState(fullNow); @@ -362,19 +386,23 @@ public boolean canFill(Fluid fluid) { private boolean canRocketFitFluid(Fluid f) { if (f == null || linkedRocket == null) return false; + boolean fits = false; + + // Check every type the fluid qualifies for; OR the results. if (FuelRegistry.instance.isFuel(FuelType.LIQUID_OXIDIZER, f)) { - return linkedRocket.getFuelAmount(FuelType.LIQUID_OXIDIZER) < linkedRocket.getFuelCapacity(FuelType.LIQUID_OXIDIZER); + fits |= linkedRocket.getFuelAmount(FuelType.LIQUID_OXIDIZER) < linkedRocket.getFuelCapacity(FuelType.LIQUID_OXIDIZER); } if (FuelRegistry.instance.isFuel(FuelType.LIQUID_BIPROPELLANT, f)) { - return linkedRocket.getFuelAmount(FuelType.LIQUID_BIPROPELLANT) < linkedRocket.getFuelCapacity(FuelType.LIQUID_BIPROPELLANT); + fits |= linkedRocket.getFuelAmount(FuelType.LIQUID_BIPROPELLANT) < linkedRocket.getFuelCapacity(FuelType.LIQUID_BIPROPELLANT); } if (FuelRegistry.instance.isFuel(FuelType.LIQUID_MONOPROPELLANT, f)) { - return linkedRocket.getFuelAmount(FuelType.LIQUID_MONOPROPELLANT) < linkedRocket.getFuelCapacity(FuelType.LIQUID_MONOPROPELLANT); + fits |= linkedRocket.getFuelAmount(FuelType.LIQUID_MONOPROPELLANT) < linkedRocket.getFuelCapacity(FuelType.LIQUID_MONOPROPELLANT); } if (FuelRegistry.instance.isFuel(FuelType.NUCLEAR_WORKING_FLUID, f)) { - return linkedRocket.getFuelAmount(FuelType.NUCLEAR_WORKING_FLUID) < linkedRocket.getFuelCapacity(FuelType.NUCLEAR_WORKING_FLUID); + fits |= linkedRocket.getFuelAmount(FuelType.NUCLEAR_WORKING_FLUID) < linkedRocket.getFuelCapacity(FuelType.NUCLEAR_WORKING_FLUID); } - return false; + + return fits; } @Override From d0324231499e3e2770ff813df59787a303023208 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 6 Nov 2025 10:42:51 +0100 Subject: [PATCH 097/424] Nuclear Working Fluid fix --- .../advancedRocketry/api/StatsRocket.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/api/StatsRocket.java b/src/main/java/zmaster587/advancedRocketry/api/StatsRocket.java index 427f01ee4..eb292e2b0 100644 --- a/src/main/java/zmaster587/advancedRocketry/api/StatsRocket.java +++ b/src/main/java/zmaster587/advancedRocketry/api/StatsRocket.java @@ -145,6 +145,10 @@ public float getWeight() { Fluid f = FluidRegistry.getFluid(getOxidizerFluid()); fluidWeight += WeightEngine.INSTANCE.getWeight(f, getFuelAmount(FuelType.LIQUID_OXIDIZER)); } + if (FluidRegistry.isFluidRegistered(getWorkingFluid())) { + Fluid f = FluidRegistry.getFluid(getWorkingFluid()); + fluidWeight += WeightEngine.INSTANCE.getWeight(f, getFuelAmount(FuelType.NUCLEAR_WORKING_FLUID)); + } } return weight + fluidWeight; } @@ -554,6 +558,7 @@ public void reset() { weight = 0; fuelFluid = "null"; oxidizerFluid = "null"; + workingFluid = "null"; drillingPower = 0f; for (FuelType type : FuelType.values()) { @@ -720,12 +725,12 @@ public void readFromNBT(NBTTagCompound nbt) { this.fuelRateNuclearWorkingFluid = stats.getInteger("fuelRateNuclearWorkingFluid"); this.fuelRateWarp = stats.getInteger("fuelRateWarp"); - this.fuelBaseRateMonopropellant = stats.getInteger("fuelBaseRateMonopropellant"); - this.fuelBaseRateBipropellant = stats.getInteger("fuelBaseRateBipropellant"); - this.fuelBaseRateOxidizer = stats.getInteger("fuelBaseRateOxidizer"); + this.fuelBaseRateMonopropellant = (int)stats.getFloat("fuelBaseRateMonopropellant"); + this.fuelBaseRateBipropellant = (int)stats.getFloat("fuelBaseRateBipropellant"); + this.fuelBaseRateOxidizer = (int)stats.getFloat("fuelBaseRateOxidizer"); this.fuelBaseRateImpulse = stats.getInteger("fuelBaseRateImpulse"); this.fuelBaseRateIon = stats.getInteger("fuelBaseRateIon"); - this.fuelBaseRateNuclearWorkingFluid = stats.getInteger("fuelBaseRateNuclearWorkingFluid"); + this.fuelBaseRateNuclearWorkingFluid = (int)stats.getFloat("fuelBaseRateNuclearWorkingFluid"); this.fuelBaseRateWarp = stats.getInteger("fuelBaseRateWarp"); @@ -766,4 +771,4 @@ else if (obj instanceof NBTTagInt) } } } -} \ No newline at end of file +} From e08ffb83dc2462fae27e31cb147b58d52401579d Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 6 Nov 2025 10:43:29 +0100 Subject: [PATCH 098/424] Add newline at end of EntityStationDeployedRocket.java Fix missing newline at end of file. From 38ebc6837e2f41e6c8b487944130b6b3f2166290 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 6 Nov 2025 10:44:01 +0100 Subject: [PATCH 099/424] Fix formatting issue in TileUnmannedVehicleAssembler From d47c70304e8fff136bf88e99a0cce4f43e4c5ef2 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 6 Nov 2025 10:59:16 +0100 Subject: [PATCH 100/424] Add newline at end of EntityStationDeployedRocket.java Fix missing newline at end of file. From 620e62fc4528be1ebffbf151bd781c56b6737072 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 6 Nov 2025 11:43:20 +0100 Subject: [PATCH 101/424] Hide energy capability and prevent EnergyConnections UX: exposing 0 RF storage is just confusing. --- .../tile/atmosphere/TileGasChargePad.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileGasChargePad.java b/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileGasChargePad.java index 503015a99..3537b10a5 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileGasChargePad.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileGasChargePad.java @@ -6,6 +6,8 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.AxisAlignedBB; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.energy.CapabilityEnergy; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; @@ -19,6 +21,7 @@ import zmaster587.libVulpes.tile.TileInventoriedRFConsumerTank; import zmaster587.libVulpes.util.FluidUtils; import zmaster587.libVulpes.util.IconResource; +import zmaster587.libVulpes.cap.TeslaHandler; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -51,6 +54,30 @@ public int getPowerPerOperation() { return 0; } + @Override + public boolean hasCapability(Capability capability, @Nullable EnumFacing facing) { + // Hide Forge Energy capability + if (capability == CapabilityEnergy.ENERGY) return false; + // Hide any Tesla capability the base class would expose + if (TeslaHandler.hasTeslaCapability(this, capability)) return false; + return super.hasCapability(capability, facing); + } + + @Override + @Nullable + public T getCapability(Capability capability, @Nullable EnumFacing facing) { + // Don’t provide energy handlers to probes/pipes + if (capability == CapabilityEnergy.ENERGY) return null; + if (TeslaHandler.hasTeslaCapability(this, capability)) return null; + return super.getCapability(capability, facing); + } + + // Optional (extra safety for mods that query IPower-style methods directly) + @Override public boolean canConnectEnergy(EnumFacing side) { return false; } + @Override public boolean canReceive() { return false; } + @Override public int getEnergyStored(EnumFacing side) { return 0; } + @Override public int getMaxEnergyStored(EnumFacing side) { return 0; } + @Override public boolean canPerformFunction() { if (!world.isRemote) { From dcfdeff3b723a442c3566db480bf6be08443a56b Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 6 Nov 2025 14:18:57 +0100 Subject: [PATCH 102/424] Fix missing newline at end of TileUnmannedVehicleAssembler.java From c0308c743e0fac8bd236f9bc826d954cc9213df8 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 6 Nov 2025 14:20:09 +0100 Subject: [PATCH 103/424] Add newline at end of WeightEngine.java Fix missing newline at end of file From 04231758ce411a023a33bb9287d7213323e8b74e Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 6 Nov 2025 14:23:45 +0100 Subject: [PATCH 104/424] Fix duration check to prevent zero or negative values Ensure duration is at least 1 tick in MissionResourceCollection. --- .../advancedRocketry/mission/MissionResourceCollection.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/mission/MissionResourceCollection.java b/src/main/java/zmaster587/advancedRocketry/mission/MissionResourceCollection.java index 18fe4e55c..4c3e4f60f 100644 --- a/src/main/java/zmaster587/advancedRocketry/mission/MissionResourceCollection.java +++ b/src/main/java/zmaster587/advancedRocketry/mission/MissionResourceCollection.java @@ -48,6 +48,10 @@ public MissionResourceCollection(long duration, EntityRocket entity, LinkedList< startWorldTime = DimensionManager.getWorld(0).getTotalWorldTime(); this.duration = duration; + if (this.duration <= 0L) { + this.duration = 1L; // at least 1 tick + } + this.launchDimension = entity.world.provider.getDimension(); rocketStorage = entity.storage; rocketStats = entity.stats; @@ -64,6 +68,7 @@ public MissionResourceCollection(long duration, EntityRocket entity, LinkedList< @Override public double getProgress(World world) { + if (duration <= 0L) return 1.0d; return Math.max((AdvancedRocketry.proxy.getWorldTimeUniversal(0) - startWorldTime) / (double) duration, 0); } From 00fd0d0e903c985cd85d6aba91ada245276c73de Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 6 Nov 2025 14:25:20 +0100 Subject: [PATCH 105/424] Add newline at end of EntityStationDeployedRocket.java Fix formatting by adding a newline at the end of the file. From 87010e8a655f1e25c08cb17be2911cb46684c7eb Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 6 Nov 2025 14:28:06 +0100 Subject: [PATCH 106/424] Fix missing newline at end of file Add missing newline at the end of StatsRocket.java From 037c6f8fee8bdc7c9259086e35a8fb144e006203 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 6 Nov 2025 16:05:11 +0100 Subject: [PATCH 107/424] Enhance rocket pad handling in TileRocketAssemblingMachine Added logic to recompute rocket pad bounds and link infrastructure during onLoad and And properly clearing caches. --- .../tile/TileRocketAssemblingMachine.java | 44 +++++++++++++++---- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java index 1b05536af..88d14b92f 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java @@ -98,33 +98,61 @@ public TileRocketAssemblingMachine() { @Override public void onLoad() { - // Called after world is set and NBT is loaded; safe place to register (server only) if (!world.isRemote && !registeredBus) { MinecraftForge.EVENT_BUS.register(this); registeredBus = true; } - } + + if (world.isRemote) return; + + // Recompute pad bounds and relink infra to any rockets already on the pad + bbCache = getRocketPadBounds(world, pos); + if (bbCache != null) { + final AxisAlignedBB box = bbCache.grow(1.0E-4, 1.0E-4, 1.0E-4); + List rockets = world.getEntitiesWithinAABB(EntityRocketBase.class, box); + if (!rockets.isEmpty()) { + for (IInfrastructure infra : getConnectedInfrastructure()) { + for (EntityRocketBase r : rockets) { + r.linkInfrastructure(infra); + } + } + } + } + } @Override public void invalidate() { super.invalidate(); unregisterFromBus(); - if (world != null) - for (HashedBlockPosition pos : blockPos) { - TileEntity tile = world.getTileEntity(pos.getBlockPos()); - if (tile instanceof IMultiblock) { - ((IMultiblock) tile).setIncomplete(); + // Notify linked multiblocks BEFORE clearing (server only) + if (world != null && !world.isRemote) { + for (HashedBlockPosition p : blockPos) { + TileEntity te = world.getTileEntity(p.getBlockPos()); + if (te instanceof IMultiblock) { + ((IMultiblock) te).setIncomplete(); } + } } + + // Clear caches + bbCache = null; + stats.reset(); + blockPos.clear(); } @Override public void onChunkUnload() { super.onChunkUnload(); unregisterFromBus(); + + // Clear caches + bbCache = null; + stats.reset(); + blockPos.clear(); } + private void unregisterFromBus() { if (registeredBus) { MinecraftForge.EVENT_BUS.unregister(this); @@ -1171,7 +1199,7 @@ public void onRocketLand(RocketLandedEvent e) { if (e.world.isRemote || e.world != this.world) return; // Ensure we have pad bounds - if (bbCache == null) bbCache = getRocketPadBounds(world, pos); + bbCache = getRocketPadBounds(world, pos); if (bbCache == null) return; // Make sure the event entity is a rocket From 15ae3190c5d73dbcc3ffed2f69866fd2e28c8d40 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 6 Nov 2025 16:05:33 +0100 Subject: [PATCH 108/424] Clear caches in unlink and onChunkUnload methods Clear cached fuel and work strings on unlink and chunk unload. --- .../tile/infrastructure/TileFuelingStation.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java index 0ca2b7021..2bc3aa5c1 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java @@ -457,6 +457,8 @@ public void unlinkRocket() { this.linkedRocket = null; this.fuelingActive = false; this.lastRs = null; + lastFuelStr = lastOxStr = lastWorkStr = null; + cachedFuelFluid = cachedOxFluid = cachedWorkFluid = null; ((BlockTileRedstoneEmitter) AdvancedRocketryBlocks.blockFuelingStation) .setRedstoneState(world, world.getBlockState(pos), pos, false); markDirty(); @@ -516,7 +518,9 @@ public void invalidate() { if (linkedRocket != null) linkedRocket.unlinkInfrastructure(this); - // Hard-off to avoid stale output when chunk unload order is weird + // Clear caches + lastFuelStr = lastOxStr = lastWorkStr = null; + cachedFuelFluid = cachedOxFluid = cachedWorkFluid = null; lastRs = null; fuelingActive = false; @@ -670,6 +674,9 @@ public void onChunkUnload() { super.onChunkUnload(); if (world == null || world.isRemote) return; + // Clear caches + lastFuelStr = lastOxStr = lastWorkStr = null; + cachedFuelFluid = cachedOxFluid = cachedWorkFluid = null; lastRs = null; fuelingActive = false; if (AdvancedRocketryBlocks.blockFuelingStation instanceof BlockTileRedstoneEmitter) { From 7c1002f9432f4115a22b5028120fa162369c8976 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 6 Nov 2025 16:18:16 +0100 Subject: [PATCH 109/424] Implement cleanup in invalidate and onChunkUnload methods Clear data structures and reset variables on invalidation and chunk unload. --- .../tile/multiblock/TileObservatory.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java index 3f1e3dcc4..7a06f4df2 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java @@ -819,6 +819,26 @@ public void clear() { } + @Override + public void invalidate() { + super.invalidate(); + dataCables.clear(); + buttonType.clear(); + printedButtonsThisSeed.clear(); + printedSetSeed = -1; + lastSeed = -1; + lastButton = -1; + lastType = ""; + ModuleContainerPanYOnlyWithScrollCache.clearScrollCache(); // static GUI cache + } + + @Override + public void onChunkUnload() { + super.onChunkUnload(); + dataCables.clear(); + ModuleContainerPanYOnlyWithScrollCache.clearScrollCache(); + } + @Override public void onModuleUpdated(ModuleBase module) { //ReopenUI on server From f556049077e2d5a7485040141872577a0ac0647b Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 6 Nov 2025 16:19:11 +0100 Subject: [PATCH 110/424] Update TileGasChargePad.java behave on idle .. --- .../tile/atmosphere/TileGasChargePad.java | 115 +++++++++++++----- 1 file changed, 82 insertions(+), 33 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileGasChargePad.java b/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileGasChargePad.java index 3537b10a5..b5ecf46b3 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileGasChargePad.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileGasChargePad.java @@ -29,10 +29,23 @@ import java.util.List; public class TileGasChargePad extends TileInventoriedRFConsumerTank implements IModularInventory { + private static final int TICK_INTERVAL = 2; + // Avoid per-tick AABB allocation: cache lazily + @Nullable + private AxisAlignedBB cachedPlayerBox; + public TileGasChargePad() { super(0, 2, 16000); } + // Lazy AABB getter + private AxisAlignedBB getPlayerBox() { + if (cachedPlayerBox == null) { + cachedPlayerBox = new AxisAlignedBB(pos, pos.add(1, 2, 1)); + } + return cachedPlayerBox; + } + @Override @Nonnull public int[] getSlotsForFace(@Nullable EnumFacing side) { @@ -81,7 +94,18 @@ public T getCapability(Capability capability, @Nullable EnumFacing facing @Override public boolean canPerformFunction() { if (!world.isRemote) { - for (EntityPlayer player : this.world.getEntitiesWithinAABB(EntityPlayer.class, new AxisAlignedBB(pos, pos.add(1, 2, 1)))) { + + // Throttle: only run every TICK_INTERVAL ticks + if ((world.getTotalWorldTime() % TICK_INTERVAL) != 0) { + return false; + } + + FluidStack tf = this.tank.getFluid(); + if (tf == null || tf.amount <= 0) { + return false; + } + + for (EntityPlayer player : this.world.getEntitiesWithinAABB(EntityPlayer.class, getPlayerBox())) { ItemStack stack = player.getItemStackFromSlot(EntityEquipmentSlot.CHEST); if (!stack.isEmpty()) { @@ -94,15 +118,18 @@ else if (ItemAirUtils.INSTANCE.isStackValidAirContainer(stack)) //Check for O2 fill if (fillable != null) { - int amtFluid = fillable.getMaxAir(stack) - fillable.getAirRemaining(stack); - FluidStack fluidStack = this.drain(amtFluid, false); - - if (amtFluid > 0 && fluidStack != null && FluidUtils.areFluidsSameType(fluidStack.getFluid(), AdvancedRocketryFluids.fluidOxygen) && fluidStack.amount > 0) { - FluidStack fstack = this.drain(amtFluid, true); - this.markDirty(); - world.markChunkDirty(getPos(), this); - fillable.increment(stack, fstack.amount); - return true; + int deficit = fillable.getMaxAir(stack) - fillable.getAirRemaining(stack); + tf = this.tank.getFluid(); // refresh + if (deficit > 0 && tf != null + && FluidUtils.areFluidsSameType(tf.getFluid(), AdvancedRocketryFluids.fluidOxygen) + && tf.amount > 0) { + int toDrain = Math.min(deficit, tf.amount); + FluidStack drained = this.drain(toDrain, true); + if (drained != null && drained.amount > 0) { + fillable.increment(stack, drained.amount); + this.markDirty(); // no world.markChunkDirty + return true; + } } } } @@ -112,36 +139,39 @@ else if (ItemAirUtils.INSTANCE.isStackValidAirContainer(stack)) if (this.tank.getFluid() != null && !FluidUtils.areFluidsSameType(this.tank.getFluid().getFluid(), AdvancedRocketryFluids.fluidOxygen) && !stack.isEmpty() && stack.getItem() instanceof IModularArmor) { IInventory inv = ((IModularArmor) stack.getItem()).loadModuleInventory(stack); - FluidStack fluidStack = this.drain(100, false); - if (fluidStack != null) { + // Create a trial FluidStack up to available amount + final int perAttempt = 100 * TICK_INTERVAL; + int trialAmt = Math.min(perAttempt, this.tank.getFluid().amount); + if (trialAmt > 0) { + FluidStack trial = new FluidStack(this.tank.getFluid(), trialAmt); for (int i = 0; i < inv.getSizeInventory(); i++) { if (!((IModularArmor) stack.getItem()).canBeExternallyModified(stack, i)) continue; ItemStack module = inv.getStackInSlot(i); - if (FluidUtils.containsFluid(module)) { - int amtFilled = module.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, EnumFacing.UP).fill(fluidStack, true); - if (amtFilled == 100) { - this.drain(100, true); - - this.markDirty(); - world.markChunkDirty(getPos(), this); - - ((IModularArmor) stack.getItem()).saveModuleInventory(stack, inv); - - return true; - } + if (!FluidUtils.containsFluid(module)) continue; // fast path + net.minecraftforge.fluids.capability.IFluidHandlerItem fh = + module.getCapability(CapabilityFluidHandler.FLUID_HANDLER_ITEM_CAPABILITY, EnumFacing.UP); + if (fh == null) continue; // null-guard + + int amtFilled = fh.fill(trial, true); + // Accept partial fills: drain exactly what was accepted + if (amtFilled > 0) { + this.drain(amtFilled, true); + this.markDirty(); // no world.markChunkDirty + ((IModularArmor) stack.getItem()).saveModuleInventory(stack, inv); + return true; } - } - } - } - - return false; - } - } - return false; - } + } + } + } + } + // no player matched this tick + return false; + } + return false; + } @Override public void performFunction() { @@ -188,4 +218,23 @@ private boolean useBucket(int slot, @Nonnull ItemStack stack) { public boolean isEmpty() { return inventory.isEmpty(); } + + @Override + public void invalidate() { + super.invalidate(); + cachedPlayerBox = null; // drop cached AABB + } + + @Override + public void onChunkUnload() { + super.onChunkUnload(); + cachedPlayerBox = null; // drop cached AABB + } + + @Override + public void onLoad() { + super.onLoad(); + // Ensure cache recomputes from the current pos after NBT load + cachedPlayerBox = null; + } } From d2278542f615af718240037f0fc9420ef6f231db Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 7 Nov 2025 18:21:40 +0100 Subject: [PATCH 111/424] hide unused datatypes in tooltips Limit data types to supported types in ItemMultiData --- .../advancedRocketry/item/ItemMultiData.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemMultiData.java b/src/main/java/zmaster587/advancedRocketry/item/ItemMultiData.java index b0b72a2bf..e9f48657b 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemMultiData.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemMultiData.java @@ -42,6 +42,14 @@ public int getData(@Nonnull ItemStack stack, DataStorage.DataType type) { public int getMaxData(@Nonnull ItemStack stack) { return getDataStorage(stack).getMaxData(); } + // Supported types for this item. Others will be ignored. + // FIX IF WE ADD MORE TYPES TO DataStorage.DataType + private static final java.util.EnumSet SUPPORTED_TYPES = + java.util.EnumSet.of( + DataStorage.DataType.COMPOSITION, + DataStorage.DataType.MASS, + DataStorage.DataType.DISTANCE + ); private MultiData getDataStorage(@Nonnull ItemStack item) { @@ -117,9 +125,9 @@ public void addInformation(@Nonnull ItemStack stack, World player, List MultiData data = getDataStorage(stack); - for (DataStorage.DataType type : DataStorage.DataType.values()) { - if (type != DataStorage.DataType.UNDEFINED) - list.add(data.getDataAmount(type) + " / " + data.getMaxData() + " " + I18n.format(type.toString(), new Object[0]) + " Data"); + for (DataStorage.DataType type : SUPPORTED_TYPES) { + final int amt = data.getDataAmount(type); + list.add(amt + " / " + data.getMaxData() + " " + I18n.format(type.toString()) + " Data"); } } } From 8df5c733e50830d0a8a668942e531d928371ae9c Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 7 Nov 2025 18:23:42 +0100 Subject: [PATCH 112/424] added public method to pass on to moniter Add method to generate a short display ID from UUID and type --- .../advancedRocketry/item/ItemAsteroidChip.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java b/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java index bddbf843e..d26d5bb00 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java @@ -23,7 +23,14 @@ public boolean isDamageable() { return false; } - + public static String shortDisplayId(Long uuid, String type) { + long base = (uuid == null) ? 0L : uuid; + long th = (type == null) ? 0L : Integer.toUnsignedLong(type.hashCode()); + long disp = mix64(base ^ (th << 1)); + String hex = Long.toUnsignedString(disp, 16).toUpperCase(); + int N = 6; + return (hex.length() > N) ? hex.substring(hex.length() - N) : hex; + } /** * Removes any Information and reset the stack to a default state * From f43b98f68ea62113b941b845b4c080735b98fe1c Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 7 Nov 2025 20:16:20 +0100 Subject: [PATCH 113/424] Update rocket error messages and add new messages --- .../assets/advancedrocketry/lang/en_US.lang | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index 45a2887da..f7d174435 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -26,7 +26,6 @@ tile.turf.name=Moon Turf tile.turfDark.name=Dark Moon Turf tile.cuttingMachine.name=Cutting Machine tile.sawBlade.name=Saw Blade Assembly -tile.controlComp.name=Mission Control Computer tile.precisionAssemblingMachine.name=Precision Assembler tile.spaceLaser.name=Orbital Laser Drill tile.Crystallizer.name=Crystallizer @@ -228,9 +227,13 @@ fluid.enrichedLava=Enriched Lava mission.asteroidmining.name=Asteroid Mining mission.gascollection.name=Gas Collection -error.rocket.cannotGetThere=Destination Unreachable -error.rocket.destinationNotExist=Cannot launch: Destination does not exist -error.rocket.notSameSystem=Cannot launch: Destination is not in the same planet system +error.rocket.notEnoughMissionFuel=Not enough fuel! +error.rocket.tooHeavy=Rocket is too heavy to launch (insufficient thrust). +error.rocket.cannotGetThere=Selected destination cannot be reached from here. +error.rocket.destinationNotExist=Selected space station does not exist. +error.rocket.notSameSystem=Interstellar travel requires a nuclear rocket and a valid route. +error.rocket.partsWornOut=Critical parts are worn out — launch aborted. +error.rocket.aborted=Launch aborted. advancement.holographic=Holographic advancement.holographic.desc=Craft a Holo-Projector @@ -313,14 +316,30 @@ msg.spaceElevator.warning.anchored1=the station anchored! msg.spaceElevator.warning.unanchored=This elevator has no tether msg.spaceElevator.turnedOff=Elevator is turned off msg.fuelingStation.link=You program the linker with the fueling station at + +msg.monitoringStation.buttonLaunch=Launch! msg.monitoringStation.missionProgressNA=Mission Progress: N/A +msg.monitoringStation.missionNoActiveMission=No Active Missions.. +msg.monitoringStation.mission.type.gas=Gas Collection Mission +msg.monitoringStation.mission.type.ore=Asteroid Mining Mission +msg.monitoringStation.mission.target.default=Harvest: (pending) +msg.monitoringStation.mission.targetPrefix=Harvest: +msg.monitoringStation.mission.Asteroid.target.default=Asteroid: +msg.monitoringStation.mission.Asteroid.targetPrefix=Asteroid: +msg.monitoringStation.mission.asteroidIdPrefix=Type: +msg.monitoringStation.mission.plannedAmountPrefix=Amount: +msg.monitoringStation.mission.plannedAmountPending=Amount: (pending) +msg.monitoringStation.mission.asteroidType=Asteroid type: (shown on chip / mission) msg.monitoringStation.link=You program the linker with the monitoring station at -msg.monitoringStation.progress= Progress: +msg.monitoringStation.progress=ETA: msg.monitoringStation.prelaunch=Initiating... msg.monitoringStation.launching=Launching! -msg.monitoringStation.orbit=Reached orbit +msg.monitoringStation.orbit=Reached orbit! +msg.monitoringStation.deorbiting=Returned from orbit! msg.monitoringStation.landed=Landed -msg.monitoringStation.aborted=Aborted +msg.monitoringStation.aborted=Aborted! + + msg.guidanceComputerHatch.loadingState=Loading State: msg.guidanceComputerHatch.ejectonlanding=Auto Eject Upon Landing msg.guidanceComputerHatch.ejectonsatlanding=Allow Ejection of Satellite Chips From b89b3109514bbc2ea5dcbbaa62402fb263cd9ebe Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 7 Nov 2025 20:16:43 +0100 Subject: [PATCH 114/424] Add error handling and fuel checks for rocket launch --- .../advancedRocketry/entity/EntityRocket.java | 65 ++++++++++++++++++- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java b/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java index af41de4a1..cc75d2f74 100644 --- a/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java +++ b/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java @@ -427,6 +427,20 @@ else if (!isInFlight()) private void setError(String error) { this.errorStr = error; this.lastErrorTime = this.world.getTotalWorldTime(); + + if (!world.isRemote) { + // notify riders only + for (Entity e : this.getPassengers()) { + if (e instanceof EntityPlayerMP) { + ((EntityPlayerMP) e).sendMessage(new TextComponentString(error)); + } + } + // post an event the monitor already consumes + MinecraftForge.EVENT_BUS.post(new RocketEvent.RocketAbortEvent(this, error)); + + // stop countdown if it was running + this.dataManager.set(LAUNCH_COUNTER, -1); + } } @Override @@ -732,6 +746,45 @@ protected boolean canFitPassenger(Entity passenger) { return this.getPassengers().size() < stats.getNumPassengerSeats(); } + + // Check if we have enough fuel to reach orbit from our current position + private boolean hasMissionFuelFor(int destDimId) { + if (!ARConfiguration.getCurrentConfig().rocketRequireFuel) return true; + + final FuelRegistry.FuelType main = getRocketFuelType(); + if (main == null) return false; // no usable tanks + + if (isInOrbit()) return true; // already at orbit + + if (stats.getThrust() <= stats.getWeight()) return false; + + final DimensionProperties src = DimensionManager.getInstance() + .getDimensionProperties(this.world.provider.getDimension()); + final float gSrc = Math.max(0.01f, src.getGravitationalMultiplier()); + final double a = Math.max(0.0001d, stats.getAcceleration(gSrc)); + final double h = Math.max(0.0, stats.orbitHeight - this.posY); + + long nTicks = (long)Math.ceil(Math.sqrt(2.0 * h / a)); + nTicks += 2L; // small safety buffer + if (nTicks <= 0) nTicks = 1; + + int mainRate = Math.max(1, getFuelConsumptionRate(main)); + long mainNeeded = nTicks * (long)mainRate; + long mainHave = getFuelAmount(main); + if (mainHave < mainNeeded) return false; + + if (main == FuelRegistry.FuelType.LIQUID_BIPROPELLANT) { + int oxRate = Math.max(1, getFuelConsumptionRate(FuelRegistry.FuelType.LIQUID_OXIDIZER)); + long oxNeeded = nTicks * (long)oxRate; + long oxHave = getFuelAmount(FuelRegistry.FuelType.LIQUID_OXIDIZER); + if (oxHave < oxNeeded) return false; + } + + // Descent currently does not burn fuel in your code path. + return true; + } + + /** * @param fluidStack the stack to check whether the rocket can fit * @return boolean on whether said fluid stack can fit into the rocket's internal fuel point storage @@ -1910,14 +1963,20 @@ public void launch() { if (this.stats.getWeight() >= this.stats.getThrust()) { - allowLaunch = false; + setError(LibVulpes.proxy.getLocalizedString("error.rocket.tooHeavy")); + return; // hard stop; no silent fall-through } //Check to see what place we should be going to //This is bad but it works and is mostly intelligible so it's here for now stats.orbitHeight = (storage.getGuidanceComputer() == null) ? getEntryHeight(this.world.provider.getDimension()) : storage.getGuidanceComputer().getLaunchSequence(this.world.provider.getDimension(), this.getPosition()); - - + + // Enough fuel for the mission? + if (!hasMissionFuelFor(destinationDimId)) { + setError(LibVulpes.proxy.getLocalizedString("error.rocket.notEnoughMissionFuel")); + return; + } + //TODO: Clean this logic a bit? if (allowLaunch || !stats.hasSeat() || ((DimensionManager.getInstance().isDimensionCreated(destinationDimId)) || destinationDimId == ARConfiguration.getCurrentConfig().spaceDimId || destinationDimId == 0)) { setInFlight(true); From 7e0e9a58ad8c7dfefab49a3c25e3a4ae183e2939 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 7 Nov 2025 20:17:37 +0100 Subject: [PATCH 115/424] Add RocketAbortEvent class for rocket abort handling --- .../java/zmaster587/advancedRocketry/api/RocketEvent.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/api/RocketEvent.java b/src/main/java/zmaster587/advancedRocketry/api/RocketEvent.java index e4c3644fc..a93b79b26 100644 --- a/src/main/java/zmaster587/advancedRocketry/api/RocketEvent.java +++ b/src/main/java/zmaster587/advancedRocketry/api/RocketEvent.java @@ -35,6 +35,13 @@ public RocketPreLaunchEvent(Entity entity) { super(entity); } } + public static class RocketAbortEvent extends RocketEvent { + public final String reason; // optional, for GUIs/logs + public RocketAbortEvent(Entity entity, String reason) { + super(entity); + this.reason = reason; + } + } /** * Fired before the rocket is finished teleporting to the destination world on the Minecraft Forge EVENT_BUS From 3cc98a19f48e810ff60cd5f72c5184c67193bb76 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 7 Nov 2025 20:18:07 +0100 Subject: [PATCH 116/424] Add orbitEventPosted flag to prevent duplicate events Added a flag to track if the orbit event has been posted to prevent duplicate events. --- .../entity/EntityStationDeployedRocket.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/entity/EntityStationDeployedRocket.java b/src/main/java/zmaster587/advancedRocketry/entity/EntityStationDeployedRocket.java index 0f6f48d83..4516ffa9c 100644 --- a/src/main/java/zmaster587/advancedRocketry/entity/EntityStationDeployedRocket.java +++ b/src/main/java/zmaster587/advancedRocketry/entity/EntityStationDeployedRocket.java @@ -62,6 +62,8 @@ public class EntityStationDeployedRocket extends EntityRocket { private short gasId; private Ticket ticket; private long plannedHarvestMb = 0L; // planned total mB to attempt this mission + private boolean orbitEventPosted = false; // not persisted to NBT + public EntityStationDeployedRocket(World world) { super(world); @@ -393,13 +395,17 @@ else if (gasId > props.getHarvestableGasses().size() - 1) /** * Called when the rocket reaches orbit */ + @Override public void onOrbitReached() { - //make it 30 minutes with one drill + if (world.isRemote) return; // client should not run any of this - if (world.isRemote)System.out.println("this code should not run on client side!"); + // Fire the standard event exactly once for monitors + if (!orbitEventPosted) { + MinecraftForge.EVENT_BUS.post(new RocketEvent.RocketReachesOrbitEvent(this)); + orbitEventPosted = true; + } - if (this.isDead) - return; + if (this.isDead) return; //Check again to make sure we are around a gas giant ISpaceObject spaceObj; From 6903006165766068c1bc584c010ea3c5c7a24b4a Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 7 Nov 2025 20:18:25 +0100 Subject: [PATCH 117/424] Initialize missionPersistantNBT and add getter for harvest Initialize missionPersistantNBT in constructors and add method to retrieve planned harvest amount. --- .../mission/MissionResourceCollection.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/mission/MissionResourceCollection.java b/src/main/java/zmaster587/advancedRocketry/mission/MissionResourceCollection.java index 4c3e4f60f..6b4e20c68 100644 --- a/src/main/java/zmaster587/advancedRocketry/mission/MissionResourceCollection.java +++ b/src/main/java/zmaster587/advancedRocketry/mission/MissionResourceCollection.java @@ -37,6 +37,7 @@ public abstract class MissionResourceCollection extends SatelliteBase implements public MissionResourceCollection() { infrastructureCoords = new LinkedList<>(); + missionPersistantNBT = new NBTTagCompound(); } public MissionResourceCollection(long duration, EntityRocket entity, LinkedList infrastructureCoords) { @@ -66,6 +67,13 @@ public MissionResourceCollection(long duration, EntityRocket entity, LinkedList< this.infrastructureCoords.add(new HashedBlockPosition(((TileEntity) tile).getPos())); } + public long getPlannedHarvestMbOrDefault() { + if (missionPersistantNBT != null && missionPersistantNBT.hasKey("plannedHarvestMb")) { + return Math.max(0L, missionPersistantNBT.getLong("plannedHarvestMb")); + } + return -1L; // means "unknown/not provided" + } + @Override public double getProgress(World world) { if (duration <= 0L) return 1.0d; @@ -148,7 +156,8 @@ public void writeToNBT(NBTTagCompound nbt) { public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); - missionPersistantNBT = nbt.getCompoundTag("persist"); + missionPersistantNBT = nbt.hasKey("persist") ? nbt.getCompoundTag("persist") : new NBTTagCompound(); + rocketStats = new StatsRocket(); rocketStats.readFromNBT(nbt.getCompoundTag("rocketStats")); From a8b5cd34d78eaf481b4d163bd140c87f2a3258c3 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 7 Nov 2025 20:34:23 +0100 Subject: [PATCH 118/424] Add asteroid metadata persistence in MissionOreMining Persist asteroid metadata for the monitor UI, including asteroid type and UUID. --- .../mission/MissionOreMining.java | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/mission/MissionOreMining.java b/src/main/java/zmaster587/advancedRocketry/mission/MissionOreMining.java index 3e180f4fa..2f777071d 100644 --- a/src/main/java/zmaster587/advancedRocketry/mission/MissionOreMining.java +++ b/src/main/java/zmaster587/advancedRocketry/mission/MissionOreMining.java @@ -34,8 +34,38 @@ public MissionOreMining() { public MissionOreMining(long l, EntityRocket entityRocket, LinkedList connectedInfrastructure) { super(l, entityRocket, connectedInfrastructure); + + // Persist asteroid metadata for the monitor UI + try { + if (rocketStorage != null && rocketStorage.getGuidanceComputer() != null) { + ItemStack chip = rocketStorage.getGuidanceComputer().getStackInSlot(0); + if (!chip.isEmpty() && chip.getItem() instanceof ItemAsteroidChip) { + ItemAsteroidChip ac = (ItemAsteroidChip) chip.getItem(); + + String type = ac.getType(chip); + Long uuid = ac.getUUID(chip); + + if (type != null && !type.isEmpty()) + missionPersistantNBT.setString("asteroidType", type); + if (uuid != null) + missionPersistantNBT.setLong("asteroidUUID", uuid); + } + } + } catch (Throwable t) { + // leave fields unset; GUI will show defaults + } } + + public String getAsteroidTypeOrEmpty() { + return (missionPersistantNBT != null && missionPersistantNBT.hasKey("asteroidType")) + ? missionPersistantNBT.getString("asteroidType") : ""; + } + @javax.annotation.Nullable + public Long getAsteroidUUIDOrNull() { + return (missionPersistantNBT != null && missionPersistantNBT.hasKey("asteroidUUID")) + ? missionPersistantNBT.getLong("asteroidUUID") : null; + } @Override public void onMissionComplete() { From dc39cdba56db3444134fd269de6e25c516c39101 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 7 Nov 2025 20:34:50 +0100 Subject: [PATCH 119/424] Add getter for gasFluid in MissionGasCollection monitor update --- .../advancedRocketry/mission/MissionGasCollection.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/mission/MissionGasCollection.java b/src/main/java/zmaster587/advancedRocketry/mission/MissionGasCollection.java index 7e48311e5..6cb80d0cc 100644 --- a/src/main/java/zmaster587/advancedRocketry/mission/MissionGasCollection.java +++ b/src/main/java/zmaster587/advancedRocketry/mission/MissionGasCollection.java @@ -128,6 +128,10 @@ public void writeToNBT(NBTTagCompound nbt) { } } + public net.minecraftforge.fluids.Fluid getGasFluid() { + return gasFluid; + } + @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); From d11d90401cdc74887f4f152aacf77b456ed54802 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 7 Nov 2025 20:37:47 +0100 Subject: [PATCH 120/424] Refactor satellite resolution and caching logic --- .../tile/satellite/TileSatelliteTerminal.java | 45 ++++++++++--------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java index 9346726cc..c930fc2c3 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java @@ -124,17 +124,13 @@ private void maybeAutoDownloadFromSatellite(boolean force) { return; } - // Hoist satellite once - final SatelliteBase sat = getCachedSatellite(); + // Resolve satellite fresh from the chip each poll + SatelliteBase sat = resolveSatelliteFresh(); if (sat == null) { if (!force) autoDlInterval = Math.min(autoDlInterval << 1, AUTO_DL_MAX_INTERVAL_TICKS); nextAutoDlTick = now + autoDlInterval; return; } - - - - // No link or power → back off (unless forced) if (!hasLinkAndPower(sat)) { if (!force) autoDlInterval = Math.min(autoDlInterval << 1, AUTO_DL_MAX_INTERVAL_TICKS); nextAutoDlTick = now + autoDlInterval; @@ -245,21 +241,22 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompou } } - @Nullable private SatelliteBase cachedSat = null; + @Nullable + private SatelliteBase resolveSatelliteFresh() { + ItemStack s0 = getStackInSlot(0); + return (!s0.isEmpty() && s0.getItem() instanceof ItemSatelliteIdentificationChip) + ? ItemSatelliteIdentificationChip.getSatellite(s0) + : null; + } @Override public void setInventorySlotContents(int slot, @Nonnull ItemStack stack) { super.setInventorySlotContents(slot, stack); if (!world.isRemote && slot == 0) { - cachedSat = (!stack.isEmpty() && stack.getItem() instanceof ItemSatelliteIdentificationChip) - ? ItemSatelliteIdentificationChip.getSatellite(stack) - : null; maybeAutoDownloadFromSatellite(true); // force reset to base } } - private @Nullable SatelliteBase getCachedSatellite() { return cachedSat; } - public SatelliteBase getSatelliteFromSlot(int slot) { ItemStack stack = getStackInSlot(slot); if (!stack.isEmpty() && stack.getItem() instanceof ItemSatelliteIdentificationChip) { @@ -377,19 +374,27 @@ public int addData(int maxAmount, DataType type, EnumFacing dir, boolean commit) public void onLoad() { super.onLoad(); if (!world.isRemote) { - // Rebuild cache from current slot-0 - ItemStack s0 = getStackInSlot(0); - cachedSat = (!s0.isEmpty() && s0.getItem() instanceof ItemSatelliteIdentificationChip) - ? ItemSatelliteIdentificationChip.getSatellite(s0) - : null; - + // Reset backoff scheduler to a sane base state autoDlInterval = AUTO_DL_BASE_INTERVAL_TICKS; - nextAutoDlTick = Math.min(nextAutoDlTick, world.getTotalWorldTime() + AUTO_DL_MAX_INTERVAL_TICKS); - maybeAutoDownloadFromSatellite(false); + long now = world.getTotalWorldTime(); + // Warm-up so neighbors/registries settle (e.g. 80 ticks ~ 4s) + nextAutoDlTick = now + 80; } } + @Override + public void onChunkUnload() { + super.onChunkUnload(); + // Hard-clear any references and scheduling + autoDlInterval = AUTO_DL_BASE_INTERVAL_TICKS; + nextAutoDlTick = 0L; + } + // Clear caches if the block/TE is invalidated (broken/replaced) + @Override + public void invalidate() { + super.invalidate(); + } @Override From f37f59bf7b872b80fd383b971089697fe58b16b5 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 7 Nov 2025 20:38:48 +0100 Subject: [PATCH 121/424] Refactor network handling and UI synchronization --- .../tile/cables/TileWirelessTransciever.java | 79 ++++++++++++------- 1 file changed, 50 insertions(+), 29 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java b/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java index 1f8c9187a..b44255465 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java @@ -156,11 +156,21 @@ public boolean onLinkStart(@Nonnull ItemStack item, TileEntity entity, EntityPla @Override public void onChunkUnload() { super.onChunkUnload(); - if (networkID == -1) return; - if (NetworkRegistry.dataNetwork.doesNetworkExist(networkID)) + + // Leave the network cleanly if linked + if (networkID != -1 && NetworkRegistry.dataNetwork.doesNetworkExist(networkID)) { NetworkRegistry.dataNetwork.getNetwork(networkID).removeFromAll(this); + } + + // Clear per-instance caches + phase = -1; + + // Clear UI-only mirror (logic stays in 'data') + uiBuffer.setMaxData(data.getMaxData()); + uiBuffer.setData(0, DataType.UNDEFINED); } + @Override public boolean onLinkComplete(@Nonnull ItemStack item, TileEntity entity, EntityPlayer player, World world) { BlockPos pos = ItemLinker.getMasterCoords(item); @@ -303,17 +313,19 @@ public void readDataFromNetwork(ByteBuf in, byte packetId, public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompound nbt) { if (!side.isServer()) return; - if (id == 1) { // enable/disable toggle — always allowed + if (id == 1) { // enable/disable enabled = nbt.getBoolean("state"); + + // persist + push to clients + this.markDirty(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); return; } - if (id == 0) { // extract/insert toggle - // Always update local state so neighbors (like the terminal) can see it + if (id == 0) { // extract/insert extractMode = nbt.getBoolean("state"); updateToggleLabel(); - // Only touch the network if we are actually linked if (networkID != -1 && NetworkRegistry.dataNetwork.doesNetworkExist(networkID)) { NetworkRegistry.dataNetwork.getNetwork(networkID).removeFromAll(this); if (extractMode) { @@ -322,31 +334,39 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompou NetworkRegistry.dataNetwork.getNetwork(networkID).addSink(this, EnumFacing.UP); } } + + // persist + push to clients + this.markDirty(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); return; } } + @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); extractMode = nbt.getBoolean("mode"); - enabled = nbt.getBoolean("enabled"); - networkID = nbt.getInteger("networkID"); + enabled = nbt.getBoolean("enabled"); + networkID = nbt.getInteger("networkID"); data.readFromNBT(nbt); + syncUiBufferFromMultiData(); - //addToNetwork(); - toggle.setToggleState(extractMode); + // Mirror persisted booleans into UI widgets (guard null on client) + if (toggle != null) toggle.setToggleState(extractMode); + if (toggleSwitch != null) toggleSwitch.setToggleState(enabled); updateToggleLabel(); - toggleSwitch.setToggleState(enabled); + + // Client-only network label text if (world != null && world.isRemote && netIdLabel != null) { - String idStr = (networkID == -1) + String idStr = (networkID == -1) ? net.minecraft.client.resources.I18n.format("msg.wirelessTransciever.network.unlinked") : Integer.toString(networkID); - String label = LibVulpes.proxy.getLocalizedString("msg.wirelessTransciever.network"); - netIdLabel.setText(label + idStr); + String label = LibVulpes.proxy.getLocalizedString("msg.wirelessTransciever.network"); + netIdLabel.setText(label + idStr); } } @@ -386,31 +406,27 @@ public void onLoad() { super.onLoad(); if (!world.isRemote) { - syncUiBufferFromMultiData(); // ensures server-side mirror matches after load - // Ensure booleans reflect current UI widgets on server after load/place - extractMode = toggle.getState(); - enabled = toggleSwitch.getState(); + // Rebuild UI mirror from authoritative MultiData + syncUiBufferFromMultiData(); + + // Mirror persisted booleans -> widgets (do NOT read from widgets) + if (toggle != null) toggle.setToggleState(extractMode); + if (toggleSwitch != null) toggleSwitch.setToggleState(enabled); + updateToggleLabel(); } - // Server side only if (world == null || world.isRemote) return; - // Ensure sane interval before using it in modulo + // Recompute throttle phase after we cleared it if (transferIntervalTicks <= 0) transferIntervalTicks = 20; - - // Stable per-tile phase to spread work over time (no persistence needed) phase = (int) Math.floorMod(this.pos.toLong(), transferIntervalTicks); - // (Re)join the data network only if we’re actually linked to one + // Rejoin the network with the correct role (source/sink) if (networkID != -1) { if (!NetworkRegistry.dataNetwork.doesNetworkExist(networkID)) { - // Create (or re-create) this specific network id NetworkRegistry.dataNetwork.getNewNetworkID(networkID); } - - // Make sure we're not double-registered, then register with the right role NetworkRegistry.dataNetwork.getNetwork(networkID).removeFromAll(this); - if (extractMode) { NetworkRegistry.dataNetwork.getNetwork(networkID).addSource(this, EnumFacing.UP); } else { @@ -419,6 +435,8 @@ public void onLoad() { } } + + @Override public void update() { // Server only @@ -511,11 +529,14 @@ public void stateUpdated(ModuleBase module) { } @Override public void invalidate() { - // called when the TE is removed because the block changed/broke - if (!world.isRemote && NetworkRegistry.dataNetwork.doesNetworkExist(networkID)) { + if (!world.isRemote && networkID != -1 && NetworkRegistry.dataNetwork.doesNetworkExist(networkID)) { NetworkRegistry.dataNetwork.getNetwork(networkID).removeFromAll(this); } + // Clear per-instance caches + phase = -1; + super.invalidate(); } + } From f79383d113b82c2b57c689bfbec60e070dc4084e Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 7 Nov 2025 21:02:25 +0100 Subject: [PATCH 122/424] Improve AABB normalization and rocket assembly logic Refactor AABB handling and normalization in rocket assembly. --- .../tile/TileRocketAssemblingMachine.java | 76 ++++++++++++++----- 1 file changed, 58 insertions(+), 18 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java index 88d14b92f..18ee1b226 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java @@ -539,7 +539,20 @@ public AxisAlignedBB scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { status = ErrorCodes.SUCCESS; } } - return new AxisAlignedBB(actualMinX, actualMinY, actualMinZ, actualMaxX, actualMaxY, actualMaxZ); + + // Normalize integer mins/maxes first + int minXi = Math.min(actualMinX, actualMaxX); + int minYi = Math.min(actualMinY, actualMaxY); + int minZi = Math.min(actualMinZ, actualMaxZ); + int maxXi = Math.max(actualMinX, actualMaxX); + int maxYi = Math.max(actualMaxY, actualMinY); + int maxZi = Math.max(actualMinZ, actualMaxZ); + + // IMPORTANT: use BlockPos ctor so the AABB is [min, max+1) in block space + return new AxisAlignedBB( + new BlockPos(minXi, minYi, minZi), + new BlockPos(maxXi, maxYi, maxZi) + ); } protected void removeReplaceableBlocks(AxisAlignedBB bb) { @@ -562,37 +575,63 @@ protected void removeReplaceableBlocks(AxisAlignedBB bb) { } } + private static boolean isEmptyAABB(@Nullable AxisAlignedBB b) { + return b == null || b.maxX < b.minX || b.maxY < b.minY || b.maxZ < b.minZ; + } + + + private static AxisAlignedBB normalize(AxisAlignedBB b) { + double minX = Math.min(b.minX, b.maxX); + double minY = Math.min(b.minY, b.maxY); + double minZ = Math.min(b.minZ, b.maxZ); + double maxX = Math.max(b.minX, b.maxX); + double maxY = Math.max(b.minY, b.maxY); + double maxZ = Math.max(b.minZ, b.maxZ); + return new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); + } + + public void assembleRocket() { + // server only + need a pad cache + if (world.isRemote || bbCache == null) return; - if (bbCache == null || world.isRemote) - return; - // Need to scan again b/c something may have changed - AxisAlignedBB rocketBB = scanRocket(world, pos, bbCache); + // Re-scan to get a *tight* non-air AABB and fresh stats/status + final AxisAlignedBB scanBB = scanRocket(world, pos, bbCache); + if (status != ErrorCodes.SUCCESS || scanBB == null) return; - if (status != ErrorCodes.SUCCESS) + // Normalize and defensively guard against degenerate boxes + final AxisAlignedBB rocketBB = normalize(scanBB); + if (isEmptyAABB(rocketBB)) { + status = ErrorCodes.FAIL_CUT; return; + } - // Remove replacable blocks that don't belong on the rocket - removeReplaceableBlocks(bbCache); + // Remove replaceable/blacklisted blocks *inside the tightened bounds* + removeReplaceableBlocks(rocketBB); - StorageChunk storageChunk; + // Cut the world using the tightened box (avoid pad air) + final StorageChunk storageChunk; try { - storageChunk = StorageChunk.cutWorldBB(world, bbCache); - } catch (NegativeArraySizeException e) { + storageChunk = StorageChunk.cutWorldBB(world, rocketBB); + } catch (Throwable t) { // covers NegativeArraySizeException & other edge errors + status = ErrorCodes.FAIL_CUT; return; } - EntityRocket rocket = new EntityRocket(world, storageChunk, stats.copy(), - rocketBB.minX + (rocketBB.maxX - rocketBB.minX) / 2f + .5f, - this.getPos().getY(), - rocketBB.minZ + (rocketBB.maxZ - rocketBB.minZ) / 2f + .5f); + // Center spawn on tightened AABB + final double cx = rocketBB.minX + (rocketBB.maxX - rocketBB.minX) / 2.0 + 0.5; + final double cz = rocketBB.minZ + (rocketBB.maxZ - rocketBB.minZ) / 2.0 + 0.5; + final double cy = this.getPos().getY(); + EntityRocket rocket = new EntityRocket(world, storageChunk, stats.copy(), cx, cy, cz); world.spawnEntity(rocket); - NBTTagCompound nbtdata = new NBTTagCompound(); + NBTTagCompound nbtdata = new NBTTagCompound(); rocket.writeToNBT(nbtdata); - PacketHandler.sendToNearby(new PacketEntity(rocket, (byte) 0, nbtdata), rocket.world.provider.getDimension(), this.pos, 64); + PacketHandler.sendToNearby(new PacketEntity(rocket, (byte) 0, nbtdata), + rocket.world.provider.getDimension(), this.pos, 64); + // Finish & link as before stats.reset(); this.status = ErrorCodes.FINISHED; this.markDirty(); @@ -602,7 +641,8 @@ public void assembleRocket() { rocket.linkInfrastructure(infrastructure); } - scanRocket(world, pos, bbCache); // to show stats + // Rescan so UI immediately reflects the post-build state + scanRocket(world, pos, bbCache); } /** From b23f175d71d92d1f9e8210455509bbe437f3a4a7 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 02:09:18 +0100 Subject: [PATCH 123/424] Add getActualState method for fuel tank detection Sticky rotation for all engines --- .../block/BlockBipropellantRocketMotor.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java b/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java index 74d3d4a6b..d847191fd 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java @@ -39,6 +39,23 @@ public int getThrust(World world, BlockPos pos) { return 10; } + @Override + public IBlockState getActualState(@Nonnull IBlockState state, IBlockAccess world, BlockPos pos) { + if (world.getBlockState(pos.up()).getBlock() instanceof BlockFuelTank) + return state.withProperty(FACING, EnumFacing.DOWN); + if (world.getBlockState(pos.down()).getBlock() instanceof BlockFuelTank) + return state.withProperty(FACING, EnumFacing.UP); + if (world.getBlockState(pos.east()).getBlock() instanceof BlockFuelTank) + return state.withProperty(FACING, EnumFacing.EAST); + if (world.getBlockState(pos.west()).getBlock() instanceof BlockFuelTank) + return state.withProperty(FACING, EnumFacing.WEST); + if (world.getBlockState(pos.south()).getBlock() instanceof BlockFuelTank) + return state.withProperty(FACING, EnumFacing.SOUTH); + if (world.getBlockState(pos.north()).getBlock() instanceof BlockFuelTank) + return state.withProperty(FACING, EnumFacing.NORTH); + return super.getActualState(state, world, pos); + } + @Override public int getFuelConsumptionRate(World world, int x, int y, int z) { return 1; From e259b7dfc18c718221a8766d8a1131274dd8d775 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 02:10:11 +0100 Subject: [PATCH 124/424] Implement facing logic for nuclear rocket motor Added logic to determine block facing based on adjacent nuclear cores. --- .../block/BlockNuclearRocketMotor.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java b/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java index ed84d34d5..0658b8725 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java @@ -3,11 +3,15 @@ import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; import zmaster587.advancedRocketry.api.ARConfiguration; +import zmaster587.advancedRocketry.api.IRocketNuclearCore; import zmaster587.advancedRocketry.tile.TileBrokenPart; +import javax.annotation.Nonnull; import javax.annotation.Nullable; public class BlockNuclearRocketMotor extends BlockRocketMotor { @@ -20,7 +24,23 @@ public BlockNuclearRocketMotor(Material mat) { public int getThrust(World world, BlockPos pos) { return 35; } - + @Override + public IBlockState getActualState(@Nonnull IBlockState state, IBlockAccess world, BlockPos pos) { + // Prefer nuclear core adjacency over tanks + if (world.getBlockState(pos.up()).getBlock() instanceof IRocketNuclearCore) + return state.withProperty(FACING, EnumFacing.DOWN); + if (world.getBlockState(pos.down()).getBlock() instanceof IRocketNuclearCore) + return state.withProperty(FACING, EnumFacing.UP); + if (world.getBlockState(pos.east()).getBlock() instanceof IRocketNuclearCore) + return state.withProperty(FACING, EnumFacing.EAST); + if (world.getBlockState(pos.west()).getBlock() instanceof IRocketNuclearCore) + return state.withProperty(FACING, EnumFacing.WEST); + if (world.getBlockState(pos.south()).getBlock() instanceof IRocketNuclearCore) + return state.withProperty(FACING, EnumFacing.SOUTH); + if (world.getBlockState(pos.north()).getBlock() instanceof IRocketNuclearCore) + return state.withProperty(FACING, EnumFacing.NORTH); + return state; + } @Override public int getFuelConsumptionRate(World world, int x, int y, int z) { return 1; From 18cb4ab107a5c3c40709eb6e4175f0ccc810db3b Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 02:11:12 +0100 Subject: [PATCH 125/424] branched for SDrockets Refactor engine eligibility checks for rockets --- .../advancedRocketry/util/StorageChunk.java | 54 ++++++++++++++----- 1 file changed, 40 insertions(+), 14 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/util/StorageChunk.java b/src/main/java/zmaster587/advancedRocketry/util/StorageChunk.java index b61cbc90e..bce2ccd3f 100644 --- a/src/main/java/zmaster587/advancedRocketry/util/StorageChunk.java +++ b/src/main/java/zmaster587/advancedRocketry/util/StorageChunk.java @@ -172,7 +172,8 @@ public void recalculateStats(StatsRocket stats) { float drillPower = 0f; //stats.reset_no_fuel(); stats.reset_no_fuel();// Oh Quarter... you can not keep adding engine and seat locations every launch - + final boolean isSD = (this.entity instanceof zmaster587.advancedRocketry.entity.EntityStationDeployedRocket); + float weight = 0; for (int yCurr = 0; yCurr <= this.sizeY; yCurr++) { @@ -193,18 +194,33 @@ public void recalculateStats(StatsRocket stats) { } //If rocketEngine increaseThrust - if (block instanceof IRocketEngine && (world.getBlockState(belowPos).getBlock().isAir(world.getBlockState(belowPos), world, belowPos) || world.getBlockState(belowPos).getBlock() instanceof BlockLandingPad || world.getBlockState(belowPos).getBlock() == AdvancedRocketryBlocks.blockLaunchpad)) { - if (block instanceof BlockNuclearRocketMotor) { - nuclearWorkingFluidUseMax += ((IRocketEngine) block).getFuelConsumptionRate(world, xCurr, yCurr, zCurr); - thrustNuclearNozzleLimit += ((IRocketEngine) block).getThrust(world, currBlockPos); - } else if (block instanceof BlockBipropellantRocketMotor) { - bipropellantfuelUse += ((IRocketEngine) block).getFuelConsumptionRate(world, xCurr, yCurr, zCurr); - thrustBipropellant += ((IRocketEngine) block).getThrust(world, currBlockPos); - } else if (block instanceof BlockRocketMotor) { - monopropellantfuelUse += ((IRocketEngine) block).getFuelConsumptionRate(world, xCurr, yCurr, zCurr); - thrustMonopropellant += ((IRocketEngine) block).getThrust(world, currBlockPos); + if (block instanceof IRocketEngine) { + boolean eligible; + if (isSD) { + // SD rockets: skip vertical requirements + eligible = true; + } else { + // Legacy vertical rule + IBlockState belowState = world.getBlockState(belowPos); + Block below = belowState.getBlock(); + eligible = below.isAir(belowState, world, belowPos) + || below instanceof BlockLandingPad + || below == AdvancedRocketryBlocks.blockLaunchpad; + } + + if (eligible) { + if (block instanceof BlockNuclearRocketMotor) { + nuclearWorkingFluidUseMax += ((IRocketEngine) block).getFuelConsumptionRate(world, xCurr, yCurr, zCurr); + thrustNuclearNozzleLimit += ((IRocketEngine) block).getThrust(world, currBlockPos); + } else if (block instanceof BlockBipropellantRocketMotor) { + bipropellantfuelUse += ((IRocketEngine) block).getFuelConsumptionRate(world, xCurr, yCurr, zCurr); + thrustBipropellant += ((IRocketEngine) block).getThrust(world, currBlockPos); + } else if (block instanceof BlockRocketMotor) { + monopropellantfuelUse += ((IRocketEngine) block).getFuelConsumptionRate(world, xCurr, yCurr, zCurr); + thrustMonopropellant += ((IRocketEngine) block).getThrust(world, currBlockPos); + } + stats.addEngineLocation(xCurr - (float)this.sizeX/2 + 0.5f, yCurr+0.5f, zCurr - (float)this.sizeZ/2 + 0.5f); } - stats.addEngineLocation(xCurr - (float) this.sizeX /2+0.5f, yCurr+0.5f, zCurr- (float) this.sizeZ /2+0.5f); } if (block instanceof IFuelTank) { @@ -219,8 +235,18 @@ public void recalculateStats(StatsRocket stats) { } } - if (block instanceof IRocketNuclearCore && ((world.getBlockState(belowPos).getBlock() instanceof IRocketNuclearCore) || (world.getBlockState(belowPos).getBlock() instanceof IRocketEngine))) { - thrustNuclearReactorLimit += ((IRocketNuclearCore) block).getMaxThrust(world, currBlockPos); + if (block instanceof IRocketNuclearCore) { + boolean counts; + if (isSD) { + // SD rockets: no vertical stack requirement + counts = true; + } else { + Block below = world.getBlockState(belowPos).getBlock(); + counts = (below instanceof IRocketNuclearCore) || (below instanceof IRocketEngine); + } + if (counts) { + thrustNuclearReactorLimit += ((IRocketNuclearCore) block).getMaxThrust(world, currBlockPos); + } } if (block instanceof BlockSeat && world.getBlockState(abovePos).getBlock().isPassable(world, abovePos)) { From 7f4726d38f729339fc9d87aef45a3a8bd05425ac Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 02:11:59 +0100 Subject: [PATCH 126/424] strenghtened linking on load Add a flag to track if the landed event was posted after loading from NBT. --- .../advancedRocketry/entity/EntityRocket.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java b/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java index cc75d2f74..4945bc0b7 100644 --- a/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java +++ b/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java @@ -130,6 +130,8 @@ public class EntityRocket extends EntityRocketBase implements INetworkEntity, IM protected ModulePlanetSelector container; boolean acceptedPacket = false; SpacePosition spacePosition; + //true if we have posted the landed event after loading from nbt + private transient boolean postedLandedAfterLoad = false; //true if the rocket is on decent private boolean isInOrbit; //True if the rocket isn't on the ground @@ -1088,7 +1090,15 @@ public void onUpdate() { super.onUpdate(); long deltaTime = world.getTotalWorldTime() - lastWorldTickTicked; lastWorldTickTicked = world.getTotalWorldTime(); - + if (!world.isRemote && !postedLandedAfterLoad && this.ticksExisted >= 5) { + // Consider "landed" = entity exists, NOT in flight, NOT in orbit + if (!isInFlight() && !isInOrbit()) { + net.minecraftforge.common.MinecraftForge.EVENT_BUS.post( + new zmaster587.advancedRocketry.api.RocketEvent.RocketLandedEvent(this) + ); + postedLandedAfterLoad = true; + } + } if (world.isRemote) { double ct = 50; From 2e27bfa98d29df6ee6ee95d95406d132c73ae14a Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 02:12:50 +0100 Subject: [PATCH 127/424] Fix missing newline at end of file Add missing newline at the end of StatsRocket.java From ed77b61d271b102188d5b1cd50d743c44cf2a4ac Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 02:13:37 +0100 Subject: [PATCH 128/424] Refactor bounding box handling in TileUnmannedVehicleAssembler Updated the bounding box calculations and entity checks for unmanned vehicle assembly. --- .../tile/TileUnmannedVehicleAssembler.java | 57 ++++++++++++------- 1 file changed, 36 insertions(+), 21 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileUnmannedVehicleAssembler.java b/src/main/java/zmaster587/advancedRocketry/tile/TileUnmannedVehicleAssembler.java index 2091c4a2c..7e5b26981 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileUnmannedVehicleAssembler.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileUnmannedVehicleAssembler.java @@ -109,14 +109,14 @@ public void assembleRocket() { AxisAlignedBB rocketBB = scanRocket(world, getPos(), bbCache); if (status != ErrorCodes.SUCCESS || rocketBB == null) return; - // 2) Remove replaceable/blacklisted blocks before cutting (uses parent’s helper) - removeReplaceableBlocks(bbCache); + // 2) Remove replaceables **inside the tight box** + removeReplaceableBlocks(rocketBB); - // 3) Cut the world into a storage chunk + // 3) Cut the world using the **tight** AABB final StorageChunk storageChunk; try { - storageChunk = StorageChunk.cutWorldBB(world, bbCache); - } catch (NegativeArraySizeException e) { + storageChunk = StorageChunk.cutWorldBB(world, rocketBB); + } catch (Throwable t) { // covers NegativeArraySizeException, etc. return; } @@ -180,22 +180,26 @@ public void assembleRocket() { @Override public AxisAlignedBB scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { + // Always refresh local bounds first + AxisAlignedBB fresh = getRocketPadBounds(world, getPos()); + if (fresh == null) { + status = ErrorCodes.INCOMPLETESTRCUTURE; // upstream typo + return null; // avoid using stale bb + } + bbCache = fresh; + bb = fresh; // ensure loops below use the fresh bounds // fast-path: rocket entity already present? - if (getBBCache() == null) bbCache = getRocketPadBounds(world, getPos()); - if (bbCache != null) { - final AxisAlignedBB buffered = bbCache.grow(1.0e-4, 1.0e-4, 1.0e-4); - - java.util.List sdr = - world.getEntitiesWithinAABB(EntityStationDeployedRocket.class, buffered); - if (sdr.size() == 1) { - EntityStationDeployedRocket r = sdr.get(0); - r.recalculateStats(); - this.stats = r.stats.copy(); - this.status = ErrorCodes.ALREADY_ASSEMBLED; - return null; - } - } + final AxisAlignedBB buffered = bb.grow(1.0e-4, 1.0e-4, 1.0e-4); + java.util.List sdr = + world.getEntitiesWithinAABB(EntityStationDeployedRocket.class, buffered); + if (sdr.size() == 1) { + EntityStationDeployedRocket r = sdr.get(0); + r.recalculateStats(); + this.stats = r.stats.copy(); + this.status = ErrorCodes.ALREADY_ASSEMBLED; + return null; + } int thrustMonopropellant = 0; int thrustBipropellant = 0; int thrustNuclearNozzleLimit = 0; @@ -399,7 +403,14 @@ public AxisAlignedBB scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { } } - return new AxisAlignedBB(actualMinX, actualMinY, actualMinZ, actualMaxX, actualMaxY, actualMaxZ); + // Normalize bounds to avoid inverted AABBs on edge cases + double minX = Math.min(actualMinX, actualMaxX); + double minY = Math.min(actualMinY, actualMaxY); + double minZ = Math.min(actualMinZ, actualMaxZ); + double maxX = Math.max(actualMinX, actualMaxX); + double maxY = Math.max(actualMaxY, actualMinY); + double maxZ = Math.max(actualMinZ, actualMaxZ); + return new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ); } @@ -450,9 +461,13 @@ private boolean hasEnoughFuelUnmanned(@Nonnull FuelType family) { return sCan >= targetS; } + @Override public void onLoad() { super.onLoad(); } + @Override public void invalidate() { super.invalidate(); } - //No additional scanning is needed + @Override public void onChunkUnload() { super.onChunkUnload(); } + + @Override protected boolean verifyScan(AxisAlignedBB bb, World world) { return true; From 8492e8a1e4fa813cdf8c1bf00750df56bb08c3cd Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 02:14:22 +0100 Subject: [PATCH 129/424] Implement relink retries for infrastructure linking Added relink retry logic for infrastructure linking in the rocket assembling machine. strengthening relinking onload avoiding races --- .../tile/TileRocketAssemblingMachine.java | 75 +++++++++++++++---- 1 file changed, 59 insertions(+), 16 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java index 18ee1b226..4620d22ff 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java @@ -82,6 +82,8 @@ public class TileRocketAssemblingMachine extends TileEntityRFConsumer implements private boolean building; //True is rocket is being built, false if only scanning or otherwise private int lastRocketID; private List blockPos; + private int relinkRetries = 0; // how many relinking tries left + private long nextRelinkAttempt = 0L; // world time for next try public TileRocketAssemblingMachine() { super(100000); @@ -102,7 +104,10 @@ public void onLoad() { MinecraftForge.EVENT_BUS.register(this); registeredBus = true; } - + if (!world.isRemote) { + relinkRetries = 10; // up to ~10 seconds + nextRelinkAttempt = world.getTotalWorldTime() + 20; // first retry in 1s + } if (world.isRemote) return; // Recompute pad bounds and relink infra to any rockets already on the pad @@ -124,7 +129,8 @@ public void onLoad() { public void invalidate() { super.invalidate(); unregisterFromBus(); - + relinkRetries = 0; + nextRelinkAttempt = 0L; // Notify linked multiblocks BEFORE clearing (server only) if (world != null && !world.isRemote) { for (HashedBlockPosition p : blockPos) { @@ -145,7 +151,8 @@ public void invalidate() { public void onChunkUnload() { super.onChunkUnload(); unregisterFromBus(); - + relinkRetries = 0; + nextRelinkAttempt = 0L; // Clear caches bbCache = null; stats.reset(); @@ -250,6 +257,44 @@ public int getPowerPerOperation() { @Override public void performFunction() { + // Retry linking infra for up to ~10s, but stop early once ALL are linked + if (!world.isRemote && relinkRetries > 0 && world.getTotalWorldTime() >= nextRelinkAttempt) { + + if (bbCache == null) bbCache = getRocketPadBounds(world, pos); + + int expected = blockPos.size(); // how many infra we remember from NBT + if (expected == 0) { relinkRetries = 0; return; } + int found = 0; // how many are currently loaded & obtainable + + if (bbCache != null) { + final AxisAlignedBB box = bbCache.grow(1.0E-4, 1.0E-4, 1.0E-4); + java.util.List rockets = world.getEntitiesWithinAABB(EntityRocketBase.class, box); + + // Only count + link if a rocket is actually on the pad + if (!rockets.isEmpty()) { + java.util.List infraNow = getConnectedInfrastructure(); // only returns loaded TEs + found = infraNow.size(); + + // Link them all (idempotent in AR) + for (EntityRocketBase r : rockets) { + for (IInfrastructure infra : infraNow) { + r.linkInfrastructure(infra); + } + } + } + } + + // Stop early only when we've linked ALL remembered infra positions + if (found >= expected && expected > 0) { + relinkRetries = 0; // done + } else { + relinkRetries--; // try again next second + nextRelinkAttempt = world.getTotalWorldTime() + 20; + } + } + + + if (!isScanning()) return; if (progress >= (totalProgress * MAXSCANDELAY)) { if (!world.isRemote) { if (building) @@ -913,6 +958,9 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, } protected void updateText() { + if (thrustText == null || weightText == null || fuelText == null || accelerationText == null || errorText == null) { + return; + } thrustText.setText(isScanning() ? (LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.thrust") + ": ???") : String.format("%s: %dkN", LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.thrust"), getThrust())); weightText.setText(isScanning() ? (LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.weight") + ": ???") : String.format("%s: %.2fkN", LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.weight"), (getWeight() * getGravityMultiplier()))); fuelText.setText(isScanning() ? (LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.fuel") + ": ???") : String.format("%s: %dmb/s", LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.fuel"), 20* getRocketStats().getFuelRate((stats.getFuelCapacity(FuelType.LIQUID_MONOPROPELLANT) > 0) ? FuelType.LIQUID_MONOPROPELLANT : (stats.getFuelCapacity(FuelType.NUCLEAR_WORKING_FLUID) > 0) ? FuelType.NUCLEAR_WORKING_FLUID : FuelType.LIQUID_BIPROPELLANT))); @@ -1217,20 +1265,15 @@ public void removeConnectedInfrastructure(TileEntity tile) { } public List getConnectedInfrastructure() { - List infrastructure = new LinkedList<>(); - - Iterator iter = blockPos.iterator(); - - while (iter.hasNext()) { - HashedBlockPosition position = iter.next(); - TileEntity tile = world.getTileEntity(position.getBlockPos()); - if (tile instanceof IInfrastructure) { - infrastructure.add((IInfrastructure) tile); - } else - iter.remove(); + List list = new LinkedList<>(); + // Don't mutate blockPos here; tiles may not be loaded yet + for (HashedBlockPosition position : blockPos) { + TileEntity te = world.getTileEntity(position.getBlockPos()); + if (te instanceof IInfrastructure) { + list.add((IInfrastructure) te); + } } - - return infrastructure; + return list; } @SubscribeEvent From c700cfd7addba9ab6becd9b77a6d58b98c823d33 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 02:14:45 +0100 Subject: [PATCH 130/424] Refactor rocket event posting logic --- .../entity/EntityStationDeployedRocket.java | 39 ++++++++++++------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/entity/EntityStationDeployedRocket.java b/src/main/java/zmaster587/advancedRocketry/entity/EntityStationDeployedRocket.java index 4516ffa9c..831401cb6 100644 --- a/src/main/java/zmaster587/advancedRocketry/entity/EntityStationDeployedRocket.java +++ b/src/main/java/zmaster587/advancedRocketry/entity/EntityStationDeployedRocket.java @@ -62,9 +62,9 @@ public class EntityStationDeployedRocket extends EntityRocket { private short gasId; private Ticket ticket; private long plannedHarvestMb = 0L; // planned total mB to attempt this mission - private boolean orbitEventPosted = false; // not persisted to NBT - - + private transient boolean postedLandedAfterLoad = false; + private transient boolean postedDeorbit = false; + public EntityStationDeployedRocket(World world) { super(world); launchDirection = EnumFacing.DOWN; @@ -167,7 +167,15 @@ public void launch() { @Override public void onUpdate() { lastWorldTickTicked = world.getTotalWorldTime(); - + if (!world.isRemote && !postedLandedAfterLoad && this.ticksExisted >= 5) { + // Consider "landed" = entity exists, NOT in flight, NOT in orbit + if (!isInFlight() && !isInOrbit()) { + net.minecraftforge.common.MinecraftForge.EVENT_BUS.post( + new zmaster587.advancedRocketry.api.RocketEvent.RocketLandedEvent(this) + ); + postedLandedAfterLoad = true; + } + } if (this.ticksExisted == 20) { //problems with loading on other world then where the infrastructure was set? for (HashedBlockPosition temp : new LinkedList<>(infrastructureCoords)) { @@ -241,6 +249,13 @@ public void onUpdate() { //Returning if (isInOrbit()) { //For unmanned rockets + // Post deorbit once, as we start the return phase + if (!world.isRemote && !postedDeorbit) { + net.minecraftforge.common.MinecraftForge.EVENT_BUS.post( + new zmaster587.advancedRocketry.api.RocketEvent.RocketDeOrbitingEvent(this) + ); + postedDeorbit = true; + } EnumFacing dir; isCoasting = Math.abs(this.posX - actualLaunchLocation.x) < 0.01 && Math.abs(this.posZ - actualLaunchLocation.z) < 0.01; @@ -398,15 +413,13 @@ else if (gasId > props.getHarvestableGasses().size() - 1) @Override public void onOrbitReached() { if (world.isRemote) return; // client should not run any of this - - // Fire the standard event exactly once for monitors - if (!orbitEventPosted) { - MinecraftForge.EVENT_BUS.post(new RocketEvent.RocketReachesOrbitEvent(this)); - orbitEventPosted = true; - } - + // Emit the “reached orbit” event directly so monitors update. + net.minecraftforge.common.MinecraftForge.EVENT_BUS.post( + new zmaster587.advancedRocketry.api.RocketEvent.RocketReachesOrbitEvent(this) + ); if (this.isDead) return; + //Check again to make sure we are around a gas giant ISpaceObject spaceObj; setInOrbit(true); @@ -461,7 +474,7 @@ public void onOrbitReached() { final long durationSeconds; if (intake <= 0 || this.plannedHarvestMb <= 0) { - durationSeconds = 360L; // safety default + durationSeconds = 180L; // safety default } else { // IMPORTANT: cap the capacity used by the curve to the harvest cap, // so durations match the table when harvest is smaller than tank size. @@ -594,7 +607,7 @@ private static double computeEffectiveCapacityMb(int liquidCapacity) { private static long computeMissionDurationSeconds(int liquidCapacity, int intakePower) { // default fallback if bad data - if (intakePower <= 0) return 360L; // 6 minutes safety default + if (intakePower <= 0) return 180L; // 3 minutes safety default // scale in double to avoid precision loss, clamp ratio >= 1 to avoid shrinking below base double ratio = Math.max(1.0d, ((double) liquidCapacity) / (double) BASE_CAP); From 595b6aa8811226937cb199ecd6e82abecd53c00d Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 02:16:38 +0100 Subject: [PATCH 131/424] Refactor TileRocketMonitoringStation class split GUI into tabs to show the player why launches failed. statustext + reason if status=abort --- .../TileRocketMonitoringStation.java | 426 ++++++++++++++---- 1 file changed, 341 insertions(+), 85 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java index 4f07181fc..15bd688a7 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java @@ -33,6 +33,7 @@ import zmaster587.libVulpes.client.util.ProgressBarImage; import zmaster587.libVulpes.interfaces.ILinkableTile; import zmaster587.libVulpes.inventory.modules.*; +import zmaster587.libVulpes.inventory.GuiHandler; import zmaster587.libVulpes.items.ItemLinker; import zmaster587.libVulpes.network.PacketHandler; import zmaster587.libVulpes.network.PacketMachine; @@ -44,8 +45,10 @@ import java.util.LinkedList; import java.util.List; -public class TileRocketMonitoringStation extends TileEntity implements IModularInventory, ITickable, IAdjBlockUpdate, IInfrastructure, ILinkableTile, INetworkMachine, IButtonInventory, IProgressBar, IComparatorOverride { - +public class TileRocketMonitoringStation extends TileEntity + implements IModularInventory, ITickable, IAdjBlockUpdate, IInfrastructure, + ILinkableTile, INetworkMachine, IButtonInventory, IProgressBar, + IComparatorOverride, IGuiCallback { // ==== TUNABLE TICK THROTTLES ==== // 2–3 ticks for height/vel feels live; 5–10 ticks is fine for fuel. private static final int T_HEIGHTVEL_TICKS = 3; // ~6.7 Hz @@ -78,15 +81,22 @@ public class TileRocketMonitoringStation extends TileEntity implements IModularI int fuelLevel, maxFuelLevel; int oxidizerFuelLevel; + // === GUI event status (server -> client via TE update) === - // 0=idle, 1=prelaunch, 2=launching, 3=orbit, 4=landed, 5=aborted + // 0=idle, 1=prelaunch, 2=launching, 3=orbit, 4=deorbiting, 5=landed, 6=aborted + private int uiStatus = 0; private transient ModuleText launchStatus; // client-only widget + private transient ModuleText abortDetail; private transient int lastUiStatusShown = -1; // client change-detect // How long a status is considered fresh after the last event (in ticks) - private static final long STATUS_STALE_TICKS = 400L; // over 20 seconds is outdated + private static final long STATUS_STALE_TICKS = 600L; // over 30 seconds is outdated private long lastStatusTick = 0L; // server-only; persisted - + private String lastAbortReason = ""; + + // Tabs (client-only) + private static final byte TAB_SWITCH = 10; + private ModuleTab tabModule; // Event bus registration flag private boolean registeredBus = false; @@ -99,13 +109,26 @@ private void pushState() { private void clearUiStatus() { uiStatus = 0; + lastAbortReason = ""; lastUiStatusShown = -1; // force client label to refresh to empty pushState(); } public TileRocketMonitoringStation() { mission = null; - missionText = new ModuleText(20, 90, LibVulpes.proxy.getLocalizedString("msg.monitoringStation.missionProgressNA"), 0x2b2b2b); + missionText = null; + + tabModule = new ModuleTab( + 4, 0, 0, this, 2, + new String[] { + LibVulpes.proxy.getLocalizedString("msg.monitoringStation.tab.status"), + LibVulpes.proxy.getLocalizedString("msg.monitoringStation.tab.mission") + }, + new net.minecraft.util.ResourceLocation[][] { + TextureResources.tabPlanet, + TextureResources.tabPlanetTracking + } + ); } // --- Lifecycle / bus registration --- @@ -127,11 +150,11 @@ public void onLoad() { boolean stale = lastStatusTick == 0L || (world.getTotalWorldTime() - lastStatusTick) > STATUS_STALE_TICKS; - if (stale || linkedRocket == null) { + if (stale || (linkedRocket == null && mission == null)) { clearUiStatus(); - lastStatusTick = 0L; // reset tick + lastStatusTick = 0L; } else { - pushState(); // keep fresh status visible + pushState(); } } @@ -214,9 +237,21 @@ public boolean linkRocket(EntityRocketBase rocket) { this.linkedRocket = rocket; this.lastComparator = -1; + // Haxy gas mission returning case if (!world.isRemote) { - clearUiStatus(); - lastStatusTick = 0L; // reset tick + boolean returning = + (rocket instanceof EntityRocket) + && ((EntityRocket) rocket).isInOrbit() + && ((EntityRocket) rocket).isInFlight(); + + if (returning) { + uiStatus = 4; // deorbiting + lastStatusTick = world.getTotalWorldTime(); + pushState(); + } else { + clearUiStatus(); + lastStatusTick = 0L; + } } return true; } @@ -234,8 +269,12 @@ public void unlinkRocket() { if (!world.isRemote) { lastComparator = 0; world.updateComparatorOutputLevel(pos, world.getBlockState(pos).getBlock()); - clearUiStatus(); - lastStatusTick = 0L; // reset tick + + // Keep "Reached orbit" visible while the mission is active. + if (mission == null) { + clearUiStatus(); + lastStatusTick = 0L; // reset tick + } } } @@ -244,6 +283,11 @@ public void unlinkRocket() { @Override public void update() { + // ensure we are listening on the bus --- + if (!world.isRemote && !registeredBus) { + MinecraftForge.EVENT_BUS.register(this); + registeredBus = true; + } if (world.isRemote) return; // One-time prime (in case no neighbor event has fired yet) @@ -252,6 +296,18 @@ public void update() { initPower = true; } + if (!world.isRemote) { + long age = world.getTotalWorldTime() - lastStatusTick; + + // Aborted + if (uiStatus == 6 && age > STATUS_STALE_TICKS) clearUiStatus(); + + // Reached orbit — only time out when no mission is linked + if (uiStatus == 3 && mission == null && age > STATUS_STALE_TICKS) clearUiStatus(); + + // Landed + if (uiStatus == 5 && age > STATUS_STALE_TICKS) clearUiStatus(); + } // Runs infrequently to recover from any missed neighbor events. if (world.getTotalWorldTime() % 100 == 0) { // every 100 ticks boolean polled = world.isBlockIndirectlyGettingPowered(pos) > 0; @@ -288,8 +344,8 @@ public void update() { // - id=2 shows the *active* rocket fuel // - id=6 shows oxidizer independently final FuelRegistry.FuelType active = linkedRocket.getRocketFuelType(); - snapFuel = linkedRocket.getFuelAmount(active); - snapFuelCap = linkedRocket.getFuelCapacity(active); + snapFuel = (active != null) ? linkedRocket.getFuelAmount(active) : 0; + snapFuelCap = (active != null) ? linkedRocket.getFuelCapacity(active) : 0; snapOx = linkedRocket.getFuelAmount(FuelRegistry.FuelType.LIQUID_OXIDIZER); snapOxCap = linkedRocket.getFuelCapacity(FuelRegistry.FuelType.LIQUID_OXIDIZER); @@ -302,9 +358,10 @@ public void update() { public void onPreLaunch(RocketEvent.RocketPreLaunchEvent e) { if (world == null || world.isRemote) return; if (linkedRocket != null && e.getEntity() == linkedRocket) { - uiStatus = e.isCanceled() ? 5 : 1; // aborted or prelaunch + uiStatus = e.isCanceled() ? 6 : 1; + if (!e.isCanceled()) lastAbortReason = ""; // fresh launch, drop old reason lastStatusTick = world.getTotalWorldTime(); - pushState(); // single place to mark+notify + pushState(); } } @@ -328,11 +385,32 @@ public void onOrbit(RocketEvent.RocketReachesOrbitEvent e) { } } + @SubscribeEvent + public void onDeorbit(RocketEvent.RocketDeOrbitingEvent e) { + if (world == null || world.isRemote) return; + if (linkedRocket != null && e.getEntity() == linkedRocket) { + uiStatus = 4; // reuse “landed”/returning state + lastStatusTick = world.getTotalWorldTime(); + pushState(); + } + } + @SubscribeEvent public void onLanded(RocketEvent.RocketLandedEvent e) { if (world == null || world.isRemote) return; if (linkedRocket != null && e.getEntity() == linkedRocket) { - uiStatus = 4; + uiStatus = 5; + lastStatusTick = world.getTotalWorldTime(); + pushState(); + } + } + + @SubscribeEvent + public void onAbort(RocketEvent.RocketAbortEvent e) { + if (world == null || world.isRemote) return; + if (linkedRocket != null && e.getEntity() == linkedRocket) { + uiStatus = 6; // “aborted” + lastAbortReason = (e.reason == null) ? "" : e.reason; lastStatusTick = world.getTotalWorldTime(); pushState(); } @@ -401,6 +479,12 @@ public void readFromNBT(NBTTagCompound nbt) { } uiStatus = nbt.getInteger("uiStatus"); lastStatusTick = nbt.getLong("lastStatusTick"); + lastAbortReason = nbt.hasKey("abortReason") ? nbt.getString("abortReason") : ""; + + // --- client: force GUI labels to refresh next frame --- + if (world != null && world.isRemote) { + lastUiStatusShown = -1; // guarantees next render tick will reapply the text + } } @Override @@ -413,6 +497,7 @@ public NBTTagCompound writeToNBT(NBTTagCompound nbt) { } nbt.setInteger("uiStatus", uiStatus); nbt.setLong("lastStatusTick", lastStatusTick); + nbt.setString("abortReason", lastAbortReason == null ? "" : lastAbortReason); return nbt; } @@ -420,17 +505,15 @@ public NBTTagCompound writeToNBT(NBTTagCompound nbt) { @Override public void writeDataToNetwork(ByteBuf out, byte id) { - if (id == 1) - out.writeLong(mission == null ? -1 : mission.getMissionId()); + if (id == 1) out.writeLong(mission == null ? -1 : mission.getMissionId()); + else if (id == TAB_SWITCH) out.writeShort(tabModule.getTab()); } @Override public void readDataFromNetwork(ByteBuf in, byte packetId, NBTTagCompound nbt) { - if (packetId == 1) { - nbt.setLong("id", in.readLong()); - } else if (packetId == 2) { - nbt.setByte("state", in.readByte()); - } + if (packetId == 1) nbt.setLong("id", in.readLong()); + else if (packetId == 2) nbt.setByte("state", in.readByte()); + else if (packetId == TAB_SWITCH) nbt.setShort("tab", in.readShort()); } @Override @@ -439,17 +522,23 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompou long idNum = nbt.getLong("id"); if (idNum == -1) { mission = null; - setMissionText(); + if (world.isRemote && missionText != null) setMissionText(); } else { SatelliteBase base = DimensionManager.getInstance().getSatellite(idNum); if (base instanceof IMission) { mission = (IMission) base; - setMissionText(); + if (world.isRemote && missionText != null) setMissionText(); } } - } else if (id == 2) { + } + else if (id == 2) { // redstone control path was commented in original; preserved } + else if (id == TAB_SWITCH && !world.isRemote) { + tabModule.setTab(nbt.getShort("tab")); + player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), + getWorld(), pos.getX(), pos.getY(), pos.getZ()); + } if (id == 100) { if (linkedRocket != null) linkedRocket.prepareLaunch(); @@ -457,55 +546,189 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompou } // --- GUI / Modules --- - @Override public List getModules(int ID, EntityPlayer player) { LinkedList modules = new LinkedList<>(); - modules.add(new ModuleButton(20, 40, 0, "Launch!", this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); + // Tabs control + modules.add(tabModule); - // Status line for rocket events (client only) - if (world.isRemote) { - launchStatus = new ModuleText(10, 30, "", 0xFFFFFF22); - modules.add(launchStatus); + if (tabModule.getTab() == 0) { + // === STATUS TAB === + modules.add(new ModuleButton(20, 40, 0, "Launch!", this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); - // Force the label to refresh on this GUI open - lastUiStatusShown = -1; - } + if (world.isRemote) { + launchStatus = new ModuleText(88, 92, "", 0xFFFFFF22, true); // centered + modules.add(launchStatus); + abortDetail = new ModuleText(88, 108, "", 0xFF4444, true); // centered + modules.add(abortDetail); - modules.add(new ModuleProgress(98, 4, 0, new IndicatorBarImage(2, 7, 12, 81, 17, 0, 6, 6, 1, 0, EnumFacing.UP, TextureResources.rocketHud), this)); - modules.add(new ModuleProgress(120, 14, 1, new IndicatorBarImage(2, 95, 12, 71, 17, 0, 6, 6, 1, 0, EnumFacing.UP, TextureResources.rocketHud), this)); - modules.add(new ModuleProgress(142, 14, 2, new ProgressBarImage(2, 173, 12, 71, 17, 6, 3, 69, 1, 1, EnumFacing.UP, TextureResources.rocketHud), this)); - modules.add(new ModuleProgress(148, 14, 6, new ProgressBarImage(2, 173, 12, 71, 17, 75, 3, 69, 1, 1, EnumFacing.UP, TextureResources.rocketHud), this)); + lastUiStatusShown = -1; + } - setMissionText(); - modules.add(missionText); - modules.add(new ModuleProgress(30, 110, 3, TextureResources.progressToMission, this)); - modules.add(new ModuleProgress(30, 120, 4, TextureResources.workMission, this)); - modules.add(new ModuleProgress(30, 130, 5, TextureResources.progressFromMission, this)); + modules.add(new ModuleProgress(98, 4, 0, new IndicatorBarImage(2, 7, 12, 81, 17, 0, 6, 6, 1, 0, EnumFacing.UP, TextureResources.rocketHud), this)); + modules.add(new ModuleProgress(120, 14, 1, new IndicatorBarImage(2, 95, 12, 71, 17, 0, 6, 6, 1, 0, EnumFacing.UP, TextureResources.rocketHud), this)); + modules.add(new ModuleProgress(142, 14, 2, new ProgressBarImage(2,173, 12, 71, 17, 6, 3, 69, 1, 1, EnumFacing.UP, TextureResources.rocketHud), this)); + modules.add(new ModuleProgress(148, 14, 6, new ProgressBarImage(2,173, 12, 71, 17,75, 3, 69, 1, 1, EnumFacing.UP, TextureResources.rocketHud), this)); - if (!world.isRemote) { - PacketHandler.sendToPlayer(new PacketMachine(this, (byte) 1), player); // mission sync - pushState(); // TE sync (includes cleared/derived uiStatus) + if (!world.isRemote) { + PacketHandler.sendToPlayer(new PacketMachine(this, (byte)1), player); + pushState(); + } + return modules; + } + + // === MISSION TAB === + { + final boolean hasMission = mission != null; + + // If there is NO mission: show a single centered line and exit early + if (!hasMission) { + modules.add(new ModuleText( + 88, 72, + LibVulpes.proxy.getLocalizedString("msg.monitoringStation.missionNoActiveMission"), + 0x2b2b2b, // color + true // centered + )); + if (!world.isRemote) { + PacketHandler.sendToPlayer(new PacketMachine(this, (byte)1), player); + pushState(); + } + return modules; + } + + // ---- Has mission: structured list ---- + final String typeLine; + { + String cls = mission.getClass().getSimpleName().toLowerCase(); + typeLine = cls.contains("gas") + ? LibVulpes.proxy.getLocalizedString("msg.monitoringStation.mission.type.gas") // "Gas Collection Mission" + : LibVulpes.proxy.getLocalizedString("msg.monitoringStation.mission.type.ore"); // "Asteroid Mining Mission" + } + + + modules.add(new ModuleText( + 88, 16, net.minecraft.util.text.TextFormatting.BOLD + typeLine + net.minecraft.util.text.TextFormatting.RESET, + 0x2b2b2b, + true // centered + )); + + // Decide mission type once (use the text you already built) + final boolean isGas = typeLine.toLowerCase().contains("gas"); + + // Target: if GAS mission, show the chosen fluid; otherwise keep default + if (isGas) { + String gasLabel = ""; + try { + if (mission instanceof zmaster587.advancedRocketry.mission.MissionGasCollection) { + net.minecraftforge.fluids.Fluid f = + ((zmaster587.advancedRocketry.mission.MissionGasCollection) mission).getGasFluid(); + if (f != null) { + gasLabel = new net.minecraftforge.fluids.FluidStack(f, 1).getLocalizedName(); + } + } + } catch (Throwable t) { /* be defensive */ } + + modules.add(new ModuleText( + 10, 39, + (gasLabel.isEmpty() + ? LibVulpes.proxy.getLocalizedString("msg.monitoringStation.mission.target.default") + : LibVulpes.proxy.getLocalizedString("msg.monitoringStation.mission.targetPrefix") + " " + gasLabel), + 0x2b2b2b + )); + } else { + // ---------- NON-GAS (ORE) SECTION — single, minimal block ---------- + String oreType = ""; + String shortId = ""; + + try { + if (mission instanceof zmaster587.advancedRocketry.mission.MissionOreMining) { + zmaster587.advancedRocketry.mission.MissionOreMining m = + (zmaster587.advancedRocketry.mission.MissionOreMining) mission; + + oreType = m.getAsteroidTypeOrEmpty(); + Long aUuid = m.getAsteroidUUIDOrNull(); + + if (aUuid != null) { + long base = aUuid; + long th = Integer.toUnsignedLong((oreType == null ? "" : oreType).hashCode()); + long z = base ^ (th << 1); + z += 0x9E3779B97F4A7C15L; + z = (z ^ (z >>> 30)) * 0xBF58476D1CE4E5B9L; + z = (z ^ (z >>> 27)) * 0x94D049BB133111EBL; + z = (z ^ (z >>> 31)); + String hex = Long.toUnsignedString(z, 16).toUpperCase(); + shortId = (hex.length() > 6) ? hex.substring(hex.length() - 6) : hex; + } + } + } catch (Throwable t) { /* defensive */ } + + // Line 1: Asteroid: (or just "Asteroid:" if id missing) + String lineAsteroid = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.mission.Asteroid.targetPrefix") + + (shortId.isEmpty() ? "" : " " + shortId); + modules.add(new ModuleText(10, 39, lineAsteroid, 0x2b2b2b)); + + // Line 2: Type: (omit if unknown) + if (oreType != null && !oreType.isEmpty()) { + String lineType = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.mission.asteroidIdPrefix") + + " " + oreType; + modules.add(new ModuleText(10, 53, lineType, 0x2b2b2b)); + } + } + + + // --- Specific line per mission type --- + if (isGas) { + // Read planned harvest written by the rocket into the mission's persist NBT + long plannedMb = -1L; + try { + if (mission instanceof zmaster587.advancedRocketry.mission.MissionResourceCollection) { + plannedMb = ((zmaster587.advancedRocketry.mission.MissionResourceCollection) mission) + .getPlannedHarvestMbOrDefault(); + } + } catch (Throwable t) { /* be defensive */ } + + final String plannedText = (plannedMb >= 0) + ? (LibVulpes.proxy.getLocalizedString("msg.monitoringStation.mission.plannedAmountPrefix") + " " + plannedMb + " mB") + : LibVulpes.proxy.getLocalizedString("msg.monitoringStation.mission.plannedAmountPending"); + + modules.add(new ModuleText(10, 53, plannedText, 0x2b2b2b)); + } + //else { if we want to add ore-specific lines later, show loot etc. } + + // Duration text (above the stage bars, like original) + missionText = new ModuleText(88, 94, "", 0x2b2b2b, true); + setMissionText(); + modules.add(missionText); + // Stage bars just above the time block + modules.add(new ModuleProgress(30, 110, 3, TextureResources.progressToMission, this)); + modules.add(new ModuleProgress(30, 120, 4, TextureResources.workMission, this)); + modules.add(new ModuleProgress(30, 130, 5, TextureResources.progressFromMission, this)); + + if (!world.isRemote) { + PacketHandler.sendToPlayer(new PacketMachine(this, (byte)1), player); + pushState(); + } + return modules; } + } - return modules; - } private void setMissionText() { + // If the text widget isn’t built yet (e.g., GUI closed or on other tab), just bail out. + if (missionText == null) return; + if (mission != null) { int time = mission.getTimeRemainingInSeconds(); int seconds = time % 60; int minutes = (time / 60) % 60; int hours = time / 3600; - String name = (mission instanceof SatelliteBase) - ? ((SatelliteBase) mission).getName() - : LibVulpes.proxy.getLocalizedString("msg.monitoringStation.mission"); - - missionText.setText(name + LibVulpes.proxy.getLocalizedString("msg.monitoringStation.progress") - + String.format("\n%02dhr:%02dm:%02ds", hours, minutes, seconds)); + missionText.setText( + LibVulpes.proxy.getLocalizedString("msg.monitoringStation.progress") + + String.format(" %02d:%02d:%02d", hours, minutes, seconds) + ); } else { missionText.setText(LibVulpes.proxy.getLocalizedString("msg.monitoringStation.missionProgressNA")); } @@ -514,9 +737,16 @@ private void setMissionText() { @Override public void onInventoryButtonPressed(int buttonId) { if (buttonId != -1) - PacketHandler.sendToServer(new PacketMachine(this, (byte) (buttonId + 100))); + PacketHandler.sendToServer(new PacketMachine(this, (byte)(buttonId + 100))); else - PacketHandler.sendToServer(new PacketMachine(this, (byte) 2)); + PacketHandler.sendToServer(new PacketMachine(this, (byte)2)); + } + + private static String wrapToWidthClient(String s, int maxWidthPx) { + if (s == null || s.isEmpty()) return ""; + net.minecraft.client.gui.FontRenderer fr = net.minecraft.client.Minecraft.getMinecraft().fontRenderer; + java.util.List lines = fr.listFormattedStringToWidth(s, Math.max(1, maxWidthPx)); + return String.join("\n", lines); } @Override @@ -526,44 +756,55 @@ public String getModularInventoryName() { @Override public float getNormallizedProgress(int id) { + if (world.isRemote) { + // Status tab label + if (launchStatus != null && uiStatus != lastUiStatusShown) { + lastUiStatusShown = uiStatus; + + String header = ""; + String detail = ""; + + switch (uiStatus) { + case 1: header = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.prelaunch"); break; + case 2: header = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.launching"); break; + case 3: header = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.orbit"); break; + case 4: header = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.deorbiting"); break; + case 5: header = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.landed"); break; + case 6: header = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.aborted"); + if (lastAbortReason != null && !lastAbortReason.isEmpty()) {detail = lastAbortReason;} break; + default: + header = ""; + } + launchStatus.setText(header); + if (abortDetail != null) { + final int ABORT_WRAP_WIDTH = 150; + abortDetail.setText(wrapToWidthClient(detail, ABORT_WRAP_WIDTH)); + } + } + + // Mission tab duration label (make it live) + if (mission != null && missionText != null) { + setMissionText(); + } + } + if (id == 1) { return Math.max(Math.min(0.5f + (getProgress(id) / (float) getTotalProgress(id)), 1), 0f); } else if (id == 3) { - if (mission == null) - return 0f; + if (mission == null) return 0f; return (float) Math.min(3f * mission.getProgress(this.world), 1f); } else if (id == 4) { - if (mission == null) - return 0f; + if (mission == null) return 0f; return (float) Math.min(Math.max(3f * (mission.getProgress(this.world) - 0.333f), 0f), 1f); } else if (id == 5) { - if (mission == null) - return 0f; + if (mission == null) return 0f; return (float) Math.min(Math.max(3f * (mission.getProgress(this.world) - 0.666f), 0f), 1f); } - // Client: reflect server-driven rocket event status in the GUI text - if (world.isRemote && launchStatus != null && uiStatus != lastUiStatusShown) { - lastUiStatusShown = uiStatus; - String msg; - switch (uiStatus) { - case 1: msg = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.prelaunch"); break; // "Pre-launch checks…" - case 2: msg = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.launching"); break; // "Launching!" - case 3: msg = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.orbit"); break; // "Reached orbit" - case 4: msg = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.landed"); break; // "Landed" - case 5: msg = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.aborted"); break; // "Launch aborted" - default: msg = ""; break; - } - launchStatus.setText(msg); - } - - // Keep mission text updated on client - if (world.isRemote && mission != null) - setMissionText(); - return Math.min(getProgress(id) / (float) getTotalProgress(id), 1.0f); } + @Override public void setProgress(int id, int progress) { if (id == 0) @@ -619,10 +860,25 @@ public void setTotalProgress(int id, int progress) { public boolean canInteractWithContainer(EntityPlayer entity) { return true; } + + @Override + public void onModuleUpdated(ModuleBase module) { + PacketHandler.sendToServer(new PacketMachine(this, TAB_SWITCH)); + } @Override public boolean linkMission(IMission mission) { this.mission = mission; + // If we don’t already have a status, show “in orbit” while mission runs. + if (!world.isRemote) { + // If we were at idle/prelaunch/launching, move to "reached orbit" now. + if (uiStatus < 3) { + uiStatus = 3; + lastStatusTick = world.getTotalWorldTime(); + pushState(); + } + } + PacketHandler.sendToNearby(new PacketMachine(this, (byte) 1), world.provider.getDimension(), getPos(), 16); return true; } @@ -630,7 +886,7 @@ public boolean linkMission(IMission mission) { @Override public void unlinkMission() { mission = null; - setMissionText(); + if (missionText != null) setMissionText(); // guard PacketHandler.sendToNearby(new PacketMachine(this, (byte) 1), world.provider.getDimension(), getPos(), 16); } From cf0bc37b618da96a0d68d736a72b5ea9ff57ab54 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 02:17:09 +0100 Subject: [PATCH 132/424] Add new localization entries for monitoring station --- src/main/resources/assets/advancedrocketry/lang/en_US.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index f7d174435..ca09d5df2 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -338,6 +338,7 @@ msg.monitoringStation.orbit=Reached orbit! msg.monitoringStation.deorbiting=Returned from orbit! msg.monitoringStation.landed=Landed msg.monitoringStation.aborted=Aborted! +msg.monitoringStation.returningToDock=Returning to dock msg.guidanceComputerHatch.loadingState=Loading State: From aac52d6e0e80f89bc5e5de7fc3f37bf701487339 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 13:27:57 +0100 Subject: [PATCH 133/424] Add fueling station integration to ARPlugin --- .../integration/jei/ARPlugin.java | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/ARPlugin.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/ARPlugin.java index e934a949b..b07be2bc2 100644 --- a/src/main/java/zmaster587/advancedRocketry/integration/jei/ARPlugin.java +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/ARPlugin.java @@ -23,6 +23,9 @@ import zmaster587.advancedRocketry.integration.jei.electrolyser.ElectrolyzerCategory; import zmaster587.advancedRocketry.integration.jei.electrolyser.ElectrolyzerRecipeHandler; import zmaster587.advancedRocketry.integration.jei.electrolyser.ElectrolyzerRecipeMaker; +import zmaster587.advancedRocketry.integration.jei.fuelingStation.FuelingStationCategory; +import zmaster587.advancedRocketry.integration.jei.fuelingStation.FuelingStationRecipeHandler; +import zmaster587.advancedRocketry.integration.jei.fuelingStation.FuelingStationRecipeMaker; import zmaster587.advancedRocketry.integration.jei.lathe.LatheCategory; import zmaster587.advancedRocketry.integration.jei.lathe.LatheRecipeHandler; import zmaster587.advancedRocketry.integration.jei.lathe.LatheRecipeMaker; @@ -44,7 +47,9 @@ import zmaster587.advancedRocketry.integration.jei.satelliteBuilder.SatelliteBuilderCategory; import zmaster587.advancedRocketry.integration.jei.satelliteBuilder.SatelliteBuilderRecipeHandler; import zmaster587.advancedRocketry.integration.jei.satelliteBuilder.SatelliteBuilderRecipeMaker; +import zmaster587.advancedRocketry.tile.infrastructure.TileFuelingStation; import zmaster587.advancedRocketry.tile.multiblock.machine.*; +import zmaster587.advancedRocketry.tile.satellite.TileSatelliteBuilder; import zmaster587.libVulpes.inventory.GuiModular; import javax.annotation.Nonnull; @@ -65,6 +70,7 @@ public class ARPlugin implements IModPlugin { public static final String centrifugeUUID = "zmaster587.AR.centrifuge"; public static final String precisionLaserEngraverUUID = "zmaster587.AR.precisionlaseretcher"; public static final String satelliteBuilderUUID = "zmaster587.AR.satelliteBuilder"; + public static final String fuelingStationUUID = "zmaster587.AR.fuelingStation"; public static IJeiHelpers jeiHelpers; //AR machines can reload recipes. We still need this for JEI to be up-to-date @@ -90,7 +96,8 @@ public void registerCategories(IRecipeCategoryRegistration registry) { new PlatePressCategory(guiHelper), new CentrifugeCategory(guiHelper), new PrecisionLaserEtcherCategory(guiHelper), - new SatelliteBuilderCategory(guiHelper) + new SatelliteBuilderCategory(guiHelper), + new FuelingStationCategory(guiHelper) ); } @@ -136,7 +143,8 @@ public Object getIngredientUnderMouse(GuiModular guiContainer, new PlatePressRecipeHandler(), new CentrifugeRecipeHandler(), new PrecisionLaserEtcherRecipeHandler(), - new SatelliteBuilderRecipeHandler() + new SatelliteBuilderRecipeHandler(), + new FuelingStationRecipeHandler() ); registry.addRecipes(RollingMachineRecipeMaker.getMachineRecipes(jeiHelpers, TileRollingMachine.class), rollingMachineUUID); @@ -150,8 +158,8 @@ public Object getIngredientUnderMouse(GuiModular guiContainer, registry.addRecipes(ChemicalReactorRecipeMaker.getMachineRecipes(jeiHelpers, TileChemicalReactor.class), chemicalReactorUUID); registry.addRecipes(CentrifugeRecipeMaker.getMachineRecipes(jeiHelpers, TileCentrifuge.class), centrifugeUUID); registry.addRecipes(PrecisionLaserEtcherRecipeMaker.getMachineRecipes(jeiHelpers, TilePrecisionLaserEtcher.class), precisionLaserEngraverUUID); - registry.addRecipes(SatelliteBuilderRecipeMaker.getMachineRecipes(jeiHelpers, null), satelliteBuilderUUID); - + registry.addRecipes(SatelliteBuilderRecipeMaker.getMachineRecipes(jeiHelpers, TileSatelliteBuilder.class), satelliteBuilderUUID); + registry.addRecipes(FuelingStationRecipeMaker.getMachineRecipes(jeiHelpers, TileFuelingStation.class), fuelingStationUUID); registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockRollingMachine), rollingMachineUUID); registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockLathe), latheUUID); @@ -165,5 +173,14 @@ public Object getIngredientUnderMouse(GuiModular guiContainer, registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockCentrifuge), centrifugeUUID); registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockPrecisionLaserEngraver), precisionLaserEngraverUUID); registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockSatelliteBuilder), satelliteBuilderUUID); + + + // One tab: Fueling Station + Tank-type catalysts (mono / biprop fuel / oxidizer / working fluid) + registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockFuelingStation), fuelingStationUUID); + registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockFuelTank), fuelingStationUUID); // mono + registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockBipropellantFuelTank), fuelingStationUUID); // biprop fuel + registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockOxidizerFuelTank), fuelingStationUUID); // oxidizer + registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockNuclearFuelTank), fuelingStationUUID); // working fluid + } } From 6c7429945c3bb4097ba1f783b6a3a9fb8ed485e3 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 13:29:18 +0100 Subject: [PATCH 134/424] Add FuelingStationCategory for JEI integration --- ...elingStation\\FuelingStationCategory.java" | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 "src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation\\FuelingStationCategory.java" diff --git "a/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation\\FuelingStationCategory.java" "b/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation\\FuelingStationCategory.java" new file mode 100644 index 000000000..1124851b1 --- /dev/null +++ "b/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation\\FuelingStationCategory.java" @@ -0,0 +1,98 @@ +package zmaster587.advancedRocketry.integration.jei.fuelingStation; + +import mezz.jei.api.IGuiHelper; +import mezz.jei.api.gui.*; +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.recipe.IRecipeCategory; +import net.minecraft.client.Minecraft; +import net.minecraft.item.ItemStack; +import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; +import zmaster587.advancedRocketry.integration.jei.ARPlugin; +import zmaster587.libVulpes.gui.CommonResources; + +public class FuelingStationCategory implements IRecipeCategory { + + private final IDrawable background; + private final IDrawable icon; + private final IDrawable tankFrame; // 14x54 bezel from generic background + private final IDrawable slotFrame; // JEI’s standard slot look + + // --- compact but accurate: 150 x 56 so 4 recipes fit on one JEI page --- + public FuelingStationCategory(IGuiHelper gui) { + this.background = gui.createBlankDrawable(150, 56); + this.icon = gui.createDrawableIngredient(new ItemStack(AdvancedRocketryBlocks.blockFuelingStation)); + + // exact bezel the in-game ModuleLiquidIndicator draws: u=176,v=58,w=14,h=54 + this.tankFrame = gui.createDrawable(CommonResources.genericBackground, 176, 58, 14, 54); + + // vanilla-looking slot border + this.slotFrame = gui.getSlotDrawable(); + } + + @Override public String getUid() { return ARPlugin.fuelingStationUUID; } + @Override public String getTitle() { return new ItemStack(AdvancedRocketryBlocks.blockFuelingStation).getDisplayName(); } + @Override public String getModName() { return "Advanced Rocketry"; } + @Override public IDrawable getBackground(){ return background; } + @Override public IDrawable getIcon() { return icon; } + + @Override + public void setRecipe(IRecipeLayout layout, FuelingStationWrapper wrapper, IIngredients ing) { + // Fluid gauge (inside the real bezel) + IGuiFluidStackGroup fluids = layout.getFluidStacks(); + fluids.init(0, true, 28, 3, 12, 52, 1000, false, null); + fluids.set(0, wrapper.getFluid()); + + IGuiItemStackGroup items = layout.getItemStacks(); + + // ITEM inputs come as two lists: [ [bucket?], [role tank] ] + java.util.List> itemInputs = + ing.getInputs(mezz.jei.api.ingredients.VanillaTypes.ITEM); + + // Slot 0: bucket INPUT (if present) + items.init(0, true, 45, 6); + if (!itemInputs.isEmpty() && !itemInputs.get(0).isEmpty() + && itemInputs.get(0).get(0).getItem() == wrapper.getFilledContainer().getItem()) { + items.set(0, itemInputs.get(0)); + } else { + items.set(0, java.util.Collections.emptyList()); + } + items.addTooltipCallback((slotIndex, input, stack, tooltip) -> { + if (slotIndex != 0 || stack == null || stack.isEmpty()) return; + + // Only decorate the bucket input slot + tooltip.add(""); + tooltip.add(net.minecraft.util.text.TextFormatting.YELLOW + + zmaster587.libVulpes.LibVulpes.proxy.getLocalizedString( + "jei.ar.fuel.role." + wrapper.getRole().langKey() + )); + }); + + // Slot 1: ROLE TANK + items.init(1, true, 120, 6); + // The role tank will be the other input list + if (itemInputs.size() >= 2) { + items.set(1, itemInputs.get(1)); + } else if (!wrapper.getRoleTankStack().isEmpty()) { + // fallback if bucket missing → the only input is the role tank + items.set(1, java.util.Collections.singletonList(wrapper.getRoleTankStack())); + } + fluids.addTooltipCallback((slotIndex, input, fluid, tooltip) -> { + if (slotIndex != 0 || fluid == null) return; + + // Blank spacer then role + usage + tooltip.add(""); + tooltip.add(net.minecraft.util.text.TextFormatting.YELLOW + + zmaster587.libVulpes.LibVulpes.proxy.getLocalizedString( + "jei.ar.fuel.role." + wrapper.getRole().langKey() + )); + }); + } + + @Override + public void drawExtras(Minecraft mc) { + // Draw tank bezel and slot frames so it looks like the real GUI + tankFrame.draw(mc, 27, 2); // 14x54 bezel + slotFrame.draw(mc, 45, 6); // bucket slot + } + +} From 2442bd48b956aa9359d07d8f90ffd0dcc658a8a5 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 13:31:00 +0100 Subject: [PATCH 135/424] Delete src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation\FuelingStationCategory.java --- ...elingStation\\FuelingStationCategory.java" | 98 ------------------- 1 file changed, 98 deletions(-) delete mode 100644 "src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation\\FuelingStationCategory.java" diff --git "a/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation\\FuelingStationCategory.java" "b/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation\\FuelingStationCategory.java" deleted file mode 100644 index 1124851b1..000000000 --- "a/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation\\FuelingStationCategory.java" +++ /dev/null @@ -1,98 +0,0 @@ -package zmaster587.advancedRocketry.integration.jei.fuelingStation; - -import mezz.jei.api.IGuiHelper; -import mezz.jei.api.gui.*; -import mezz.jei.api.ingredients.IIngredients; -import mezz.jei.api.recipe.IRecipeCategory; -import net.minecraft.client.Minecraft; -import net.minecraft.item.ItemStack; -import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; -import zmaster587.advancedRocketry.integration.jei.ARPlugin; -import zmaster587.libVulpes.gui.CommonResources; - -public class FuelingStationCategory implements IRecipeCategory { - - private final IDrawable background; - private final IDrawable icon; - private final IDrawable tankFrame; // 14x54 bezel from generic background - private final IDrawable slotFrame; // JEI’s standard slot look - - // --- compact but accurate: 150 x 56 so 4 recipes fit on one JEI page --- - public FuelingStationCategory(IGuiHelper gui) { - this.background = gui.createBlankDrawable(150, 56); - this.icon = gui.createDrawableIngredient(new ItemStack(AdvancedRocketryBlocks.blockFuelingStation)); - - // exact bezel the in-game ModuleLiquidIndicator draws: u=176,v=58,w=14,h=54 - this.tankFrame = gui.createDrawable(CommonResources.genericBackground, 176, 58, 14, 54); - - // vanilla-looking slot border - this.slotFrame = gui.getSlotDrawable(); - } - - @Override public String getUid() { return ARPlugin.fuelingStationUUID; } - @Override public String getTitle() { return new ItemStack(AdvancedRocketryBlocks.blockFuelingStation).getDisplayName(); } - @Override public String getModName() { return "Advanced Rocketry"; } - @Override public IDrawable getBackground(){ return background; } - @Override public IDrawable getIcon() { return icon; } - - @Override - public void setRecipe(IRecipeLayout layout, FuelingStationWrapper wrapper, IIngredients ing) { - // Fluid gauge (inside the real bezel) - IGuiFluidStackGroup fluids = layout.getFluidStacks(); - fluids.init(0, true, 28, 3, 12, 52, 1000, false, null); - fluids.set(0, wrapper.getFluid()); - - IGuiItemStackGroup items = layout.getItemStacks(); - - // ITEM inputs come as two lists: [ [bucket?], [role tank] ] - java.util.List> itemInputs = - ing.getInputs(mezz.jei.api.ingredients.VanillaTypes.ITEM); - - // Slot 0: bucket INPUT (if present) - items.init(0, true, 45, 6); - if (!itemInputs.isEmpty() && !itemInputs.get(0).isEmpty() - && itemInputs.get(0).get(0).getItem() == wrapper.getFilledContainer().getItem()) { - items.set(0, itemInputs.get(0)); - } else { - items.set(0, java.util.Collections.emptyList()); - } - items.addTooltipCallback((slotIndex, input, stack, tooltip) -> { - if (slotIndex != 0 || stack == null || stack.isEmpty()) return; - - // Only decorate the bucket input slot - tooltip.add(""); - tooltip.add(net.minecraft.util.text.TextFormatting.YELLOW + - zmaster587.libVulpes.LibVulpes.proxy.getLocalizedString( - "jei.ar.fuel.role." + wrapper.getRole().langKey() - )); - }); - - // Slot 1: ROLE TANK - items.init(1, true, 120, 6); - // The role tank will be the other input list - if (itemInputs.size() >= 2) { - items.set(1, itemInputs.get(1)); - } else if (!wrapper.getRoleTankStack().isEmpty()) { - // fallback if bucket missing → the only input is the role tank - items.set(1, java.util.Collections.singletonList(wrapper.getRoleTankStack())); - } - fluids.addTooltipCallback((slotIndex, input, fluid, tooltip) -> { - if (slotIndex != 0 || fluid == null) return; - - // Blank spacer then role + usage - tooltip.add(""); - tooltip.add(net.minecraft.util.text.TextFormatting.YELLOW + - zmaster587.libVulpes.LibVulpes.proxy.getLocalizedString( - "jei.ar.fuel.role." + wrapper.getRole().langKey() - )); - }); - } - - @Override - public void drawExtras(Minecraft mc) { - // Draw tank bezel and slot frames so it looks like the real GUI - tankFrame.draw(mc, 27, 2); // 14x54 bezel - slotFrame.draw(mc, 45, 6); // bucket slot - } - -} From 8adb4044cf1961b339695f14667df4745dd425c2 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 13:31:35 +0100 Subject: [PATCH 136/424] Add FuelingStationCategory for JEI integration --- .../FuelingStationCategory.java | 98 +++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationCategory.java diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationCategory.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationCategory.java new file mode 100644 index 000000000..1124851b1 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationCategory.java @@ -0,0 +1,98 @@ +package zmaster587.advancedRocketry.integration.jei.fuelingStation; + +import mezz.jei.api.IGuiHelper; +import mezz.jei.api.gui.*; +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.recipe.IRecipeCategory; +import net.minecraft.client.Minecraft; +import net.minecraft.item.ItemStack; +import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; +import zmaster587.advancedRocketry.integration.jei.ARPlugin; +import zmaster587.libVulpes.gui.CommonResources; + +public class FuelingStationCategory implements IRecipeCategory { + + private final IDrawable background; + private final IDrawable icon; + private final IDrawable tankFrame; // 14x54 bezel from generic background + private final IDrawable slotFrame; // JEI’s standard slot look + + // --- compact but accurate: 150 x 56 so 4 recipes fit on one JEI page --- + public FuelingStationCategory(IGuiHelper gui) { + this.background = gui.createBlankDrawable(150, 56); + this.icon = gui.createDrawableIngredient(new ItemStack(AdvancedRocketryBlocks.blockFuelingStation)); + + // exact bezel the in-game ModuleLiquidIndicator draws: u=176,v=58,w=14,h=54 + this.tankFrame = gui.createDrawable(CommonResources.genericBackground, 176, 58, 14, 54); + + // vanilla-looking slot border + this.slotFrame = gui.getSlotDrawable(); + } + + @Override public String getUid() { return ARPlugin.fuelingStationUUID; } + @Override public String getTitle() { return new ItemStack(AdvancedRocketryBlocks.blockFuelingStation).getDisplayName(); } + @Override public String getModName() { return "Advanced Rocketry"; } + @Override public IDrawable getBackground(){ return background; } + @Override public IDrawable getIcon() { return icon; } + + @Override + public void setRecipe(IRecipeLayout layout, FuelingStationWrapper wrapper, IIngredients ing) { + // Fluid gauge (inside the real bezel) + IGuiFluidStackGroup fluids = layout.getFluidStacks(); + fluids.init(0, true, 28, 3, 12, 52, 1000, false, null); + fluids.set(0, wrapper.getFluid()); + + IGuiItemStackGroup items = layout.getItemStacks(); + + // ITEM inputs come as two lists: [ [bucket?], [role tank] ] + java.util.List> itemInputs = + ing.getInputs(mezz.jei.api.ingredients.VanillaTypes.ITEM); + + // Slot 0: bucket INPUT (if present) + items.init(0, true, 45, 6); + if (!itemInputs.isEmpty() && !itemInputs.get(0).isEmpty() + && itemInputs.get(0).get(0).getItem() == wrapper.getFilledContainer().getItem()) { + items.set(0, itemInputs.get(0)); + } else { + items.set(0, java.util.Collections.emptyList()); + } + items.addTooltipCallback((slotIndex, input, stack, tooltip) -> { + if (slotIndex != 0 || stack == null || stack.isEmpty()) return; + + // Only decorate the bucket input slot + tooltip.add(""); + tooltip.add(net.minecraft.util.text.TextFormatting.YELLOW + + zmaster587.libVulpes.LibVulpes.proxy.getLocalizedString( + "jei.ar.fuel.role." + wrapper.getRole().langKey() + )); + }); + + // Slot 1: ROLE TANK + items.init(1, true, 120, 6); + // The role tank will be the other input list + if (itemInputs.size() >= 2) { + items.set(1, itemInputs.get(1)); + } else if (!wrapper.getRoleTankStack().isEmpty()) { + // fallback if bucket missing → the only input is the role tank + items.set(1, java.util.Collections.singletonList(wrapper.getRoleTankStack())); + } + fluids.addTooltipCallback((slotIndex, input, fluid, tooltip) -> { + if (slotIndex != 0 || fluid == null) return; + + // Blank spacer then role + usage + tooltip.add(""); + tooltip.add(net.minecraft.util.text.TextFormatting.YELLOW + + zmaster587.libVulpes.LibVulpes.proxy.getLocalizedString( + "jei.ar.fuel.role." + wrapper.getRole().langKey() + )); + }); + } + + @Override + public void drawExtras(Minecraft mc) { + // Draw tank bezel and slot frames so it looks like the real GUI + tankFrame.draw(mc, 27, 2); // 14x54 bezel + slotFrame.draw(mc, 45, 6); // bucket slot + } + +} From f2f60f50f2889dc3defddd0fe8fcf14745592dbf Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 13:32:01 +0100 Subject: [PATCH 137/424] Implement FuelingStationRecipeHandler class --- .../fuelingStation/FuelingStationRecipeHandler.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationRecipeHandler.java diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationRecipeHandler.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationRecipeHandler.java new file mode 100644 index 000000000..efc87ce5d --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationRecipeHandler.java @@ -0,0 +1,12 @@ +package zmaster587.advancedRocketry.integration.jei.fuelingStation; + +import mezz.jei.api.recipe.IRecipeHandler; +import mezz.jei.api.recipe.IRecipeWrapper; +import zmaster587.advancedRocketry.integration.jei.ARPlugin; + +public class FuelingStationRecipeHandler implements IRecipeHandler { + @Override public Class getRecipeClass() { return FuelingStationWrapper.class; } + @Override public String getRecipeCategoryUid(FuelingStationWrapper r) { return ARPlugin.fuelingStationUUID; } + @Override public IRecipeWrapper getRecipeWrapper(FuelingStationWrapper r) { return r; } + @Override public boolean isRecipeValid(FuelingStationWrapper r) { return r != null; } +} From 1b286eb18b8ac00537f263892af94d583267f0a7 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 13:32:23 +0100 Subject: [PATCH 138/424] Implement FuelingStationRecipeMaker class --- .../FuelingStationRecipeMaker.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationRecipeMaker.java diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationRecipeMaker.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationRecipeMaker.java new file mode 100644 index 000000000..76bc797ec --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationRecipeMaker.java @@ -0,0 +1,42 @@ +package zmaster587.advancedRocketry.integration.jei.fuelingStation; + +import mezz.jei.api.IJeiHelpers; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidStack; +import zmaster587.advancedRocketry.api.fuel.FuelRegistry; +import zmaster587.advancedRocketry.api.fuel.FuelRegistry.FuelType; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class FuelingStationRecipeMaker { + + public static List getRecipes(IJeiHelpers helpers) { + List out = new ArrayList<>(); + + add(out, FuelType.LIQUID_MONOPROPELLANT, FuelingStationWrapper.Role.MONO); + add(out, FuelType.LIQUID_BIPROPELLANT, FuelingStationWrapper.Role.BIPROP_FUEL); + add(out, FuelType.LIQUID_OXIDIZER, FuelingStationWrapper.Role.OXIDIZER); + add(out, FuelType.NUCLEAR_WORKING_FLUID, FuelingStationWrapper.Role.WORKING_FLUID); + + return out; + } + + private static void add(List list, + FuelType type, + FuelingStationWrapper.Role role) { + // Avoid name clash with AR’s FuelRegistry by fully-qualifying Forge’s registry here. + for (Map.Entry e : net.minecraftforge.fluids.FluidRegistry.getRegisteredFluids().entrySet()) { + Fluid f = e.getValue(); + if (f != null && FuelRegistry.instance.isFuel(type, f)) { + list.add(new FuelingStationWrapper(new FluidStack(f, 1000), role)); + } + } + } + + // Optional: keep this to match your existing makers + public static List getMachineRecipes(IJeiHelpers helpers, Class ignored) { + return getRecipes(helpers); + } +} From a14bf826905a6bb6758c146ca1eead6898e8f8c2 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 13:32:45 +0100 Subject: [PATCH 139/424] Add FuelingStationWrapper for JEI integration --- .../fuelingStation/FuelingStationWrapper.java | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationWrapper.java diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationWrapper.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationWrapper.java new file mode 100644 index 000000000..2f0af02ef --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationWrapper.java @@ -0,0 +1,96 @@ +package zmaster587.advancedRocketry.integration.jei.fuelingStation; + +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.recipe.IRecipeWrapper; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidUtil; +import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; + +import java.util.Collections; + +public class FuelingStationWrapper implements IRecipeWrapper { + + public enum Role { + MONO("monopropellant"), BIPROP_FUEL("biprop_fuel"), + OXIDIZER("oxidizer"), WORKING_FLUID("working_fluid"); + private final String key; Role(String k){ this.key = k; } + public String langKey(){ return key; } + } + + private final FluidStack fluid; + private final Role role; + + public FuelingStationWrapper(FluidStack fluid, Role role) { + this.fluid = fluid; + this.role = role; + } + + public Role getRole() { return role; } + public FluidStack getFluid() { return fluid; } + + @Override + public void getIngredients(IIngredients ing) { + // Fluid input (internal tank) + ing.setInputs(mezz.jei.api.ingredients.VanillaTypes.FLUID, + java.util.Collections.singletonList(fluid)); + + // ITEM inputs in order: + // 0: [filled bucket?] + // 1: [role tank] + // 2: [fueling station] <-- hidden, just for discoverability via U/R on the block + java.util.List> itemInputs = new java.util.ArrayList<>(3); + + // 0) filled bucket (if present) + ItemStack filled = getFilledContainer(); + if (!filled.isEmpty()) { + itemInputs.add(java.util.Collections.singletonList(filled)); + } + + // 1) role tank (always try to include) + ItemStack roleTank = getRoleTankStack(); + if (!roleTank.isEmpty()) { + itemInputs.add(java.util.Collections.singletonList(roleTank)); + } + + // 2) fueling station (hidden ingredient so U/R on the block opens this tab) + ItemStack station = new ItemStack(zmaster587.advancedRocketry.api.AdvancedRocketryBlocks.blockFuelingStation); + itemInputs.add(java.util.Collections.singletonList(station)); + + // commit item inputs + ing.setInputLists(mezz.jei.api.ingredients.VanillaTypes.ITEM, itemInputs); + + // Outputs: keep role tank (if present) and ALSO the station (so R on the block opens this tab) + java.util.List outs = new java.util.ArrayList<>(2); + if (!roleTank.isEmpty()) outs.add(roleTank); + outs.add(station); + ing.setOutputs(mezz.jei.api.ingredients.VanillaTypes.ITEM, outs); + } + + + public ItemStack getRoleTankStack() { + switch (role) { + case MONO: + return AdvancedRocketryBlocks.blockFuelTank != null ? new ItemStack(AdvancedRocketryBlocks.blockFuelTank) : ItemStack.EMPTY; + case BIPROP_FUEL: + return AdvancedRocketryBlocks.blockBipropellantFuelTank != null ? new ItemStack(AdvancedRocketryBlocks.blockBipropellantFuelTank) : ItemStack.EMPTY; + case OXIDIZER: + return AdvancedRocketryBlocks.blockOxidizerFuelTank != null ? new ItemStack(AdvancedRocketryBlocks.blockOxidizerFuelTank) : ItemStack.EMPTY; + case WORKING_FLUID: + return AdvancedRocketryBlocks.blockNuclearFuelTank != null ? new ItemStack(AdvancedRocketryBlocks.blockNuclearFuelTank) : ItemStack.EMPTY; + default: + return ItemStack.EMPTY; + } + } + + // keep this helper; category uses it conditionally + public ItemStack getFilledContainer() { + ItemStack is = net.minecraftforge.fluids.FluidUtil.getFilledBucket(fluid); + return is == null ? ItemStack.EMPTY : is; + } + + static ItemStack fuelStationDisplayStack() { + return new ItemStack(AdvancedRocketryBlocks.blockFuelingStation); + } +} From a3b80b2bee6c37378aa3dd3742fd6b0dcc035b57 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 13:33:14 +0100 Subject: [PATCH 140/424] Increase max stack size of ItemPressureTank --- .../advancedRocketry/item/components/ItemPressureTank.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java b/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java index 0f727dc9c..d5e2f9815 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java +++ b/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java @@ -34,7 +34,7 @@ public class ItemPressureTank extends ItemIngredient implements IArmorComponent public ItemPressureTank(int number, int capacity) { super(number); this.capacity = capacity; - this.maxStackSize = 1; + this.maxStackSize = 8; } @Override From b15ad956ea22827bfdef0b63ebfcf74899cfb20b Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 14:49:07 +0100 Subject: [PATCH 141/424] Implement Co2ScrubberCategory for JEI integration --- .../jei/co2scrubber/Co2ScrubberCategory.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberCategory.java diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberCategory.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberCategory.java new file mode 100644 index 000000000..7d9dc22b0 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberCategory.java @@ -0,0 +1,67 @@ +package zmaster587.advancedRocketry.integration.jei.co2scrubber; + +import mezz.jei.api.IGuiHelper; +import mezz.jei.api.gui.IDrawable; +import mezz.jei.api.gui.IGuiItemStackGroup; +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.recipe.IRecipeCategory; +import mezz.jei.api.gui.IRecipeLayout; +import net.minecraft.client.Minecraft; +import net.minecraft.item.ItemStack; +import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; +import zmaster587.advancedRocketry.integration.jei.ARPlugin; + +public class Co2ScrubberCategory implements IRecipeCategory { + + private final IDrawable bg; + private final IDrawable icon; + private final IDrawable slot; + + // Compact like your fueling station: 150x40 + public Co2ScrubberCategory(IGuiHelper gui) { + this.bg = gui.createBlankDrawable(150, 40); + this.icon = gui.createDrawableIngredient(new ItemStack(AdvancedRocketryBlocks.blockCO2Scrubber)); + this.slot = gui.getSlotDrawable(); + } + + @Override public String getUid() { return ARPlugin.co2ScrubberUUID; } + @Override public String getTitle() { return new ItemStack(AdvancedRocketryBlocks.blockCO2Scrubber).getDisplayName(); } + @Override public String getModName() { return "Advanced Rocketry"; } + @Override public IDrawable getBackground(){ return bg; } + @Override public IDrawable getIcon() { return icon; } + + @Override + public void setRecipe(IRecipeLayout layout, Co2ScrubberWrapper wrapper, IIngredients ing) { + IGuiItemStackGroup items = layout.getItemStacks(); + + // Register tooltip handler first + items.addTooltipCallback((slotIndex, isInput, stack, tooltip) -> { + if (stack == null || stack.isEmpty()) return; + + if (slotIndex == 0) { + // Cartridge (left) + tooltip.add(net.minecraft.util.text.TextFormatting.YELLOW + + zmaster587.libVulpes.LibVulpes.proxy.getLocalizedString("jei.ar.scrubber.cartridge")); + } else if (slotIndex == 1) { + // Oxygen Vent ghost (right) + tooltip.add(net.minecraft.util.text.TextFormatting.YELLOW + + zmaster587.libVulpes.LibVulpes.proxy.getLocalizedString("jei.ar.scrubber.info_compact")); + } + }); + + // One input slot (cartridge), left side + items.init(0, true, 20, 11); + items.set(0, ing.getInputs(mezz.jei.api.ingredients.VanillaTypes.ITEM).get(0)); + + // Oxygen Vent ghost on the right + items.init(1, false, 120, 11); + items.set(1, new ItemStack(AdvancedRocketryBlocks.blockOxygenVent)); + } + + + @Override + public void drawExtras(Minecraft mc) { + // Draw the slot frame behind the cartridge + slot.draw(mc, 20, 11); + } +} From f74fb2e8598911390e79dec6b06ceba5d5b71c05 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 14:49:30 +0100 Subject: [PATCH 142/424] Implement Co2ScrubberRecipeHandler class --- .../co2scrubber/Co2ScrubberRecipeHandler.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberRecipeHandler.java diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberRecipeHandler.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberRecipeHandler.java new file mode 100644 index 000000000..5ebc0a039 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberRecipeHandler.java @@ -0,0 +1,28 @@ +package zmaster587.advancedRocketry.integration.jei.co2scrubber; + +import mezz.jei.api.recipe.IRecipeHandler; +import mezz.jei.api.recipe.IRecipeWrapper; +import zmaster587.advancedRocketry.integration.jei.ARPlugin; + +public class Co2ScrubberRecipeHandler implements IRecipeHandler { + + @Override + public Class getRecipeClass() { + return Co2ScrubberWrapper.class; + } + + @Override + public String getRecipeCategoryUid(Co2ScrubberWrapper recipe) { + return ARPlugin.co2ScrubberUUID; + } + + @Override + public IRecipeWrapper getRecipeWrapper(Co2ScrubberWrapper recipe) { + return recipe; + } + + @Override + public boolean isRecipeValid(Co2ScrubberWrapper recipe) { + return recipe != null && !recipe.getCartridgeStack().isEmpty(); + } +} From 14809e6ec70aefa80d05a8d19b991836512ae513 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 14:50:18 +0100 Subject: [PATCH 143/424] Add Co2ScrubberRecipeMaker class for recipe handling --- .../co2scrubber/Co2ScrubberRecipeMaker.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberRecipeMaker.java diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberRecipeMaker.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberRecipeMaker.java new file mode 100644 index 000000000..a8354d898 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberRecipeMaker.java @@ -0,0 +1,19 @@ +package zmaster587.advancedRocketry.integration.jei.co2scrubber; + +import mezz.jei.api.IJeiHelpers; +import net.minecraft.item.ItemStack; +import zmaster587.advancedRocketry.api.AdvancedRocketryItems; + +import java.util.ArrayList; +import java.util.List; + +public class Co2ScrubberRecipeMaker { + public static List getRecipes(IJeiHelpers helpers) { + List list = new ArrayList<>(); + + ItemStack cart = new ItemStack(AdvancedRocketryItems.itemCarbonScrubberCartridge, 1, net.minecraftforge.oredict.OreDictionary.WILDCARD_VALUE); + list.add(new Co2ScrubberWrapper(cart)); + + return list; + } +} From 11993721358be461429358d628cf946f01b4b222 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 14:51:01 +0100 Subject: [PATCH 144/424] Implement Co2ScrubberWrapper for JEI integration --- .../jei/co2scrubber/Co2ScrubberWrapper.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberWrapper.java diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberWrapper.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberWrapper.java new file mode 100644 index 000000000..cbddae11f --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberWrapper.java @@ -0,0 +1,34 @@ +package zmaster587.advancedRocketry.integration.jei.co2scrubber; + +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.recipe.BlankRecipeWrapper; +import net.minecraft.item.ItemStack; +import java.util.Collections; + +public class Co2ScrubberWrapper extends BlankRecipeWrapper { + private final ItemStack cartridge; + + public Co2ScrubberWrapper(ItemStack cartridge) { + this.cartridge = cartridge; + } + + @Override + public void getIngredients(IIngredients ing) { + // INPUTS: the cartridge (as a list-of-lists) + ing.setInputLists(mezz.jei.api.ingredients.VanillaTypes.ITEM, + java.util.Collections.singletonList( + java.util.Collections.singletonList(cartridge))); + + // OUTPUTS: expose BOTH blocks + the cartridge + java.util.List outs = new java.util.ArrayList<>(3); + outs.add(new net.minecraft.item.ItemStack(zmaster587.advancedRocketry.api.AdvancedRocketryBlocks.blockCO2Scrubber)); + outs.add(new net.minecraft.item.ItemStack(zmaster587.advancedRocketry.api.AdvancedRocketryBlocks.blockOxygenVent)); + outs.add(cartridge); + ing.setOutputs(mezz.jei.api.ingredients.VanillaTypes.ITEM, outs); + } + + // Used by the recipe handler's isRecipeValid + public ItemStack getCartridgeStack() { + return cartridge; + } +} From aee6916c8e05259f9d9f4fb97859f6d37f32b5ef Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 14:54:53 +0100 Subject: [PATCH 145/424] Add CO2 Scrubber integration to ARPlugin --- .../integration/jei/ARPlugin.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/ARPlugin.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/ARPlugin.java index b07be2bc2..57302621c 100644 --- a/src/main/java/zmaster587/advancedRocketry/integration/jei/ARPlugin.java +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/ARPlugin.java @@ -17,6 +17,9 @@ import zmaster587.advancedRocketry.integration.jei.chemicalReactor.ChemicalReactorCategory; import zmaster587.advancedRocketry.integration.jei.chemicalReactor.ChemicalReactorRecipeHandler; import zmaster587.advancedRocketry.integration.jei.chemicalReactor.ChemicalReactorRecipeMaker; +import zmaster587.advancedRocketry.integration.jei.co2scrubber.Co2ScrubberCategory; +import zmaster587.advancedRocketry.integration.jei.co2scrubber.Co2ScrubberRecipeHandler; +import zmaster587.advancedRocketry.integration.jei.co2scrubber.Co2ScrubberRecipeMaker; import zmaster587.advancedRocketry.integration.jei.crystallizer.CrystallizerCategory; import zmaster587.advancedRocketry.integration.jei.crystallizer.CrystallizerRecipeHandler; import zmaster587.advancedRocketry.integration.jei.crystallizer.CrystallizerRecipeMaker; @@ -71,6 +74,7 @@ public class ARPlugin implements IModPlugin { public static final String precisionLaserEngraverUUID = "zmaster587.AR.precisionlaseretcher"; public static final String satelliteBuilderUUID = "zmaster587.AR.satelliteBuilder"; public static final String fuelingStationUUID = "zmaster587.AR.fuelingStation"; + public static final String co2ScrubberUUID = "zmaster587.AR.co2scrubber"; public static IJeiHelpers jeiHelpers; //AR machines can reload recipes. We still need this for JEI to be up-to-date @@ -97,7 +101,8 @@ public void registerCategories(IRecipeCategoryRegistration registry) { new CentrifugeCategory(guiHelper), new PrecisionLaserEtcherCategory(guiHelper), new SatelliteBuilderCategory(guiHelper), - new FuelingStationCategory(guiHelper) + new FuelingStationCategory(guiHelper), + new Co2ScrubberCategory(guiHelper) ); } @@ -144,7 +149,8 @@ public Object getIngredientUnderMouse(GuiModular guiContainer, new CentrifugeRecipeHandler(), new PrecisionLaserEtcherRecipeHandler(), new SatelliteBuilderRecipeHandler(), - new FuelingStationRecipeHandler() + new FuelingStationRecipeHandler(), + new Co2ScrubberRecipeHandler() ); registry.addRecipes(RollingMachineRecipeMaker.getMachineRecipes(jeiHelpers, TileRollingMachine.class), rollingMachineUUID); @@ -160,6 +166,8 @@ public Object getIngredientUnderMouse(GuiModular guiContainer, registry.addRecipes(PrecisionLaserEtcherRecipeMaker.getMachineRecipes(jeiHelpers, TilePrecisionLaserEtcher.class), precisionLaserEngraverUUID); registry.addRecipes(SatelliteBuilderRecipeMaker.getMachineRecipes(jeiHelpers, TileSatelliteBuilder.class), satelliteBuilderUUID); registry.addRecipes(FuelingStationRecipeMaker.getMachineRecipes(jeiHelpers, TileFuelingStation.class), fuelingStationUUID); + registry.addRecipes(Co2ScrubberRecipeMaker.getRecipes(jeiHelpers), co2ScrubberUUID); + registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockRollingMachine), rollingMachineUUID); registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockLathe), latheUUID); @@ -173,7 +181,10 @@ public Object getIngredientUnderMouse(GuiModular guiContainer, registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockCentrifuge), centrifugeUUID); registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockPrecisionLaserEngraver), precisionLaserEngraverUUID); registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockSatelliteBuilder), satelliteBuilderUUID); - + + // Co2 Scrubber catalysts + registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockCO2Scrubber), co2ScrubberUUID); + registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockOxygenVent), co2ScrubberUUID); // One tab: Fueling Station + Tank-type catalysts (mono / biprop fuel / oxidizer / working fluid) registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockFuelingStation), fuelingStationUUID); From 2446992882adf48651999345e9163989be55425e Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 17:25:58 +0100 Subject: [PATCH 146/424] Enhance tooltip information for Launchpad Add tooltip information --- .../block/BlockLinkedHorizontalTexture.java | 54 ++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockLinkedHorizontalTexture.java b/src/main/java/zmaster587/advancedRocketry/block/BlockLinkedHorizontalTexture.java index 7e9153b17..71be73a13 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockLinkedHorizontalTexture.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockLinkedHorizontalTexture.java @@ -1,13 +1,25 @@ package zmaster587.advancedRocketry.block; +import java.util.List; + +import javax.annotation.Nullable; + import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.properties.PropertyEnum; import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; import net.minecraft.util.IStringSerializable; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; public class BlockLinkedHorizontalTexture extends Block { @@ -84,4 +96,44 @@ public String getName() { return suffix; } } -} \ No newline at end of file + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.launchpad")); + + final boolean shift = GuiScreen.isShiftKeyDown(); + final boolean alt = isAltDown(); + + if (alt) { + // Advanced details + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.launchpad.alt.1")); + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.launchpad.alt.2")); + } else if (shift) { + // More info + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.launchpad.shift.1")); + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.launchpad.shift.2")); + if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) + tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); + } else { + // Hints + if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) + tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_shift")); + if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) + tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); + } + } + + @SideOnly(Side.CLIENT) + private static boolean isAltDown() { + try { + // Works on Forge 1.12.x; LWJGL fallback for safety + return GuiScreen.isAltKeyDown() + || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_LMENU) + || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_RMENU); + } catch (Throwable t) { + return false; + } + } + +} From 408be66df0742d5739897f61d9a261b4c6d3eb40 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 17:27:52 +0100 Subject: [PATCH 147/424] Enhance tooltip information for BlockLandingPad Added tooltip information for the landing pad block, including advanced details and hints based on key presses. --- .../block/BlockLandingPad.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockLandingPad.java b/src/main/java/zmaster587/advancedRocketry/block/BlockLandingPad.java index 4eb73f072..170ed0bb8 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockLandingPad.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockLandingPad.java @@ -1,14 +1,25 @@ package zmaster587.advancedRocketry.block; +import java.util.List; + +import javax.annotation.Nullable; + import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.advancedRocketry.tile.station.TileLandingPad; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.inventory.GuiHandler; @@ -48,6 +59,46 @@ public boolean onBlockActivated(World world, BlockPos pos, return true; } + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.landingpad")); + + final boolean shift = GuiScreen.isShiftKeyDown(); + final boolean alt = isAltDown(); + + if (alt) { + // Advanced details + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.landingpad.alt.1")); + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.landingpad.alt.2")); + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.landingpad.alt.3")); + } else if (shift) { + // More info + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.landingpad.shift.1")); + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.landingpad.shift.2")); + if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) + tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); + } else { + // Hints + if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) + tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_shift")); + if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) + tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); + } + } + + @SideOnly(Side.CLIENT) + private static boolean isAltDown() { + try { + // Works on Forge 1.12.x; LWJGL fallback for safety + return GuiScreen.isAltKeyDown() + || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_LMENU) + || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_RMENU); + } catch (Throwable t) { + return false; + } + } + @Override public void breakBlock(World world, BlockPos pos, IBlockState state) { TileEntity tile = world.getTileEntity(pos); From a8f1a451cbaa4e72d9ed250aab4f827e46bbf91e Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 17:32:58 +0100 Subject: [PATCH 148/424] Enhance tooltip information for BlockNuclearCore Added tooltip information for the Nuclear Core block, including advanced details and hints based on key presses. --- .../block/BlockNuclearCore.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearCore.java b/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearCore.java index 7cdc3d25b..a1359d23b 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearCore.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearCore.java @@ -2,11 +2,21 @@ import net.minecraft.block.Block; import net.minecraft.block.material.Material; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.IRocketNuclearCore; +import javax.annotation.Nullable; +import java.util.List; + public class BlockNuclearCore extends Block implements IRocketNuclearCore { public BlockNuclearCore(Material mat) { @@ -18,5 +28,42 @@ public int getMaxThrust(World world, BlockPos pos) { return (int) (1000 * ARConfiguration.getCurrentConfig().nuclearCoreThrustRatio); } + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearcore")); + + final boolean shift = GuiScreen.isShiftKeyDown(); + final boolean alt = isAltDown(); + if (alt) { + // Advanced details + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearcore.alt.1")); + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearcore.alt.2")); + } else if (shift) { + // More info + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearcore.shift.1")); + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearcore.shift.2")); + if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) + tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); + } else { + // Hints + if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) + tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_shift")); + if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) + tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); + } + } + + @SideOnly(Side.CLIENT) + private static boolean isAltDown() { + try { + // Works on Forge 1.12.x; LWJGL fallback for safety + return GuiScreen.isAltKeyDown() + || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_LMENU) + || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_RMENU); + } catch (Throwable t) { + return false; + } + } } From 55f15be55c79d59dc3b287b71b4f3b2c908a4568 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 17:39:40 +0100 Subject: [PATCH 149/424] Enhance tooltip information for BlockRocketMotor Added tooltip information for the BlockRocketMotor class, providing advanced details based on key presses. --- .../block/BlockRocketMotor.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockRocketMotor.java b/src/main/java/zmaster587/advancedRocketry/block/BlockRocketMotor.java index 088ac702e..7ae489ab2 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockRocketMotor.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockRocketMotor.java @@ -2,6 +2,9 @@ import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; @@ -11,14 +14,19 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.IRocketEngine; import zmaster587.advancedRocketry.tile.TileBrokenPart; import zmaster587.advancedRocketry.util.IBrokenPartBlock; import zmaster587.libVulpes.block.BlockFullyRotatable; +import java.util.List; + import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -137,4 +145,42 @@ public ItemStack getDropItem(final IBlockState state, final World world, final @ } return drop; } + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.monopropmotor")); + + final boolean shift = GuiScreen.isShiftKeyDown(); + final boolean alt = isAltDown(); + + if (alt) { + // Advanced details + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.monopropmotor.alt.1")); + } else if (shift) { + // More info + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.monopropmotor.shift.1")); + if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) + tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); + } else { + // Hints + if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) + tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_shift")); + if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) + tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); + } + } + + @SideOnly(Side.CLIENT) + private static boolean isAltDown() { + try { + // Works on Forge 1.12.x; LWJGL fallback for safety + return GuiScreen.isAltKeyDown() + || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_LMENU) + || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_RMENU); + } catch (Throwable t) { + return false; + } + } + } From 04128cb0ab2427f2922ab6dbd47cefa7c7a293f0 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 17:41:37 +0100 Subject: [PATCH 150/424] Enhance tooltip details for rocket motor block Add tooltip information for BlockBipropellantRocketMotor --- .../block/BlockBipropellantRocketMotor.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java b/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java index d847191fd..66c6efe5c 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java @@ -2,6 +2,9 @@ import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; @@ -11,14 +14,19 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.IRocketEngine; import zmaster587.advancedRocketry.tile.TileBrokenPart; import zmaster587.advancedRocketry.util.IBrokenPartBlock; import zmaster587.libVulpes.block.BlockFullyRotatable; +import java.util.List; + import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -119,6 +127,44 @@ public TileEntity createTileEntity(final World worldIn, final IBlockState state) return new TileBrokenPart(10, (float) ARConfiguration.getCurrentConfig().increaseWearIntensityProb); } + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.bipropmotor")); + + final boolean shift = GuiScreen.isShiftKeyDown(); + final boolean alt = isAltDown(); + + if (alt) { + // Advanced details + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.bipropmotor.alt.1")); + } else if (shift) { + // More info + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.bipropmotor.shift.1")); + if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) + tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); + } else { + // Hints + if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) + tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_shift")); + if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) + tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); + } + } + + @SideOnly(Side.CLIENT) + private static boolean isAltDown() { + try { + // Works on Forge 1.12.x; LWJGL fallback for safety + return GuiScreen.isAltKeyDown() + || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_LMENU) + || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_RMENU); + } catch (Throwable t) { + return false; + } + } + @Override public ItemStack getDropItem(final IBlockState state, final World world, final @Nullable TileBrokenPart te) { ItemStack drop = new ItemStack(this.getItemDropped(state, world.rand, 0)); From b3f51ce0abdfc29fe9bd9b146d3e10c66686c368 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 17:41:59 +0100 Subject: [PATCH 151/424] Enhance tooltip for BlockNuclearRocketMotor Added tooltip information for the nuclear rocket motor, including advanced details and hints based on key presses. --- .../block/BlockNuclearRocketMotor.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java b/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java index 0658b8725..acfd046aa 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java @@ -2,15 +2,24 @@ import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.IRocketNuclearCore; import zmaster587.advancedRocketry.tile.TileBrokenPart; +import java.util.List; + import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -51,4 +60,42 @@ public int getFuelConsumptionRate(World world, int x, int y, int z) { public TileEntity createTileEntity(final World worldIn, final IBlockState state) { return new TileBrokenPart(10, 4 * (float) ARConfiguration.getCurrentConfig().increaseWearIntensityProb); } + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearmotor")); + + final boolean shift = GuiScreen.isShiftKeyDown(); + final boolean alt = isAltDown(); + + if (alt) { + // Advanced details + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearmotor.alt.1")); + } else if (shift) { + // More info + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearmotor.shift.1")); + tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearmotor.shift.2")); + if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) + tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); + } else { + // Hints + if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) + tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_shift")); + if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) + tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); + } + } + + @SideOnly(Side.CLIENT) + private static boolean isAltDown() { + try { + // Works on Forge 1.12.x; LWJGL fallback for safety + return GuiScreen.isAltKeyDown() + || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_LMENU) + || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_RMENU); + } catch (Throwable t) { + return false; + } + } } + From f09271c988cab55d8c9eacb90c93452bbb032547 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 18:45:28 +0100 Subject: [PATCH 152/424] Update tooltip formatting for nuclear rocket motor --- .../advancedRocketry/block/BlockNuclearRocketMotor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java b/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java index acfd046aa..830433b5f 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java @@ -70,7 +70,7 @@ public void addInformation(ItemStack stack, @Nullable World world, List if (alt) { // Advanced details - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearmotor.alt.1")); + tooltip.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.nuclearmotor.alt.1")); } else if (shift) { // More info tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearmotor.shift.1")); From 08b3d61593f80c30a150e595bf833de0ea6d8094 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 18:45:43 +0100 Subject: [PATCH 153/424] Change tooltip text color for nuclear core details --- .../zmaster587/advancedRocketry/block/BlockNuclearCore.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearCore.java b/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearCore.java index a1359d23b..0cf140dc6 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearCore.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearCore.java @@ -38,8 +38,8 @@ public void addInformation(ItemStack stack, @Nullable World world, List if (alt) { // Advanced details - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearcore.alt.1")); - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearcore.alt.2")); + tooltip.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.nuclearcore.alt.1")); + tooltip.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.nuclearcore.alt.2")); } else if (shift) { // More info tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearcore.shift.1")); From e96f6503a30c3b1f85b2e0a73e4c68369d2f2548 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 18:46:11 +0100 Subject: [PATCH 154/424] Change tooltip color for alt key details --- .../advancedRocketry/block/BlockBipropellantRocketMotor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java b/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java index 66c6efe5c..a63f09c1c 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java @@ -138,7 +138,7 @@ public void addInformation(ItemStack stack, @Nullable World world, List if (alt) { // Advanced details - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.bipropmotor.alt.1")); + tooltip.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.bipropmotor.alt.1")); } else if (shift) { // More info tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.bipropmotor.shift.1")); From 2b7ef2943c3faf93a61135cbc66470301df293c3 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 18:46:41 +0100 Subject: [PATCH 155/424] Change tooltip formatting for alt key details --- .../zmaster587/advancedRocketry/block/BlockRocketMotor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockRocketMotor.java b/src/main/java/zmaster587/advancedRocketry/block/BlockRocketMotor.java index 7ae489ab2..567701c5c 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockRocketMotor.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockRocketMotor.java @@ -156,7 +156,7 @@ public void addInformation(ItemStack stack, @Nullable World world, List if (alt) { // Advanced details - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.monopropmotor.alt.1")); + tooltip.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.monopropmotor.alt.1")); } else if (shift) { // More info tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.monopropmotor.shift.1")); From f64ddaca04c8c1a69458e1891dd94b6856846364 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 18:48:10 +0100 Subject: [PATCH 156/424] Change tooltip text color for landing pad details --- .../zmaster587/advancedRocketry/block/BlockLandingPad.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockLandingPad.java b/src/main/java/zmaster587/advancedRocketry/block/BlockLandingPad.java index 170ed0bb8..b738003fb 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockLandingPad.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockLandingPad.java @@ -69,9 +69,9 @@ public void addInformation(ItemStack stack, @Nullable World world, List if (alt) { // Advanced details - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.landingpad.alt.1")); - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.landingpad.alt.2")); - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.landingpad.alt.3")); + tooltip.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.landingpad.alt.1")); + tooltip.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.landingpad.alt.2")); + tooltip.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.landingpad.alt.3")); } else if (shift) { // More info tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.landingpad.shift.1")); From a0d7e605a185467a16a319f9b8a33595eea52d00 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 18:48:43 +0100 Subject: [PATCH 157/424] Change tooltip text color for alt key Updated tooltip text color for advanced details. --- .../advancedRocketry/block/BlockLinkedHorizontalTexture.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockLinkedHorizontalTexture.java b/src/main/java/zmaster587/advancedRocketry/block/BlockLinkedHorizontalTexture.java index 71be73a13..5c5e574ba 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockLinkedHorizontalTexture.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockLinkedHorizontalTexture.java @@ -107,8 +107,8 @@ public void addInformation(ItemStack stack, @Nullable World world, List if (alt) { // Advanced details - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.launchpad.alt.1")); - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.launchpad.alt.2")); + tooltip.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.launchpad.alt.1")); + tooltip.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.launchpad.alt.2")); } else if (shift) { // More info tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.launchpad.shift.1")); From 10588e9dc533994566dcc2e9d91da5479f765f12 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 20:00:33 +0100 Subject: [PATCH 158/424] Remove tooltip callback from Co2ScrubberCategory Removed tooltip handler for item stacks in Co2ScrubberCategory. --- .../jei/co2scrubber/Co2ScrubberCategory.java | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberCategory.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberCategory.java index 7d9dc22b0..6aac19c5c 100644 --- a/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberCategory.java +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberCategory.java @@ -34,21 +34,6 @@ public Co2ScrubberCategory(IGuiHelper gui) { public void setRecipe(IRecipeLayout layout, Co2ScrubberWrapper wrapper, IIngredients ing) { IGuiItemStackGroup items = layout.getItemStacks(); - // Register tooltip handler first - items.addTooltipCallback((slotIndex, isInput, stack, tooltip) -> { - if (stack == null || stack.isEmpty()) return; - - if (slotIndex == 0) { - // Cartridge (left) - tooltip.add(net.minecraft.util.text.TextFormatting.YELLOW + - zmaster587.libVulpes.LibVulpes.proxy.getLocalizedString("jei.ar.scrubber.cartridge")); - } else if (slotIndex == 1) { - // Oxygen Vent ghost (right) - tooltip.add(net.minecraft.util.text.TextFormatting.YELLOW + - zmaster587.libVulpes.LibVulpes.proxy.getLocalizedString("jei.ar.scrubber.info_compact")); - } - }); - // One input slot (cartridge), left side items.init(0, true, 20, 11); items.set(0, ing.getInputs(mezz.jei.api.ingredients.VanillaTypes.ITEM).get(0)); From 8847357c5544645f07b19628f3f631c7a01d29a5 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 20:34:41 +0100 Subject: [PATCH 159/424] Implement tooltip for ItemAtmosphereAnalyzer Added tooltip information display for ItemAtmosphereAnalyzer. --- .../advancedRocketry/item/ItemAtmosphereAnalzer.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemAtmosphereAnalzer.java b/src/main/java/zmaster587/advancedRocketry/item/ItemAtmosphereAnalzer.java index e02ffccf4..eec4f7ef9 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemAtmosphereAnalzer.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemAtmosphereAnalzer.java @@ -6,6 +6,7 @@ import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.EntityEquipmentSlot; @@ -26,6 +27,7 @@ import org.lwjgl.opengl.GL11; import zmaster587.advancedRocketry.atmosphere.AtmosphereHandler; import zmaster587.advancedRocketry.atmosphere.AtmosphereType; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.advancedRocketry.event.RocketEventHandler; import zmaster587.advancedRocketry.inventory.TextureResources; @@ -107,6 +109,14 @@ public boolean isAllowedInSlot(@Nonnull ItemStack componentStack, EntityEquipmen return targetSlot == EntityEquipmentSlot.HEAD; } + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.atmanalyzer", insertAt); + } + + @Override @SideOnly(Side.CLIENT) public void renderScreen(@Nonnull ItemStack componentStack, List modules, From d77c430c749141e81c2eee869d3d934c9f88396e Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 21:39:40 +0100 Subject: [PATCH 160/424] Implement tooltip for BlockTileRedstoneEmitter Added tooltip information for the Redstone Emitter block. --- .../block/BlockTileRedstoneEmitter.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockTileRedstoneEmitter.java b/src/main/java/zmaster587/advancedRocketry/block/BlockTileRedstoneEmitter.java index b59042f81..8d0604a0d 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockTileRedstoneEmitter.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockTileRedstoneEmitter.java @@ -1,13 +1,23 @@ package zmaster587.advancedRocketry.block; +import javax.annotation.Nullable; + import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.libVulpes.block.BlockTile; +import javax.annotation.Nullable; +import java.util.List; + // Fueling Station block public class BlockTileRedstoneEmitter extends BlockTile { @@ -25,6 +35,13 @@ public int getStrongPower(IBlockState state, IBlockAccess world, BlockPos pos, E return getWeakPower(state, world, pos, side); } + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.fuelingstation", insertAt); + } + @Override public boolean canProvidePower(IBlockState state) { return true; From 244a7292ff920fbc49dec25fb3b19af3314bae3d Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 22:18:20 +0100 Subject: [PATCH 161/424] Implement tooltip for ItemBeaconFinder Add tooltip information for ItemBeaconFinder. --- .../advancedRocketry/item/ItemBeaconFinder.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemBeaconFinder.java b/src/main/java/zmaster587/advancedRocketry/item/ItemBeaconFinder.java index 3c385c1ad..27e263ec9 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemBeaconFinder.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemBeaconFinder.java @@ -6,6 +6,7 @@ import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.EntityEquipmentSlot; @@ -19,6 +20,8 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import org.lwjgl.opengl.GL11; + +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.libVulpes.api.IArmorComponent; import zmaster587.libVulpes.client.ResourceIcon; @@ -27,6 +30,8 @@ import zmaster587.libVulpes.util.HashedBlockPosition; import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import java.util.List; public class ItemBeaconFinder extends Item implements IArmorComponent { @@ -95,6 +100,13 @@ public void renderScreen(@Nonnull ItemStack componentStack, List modu } } + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.beaconfinder", insertAt); + } + @Override public ResourceIcon getComponentIcon(@Nonnull ItemStack armorStack) { return null; From 479636fd9d43e649de7ff9a6f625605ee9021895 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 22:37:08 +0100 Subject: [PATCH 162/424] Refactor BlockPressurizedFluidTank methods for clarity --- .../advancedRocketry/block/BlockPressurizedFluidTank.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockPressurizedFluidTank.java b/src/main/java/zmaster587/advancedRocketry/block/BlockPressurizedFluidTank.java index ed15835d6..53cc745a2 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockPressurizedFluidTank.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockPressurizedFluidTank.java @@ -95,7 +95,7 @@ public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, En @Override public void onBlockAdded(World world, BlockPos pos, IBlockState state) { super.onBlockAdded(world, pos, state); - if (world.isRemote) return; // <- add this + if (world.isRemote) return; TileEntity teAbove = world.getTileEntity(pos.up()); if (teAbove instanceof TileFluidTank) { ((TileFluidTank) teAbove).onAdjacentBlockUpdated(EnumFacing.DOWN); @@ -122,7 +122,6 @@ public List getDrops(IBlockAccess world, BlockPos pos, IBlockState st if (te instanceof TileFluidTank) { net.minecraftforge.fluids.FluidStack own = ((TileFluidTank) te).getOwnContentsCopy(); - // 1.12: FluidStack has no isEmpty(); guard on null and amount > 0 if (own != null && own.amount > 0) { ((ItemBlockFluidTank) out.getItem()).fill(out, own); } @@ -138,7 +137,7 @@ public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, Ent if (!world.isRemote) { TileEntity te = world.getTileEntity(pos); if (te instanceof TileFluidTank) { - ((TileFluidTank) te).setRemoving(true); // <- you’ll add this setter in the tile + ((TileFluidTank) te).setRemoving(true); } } // Let vanilla handle removal; we’ll control drops in harvestBlock @@ -168,12 +167,10 @@ public void harvestBlock(World world, EntityPlayer player, BlockPos pos, IBlockS } } - // Spawn our single, correct drop EntityItem ei = new EntityItem(world, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, drop); world.spawnEntity(ei); - // Finally remove the block (this will call breakBlock and clear TE) world.setBlockToAir(pos); } From 1f6b5f61620a6132343119308facce2e1b5a15dd Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 22:38:40 +0100 Subject: [PATCH 163/424] Fix guard condition for fluid draining --- .../zmaster587/advancedRocketry/item/ItemBlockFluidTank.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java b/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java index f034a86ad..ec57cc084 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java @@ -72,7 +72,7 @@ public boolean placeBlockAt(@Nonnull ItemStack stack, EntityPlayer player, World ItemStack one = stack.copy(); one.setCount(1); FluidStack drained = drain(one, Integer.MAX_VALUE); - if (drained != null && drained.amount > 0) { // <- guard + if (drained != null && drained.amount > 0) { handler.fill(drained, true); } } From be3489dd9767f9fd5432e681a90e33c4eda92c0e Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 23:21:18 +0100 Subject: [PATCH 164/424] Refactor addInformation method for clarity --- .../item/components/ItemPressureTank.java | 49 +++++++++++++++---- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java b/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java index d5e2f9815..96d87b60f 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java +++ b/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java @@ -1,7 +1,9 @@ package zmaster587.advancedRocketry.item.components; import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.client.resources.I18n; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.EntityEquipmentSlot; @@ -9,12 +11,14 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.DamageSource; +import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.common.capabilities.ICapabilityProvider; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import org.lwjgl.input.Keyboard; import zmaster587.advancedRocketry.capability.TankCapabilityItemStack; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.api.IArmorComponent; @@ -23,6 +27,8 @@ import zmaster587.libVulpes.util.FluidUtils; import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import java.util.List; public class ItemPressureTank extends ItemIngredient implements IArmorComponent { @@ -36,24 +42,45 @@ public ItemPressureTank(int number, int capacity) { this.capacity = capacity; this.maxStackSize = 8; } - + + @SideOnly(Side.CLIENT) @Override - public void addInformation(@Nonnull ItemStack stack, World player, List list, ITooltipFlag bool) { - super.addInformation(stack, player, list, bool); - - FluidStack fluidStack = FluidUtils.getFluidForItem(stack); + public void addInformation(@Nonnull ItemStack stack, @Nullable World world, + List list, ITooltipFlag flag) { + super.addInformation(stack, world, list, flag); + + final int capMb = Math.max(0, getCapacity(stack)); + final net.minecraftforge.fluids.FluidStack fs = zmaster587.libVulpes.util.FluidUtils.getFluidForItem(stack); + + final String fluidName = (fs != null && fs.getFluid() != null) ? fs.getLocalizedName() : "Empty"; + final int amount = (fs != null) ? fs.amount : 0; + + // Match main tank style + list.add("Fluid: " + fluidName); + list.add("Level: " + amount + "/" + capMb + " mB"); + + // SHIFT block + if (GuiScreen.isShiftKeyDown()) { + list.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.pressuretank.shift.1")); + list.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.pressuretank.shift.2")); + } else if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) { + list.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + + I18n.format("tooltip.advancedrocketry.hold_shift")); + } - if (fluidStack == null) { - list.add(LibVulpes.proxy.getLocalizedString("msg.empty")); - } else { - list.add(fluidStack.getLocalizedName() + ": " + fluidStack.amount); + // ALT block (independent of SHIFT) + if (Keyboard.isKeyDown(Keyboard.KEY_LMENU) || Keyboard.isKeyDown(Keyboard.KEY_RMENU)) { + list.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.pressuretank.alt.1")); + list.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.pressuretank.alt.2")); + } else if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) { + list.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + + I18n.format("tooltip.advancedrocketry.hold_alt")); } } @Override public void onTick(World world, EntityPlayer player, @Nonnull ItemStack armorStack, IInventory inv, @Nonnull ItemStack componentStack) { - } @Override @@ -93,6 +120,8 @@ public void renderScreen(@Nonnull ItemStack componentStack, List modu } + + @Override public ICapabilityProvider initCapabilities(@Nonnull ItemStack stack, NBTTagCompound nbt) { return new TankCapabilityItemStack(stack, getCapacity(stack)); From 0890ada6a212a5ed7eaccbae1cb1c7d5965a58de Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 8 Nov 2025 23:21:43 +0100 Subject: [PATCH 165/424] Enhance fluid tank item tooltips with localization Added localization support and tooltip enhancements for the fluid tank item. --- .../item/ItemBlockFluidTank.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java b/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java index ec57cc084..40600e989 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java @@ -3,6 +3,7 @@ import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.resources.I18n; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemBlock; @@ -17,6 +18,9 @@ import net.minecraftforge.fluids.FluidTank; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.lwjgl.input.Keyboard; import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.tile.TileFluidTank; @@ -26,6 +30,9 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; + +import org.lwjgl.input.Keyboard; + import java.util.List; public class ItemBlockFluidTank extends ItemBlock { @@ -56,6 +63,15 @@ public void addInformation(@Nonnull ItemStack stack, @Nullable World world, List list.add("Fluid: " + fluidName); list.add("Level: " + amount + "/" + capMb + " mB"); + + // --- SHIFT for more info (adds two short lines) --- + if (GuiScreen.isShiftKeyDown()) { + list.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.fluidtank.shift.1")); + list.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.fluidtank.shift.2")); + } else if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) { + list.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + + I18n.format("tooltip.advancedrocketry.hold_shift")); + } } @Override From 223b0da54ef556e547efe690e0f650b8b591e9bf Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 9 Nov 2025 00:04:17 +0100 Subject: [PATCH 166/424] Implement tooltip for BlockIntake class Added tooltip information for BlockIntake. --- .../advancedRocketry/block/BlockIntake.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockIntake.java b/src/main/java/zmaster587/advancedRocketry/block/BlockIntake.java index 33a7260fe..652466352 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockIntake.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockIntake.java @@ -1,15 +1,32 @@ package zmaster587.advancedRocketry.block; +import java.util.List; + +import javax.annotation.Nullable; + import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.advancedRocketry.api.IIntake; +import zmaster587.advancedRocketry.client.TooltipInjector; public class BlockIntake extends Block implements IIntake { public BlockIntake(Material material) { super(material); } + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.intake", insertAt); + } @Override public int getIntakeAmt(IBlockState state) { From 6be0bb1037bb8e1bf80f76a415cb372cda6c41b0 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 9 Nov 2025 00:04:37 +0100 Subject: [PATCH 167/424] Implement tooltip for BlockMiningDrill Added tooltip information for BlockMiningDrill. --- .../advancedRocketry/block/BlockMiningDrill.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockMiningDrill.java b/src/main/java/zmaster587/advancedRocketry/block/BlockMiningDrill.java index 432bf6dac..db5141062 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockMiningDrill.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockMiningDrill.java @@ -1,10 +1,19 @@ package zmaster587.advancedRocketry.block; +import java.util.List; + +import javax.annotation.Nullable; + import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.advancedRocketry.api.IMiningDrill; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.libVulpes.block.BlockFullyRotatable; public class BlockMiningDrill extends BlockFullyRotatable implements IMiningDrill { @@ -24,6 +33,13 @@ public float getMiningSpeed(World world, BlockPos pos) { return world.isAirBlock(pos.add(0, 1, 0)) && world.isAirBlock(pos.add(0, 2, 0)) ? 0.02f : 0.01f; } + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.drill", insertAt); + } + @Override public int powerConsumption() { return 0; From 6abe8a1841b6ff33163ab2fc36836b17517a598c Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 9 Nov 2025 00:54:45 +0100 Subject: [PATCH 168/424] Implement tooltip for BlockLens class Added tooltip information for BlockLens in the client. --- .../advancedRocketry/block/BlockLens.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockLens.java b/src/main/java/zmaster587/advancedRocketry/block/BlockLens.java index 6807ad386..4e71391ad 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockLens.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockLens.java @@ -1,8 +1,18 @@ package zmaster587.advancedRocketry.block; +import java.util.List; + +import javax.annotation.Nullable; + import net.minecraft.block.BlockGlass; import net.minecraft.block.SoundType; import net.minecraft.block.material.Material; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import zmaster587.advancedRocketry.client.TooltipInjector; /** * Yes, this class may seem useless, but setSoundType can't be run in the registry, only by a subclass of Block. @@ -12,4 +22,11 @@ public BlockLens() { super(Material.GLASS, true); setSoundType(SoundType.GLASS); } + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.lens", insertAt); + } } From 64632bc1fefd0cb62644efa9b2ecd7686628b600 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 9 Nov 2025 00:55:05 +0100 Subject: [PATCH 169/424] Implement tooltip for BlockTransciever Added tooltip information for BlockTransciever. --- .../advancedRocketry/block/BlockTransciever.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java b/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java index a83b44248..9dd359601 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java @@ -4,6 +4,7 @@ import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; @@ -18,6 +19,14 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.libVulpes.block.BlockTile; +import zmaster587.advancedRocketry.client.TooltipInjector; + +import javax.annotation.Nullable; +import java.util.List; + + + + public class BlockTransciever extends BlockTile { @@ -138,6 +147,13 @@ public boolean rotateBlock(World world, BlockPos pos, EnumFacing axis) { return false; } + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.transciever", insertAt); + } + public static EnumFacing getFront(IBlockState state) { if (state == null || !state.getPropertyKeys().contains(FACING)) return EnumFacing.NORTH; return state.getValue(FACING); From b27ad63d2427debdd7958e442efb6a3c63c20ac0 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 9 Nov 2025 00:55:24 +0100 Subject: [PATCH 170/424] Implement tooltip for BlockSeat item Added tooltip information for BlockSeat. --- .../advancedRocketry/block/BlockSeat.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockSeat.java b/src/main/java/zmaster587/advancedRocketry/block/BlockSeat.java index ea2676456..0e3a63004 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockSeat.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockSeat.java @@ -3,8 +3,10 @@ import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; import net.minecraft.util.BlockRenderLayer; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; @@ -13,6 +15,9 @@ import net.minecraft.world.Explosion; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.advancedRocketry.entity.EntityDummy; import javax.annotation.Nonnull; @@ -107,4 +112,12 @@ public boolean onBlockActivated(World world, BlockPos pos, return true; } + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.seat", insertAt); + } + } From 6bde1836324f2817cd9bba94d6d7ee5c74830925 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 9 Nov 2025 01:24:37 +0100 Subject: [PATCH 171/424] Adjust panning container dimensions in TileAtmosphereDetector fixes GUI overlapping hotbar.... --- .../tile/atmosphere/TileAtmosphereDetector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileAtmosphereDetector.java b/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileAtmosphereDetector.java index 169933db3..a18de9642 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileAtmosphereDetector.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileAtmosphereDetector.java @@ -80,7 +80,7 @@ public List getModules(int id, EntityPlayer player) { i++; } - ModuleContainerPan panningContainer = new ModuleContainerPan(5, 20, btns, new LinkedList<>(), zmaster587.libVulpes.inventory.TextureResources.starryBG, 165, 120, 0, 500); + ModuleContainerPan panningContainer = new ModuleContainerPan(5, 20, btns, new LinkedList<>(), zmaster587.libVulpes.inventory.TextureResources.starryBG, 160, 100, 0, 500); modules.add(panningContainer); return modules; } From a251eb93bb6c3172d47ccbc2286e897584744597 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 9 Nov 2025 01:25:13 +0100 Subject: [PATCH 172/424] Implement tooltip for Atmospheredetector Implement tooltip for Atmospheredetector --- .../block/BlockRedstoneEmitter.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockRedstoneEmitter.java b/src/main/java/zmaster587/advancedRocketry/block/BlockRedstoneEmitter.java index 99720b44b..94131b83a 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockRedstoneEmitter.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockRedstoneEmitter.java @@ -5,20 +5,28 @@ import net.minecraft.block.properties.PropertyBool; import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.advancedRocketry.tile.atmosphere.TileAtmosphereDetector; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.inventory.GuiHandler; +import java.util.List; + import javax.annotation.Nonnull; +import javax.annotation.Nullable; import javax.annotation.ParametersAreNullableByDefault; - +// Atmosphere Detector that emits redstone signal when a specific atmosphere is detected public class BlockRedstoneEmitter extends Block { public static final PropertyBool POWERED = PropertyBool.create("powered"); @@ -86,6 +94,13 @@ public int getWeakPower(IBlockState blockState, IBlockAccess blockAccess, return blockState.getValue(POWERED) ? 15 : 0; } + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.atmosphereDetector", insertAt); + } + @Override public boolean canProvidePower(IBlockState state) { return true; From d6f8edd9f619d3603ec69f781c66883670f7127c Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 9 Nov 2025 01:57:14 +0100 Subject: [PATCH 173/424] Add tooltip information to BlockSuitWorkstation --- .../block/BlockSuitWorkstation.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockSuitWorkstation.java b/src/main/java/zmaster587/advancedRocketry/block/BlockSuitWorkstation.java index f51998463..84cca8f0e 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockSuitWorkstation.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockSuitWorkstation.java @@ -1,12 +1,20 @@ package zmaster587.advancedRocketry.block; +import java.util.List; + +import javax.annotation.Nullable; + import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.item.EntityItem; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.libVulpes.block.BlockTile; public class BlockSuitWorkstation extends BlockTile { @@ -54,4 +62,12 @@ public void breakBlock(World world, BlockPos pos, IBlockState state) { world.removeTileEntity(pos); } + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.suitworkingstation", insertAt); + } + } From 8395506c8ef8d0aebc9744902525b03e2695b1c4 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 9 Nov 2025 03:40:59 +0100 Subject: [PATCH 174/424] Implement tooltip for BlockStationModuleDockingPort Added tooltip information for the docking port block. --- .../block/BlockStationModuleDockingPort.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockStationModuleDockingPort.java b/src/main/java/zmaster587/advancedRocketry/block/BlockStationModuleDockingPort.java index 7cec3efe0..168a9d20e 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockStationModuleDockingPort.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockStationModuleDockingPort.java @@ -2,6 +2,7 @@ import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; @@ -10,13 +11,19 @@ import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.advancedRocketry.tile.station.TileDockingPort; import zmaster587.advancedRocketry.tile.station.TileLandingPad; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.block.BlockFullyRotatable; import zmaster587.libVulpes.inventory.GuiHandler; +import java.util.List; + import javax.annotation.Nonnull; +import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNullableByDefault; @@ -56,6 +63,13 @@ public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, } } + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.dockingport", insertAt); + } + @Override @ParametersAreNonnullByDefault public void breakBlock(World world, BlockPos pos, IBlockState state) { From 3aaee158baf8f8c05c753ba62501fa964d4d6735 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 9 Nov 2025 03:55:40 +0100 Subject: [PATCH 175/424] Implement tooltip for BlockSeal item Add tooltip information for BlockSeal in client-side. --- .../advancedRocketry/block/BlockSeal.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockSeal.java b/src/main/java/zmaster587/advancedRocketry/block/BlockSeal.java index 894c1028a..f19828940 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockSeal.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockSeal.java @@ -3,13 +3,18 @@ import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.advancedRocketry.api.AreaBlob; import zmaster587.advancedRocketry.api.util.IBlobHandler; import zmaster587.advancedRocketry.atmosphere.AtmosphereHandler; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.advancedRocketry.tile.atmosphere.TileSeal; import zmaster587.libVulpes.util.HashedBlockPosition; @@ -18,6 +23,7 @@ import javax.annotation.ParametersAreNonnullByDefault; import java.util.HashMap; import java.util.LinkedList; +import java.util.List; public class BlockSeal extends Block { @@ -196,4 +202,12 @@ public int getTraceDistance() { return -1; } } + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.pipeseal", insertAt); + } + } From d812a4195602262a3522dd57bef38306e5e0770e Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 9 Nov 2025 04:32:32 +0100 Subject: [PATCH 176/424] Implement tooltip for BlockTileTerraformer Add tooltip information for BlockTileTerraformer. --- .../block/BlockTileTerraformer.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockTileTerraformer.java b/src/main/java/zmaster587/advancedRocketry/block/BlockTileTerraformer.java index 824464b51..55f038c9a 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockTileTerraformer.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockTileTerraformer.java @@ -8,6 +8,7 @@ import net.minecraft.block.properties.PropertyBool; import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; @@ -21,8 +22,12 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.IBlockAccess; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + import org.lwjgl.Sys; import scala.tools.nsc.doc.base.comment.EntityLink; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.advancedRocketry.dimension.DimensionProperties; import zmaster587.advancedRocketry.tile.satellite.TileTerraformingTerminal; @@ -31,7 +36,10 @@ import zmaster587.libVulpes.block.RotatableBlock; import zmaster587.libVulpes.util.IAdjBlockUpdate; +import java.util.List; + import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class BlockTileTerraformer extends RotatableBlock { protected Class tileClass; @@ -163,4 +171,11 @@ public void breakBlock(World world, BlockPos pos, IBlockState state) { super.breakBlock(world, pos, state); } + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.terraformer", insertAt); + } + } From 1f204bde89d2115a1b05bacaffc3e5a478ac73f6 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 9 Nov 2025 05:18:32 +0100 Subject: [PATCH 177/424] Add tooltip information to BlockWarpController --- .../block/BlockWarpController.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockWarpController.java b/src/main/java/zmaster587/advancedRocketry/block/BlockWarpController.java index 6d02996fb..227058aa7 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockWarpController.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockWarpController.java @@ -1,17 +1,24 @@ package zmaster587.advancedRocketry.block; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.EntityLivingBase; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.advancedRocketry.api.stations.ISpaceObject; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.advancedRocketry.stations.SpaceObjectManager; import zmaster587.advancedRocketry.stations.SpaceStationObject; import zmaster587.libVulpes.block.BlockTile; +import java.util.List; + import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class BlockWarpController extends BlockTile { @@ -30,4 +37,12 @@ public void onBlockPlacedBy(World world, BlockPos pos, IBlockState state, ((SpaceStationObject) spaceObject).setForwardDirection(getFront(state).getOpposite()); } } + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.warpcontroller", insertAt); + } + } From 620a003d3e424d92591cba513f6d75b5f3e633da Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 9 Nov 2025 12:48:15 +0100 Subject: [PATCH 178/424] Implement tooltip for ItemJetpack Added tooltip information for the ItemJetpack. --- .../item/components/ItemJetpack.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/item/components/ItemJetpack.java b/src/main/java/zmaster587/advancedRocketry/item/components/ItemJetpack.java index fc219584b..1e41e822d 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/components/ItemJetpack.java +++ b/src/main/java/zmaster587/advancedRocketry/item/components/ItemJetpack.java @@ -2,6 +2,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.EntityEquipmentSlot; @@ -22,6 +23,7 @@ import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.AdvancedRocketryFluids; import zmaster587.advancedRocketry.api.AdvancedRocketryItems; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.advancedRocketry.event.RocketEventHandler; import zmaster587.advancedRocketry.inventory.TextureResources; import zmaster587.libVulpes.api.IArmorComponent; @@ -32,6 +34,8 @@ import zmaster587.libVulpes.util.InputSyncHandler; import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import java.util.List; public class ItemJetpack extends Item implements IArmorComponent, IJetPack { @@ -345,4 +349,12 @@ private enum MODES { NORMAL, HOVER } + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.jetpack", insertAt); + } + } From 34b0975d3279ea228c0b2fa138c5b76f62792e42 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 9 Nov 2025 14:16:19 +0100 Subject: [PATCH 179/424] Implement tooltip for ItemSealDetector Added tooltip information for ItemSealDetector. --- .../advancedRocketry/item/ItemSealDetector.java | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemSealDetector.java b/src/main/java/zmaster587/advancedRocketry/item/ItemSealDetector.java index b01a05aa2..cace938ce 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemSealDetector.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemSealDetector.java @@ -1,7 +1,12 @@ package zmaster587.advancedRocketry.item; +import java.util.List; + +import javax.annotation.Nullable; + import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; @@ -13,6 +18,9 @@ import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; import net.minecraftforge.fluids.IFluidBlock; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.advancedRocketry.util.SealableBlockHandler; /** @@ -20,7 +28,6 @@ * Created by Dark(DarkGuardsman, Robert) on 1/6/2016. */ public class ItemSealDetector extends Item { - //TODO make consume power? @Override public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand hand) { @@ -53,4 +60,10 @@ public EnumActionResult onItemUse(EntityPlayer player, return EnumActionResult.SUCCESS; } + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.sealdetector", insertAt); + } } From 7651f06bfb755101ed4bf133ab38798d9287b88d Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 9 Nov 2025 14:17:39 +0100 Subject: [PATCH 180/424] Add tooltip information for ItemData when shift is held --- .../zmaster587/advancedRocketry/item/ItemData.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemData.java b/src/main/java/zmaster587/advancedRocketry/item/ItemData.java index 61ee7848f..ec625eefd 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemData.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemData.java @@ -1,9 +1,11 @@ package zmaster587.advancedRocketry.item; +import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.resources.I18n; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -96,7 +98,13 @@ public void addInformation(@Nonnull ItemStack stack, World player, List list.add(data.getData() + " / " + data.getMaxData() + " Data"); list.add(I18n.format(data.getDataType().toString())); - + // --- SHIFT for more info (adds two short lines) --- + if (GuiScreen.isShiftKeyDown()) { + list.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.itemdataunit.shift.1")); + list.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.itemdataunit.shift.2")); + } else if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) { + list.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + + I18n.format("tooltip.advancedrocketry.hold_shift")); + } } - } From 0fe789fce4892d802e6c4b588d509e09eaeb81ba Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 9 Nov 2025 15:09:52 +0100 Subject: [PATCH 181/424] Improve tooltip display for ItemAsteroidChip Enhanced tooltip information for ItemAsteroidChip. --- .../advancedRocketry/item/ItemAsteroidChip.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java b/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java index d26d5bb00..ece6bb14d 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java @@ -1,9 +1,13 @@ package zmaster587.advancedRocketry.item; import com.mojang.realmsclient.gui.ChatFormatting; + +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.resources.I18n; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; import zmaster587.libVulpes.LibVulpes; @@ -94,6 +98,15 @@ private static long makeDisplayId(Long uuid, String type) { public void addInformation(@Nonnull ItemStack stack, World world, List list, ITooltipFlag flag) { if (!stack.hasTagCompound()) { list.add(LibVulpes.proxy.getLocalizedString("msg.unprogrammed")); + + // --- SHIFT for more info (adds two short lines) --- + if (GuiScreen.isShiftKeyDown()) { + list.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.asteroidchip.shift.1")); + list.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.asteroidchip.shift.2")); + } else if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) { + list.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + + I18n.format("tooltip.advancedrocketry.hold_shift")); + } return; } if (stack.getItemDamage() == 0) { @@ -116,8 +129,7 @@ public void addInformation(@Nonnull ItemStack stack, World world, List l list.add(LibVulpes.proxy.getLocalizedString("msg.asteroidChip.asteroid") + ": " + ChatFormatting.DARK_GREEN + shortHex); - super.addInformation(stack, world, list, flag); + super.addInformation(stack, world, list, flag); } } - } From d358febcabcb33a06cd2d72e6644bb06ae2642bf Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 10 Nov 2025 12:27:57 +0100 Subject: [PATCH 182/424] Fix missing newline at end of TileSatelliteTerminal.java From 4640565943bbafb2cdca7ae5319c8d31addc49a7 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 10 Nov 2025 12:33:42 +0100 Subject: [PATCH 183/424] moved tooltip to centralized injector --- .../block/BlockNuclearCore.java | 37 ++----------------- 1 file changed, 3 insertions(+), 34 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearCore.java b/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearCore.java index 0cf140dc6..1664ad679 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearCore.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearCore.java @@ -13,6 +13,7 @@ import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.IRocketNuclearCore; +import zmaster587.advancedRocketry.client.TooltipInjector; import javax.annotation.Nullable; import java.util.List; @@ -31,39 +32,7 @@ public int getMaxThrust(World world, BlockPos pos) { @SideOnly(Side.CLIENT) @Override public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearcore")); - - final boolean shift = GuiScreen.isShiftKeyDown(); - final boolean alt = isAltDown(); - - if (alt) { - // Advanced details - tooltip.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.nuclearcore.alt.1")); - tooltip.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.nuclearcore.alt.2")); - } else if (shift) { - // More info - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearcore.shift.1")); - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearcore.shift.2")); - if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) - tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); - } else { - // Hints - if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) - tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_shift")); - if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) - tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); - } - } - - @SideOnly(Side.CLIENT) - private static boolean isAltDown() { - try { - // Works on Forge 1.12.x; LWJGL fallback for safety - return GuiScreen.isAltKeyDown() - || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_LMENU) - || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_RMENU); - } catch (Throwable t) { - return false; - } + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.nuclearcore", insertAt); } } From 6802d853950fc3cb5d38aec5bf1dcde97c788747 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 10 Nov 2025 12:52:32 +0100 Subject: [PATCH 184/424] Refactor tooltip information handling in BlockLandingPad --- .../block/BlockLandingPad.java | 38 ++----------------- 1 file changed, 3 insertions(+), 35 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockLandingPad.java b/src/main/java/zmaster587/advancedRocketry/block/BlockLandingPad.java index b738003fb..d559f1835 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockLandingPad.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockLandingPad.java @@ -20,6 +20,7 @@ import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.advancedRocketry.tile.station.TileLandingPad; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.inventory.GuiHandler; @@ -62,41 +63,8 @@ public boolean onBlockActivated(World world, BlockPos pos, @SideOnly(Side.CLIENT) @Override public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.landingpad")); - - final boolean shift = GuiScreen.isShiftKeyDown(); - final boolean alt = isAltDown(); - - if (alt) { - // Advanced details - tooltip.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.landingpad.alt.1")); - tooltip.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.landingpad.alt.2")); - tooltip.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.landingpad.alt.3")); - } else if (shift) { - // More info - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.landingpad.shift.1")); - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.landingpad.shift.2")); - if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) - tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); - } else { - // Hints - if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) - tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_shift")); - if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) - tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); - } - } - - @SideOnly(Side.CLIENT) - private static boolean isAltDown() { - try { - // Works on Forge 1.12.x; LWJGL fallback for safety - return GuiScreen.isAltKeyDown() - || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_LMENU) - || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_RMENU); - } catch (Throwable t) { - return false; - } + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.landingpad", insertAt); } @Override From 385a9f6969a3b7aa8e74a2debd76a4bf07d4022e Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 10 Nov 2025 12:55:56 +0100 Subject: [PATCH 185/424] Refactor tooltip information handling in BlockNuclearRocketMotor --- .../block/BlockNuclearRocketMotor.java | 38 ++----------------- 1 file changed, 4 insertions(+), 34 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java b/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java index 830433b5f..604f1321b 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockNuclearRocketMotor.java @@ -16,6 +16,7 @@ import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.IRocketNuclearCore; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.advancedRocketry.tile.TileBrokenPart; import java.util.List; @@ -60,42 +61,11 @@ public int getFuelConsumptionRate(World world, int x, int y, int z) { public TileEntity createTileEntity(final World worldIn, final IBlockState state) { return new TileBrokenPart(10, 4 * (float) ARConfiguration.getCurrentConfig().increaseWearIntensityProb); } + @SideOnly(Side.CLIENT) @Override public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearmotor")); - - final boolean shift = GuiScreen.isShiftKeyDown(); - final boolean alt = isAltDown(); - - if (alt) { - // Advanced details - tooltip.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.nuclearmotor.alt.1")); - } else if (shift) { - // More info - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearmotor.shift.1")); - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.nuclearmotor.shift.2")); - if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) - tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); - } else { - // Hints - if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) - tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_shift")); - if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) - tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); - } - } - - @SideOnly(Side.CLIENT) - private static boolean isAltDown() { - try { - // Works on Forge 1.12.x; LWJGL fallback for safety - return GuiScreen.isAltKeyDown() - || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_LMENU) - || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_RMENU); - } catch (Throwable t) { - return false; - } + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.nuclearmotor", insertAt); } } - From ebb0bc486401744fee3eb5792fb2b3c5c6568283 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 10 Nov 2025 14:08:37 +0100 Subject: [PATCH 186/424] Simplify tooltip display logic in BlockBipropellantRocketMotor Refactor tooltip information handling for bipropellant rocket motor. --- .../block/BlockBipropellantRocketMotor.java | 36 ++----------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java b/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java index a63f09c1c..e9342d566 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockBipropellantRocketMotor.java @@ -21,6 +21,7 @@ import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.IRocketEngine; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.advancedRocketry.tile.TileBrokenPart; import zmaster587.advancedRocketry.util.IBrokenPartBlock; import zmaster587.libVulpes.block.BlockFullyRotatable; @@ -127,42 +128,11 @@ public TileEntity createTileEntity(final World worldIn, final IBlockState state) return new TileBrokenPart(10, (float) ARConfiguration.getCurrentConfig().increaseWearIntensityProb); } - @SideOnly(Side.CLIENT) @Override public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.bipropmotor")); - - final boolean shift = GuiScreen.isShiftKeyDown(); - final boolean alt = isAltDown(); - - if (alt) { - // Advanced details - tooltip.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.bipropmotor.alt.1")); - } else if (shift) { - // More info - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.bipropmotor.shift.1")); - if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) - tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); - } else { - // Hints - if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) - tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_shift")); - if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) - tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); - } - } - - @SideOnly(Side.CLIENT) - private static boolean isAltDown() { - try { - // Works on Forge 1.12.x; LWJGL fallback for safety - return GuiScreen.isAltKeyDown() - || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_LMENU) - || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_RMENU); - } catch (Throwable t) { - return false; - } + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.bipropmotor", insertAt); } @Override From e2a5ea099cd4f22dfc3d6ec5b299ef56ff1c4b82 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 10 Nov 2025 14:09:26 +0100 Subject: [PATCH 187/424] Refactor tooltip information handling in BlockRocketMotor --- .../block/BlockRocketMotor.java | 36 ++----------------- 1 file changed, 3 insertions(+), 33 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockRocketMotor.java b/src/main/java/zmaster587/advancedRocketry/block/BlockRocketMotor.java index 567701c5c..cba1024bc 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockRocketMotor.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockRocketMotor.java @@ -21,6 +21,7 @@ import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.IRocketEngine; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.advancedRocketry.tile.TileBrokenPart; import zmaster587.advancedRocketry.util.IBrokenPartBlock; import zmaster587.libVulpes.block.BlockFullyRotatable; @@ -149,38 +150,7 @@ public ItemStack getDropItem(final IBlockState state, final World world, final @ @SideOnly(Side.CLIENT) @Override public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.monopropmotor")); - - final boolean shift = GuiScreen.isShiftKeyDown(); - final boolean alt = isAltDown(); - - if (alt) { - // Advanced details - tooltip.add(TextFormatting.DARK_GRAY + I18n.format("tooltip.advancedrocketry.monopropmotor.alt.1")); - } else if (shift) { - // More info - tooltip.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.monopropmotor.shift.1")); - if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) - tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); - } else { - // Hints - if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) - tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_shift")); - if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) - tooltip.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_alt")); - } - } - - @SideOnly(Side.CLIENT) - private static boolean isAltDown() { - try { - // Works on Forge 1.12.x; LWJGL fallback for safety - return GuiScreen.isAltKeyDown() - || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_LMENU) - || org.lwjgl.input.Keyboard.isKeyDown(org.lwjgl.input.Keyboard.KEY_RMENU); - } catch (Throwable t) { - return false; - } + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.monopropmotor", insertAt); } - } From 43fcc74509f26059feea8bb033939afd6b8a0918 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 10 Nov 2025 17:52:54 +0100 Subject: [PATCH 188/424] Remove shift key tooltip from ItemAsteroidChip Removed shift key information display from addInformation method. --- .../advancedRocketry/item/ItemAsteroidChip.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java b/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java index ece6bb14d..d2fbad2d1 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java @@ -98,15 +98,6 @@ private static long makeDisplayId(Long uuid, String type) { public void addInformation(@Nonnull ItemStack stack, World world, List list, ITooltipFlag flag) { if (!stack.hasTagCompound()) { list.add(LibVulpes.proxy.getLocalizedString("msg.unprogrammed")); - - // --- SHIFT for more info (adds two short lines) --- - if (GuiScreen.isShiftKeyDown()) { - list.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.asteroidchip.shift.1")); - list.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.asteroidchip.shift.2")); - } else if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) { - list.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + - I18n.format("tooltip.advancedrocketry.hold_shift")); - } return; } if (stack.getItemDamage() == 0) { From 93b9e1311b6245629641dd25751c9fe303ec1e9f Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 10 Nov 2025 17:53:23 +0100 Subject: [PATCH 189/424] Fix missing newline at end of ItemStationChip.java From 18e7dc143d1fbb86e7fbfc62e3234c96dc48ba55 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 10 Nov 2025 17:54:07 +0100 Subject: [PATCH 190/424] Fix missing newline at end of ItemSatelliteIdentificationChip.java Added a newline at the end of the file. From 1ab910e762b76a81f7889fbbf77fd3f015f830b8 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 10 Nov 2025 23:58:54 +0100 Subject: [PATCH 191/424] Refactor addInformation to enhance tooltip display Updated addInformation method to include type and formatted data display. --- .../advancedRocketry/item/ItemData.java | 38 +++++++++++++------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemData.java b/src/main/java/zmaster587/advancedRocketry/item/ItemData.java index ec625eefd..6c9408082 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemData.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemData.java @@ -13,6 +13,8 @@ import zmaster587.libVulpes.items.ItemIngredient; import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import java.util.List; public class ItemData extends ItemIngredient { @@ -91,20 +93,32 @@ public void setData(@Nonnull ItemStack item, int amount, DataStorage.DataType da @Override @SideOnly(Side.CLIENT) - public void addInformation(@Nonnull ItemStack stack, World player, List list, ITooltipFlag bool) { - super.addInformation(stack, player, list, bool); + public void addInformation(@Nonnull ItemStack stack, @Nullable World world, List list, ITooltipFlag flag) { + super.addInformation(stack, world, list, flag); DataStorage data = getDataStorage(stack); - list.add(data.getData() + " / " + data.getMaxData() + " Data"); - list.add(I18n.format(data.getDataType().toString())); - // --- SHIFT for more info (adds two short lines) --- - if (GuiScreen.isShiftKeyDown()) { - list.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.itemdataunit.shift.1")); - list.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.itemdataunit.shift.2")); - } else if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) { - list.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + - I18n.format("tooltip.advancedrocketry.hold_shift")); - } + // 1) Type: + String typeText = net.minecraft.client.resources.I18n.format(data.getDataType().toString()); + list.add("Type: " + typeText); + + // 2) §fData stored: §6 §f/§6 + list.add(net.minecraft.util.text.TextFormatting.WHITE + "Data stored: " + + net.minecraft.util.text.TextFormatting.GOLD + data.getData() + + net.minecraft.util.text.TextFormatting.WHITE + " / " + + net.minecraft.util.text.TextFormatting.GOLD + data.getMaxData()); + + // 3) Hold Shift for more info + if (net.minecraft.client.gui.GuiScreen.isShiftKeyDown()) { + list.add(net.minecraft.util.text.TextFormatting.GRAY + + net.minecraft.client.resources.I18n.format("tooltip.advancedrocketry.itemdataunit.shift.1")); + list.add(net.minecraft.util.text.TextFormatting.GRAY + + net.minecraft.client.resources.I18n.format("tooltip.advancedrocketry.itemdataunit.shift.2")); + } else if (net.minecraft.client.resources.I18n.hasKey("tooltip.advancedrocketry.hold_shift")) { + list.add(net.minecraft.util.text.TextFormatting.DARK_GRAY.toString() + + net.minecraft.util.text.TextFormatting.ITALIC + + net.minecraft.client.resources.I18n.format("tooltip.advancedrocketry.hold_shift")); + } } + } From c62e305e866f9be4356867a68fcd0b904d3b77e6 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 10 Nov 2025 23:59:34 +0100 Subject: [PATCH 192/424] Implement tooltip for BlockSolarGenerator Added tooltip information for the solar generator block. --- .../block/BlockSolarGenerator.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockSolarGenerator.java b/src/main/java/zmaster587/advancedRocketry/block/BlockSolarGenerator.java index 32e58c13f..23f15865d 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockSolarGenerator.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockSolarGenerator.java @@ -1,7 +1,17 @@ package zmaster587.advancedRocketry.block; +import java.util.List; + +import javax.annotation.Nullable; + import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.libVulpes.block.BlockTile; /** @@ -22,4 +32,10 @@ public boolean isBlockNormalCube(IBlockState state) { public boolean isOpaqueCube(IBlockState state) { return true; } + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.solargenerator", insertAt); + } } From ac06d6b4753d5fbd8b9413a9b5bbbe0181d897f6 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Tue, 11 Nov 2025 01:17:21 +0100 Subject: [PATCH 193/424] Add JEI wrapper for Station Assembler --- .../StationAssemblerWrapper.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerWrapper.java diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerWrapper.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerWrapper.java new file mode 100644 index 000000000..803ac3d15 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerWrapper.java @@ -0,0 +1,67 @@ +package zmaster587.advancedRocketry.integration.jei.stationAssembler; + +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.recipe.IRecipeWrapper; +import net.minecraft.item.ItemStack; +import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; +import zmaster587.advancedRocketry.api.AdvancedRocketryItems; + +/** + * JEI wrapper for the Station Assembler flow shown in TileStationAssembler. + * Inputs (by code): + * - slot 0: AdvancedRocketryBlocks.blockLoader (meta 1) -> Satellite Loading Hatch + * - slot 1: AdvancedRocketryItems.itemSpaceStationChip -> Station Chip (can be blank or programmed) + * Outputs (by code): + * - slot 2: AdvancedRocketryItems.itemSpaceStation -> Packed station (ItemPackedStructure) + * - slot 3: AdvancedRocketryItems.itemSpaceStationChip -> New chip ONLY when making a brand-new station + * + * We present both outputs (JEI is illustrative, not conditional). + */ +public class StationAssemblerWrapper implements IRecipeWrapper { + + private final ItemStack inputHatch; + private final ItemStack inputChip; + private final ItemStack outStation; + private final ItemStack outChipMaybe; + + public StationAssemblerWrapper() { + // Input 0: blockLoader with meta 1 + this.inputHatch = new ItemStack(AdvancedRocketryBlocks.blockLoader, 1, 1); + + // Input 1: station chip item (no NBT required for JEI showcase) + this.inputChip = new ItemStack(AdvancedRocketryItems.itemSpaceStationChip); + + // Output 2: station item + this.outStation = new ItemStack(AdvancedRocketryItems.itemSpaceStation); + + // Output 3: station chip (appears when creating a new station) + this.outChipMaybe = new ItemStack(AdvancedRocketryItems.itemSpaceStationChip); + } + + @Override + public void getIngredients(IIngredients ing) { + // No fluids; only items. + java.util.List> inputs = new java.util.ArrayList<>(2); + inputs.add(java.util.Collections.singletonList(inputHatch)); + inputs.add(java.util.Collections.singletonList(inputChip)); + ing.setInputLists(mezz.jei.api.ingredients.VanillaTypes.ITEM, inputs); + + // Show both outputs to reflect possible results of "Build". + java.util.List outs = new java.util.ArrayList<>(2); + outs.add(outStation); + outs.add(outChipMaybe); + ing.setOutputs(mezz.jei.api.ingredients.VanillaTypes.ITEM, outs); + } + + // Convenience accessors (used by Category layout) + public ItemStack getInputHatch() { return inputHatch; } + public ItemStack getInputChip() { return inputChip; } + public ItemStack getOutStation() { return outStation; } + public ItemStack getOutChipMaybe() { return outChipMaybe; } + + // Optional: a display/catalyst icon you can use if you decide later. + static ItemStack iconStack() { + // Safe: chip exists and isn’t blacklisted in your ARPlugin snippet. + return new ItemStack(AdvancedRocketryItems.itemSpaceStationChip); + } +} From 636f6ef8015512d2c239cc159c4b2f6053ec1097 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Tue, 11 Nov 2025 01:18:01 +0100 Subject: [PATCH 194/424] Add StationAssemblerRecipeMaker for JEI integration --- .../StationAssemblerRecipeMaker.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerRecipeMaker.java diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerRecipeMaker.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerRecipeMaker.java new file mode 100644 index 000000000..2209d379c --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerRecipeMaker.java @@ -0,0 +1,17 @@ +package zmaster587.advancedRocketry.integration.jei.stationAssembler; + +import mezz.jei.api.IJeiHelpers; +import java.util.Collections; +import java.util.List; + +/** Single illustrative entry: the Station Assembler has no craft-list; it’s a process gate. */ +public class StationAssemblerRecipeMaker { + public static List getRecipes(IJeiHelpers helpers) { + return java.util.Collections.singletonList(new StationAssemblerWrapper()); + } + + // Keep this to match existing pattern in your makers + public static List getMachineRecipes(IJeiHelpers helpers, Class ignored) { + return getRecipes(helpers); + } +} From 0f1adf6814129a55bd9f56bd9ced110fcc0f35b0 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Tue, 11 Nov 2025 01:18:44 +0100 Subject: [PATCH 195/424] Implement StationAssemblerRecipeHandler class --- .../StationAssemblerRecipeHandler.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerRecipeHandler.java diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerRecipeHandler.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerRecipeHandler.java new file mode 100644 index 000000000..8ff1af524 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerRecipeHandler.java @@ -0,0 +1,12 @@ +package zmaster587.advancedRocketry.integration.jei.stationAssembler; + +import mezz.jei.api.recipe.IRecipeHandler; +import mezz.jei.api.recipe.IRecipeWrapper; +import zmaster587.advancedRocketry.integration.jei.ARPlugin; + +public class StationAssemblerRecipeHandler implements IRecipeHandler { + @Override public Class getRecipeClass() { return StationAssemblerWrapper.class; } + @Override public String getRecipeCategoryUid(StationAssemblerWrapper r) { return ARPlugin.stationAssemblerUUID; } + @Override public IRecipeWrapper getRecipeWrapper(StationAssemblerWrapper r) { return r; } + @Override public boolean isRecipeValid(StationAssemblerWrapper r) { return r != null; } +} From ec20523eeaa6293d686f5c7f1fd718a326be55f5 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Tue, 11 Nov 2025 01:23:34 +0100 Subject: [PATCH 196/424] Implement tooltip for BlockForceFieldProjector Added tooltip information for BlockForceFieldProjector. --- .../block/BlockForceFieldProjector.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockForceFieldProjector.java b/src/main/java/zmaster587/advancedRocketry/block/BlockForceFieldProjector.java index 59958642e..513c5e741 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockForceFieldProjector.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockForceFieldProjector.java @@ -1,10 +1,19 @@ package zmaster587.advancedRocketry.block; +import java.util.List; + +import javax.annotation.Nullable; + import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.advancedRocketry.tile.TileForceFieldProjector; import zmaster587.libVulpes.block.BlockFullyRotatable; @@ -33,5 +42,11 @@ public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { public TileEntity createTileEntity(World world, IBlockState state) { return new TileForceFieldProjector(); } + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.forcefieldprojector", insertAt); + } } From 6f3ede6e59edd3dce4c99b2abcd7558eff82fded Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 12 Nov 2025 10:12:33 +0100 Subject: [PATCH 197/424] Fix typo in tooltip for BlockTransciever --- .../zmaster587/advancedRocketry/block/BlockTransciever.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java b/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java index 9dd359601..a7a966723 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java @@ -151,7 +151,7 @@ public boolean rotateBlock(World world, BlockPos pos, EnumFacing axis) { @Override public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); - TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.transciever", insertAt); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.transceiver", insertAt); } public static EnumFacing getFront(IBlockState state) { From 03c8f76225afc003866326ce9c2f429014f3bb29 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 12 Nov 2025 10:53:49 +0100 Subject: [PATCH 198/424] Remove second SHIFT tooltip line from fluid tank Removed the second tooltip line when SHIFT is pressed. --- .../zmaster587/advancedRocketry/item/ItemBlockFluidTank.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java b/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java index 40600e989..4b19ff280 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java @@ -67,7 +67,6 @@ public void addInformation(@Nonnull ItemStack stack, @Nullable World world, List // --- SHIFT for more info (adds two short lines) --- if (GuiScreen.isShiftKeyDown()) { list.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.fluidtank.shift.1")); - list.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.fluidtank.shift.2")); } else if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) { list.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_shift")); From c94bf939b5f52799d8e72d34f563644e9bf5d365 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 12 Nov 2025 12:40:29 +0100 Subject: [PATCH 199/424] Add BlockPump class for fluid handling --- .../advancedRocketry/block/BlockPump.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/block/BlockPump.java diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockPump.java b/src/main/java/zmaster587/advancedRocketry/block/BlockPump.java new file mode 100644 index 000000000..94a888dc9 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockPump.java @@ -0,0 +1,28 @@ +package zmaster587.advancedRocketry.block; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fluids.FluidUtil; +import zmaster587.libVulpes.block.BlockTile; + +public class BlockPump extends BlockTile { + + public BlockPump(Class tileClass, int guiId) { + super(tileClass, guiId); + } + + @Override + public boolean onBlockActivated(World world, BlockPos pos, IBlockState state, + EntityPlayer player, EnumHand hand, + EnumFacing side, float hitX, float hitY, float hitZ) { + // Try container <-> TE interaction first (handles buckets both directions). + if (FluidUtil.interactWithFluidHandler(player, hand, world, pos, side)) { + return true; + } + return super.onBlockActivated(world, pos, state, player, hand, side, hitX, hitY, hitZ); + } +} From c0244ebc027d980789f58d61e3e13af44731e67d Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 12 Nov 2025 13:09:16 +0100 Subject: [PATCH 200/424] Remove redundant tooltip line from pressure tank Removed a tooltip line for the pressure tank item. --- .../advancedRocketry/item/components/ItemPressureTank.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java b/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java index 96d87b60f..39007f1b0 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java +++ b/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java @@ -56,13 +56,13 @@ public void addInformation(@Nonnull ItemStack stack, @Nullable World world, final int amount = (fs != null) ? fs.amount : 0; // Match main tank style + list.add(TextFormatting.DARK_PURPLE + "Space Suit Component"); list.add("Fluid: " + fluidName); list.add("Level: " + amount + "/" + capMb + " mB"); // SHIFT block if (GuiScreen.isShiftKeyDown()) { list.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.pressuretank.shift.1")); - list.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.pressuretank.shift.2")); } else if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) { list.add(TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + I18n.format("tooltip.advancedrocketry.hold_shift")); From 907a63cde58875f27dda681d8d82de02c2c2ae99 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 12 Nov 2025 13:20:41 +0100 Subject: [PATCH 201/424] Update ItemData.java --- src/main/java/zmaster587/advancedRocketry/item/ItemData.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemData.java b/src/main/java/zmaster587/advancedRocketry/item/ItemData.java index 6c9408082..ccd62a615 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemData.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemData.java @@ -99,8 +99,9 @@ public void addInformation(@Nonnull ItemStack stack, @Nullable World world, List DataStorage data = getDataStorage(stack); // 1) Type: + list.add(TextFormatting.DARK_PURPLE + "Space Suit Component"); String typeText = net.minecraft.client.resources.I18n.format(data.getDataType().toString()); - list.add("Type: " + typeText); + list.add(net.minecraft.util.text.TextFormatting.WHITE + "Type: " + typeText); // 2) §fData stored: §6 §f/§6 list.add(net.minecraft.util.text.TextFormatting.WHITE + "Data stored: " @@ -112,8 +113,6 @@ public void addInformation(@Nonnull ItemStack stack, @Nullable World world, List if (net.minecraft.client.gui.GuiScreen.isShiftKeyDown()) { list.add(net.minecraft.util.text.TextFormatting.GRAY + net.minecraft.client.resources.I18n.format("tooltip.advancedrocketry.itemdataunit.shift.1")); - list.add(net.minecraft.util.text.TextFormatting.GRAY + - net.minecraft.client.resources.I18n.format("tooltip.advancedrocketry.itemdataunit.shift.2")); } else if (net.minecraft.client.resources.I18n.hasKey("tooltip.advancedrocketry.hold_shift")) { list.add(net.minecraft.util.text.TextFormatting.DARK_GRAY.toString() + net.minecraft.util.text.TextFormatting.ITALIC + From 1f0c7cbcf450565714708671b0c33993f47408b1 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 12 Nov 2025 13:41:32 +0100 Subject: [PATCH 202/424] Enhance fluid handling in TilePump class Refactor TilePump class to improve fluid handling and add new utility methods for fluid checks. --- .../advancedRocketry/tile/TilePump.java | 273 ++++++++++++++---- 1 file changed, 214 insertions(+), 59 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TilePump.java b/src/main/java/zmaster587/advancedRocketry/tile/TilePump.java index 59c57298f..3d487d76c 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TilePump.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TilePump.java @@ -1,8 +1,11 @@ package zmaster587.advancedRocketry.tile; import net.minecraft.block.Block; +import net.minecraft.block.BlockLiquid; import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; @@ -11,6 +14,7 @@ import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.FluidTank; +import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.IFluidBlock; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; @@ -22,6 +26,9 @@ import zmaster587.libVulpes.network.PacketHandler; import zmaster587.libVulpes.tile.TileEntityRFConsumer; + + + import java.util.*; public class TilePump extends TileEntityRFConsumer implements IFluidHandler, IModularInventory { @@ -29,6 +36,7 @@ public class TilePump extends TileEntityRFConsumer implements IFluidHandler, IMo private final int RANGE = 64; private FluidTank tank; private List cache; + private Fluid lastFluidType = null; public TilePump() { super(1000); @@ -36,6 +44,15 @@ public TilePump() { cache = new LinkedList<>(); } + private static final int PUMP_INTERVAL_TICKS = 25; // ~1 Hz + private static final int EJECT_INTERVAL_TICKS = 20; // 1 Hz + private final IFluidHandler fluidCap = new FluidCapability(this); + + private boolean shouldRunThisTick(int interval) { + // world time is long; 0 mod interval fires once per interval + return interval <= 1 || (world.getWorldTime() % interval) == 0; + } + public int getPowerPerOperation() { return 100; } @@ -50,132 +67,242 @@ public boolean hasCapability(Capability capability, EnumFacing facing) { @Override public T getCapability(Capability capability, EnumFacing facing) { if (capability == CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY) { - return (T) new FluidCapability(this); + return CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY.cast(fluidCap); } return super.getCapability(capability, facing); } @Override public void update() { + if (world.isRemote) return; + + // Drop stale plan if accepted fluid changed + Fluid cur = tank.getFluid() == null ? null : tank.getFluid().getFluid(); + if (cur != lastFluidType) { + if (!cache.isEmpty()) cache.clear(); + lastFluidType = cur; + } + + if (isRedstoneDisabled()) { + // optional: cache.clear(); + return; + } + super.update(); - //Attempt fluid Eject - if (!world.isRemote && tank.getFluid() != null) { - for (EnumFacing direction : EnumFacing.values()) { - BlockPos newBlock = getPos().offset(direction); - TileEntity tile = world.getTileEntity(newBlock); - if (tile != null && tile.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction.getOpposite())) { - IFluidHandler cap = tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, direction.getOpposite()); - FluidStack stack = tank.getFluid().copy(); - stack.amount = Math.min(tank.getFluid().amount, 1000); - //Perform the drain - cap.fill(tank.drain(cap.fill(stack, false), true), true); - - //Abort if we run out of fluid - if (tank.getFluid() == null) - break; + // Attempt fluid Eject (throttled; see section 3) + if (shouldRunThisTick(EJECT_INTERVAL_TICKS) && tank.getFluid() != null) { + final FluidStack src = tank.getFluid(); + final int toOffer = Math.min(src.amount, 1000); + if (toOffer > 0) { + for (EnumFacing dir : EnumFacing.values()) { + TileEntity te = world.getTileEntity(pos.offset(dir)); + if (te == null || !te.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, dir.getOpposite())) + continue; + + IFluidHandler out = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, dir.getOpposite()); + if (out == null) continue; + + int simAccepted = out.fill(new FluidStack(src, toOffer), false); + if (simAccepted > 0) { + FluidStack drained = tank.drain(simAccepted, true); + if (drained != null && drained.amount > 0) { + out.fill(drained, true); + if (tank.getFluid() == null) break; // ran out + } + } } } } } - private int getFrequencyFromPower() { - float ratio = energy.getUniversalEnergyStored() / (float) energy.getMaxEnergyStored(); - if (ratio > 0.5) - return 1; - return 10; + private boolean isVanillaLiquid(BlockPos pos) { + IBlockState state = world.getBlockState(pos); + Material mat = state.getMaterial(); + return mat == Material.WATER || mat == Material.LAVA; + } + + private boolean isVanillaSource(BlockPos pos) { + IBlockState state = world.getBlockState(pos); + Block block = state.getBlock(); + if (block instanceof BlockLiquid) { + // 0 == source, 1..7 flowing (or up to 15, depending) + Integer lvl = state.getValue(BlockLiquid.LEVEL); + return lvl != null && lvl == 0; + } + return false; + } + + private Fluid getVanillaFluid(BlockPos pos) { + Material mat = world.getBlockState(pos).getMaterial(); + if (mat == Material.WATER) return FluidRegistry.WATER; + if (mat == Material.LAVA) return FluidRegistry.LAVA; + return null; } + + @Override public void performFunction() { - if (!world.isRemote) { - //Do we have room? if (tank.getCapacity() - 1000 < tank.getFluidAmount()) return; BlockPos nextPos = getNextBlockLocation(); - if (nextPos != null) { - if (canFitFluid(nextPos)) { - Block worldBlock = world.getBlockState(nextPos).getBlock(); - Material mat = world.getBlockState(nextPos).getMaterial(); - if (worldBlock instanceof IFluidBlock) { - FluidStack fStack = ((IFluidBlock) worldBlock).drain(world, nextPos, true); - - if (fStack != null) - tank.fill(fStack, true); - int colour = ((IFluidBlock) worldBlock).getFluid().getColor(); - if (mat == Material.LAVA) - colour = 0xFFbd3718; - - PacketHandler.sendToNearby(new PacketFluidParticle(nextPos, this.pos, 200, colour), world.provider.getDimension(), this.pos, 128); + if (nextPos != null && canFitFluid(nextPos)) { + IBlockState state = world.getBlockState(nextPos); + Block worldBlock = state.getBlock(); + Material mat = state.getMaterial(); + + if (worldBlock instanceof IFluidBlock) { + FluidStack fStack = ((IFluidBlock) worldBlock).drain(world, nextPos, true); + if (fStack != null) tank.fill(fStack, true); + + int colour = ((IFluidBlock) worldBlock).getFluid().getColor(); + if (mat == Material.LAVA) colour = 0xFFbd3718; + PacketHandler.sendToNearby(new PacketFluidParticle(nextPos, this.pos, 200, colour), world.provider.getDimension(), this.pos, 128); + } else if (isVanillaLiquid(nextPos) && isVanillaSource(nextPos)) { + Fluid f = getVanillaFluid(nextPos); + if (f != null) { + FluidStack stack = new FluidStack(f, 1000); + int filled = tank.fill(stack, true); + if (filled == 1000) { + world.setBlockToAir(nextPos); // remove the source + int colour = (mat == Material.LAVA) ? 0xFFbd3718 : 0xFF3F76E4; // MC-ish tint + PacketHandler.sendToNearby(new PacketFluidParticle(nextPos, this.pos, 200, colour), world.provider.getDimension(), this.pos, 128); + } } } } } } + private boolean canFitFluid(BlockPos pos) { Block worldBlock = world.getBlockState(pos).getBlock(); if (worldBlock instanceof IFluidBlock) { - // Can we put it into the tank? return tank.getFluid() == null || tank.getFluid().getFluid() == ((IFluidBlock) worldBlock).getFluid(); } + if (isVanillaLiquid(pos)) { + Fluid f = getVanillaFluid(pos); + return f != null && (tank.getFluid() == null || tank.getFluid().getFluid() == f); + } return false; } - private BlockPos getNextBlockLocation() { + private BlockPos getNextBlockLocation() { if (!cache.isEmpty()) return cache.remove(0); BlockPos currentPos = new MutableBlockPos(getPos().down()); - while (world.isAirBlock(currentPos)) currentPos = currentPos.down(); - // We found a fluid Block worldBlock = world.getBlockState(currentPos).getBlock(); - if (canFitFluid(currentPos)) - findFluidAtOrAbove(currentPos, ((IFluidBlock) worldBlock).getFluid()); + if (canFitFluid(currentPos)) { + Fluid target = null; + if (worldBlock instanceof IFluidBlock) { + target = ((IFluidBlock) worldBlock).getFluid(); + } else if (isVanillaLiquid(currentPos)) { + target = getVanillaFluid(currentPos); + } + findFluidAtOrAbove(currentPos, target); + } if (!cache.isEmpty()) return cache.remove(0); return null; } - private void findFluidAtOrAbove(BlockPos pos, Fluid fluid) { + + private void findFluidAtOrAbove(BlockPos pos, Fluid targetFluid) { Queue queue = new LinkedList<>(); Set visited = new HashSet<>(); queue.add(pos); while (!queue.isEmpty()) { - BlockPos nextElement = queue.poll(); - if (visited.contains(nextElement) || nextElement.getDistance(pos.getX(), nextElement.getY(), pos.getZ()) > RANGE) + BlockPos next = queue.poll(); + if (visited.contains(next) || next.getDistance(pos.getX(), pos.getY(), pos.getZ()) > RANGE) continue; - Block worldBlock = world.getBlockState(nextElement).getBlock(); - if (worldBlock instanceof IFluidBlock) { - if (fluid == null || ((IFluidBlock) worldBlock).getFluid() == fluid) { - //only add drainable fluids, allow chaining along flowing fluid tho - if (((IFluidBlock) worldBlock).canDrain(world, nextElement)) - cache.add(0, nextElement); - visited.add(nextElement); - queue.add(nextElement.west()); - queue.add(nextElement.east()); - queue.add(nextElement.north()); - queue.add(nextElement.south()); - queue.add(nextElement.up()); + IBlockState state = world.getBlockState(next); + Block block = state.getBlock(); + + // Case 1: IFluidBlock (existing behavior) + if (block instanceof IFluidBlock) { + IFluidBlock fb = (IFluidBlock) block; + Fluid f = fb.getFluid(); + if (targetFluid == null || f == targetFluid) { + if (fb.canDrain(world, next)) { + cache.add(0, next); // drainable + } + visited.add(next); + queue.add(next.west()); + queue.add(next.east()); + queue.add(next.north()); + queue.add(next.south()); + queue.add(next.up()); + } + continue; + } + + // Case 2: Vanilla BlockLiquid + if (isVanillaLiquid(next)) { + Fluid f = getVanillaFluid(next); + if (f != null && (targetFluid == null || f == targetFluid)) { + // Only sources are drainable; but we still traverse through flowing + if (isVanillaSource(next)) { + cache.add(0, next); + } + visited.add(next); + queue.add(next.west()); + queue.add(next.east()); + queue.add(next.north()); + queue.add(next.south()); + queue.add(next.up()); } } } } + private boolean isRedstoneDisabled() { + return world.isBlockPowered(pos); + } + @Override public boolean canPerformFunction() { - return tank.getFluidAmount() <= tank.getCapacity() && world.getWorldTime() % getFrequencyFromPower() == 0; + if (isRedstoneDisabled()) return false; + if (!shouldRunThisTick(PUMP_INTERVAL_TICKS)) return false; + + // must have at least 100 RF for one bucket operation + if (energy.getUniversalEnergyStored() < getPowerPerOperation()) return false; + + // must be able to accept a full bucket + if ((tank.getCapacity() - tank.getFluidAmount()) < 1000) return false; + + // must have a drainable source available; if not, try to populate cache now (cheap probe) + if (cache.isEmpty()) { + // very small, one-shot version of your getNextBlockLocation() to populate cache + BlockPos currentPos = new MutableBlockPos(getPos().down()); + while (world.isAirBlock(currentPos)) + currentPos = ((MutableBlockPos) currentPos).down(); + + if (canFitFluid(currentPos)) { + Fluid target = null; + Block worldBlock = world.getBlockState(currentPos).getBlock(); + if (worldBlock instanceof IFluidBlock) { + target = ((IFluidBlock) worldBlock).getFluid(); + } else if (isVanillaLiquid(currentPos)) { + target = getVanillaFluid(currentPos); + } + findFluidAtOrAbove(currentPos, target); + } + } + return !cache.isEmpty(); // only authorize (and thus spend 100 RF) if we have a source to drain } + @Override public IFluidTankProperties[] getTankProperties() { return tank.getTankProperties(); @@ -207,6 +334,34 @@ public String getModularInventoryName() { return "tile.pump.name"; } + @Override + public void onLoad() { + super.onLoad(); + lastFluidType = tank.getFluid() == null ? null : tank.getFluid().getFluid(); + } + + @Override + public void onChunkUnload() { + super.onChunkUnload(); + if (!cache.isEmpty()) cache.clear(); + } + + @Override + public void invalidate() { + super.invalidate(); + if (!cache.isEmpty()) cache.clear(); + } + + @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { + super.writeToNBT(nbt); + nbt.setTag("tank", tank.writeToNBT(new NBTTagCompound())); + return nbt; + } + @Override public void readFromNBT(NBTTagCompound nbt) { + super.readFromNBT(nbt); + tank.readFromNBT(nbt.getCompoundTag("tank")); + } + @Override public boolean canInteractWithContainer(EntityPlayer entity) { return false; From d90dce2fab01f182383208f4ce2a80cc5056c532 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 12 Nov 2025 13:44:02 +0100 Subject: [PATCH 203/424] Replace BlockTile with BlockPump for pump block --- src/main/java/zmaster587/advancedRocketry/AdvancedRocketry.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/AdvancedRocketry.java b/src/main/java/zmaster587/advancedRocketry/AdvancedRocketry.java index 77d37f955..ffb6b7127 100644 --- a/src/main/java/zmaster587/advancedRocketry/AdvancedRocketry.java +++ b/src/main/java/zmaster587/advancedRocketry/AdvancedRocketry.java @@ -628,7 +628,7 @@ public void registerBlocks(RegistryEvent.Register evt) { AdvancedRocketryBlocks.blockForceFieldProjector = new BlockForceFieldProjector(Material.IRON).setUnlocalizedName("forceFieldProjector").setCreativeTab(tabAdvRocketry).setHardness(3f); AdvancedRocketryBlocks.blockForceField = new BlockForceField(Material.BARRIER).setBlockUnbreakable().setResistance(6000000.0F).setUnlocalizedName("forceField"); AdvancedRocketryBlocks.blockVacuumLaser = new BlockFullyRotatable(Material.IRON).setUnlocalizedName("vacuumLaser").setCreativeTab(tabAdvRocketry).setHardness(4f); - AdvancedRocketryBlocks.blockPump = new BlockTile(TilePump.class, GuiHandler.guiId.MODULAR.ordinal()).setUnlocalizedName("pump").setCreativeTab(tabAdvRocketry).setHardness(3f); + AdvancedRocketryBlocks.blockPump = new BlockPump(TilePump.class, GuiHandler.guiId.MODULAR.ordinal()).setUnlocalizedName("pump").setCreativeTab(tabAdvRocketry).setHardness(3f); AdvancedRocketryBlocks.blockSuitWorkStation = new BlockSuitWorkstation(TileSuitWorkStation.class, GuiHandler.guiId.MODULAR.ordinal()).setUnlocalizedName("suitWorkStation").setCreativeTab(tabAdvRocketry).setHardness(3f); AdvancedRocketryBlocks.blockPressureTank = new BlockPressurizedFluidTank(Material.IRON).setUnlocalizedName("pressurizedTank").setCreativeTab(tabAdvRocketry).setHardness(3f); AdvancedRocketryBlocks.blockSolarGenerator = new BlockSolarGenerator(TileSolarPanel.class, GuiHandler.guiId.MODULAR.ordinal()).setCreativeTab(tabAdvRocketry).setHardness(3f).setUnlocalizedName("solarGenerator"); From 3f2d61546db6aac58d87f54bef200582ffa542d6 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 12 Nov 2025 13:49:53 +0100 Subject: [PATCH 204/424] Refactor TileMicrowaveReciever for robustness and clarity --- .../energy/TileMicrowaveReciever.java | 133 +++++++++++++----- 1 file changed, 96 insertions(+), 37 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/energy/TileMicrowaveReciever.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/energy/TileMicrowaveReciever.java index 9d33963a5..6957636ea 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/energy/TileMicrowaveReciever.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/energy/TileMicrowaveReciever.java @@ -2,6 +2,7 @@ import io.netty.buffer.ByteBuf; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; @@ -14,15 +15,18 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; import zmaster587.advancedRocketry.api.SatelliteRegistry; import zmaster587.advancedRocketry.api.satellite.SatelliteBase; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.advancedRocketry.dimension.DimensionProperties; import zmaster587.advancedRocketry.item.ItemSatelliteIdentificationChip; import zmaster587.advancedRocketry.stations.SpaceObjectManager; import zmaster587.advancedRocketry.stations.SpaceStationObject; +import zmaster587.advancedRocketry.util.PlanetaryTravelHelper; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.api.IUniversalEnergyTransmitter; import zmaster587.libVulpes.block.BlockMeta; @@ -34,9 +38,12 @@ import zmaster587.libVulpes.tile.multiblock.TileMultiPowerProducer; import zmaster587.libVulpes.util.Vector3F; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; +import javax.annotation.Nullable; + public class TileMicrowaveReciever extends TileMultiPowerProducer implements ITickable { static final BlockMeta iron_block = new BlockMeta(AdvancedRocketryBlocks.blockSolarPanel); @@ -113,18 +120,17 @@ public void onInventoryUpdated() { List list = new LinkedList<>(); - for (IInventory inv : itemInPorts) { - for (int i = 0; i < inv.getSizeInventory(); i++) { - ItemStack stack = inv.getStackInSlot(i); - if (!stack.isEmpty() && stack.getItem() instanceof ItemSatelliteIdentificationChip) { - list.add(SatelliteRegistry.getSatelliteId(stack)); + if (itemInPorts != null) { // <--- guard + for (IInventory inv : itemInPorts) { + for (int i = 0; i < inv.getSizeInventory(); i++) { + ItemStack stack = inv.getStackInSlot(i); + if (!stack.isEmpty() && stack.getItem() instanceof ItemSatelliteIdentificationChip) { + list.add(SatelliteRegistry.getSatelliteId(stack)); + } } } } - - - connectedSatellites = list; - + connectedSatellites = new LinkedList<>(new LinkedHashSet<>(list)); } @Override @@ -137,13 +143,40 @@ public void update() { } //Checks whenever a station changes dimensions or when the multiblock is intialized - ie any time the multipler could concieveably change - if (insolationPowerMultiplier == 0 || ((world.provider.getDimension() == ARConfiguration.getCurrentConfig().spaceDimId) && (powerSourceDimensionID != SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(this.pos).getOrbitingPlanetId()))) { - DimensionProperties properties = DimensionManager.getInstance().getDimensionProperties(world.provider.getDimension()); - insolationPowerMultiplier = (world.provider.getDimension() == ARConfiguration.getCurrentConfig().spaceDimId) ? SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(this.pos).getInsolationMultiplier() : properties.getPeakInsolationMultiplierWithoutAtmosphere(); - //Sets the ID of the place it's sourcing power from so it does not have to recheck - if (world.provider.getDimension() == ARConfiguration.getCurrentConfig().spaceDimId) - powerSourceDimensionID = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(this.pos).getOrbitingPlanetId(); + // --- BEGIN robust insolation block (mirror SatelliteTerminal style) --- + final int curDim = world.provider.getDimension(); + final int spaceDim = ARConfiguration.getCurrentConfig().spaceDimId; + + // Cache station once; can be null + final zmaster587.advancedRocketry.stations.SpaceStationObject station = + (curDim == spaceDim) + ? (zmaster587.advancedRocketry.stations.SpaceStationObject) + zmaster587.advancedRocketry.stations.SpaceObjectManager.getSpaceManager() + .getSpaceStationFromBlockCoords(this.pos) + : null; + + // Recompute when uninitialized OR (in space AND orbiting planet changed and station exists) + final boolean needRecompute = + (insolationPowerMultiplier == 0) + || (curDim == spaceDim && station != null && powerSourceDimensionID != station.getOrbitingPlanetId()); + + if (needRecompute) { + if (curDim == spaceDim && station != null) { + insolationPowerMultiplier = station.getInsolationMultiplier(); + powerSourceDimensionID = station.getOrbitingPlanetId(); + } else { + final zmaster587.advancedRocketry.dimension.DimensionProperties props = + zmaster587.advancedRocketry.dimension.DimensionManager.getInstance() + .getDimensionProperties(curDim); + insolationPowerMultiplier = (props != null) + ? props.getPeakInsolationMultiplierWithoutAtmosphere() + : 1.0; // safe fallback + powerSourceDimensionID = curDim; + } } + // If we're in space but station==null (early ticks), keep previous multiplier and carry on. + // --- END robust insolation block --- + if (!isComplete()) return; @@ -174,37 +207,66 @@ public void update() { } } - DimensionProperties properties; - int dimId = world.provider.getDimension(); - SpaceStationObject spaceStation = (SpaceStationObject) SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(this.pos); - if (!world.isRemote && (DimensionManager.getInstance().isDimensionCreated(dimId) || world.provider.getDimension() == 0)) { - //This way we check to see if it's on a station, and if so, if it has any satellites in orbit around the planet the station is around to pull from - properties = (spaceStation != null) ? spaceStation.getOrbitingPlanet() : DimensionManager.getInstance().getDimensionProperties(dimId); + // --- BEGIN robust energy gather (mirrors SatelliteTerminal) --- + final int dimId = world.provider.getDimension(); + final boolean dimOk = DimensionManager.getInstance().isDimensionCreated(dimId) || dimId == 0; + + if (!world.isRemote && dimOk) { + // If we’re on a station, prefer its orbiting planet; otherwise use the local dim props + final SpaceStationObject stationHere = (dimId == ARConfiguration.getCurrentConfig().spaceDimId) + ? (SpaceStationObject) SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(this.pos) + : null; + + final DimensionProperties props = (stationHere != null) + ? stationHere.getOrbitingPlanet() + : DimensionManager.getInstance().getDimensionProperties(dimId); + int energyReceived = 0; - if (enabled) { - for (long lng : connectedSatellites) { - SatelliteBase satellite = properties.getSatellite(lng); - if (satellite instanceof IUniversalEnergyTransmitter) { - energyReceived += ((IUniversalEnergyTransmitter) satellite).transmitEnergy(EnumFacing.UP, false); + if (enabled && props != null && connectedSatellites != null && !connectedSatellites.isEmpty()) { + // Snapshot to avoid concurrent modification + final LinkedHashSet sats = new LinkedHashSet<>(connectedSatellites); + + // Resolve “here” dim exactly like SatelliteTerminal + final int hereDim = DimensionManager.getEffectiveDimId(world, pos).getId(); + + for (long lng : sats) { + final SatelliteBase sat = props.getSatellite(lng); + if (sat == null) continue; + + // Range/link check (same logic as Terminal) + final int satDim = sat.getDimensionId(); + final boolean inRange = PlanetaryTravelHelper.isTravelAnywhereInPlanetarySystem(satDim, hereDim); + if (!inRange) continue; + + if (sat instanceof IUniversalEnergyTransmitter) { + energyReceived += ((IUniversalEnergyTransmitter) sat).transmitEnergy(EnumFacing.UP, false); } } - //Multiplied by two for 520W = 1 RF/t becoming 2 RF/t @ 100% efficiency, and by insolation mult for solar stuff - energyReceived *= 2 * insolationPowerMultiplier; + // 520W = 1 RF/t -> 2 RF/t @ 100%; scale by insolation + energyReceived = (int) Math.round(energyReceived * (2 * insolationPowerMultiplier)); } + powerMadeLastTick = energyReceived; if (powerMadeLastTick != prevPowerMadeLastTick) { prevPowerMadeLastTick = powerMadeLastTick; - PacketHandler.sendToNearby(new PacketMachine(this, (byte) 1), world.provider.getDimension(), pos, 128); - + PacketHandler.sendToNearby(new PacketMachine(this, (byte) 1), + world.provider.getDimension(), pos, 128); } producePower(powerMadeLastTick); } - if (world.isRemote) - textModule.setText(LibVulpes.proxy.getLocalizedString("msg.microwaverec.generating") + " " + powerMadeLastTick + " " + LibVulpes.proxy.getLocalizedString("msg.powerunit.rfpertick")); - } + + if (world.isRemote) { + textModule.setText( + LibVulpes.proxy.getLocalizedString("msg.microwaverec.generating") + " " + + powerMadeLastTick + " " + + LibVulpes.proxy.getLocalizedString("msg.powerunit.rfpertick")); + } + // --- END robust energy gather --- + } + @Override public SPacketUpdateTileEntity getUpdatePacket() { @@ -287,13 +349,10 @@ public NBTTagCompound writeToNBT(NBTTagCompound nbt) { @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); - int[] intArray = nbt.getIntArray("satilliteList"); connectedSatellites.clear(); - for (int i = 0; i < intArray.length / 2; i += 2) { + for (int i = 0; i < intArray.length; i += 2) { connectedSatellites.add(intArray[i] | (((long) intArray[i + 1]) << 32)); } - } - } From 4620cde4f49d993b7ba2e8685699973ba7edce9a Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 12 Nov 2025 14:09:44 +0100 Subject: [PATCH 205/424] Implement tooltip for ItemPackedStructure Add tooltip information for ItemPackedStructure. --- .../item/ItemPackedStructure.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemPackedStructure.java b/src/main/java/zmaster587/advancedRocketry/item/ItemPackedStructure.java index 70e68cae1..3bb596dac 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemPackedStructure.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemPackedStructure.java @@ -1,11 +1,19 @@ package zmaster587.advancedRocketry.item; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.advancedRocketry.util.StorageChunk; +import java.util.List; + import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class ItemPackedStructure extends Item { @@ -38,4 +46,11 @@ public StorageChunk getStructure(@Nonnull ItemStack stack) { } return null; } + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.packedstructure", insertAt); + } } From a3aa73e417fd61f70d4e27869d7a168ffd675bac Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 12 Nov 2025 14:53:14 +0100 Subject: [PATCH 206/424] Implement hatch inventory snapshot and restore Added functionality to snapshot and restore hatch inventories during multiblock structure formation and deconstruction. --- .../energy/TileMicrowaveReciever.java | 361 +++++++++++++++++- 1 file changed, 352 insertions(+), 9 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/energy/TileMicrowaveReciever.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/energy/TileMicrowaveReciever.java index 6957636ea..9ead1c15a 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/energy/TileMicrowaveReciever.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/energy/TileMicrowaveReciever.java @@ -4,12 +4,15 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; import net.minecraft.network.NetworkManager; import net.minecraft.network.play.server.SPacketUpdateTileEntity; +import net.minecraft.tileentity.TileEntity; import net.minecraft.util.*; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; @@ -34,18 +37,25 @@ import zmaster587.libVulpes.inventory.modules.ModuleText; import zmaster587.libVulpes.network.PacketHandler; import zmaster587.libVulpes.network.PacketMachine; +import zmaster587.libVulpes.tile.multiblock.TilePlaceholder; +import zmaster587.libVulpes.tile.multiblock.hatch.TileInventoryHatch; import zmaster587.libVulpes.tile.multiblock.TileMultiBlock; import zmaster587.libVulpes.tile.multiblock.TileMultiPowerProducer; import zmaster587.libVulpes.util.Vector3F; +import javax.annotation.Nullable; +import java.util.HashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; +import java.util.Map; -import javax.annotation.Nullable; public class TileMicrowaveReciever extends TileMultiPowerProducer implements ITickable { + // key: BlockPos.toLong(), value: saved non-empty stacks for that hatch (slot order preserved) + private final Map> savedHatchInv = new HashMap<>(); + static final BlockMeta iron_block = new BlockMeta(AdvancedRocketryBlocks.blockSolarPanel); static final Object[][][] structure = new Object[][][]{ { @@ -120,7 +130,7 @@ public void onInventoryUpdated() { List list = new LinkedList<>(); - if (itemInPorts != null) { // <--- guard + if (itemInPorts != null) { for (IInventory inv : itemInPorts) { for (int i = 0; i < inv.getSizeInventory(); i++) { ItemStack stack = inv.getStackInSlot(i); @@ -133,6 +143,41 @@ public void onInventoryUpdated() { connectedSatellites = new LinkedList<>(new LinkedHashSet<>(list)); } + @Override + public boolean attemptCompleteStructure(IBlockState state) { + if (!world.isRemote) { + // Snapshot BEFORE formation (real hatches) + snapshotHatchInventories(); + } + boolean ok = super.attemptCompleteStructure(state); + + if (!world.isRemote) { + if (ok) { + // Formation succeeded → push snapshot into placeholders (alive state) + writeSnapshotIntoPlaceholders(); + } else { + // Formation failed → discard + savedHatchInv.clear(); + } + } + return ok; + } + + + @Override + public void deconstructMultiBlock(World worldIn, BlockPos destroyedPos, boolean blockBroken, IBlockState state) { + if (!worldIn.isRemote) { + snapshotFromPlaceholders(); + } + + super.deconstructMultiBlock(worldIn, destroyedPos, blockBroken, state); + + if (!worldIn.isRemote) { + restoreHatchInventories(); + } + } + + @Override public void update() { @@ -143,7 +188,7 @@ public void update() { } //Checks whenever a station changes dimensions or when the multiblock is intialized - ie any time the multipler could concieveably change - // --- BEGIN robust insolation block (mirror SatelliteTerminal style) --- + // --- BEGIN mirror SatelliteTerminal style) --- final int curDim = world.provider.getDimension(); final int spaceDim = ARConfiguration.getCurrentConfig().spaceDimId; @@ -207,7 +252,7 @@ public void update() { } } - // --- BEGIN robust energy gather (mirrors SatelliteTerminal) --- + // --- BEGIN (mirrors SatelliteTerminal) --- final int dimId = world.provider.getDimension(); final boolean dimOk = DimensionManager.getInstance().isDimensionCreated(dimId) || dimId == 0; @@ -264,7 +309,6 @@ public void update() { powerMadeLastTick + " " + LibVulpes.proxy.getLocalizedString("msg.powerunit.rfpertick")); } - // --- END robust energy gather --- } @@ -334,25 +378,324 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompou public NBTTagCompound writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); + // ---- satellites ---- int[] intArray = new int[connectedSatellites.size() * 2]; - for (int i = 0; i < connectedSatellites.size() * 2; i += 2) { - intArray[i] = (connectedSatellites.get(i / 2)).intValue(); - intArray[i + 1] = (int) ((connectedSatellites.get(i / 2) >>> 32)); + intArray[i] = (connectedSatellites.get(i / 2)).intValue(); + intArray[i+1] = (int)((connectedSatellites.get(i / 2) >>> 32)); } - nbt.setIntArray("satilliteList", intArray); + // ---- saved hatch inventories ---- + NBTTagList hatchList = new NBTTagList(); + if (savedHatchInv != null && !savedHatchInv.isEmpty()) { + for (Map.Entry> e : savedHatchInv.entrySet()) { + NBTTagCompound entry = new NBTTagCompound(); + entry.setLong("pos", e.getKey()); + + NBTTagList items = new NBTTagList(); + NonNullList arr = e.getValue(); + for (int slot = 0; slot < arr.size(); slot++) { + ItemStack s = arr.get(slot); + if (s.isEmpty()) continue; + NBTTagCompound it = new NBTTagCompound(); + it.setInteger("slot", slot); + s.writeToNBT(it); + items.appendTag(it); + } + entry.setTag("items", items); + hatchList.appendTag(entry); + } + } + nbt.setTag("savedHatchInv", hatchList); + return nbt; } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); + + // ---- satellites ---- int[] intArray = nbt.getIntArray("satilliteList"); connectedSatellites.clear(); for (int i = 0; i < intArray.length; i += 2) { connectedSatellites.add(intArray[i] | (((long) intArray[i + 1]) << 32)); } + + // ---- saved hatch inventories ---- + savedHatchInv.clear(); + + NBTTagList hatchList = nbt.getTagList("savedHatchInv", 10); + for (int i = 0; i < hatchList.tagCount(); i++) { + NBTTagCompound entry = hatchList.getCompoundTagAt(i); + long posKey = entry.getLong("pos"); + NBTTagList items = entry.getTagList("items", 10); + + int maxSlot = -1; + for (int j = 0; j < items.tagCount(); j++) { + int slot = items.getCompoundTagAt(j).getInteger("slot"); + if (slot > maxSlot) maxSlot = slot; + } + NonNullList arr = NonNullList.withSize(Math.max(maxSlot + 1, 1), ItemStack.EMPTY); + + for (int j = 0; j < items.tagCount(); j++) { + NBTTagCompound it = items.getCompoundTagAt(j); + int slot = it.getInteger("slot"); + arr.set(slot, new ItemStack(it)); + } + savedHatchInv.put(posKey, arr); + } } + + // Push the pre-formation snapshot into the placeholders' replaced inventories (after formation) + private void writeSnapshotIntoPlaceholders() { + if (world == null || savedHatchInv.isEmpty()) return; + + final Object[][][] struct = getStructure(); + if (struct == null) return; + + final Vector3F off = getControllerOffset(struct); + final EnumFacing front = getFrontDirection(world.getBlockState(pos)); + + for (int y = 0; y < struct.length; y++) { + for (int z = 0; z < struct[0].length; z++) { + for (int x = 0; x < struct[0][0].length; x++) { + if (struct[y][z][x] == null) continue; + + int gx = pos.getX() + (x - off.x) * front.getFrontOffsetZ() - (z - off.z) * front.getFrontOffsetX(); + int gy = pos.getY() - y + off.y; + int gz = pos.getZ() - (x - off.x) * front.getFrontOffsetX() - (z - off.z) * front.getFrontOffsetZ(); + BlockPos bp = new BlockPos(gx, gy, gz); + + TileEntity te = world.getTileEntity(bp); + if (!(te instanceof TilePlaceholder)) continue; + + NonNullList snapshot = savedHatchInv.get(bp.toLong()); + if (snapshot == null || snapshot.isEmpty()) continue; + + TileEntity rep = ((TilePlaceholder) te).getReplacedTileEntity(); + if (!(rep instanceof IInventory)) continue; + + IInventory inv = (IInventory) rep; + + // First try to restore to original slots + for (int i = 0; i < snapshot.size(); i++) { + ItemStack src = snapshot.get(i); + if (src.isEmpty()) continue; + ItemStack cur = (i < inv.getSizeInventory()) ? inv.getStackInSlot(i) : ItemStack.EMPTY; + if (i < inv.getSizeInventory() && cur.isEmpty()) { + inv.setInventorySlotContents(i, src.copy()); + snapshot.set(i, ItemStack.EMPTY); + } + } + // Then merge leftovers + for (int i = 0; i < snapshot.size(); i++) { + ItemStack left = snapshot.get(i); + if (left.isEmpty()) continue; + + ItemStack rem = left.copy(); + // merge into existing stacks + for (int slot = 0; slot < inv.getSizeInventory() && !rem.isEmpty(); slot++) { + ItemStack dst = inv.getStackInSlot(slot); + if (dst.isEmpty()) continue; + if (ItemStack.areItemsEqual(dst, rem) && ItemStack.areItemStackTagsEqual(dst, rem)) { + int can = Math.min(inv.getInventoryStackLimit(), dst.getMaxStackSize()) - dst.getCount(); + if (can > 0) { + int move = Math.min(can, rem.getCount()); + dst.grow(move); + rem.shrink(move); + inv.setInventorySlotContents(slot, dst); + } + } + } + // fill empties + for (int slot = 0; slot < inv.getSizeInventory() && !rem.isEmpty(); slot++) { + if (inv.getStackInSlot(slot).isEmpty()) { + int put = Math.min(inv.getInventoryStackLimit(), rem.getMaxStackSize()); + ItemStack putStack = rem.splitStack(put); + inv.setInventorySlotContents(slot, putStack); + } + } + // any remainder stays in snapshot (shouldn’t normally happen) + snapshot.set(i, rem.isEmpty() ? ItemStack.EMPTY : rem); + } + inv.markDirty(); + } + } + } + + // After pushing into placeholders, discard snapshot + savedHatchInv.clear(); + } + + // Pull current contents back out of placeholders' replaced inventories (before teardown) + private void snapshotFromPlaceholders() { + savedHatchInv.clear(); + if (world == null) return; + + final Object[][][] struct = getStructure(); + if (struct == null) return; + + final Vector3F off = getControllerOffset(struct); + final EnumFacing front = getFrontDirection(world.getBlockState(pos)); + + for (int y = 0; y < struct.length; y++) { + for (int z = 0; z < struct[0].length; z++) { + for (int x = 0; x < struct[0][0].length; x++) { + if (struct[y][z][x] == null) continue; + + int gx = pos.getX() + (x - off.x) * front.getFrontOffsetZ() - (z - off.z) * front.getFrontOffsetX(); + int gy = pos.getY() - y + off.y; + int gz = pos.getZ() - (x - off.x) * front.getFrontOffsetX() - (z - off.z) * front.getFrontOffsetZ(); + BlockPos bp = new BlockPos(gx, gy, gz); + + TileEntity te = world.getTileEntity(bp); + + // Prefer the underlying hatch if this position is a placeholder + IInventory inv = null; + if (te instanceof TilePlaceholder) { + TileEntity rep = ((TilePlaceholder) te).getReplacedTileEntity(); + if (rep instanceof TileInventoryHatch) inv = (IInventory) rep; + } else if (te instanceof TileInventoryHatch) { + // Real multiblock component hatch (hidden block), still a live TE + inv = (IInventory) te; + } + + if (inv != null) { + NonNullList copy = NonNullList.withSize(inv.getSizeInventory(), ItemStack.EMPTY); + boolean any = false; + for (int i = 0; i < inv.getSizeInventory(); i++) { + ItemStack s = inv.getStackInSlot(i); + if (!s.isEmpty()) { + copy.set(i, s.copy()); + any = true; + } + } + if (any) savedHatchInv.put(bp.toLong(), copy); + } + } + } + } + } + + + + + private void snapshotHatchInventories() { + savedHatchInv.clear(); + final Object[][][] struct = getStructure(); + if (struct == null || world == null) return; + + final Vector3F off = getControllerOffset(struct); + final EnumFacing front = getFrontDirection(world.getBlockState(pos)); + + for (int y = 0; y < struct.length; y++) { + for (int z = 0; z < struct[0].length; z++) { + for (int x = 0; x < struct[0][0].length; x++) { + if (struct[y][z][x] == null) continue; + + int gx = pos.getX() + (x - off.x) * front.getFrontOffsetZ() - (z - off.z) * front.getFrontOffsetX(); + int gy = pos.getY() - y + off.y; + int gz = pos.getZ() - (x - off.x) * front.getFrontOffsetX() - (z - off.z) * front.getFrontOffsetZ(); + BlockPos bp = new BlockPos(gx, gy, gz); + + if (!world.getChunkFromBlockCoords(bp).isLoaded()) continue; + + TileEntity te = world.getTileEntity(bp); + + // If already replaced, pull from the placeholder’s replaced tile + if (te instanceof TilePlaceholder) te = ((TilePlaceholder) te).getReplacedTileEntity(); + + if (te instanceof IInventory) { + IInventory inv = (IInventory) te; + NonNullList copy = NonNullList.withSize(inv.getSizeInventory(), ItemStack.EMPTY); + boolean any = false; + for (int i = 0; i < inv.getSizeInventory(); i++) { + ItemStack s = inv.getStackInSlot(i); + if (!s.isEmpty()) { + copy.set(i, s.copy()); + any = true; + } + } + if (any) savedHatchInv.put(bp.toLong(), copy); + } + } + } + } + } + + private void restoreHatchInventories() { + if (world == null || savedHatchInv.isEmpty()) return; + + for (Map.Entry> e : savedHatchInv.entrySet()) { + BlockPos bp = BlockPos.fromLong(e.getKey()); + TileEntity te = world.getTileEntity(bp); + + // If placeholder is still present for any reason, restore into the underlying replaced tile + if (te instanceof TilePlaceholder) te = ((TilePlaceholder) te).getReplacedTileEntity(); + + if (te instanceof IInventory) { + IInventory inv = (IInventory) te; + NonNullList items = e.getValue(); + + // naive merge: try to put stacks back in their original slots first, then merge to any slot + // 1) original slots + for (int i = 0; i < items.size(); i++) { + ItemStack src = items.get(i); + if (src.isEmpty()) continue; + ItemStack cur = inv.getStackInSlot(i); + if (cur.isEmpty()) { + inv.setInventorySlotContents(i, src.copy()); + items.set(i, ItemStack.EMPTY); + } + } + // 2) merge leftovers anywhere they fit, otherwise drop + for (int i = 0; i < items.size(); i++) { + ItemStack left = items.get(i); + if (left.isEmpty()) continue; + + ItemStack rem = left.copy(); + // try merging into existing stacks + for (int slot = 0; slot < inv.getSizeInventory() && !rem.isEmpty(); slot++) { + ItemStack dst = inv.getStackInSlot(slot); + if (dst.isEmpty()) continue; + if (ItemStack.areItemsEqual(dst, rem) && ItemStack.areItemStackTagsEqual(dst, rem)) { + int can = Math.min(inv.getInventoryStackLimit(), dst.getMaxStackSize()) - dst.getCount(); + if (can > 0) { + int move = Math.min(can, rem.getCount()); + dst.grow(move); + rem.shrink(move); + inv.setInventorySlotContents(slot, dst); + } + } + } + // fill empty slots + for (int slot = 0; slot < inv.getSizeInventory() && !rem.isEmpty(); slot++) { + if (inv.getStackInSlot(slot).isEmpty()) { + int put = Math.min(inv.getInventoryStackLimit(), rem.getMaxStackSize()); + ItemStack putStack = rem.splitStack(put); + inv.setInventorySlotContents(slot, putStack); + } + } + // drop remainder to world + if (!rem.isEmpty()) { + world.spawnEntity(new EntityItem(world, bp.getX() + 0.5, bp.getY() + 0.5, bp.getZ() + 0.5, rem)); + } + items.set(i, ItemStack.EMPTY); + } + inv.markDirty(); + } else { + // no inventory to restore into → drop all + for (ItemStack s : e.getValue()) { + if (!s.isEmpty()) { + world.spawnEntity(new EntityItem(world, bp.getX() + 0.5, bp.getY() + 0.5, bp.getZ() + 0.5, s.copy())); + } + } + } + } + savedHatchInv.clear(); + } + + } From 3f586e54f7a0e4d1ec6a36d68f892d1810a8fc08 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 12 Nov 2025 15:09:49 +0100 Subject: [PATCH 207/424] Add newline at end of TileMicrowaveReciever.java Fix missing newline at the end of the file. From df18b0d609d6e9b04d378027b4e0f5a8b1dea6d0 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 12 Nov 2025 15:26:27 +0100 Subject: [PATCH 208/424] Update StationAssemblerWrapper to include station block --- .../StationAssemblerWrapper.java | 37 ++++++++++--------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerWrapper.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerWrapper.java index 803ac3d15..496a26307 100644 --- a/src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerWrapper.java +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerWrapper.java @@ -40,28 +40,29 @@ public StationAssemblerWrapper() { @Override public void getIngredients(IIngredients ing) { - // No fluids; only items. - java.util.List> inputs = new java.util.ArrayList<>(2); - inputs.add(java.util.Collections.singletonList(inputHatch)); - inputs.add(java.util.Collections.singletonList(inputChip)); + // --- Inputs (your two visible inputs) --- + java.util.List> inputs = new java.util.ArrayList<>(3); + inputs.add(java.util.Collections.singletonList(inputHatch)); // bay (loader meta 1) + inputs.add(java.util.Collections.singletonList(inputChip)); // empty chip + + // --- Hidden machine block for discoverability (so R/U on block opens this page) --- + ItemStack stationBlock = new ItemStack( + zmaster587.advancedRocketry.api.AdvancedRocketryBlocks.blockStationBuilder + ); + inputs.add(java.util.Collections.singletonList(stationBlock)); + ing.setInputLists(mezz.jei.api.ingredients.VanillaTypes.ITEM, inputs); - // Show both outputs to reflect possible results of "Build". - java.util.List outs = new java.util.ArrayList<>(2); + // --- Outputs (show both possible results of "Build") --- + java.util.List outs = new java.util.ArrayList<>(3); outs.add(outStation); - outs.add(outChipMaybe); - ing.setOutputs(mezz.jei.api.ingredients.VanillaTypes.ITEM, outs); - } + if (outChipMaybe != null && !outChipMaybe.isEmpty()) { + outs.add(outChipMaybe); + } - // Convenience accessors (used by Category layout) - public ItemStack getInputHatch() { return inputHatch; } - public ItemStack getInputChip() { return inputChip; } - public ItemStack getOutStation() { return outStation; } - public ItemStack getOutChipMaybe() { return outChipMaybe; } + // Also include the block as an output so R on the block finds this page too + outs.add(stationBlock); - // Optional: a display/catalyst icon you can use if you decide later. - static ItemStack iconStack() { - // Safe: chip exists and isn’t blacklisted in your ARPlugin snippet. - return new ItemStack(AdvancedRocketryItems.itemSpaceStationChip); + ing.setOutputs(mezz.jei.api.ingredients.VanillaTypes.ITEM, outs); } } From d3aea73048b443ef9c9a1ba24cfad147c1cfcb66 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 12 Nov 2025 15:27:07 +0100 Subject: [PATCH 209/424] Add Station Assembler integration to ARPlugin --- .../integration/jei/ARPlugin.java | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/ARPlugin.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/ARPlugin.java index 57302621c..addaa0c5d 100644 --- a/src/main/java/zmaster587/advancedRocketry/integration/jei/ARPlugin.java +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/ARPlugin.java @@ -50,6 +50,10 @@ import zmaster587.advancedRocketry.integration.jei.satelliteBuilder.SatelliteBuilderCategory; import zmaster587.advancedRocketry.integration.jei.satelliteBuilder.SatelliteBuilderRecipeHandler; import zmaster587.advancedRocketry.integration.jei.satelliteBuilder.SatelliteBuilderRecipeMaker; +import zmaster587.advancedRocketry.integration.jei.stationAssembler.StationAssemblerCategory; +import zmaster587.advancedRocketry.integration.jei.stationAssembler.StationAssemblerRecipeHandler; +import zmaster587.advancedRocketry.integration.jei.stationAssembler.StationAssemblerRecipeMaker; +import zmaster587.advancedRocketry.tile.TileStationAssembler; import zmaster587.advancedRocketry.tile.infrastructure.TileFuelingStation; import zmaster587.advancedRocketry.tile.multiblock.machine.*; import zmaster587.advancedRocketry.tile.satellite.TileSatelliteBuilder; @@ -75,6 +79,7 @@ public class ARPlugin implements IModPlugin { public static final String satelliteBuilderUUID = "zmaster587.AR.satelliteBuilder"; public static final String fuelingStationUUID = "zmaster587.AR.fuelingStation"; public static final String co2ScrubberUUID = "zmaster587.AR.co2scrubber"; + public static final String stationAssemblerUUID = "zmaster587.AR.stationAssembler"; public static IJeiHelpers jeiHelpers; //AR machines can reload recipes. We still need this for JEI to be up-to-date @@ -102,7 +107,8 @@ public void registerCategories(IRecipeCategoryRegistration registry) { new PrecisionLaserEtcherCategory(guiHelper), new SatelliteBuilderCategory(guiHelper), new FuelingStationCategory(guiHelper), - new Co2ScrubberCategory(guiHelper) + new Co2ScrubberCategory(guiHelper), + new StationAssemblerCategory(guiHelper) ); } @@ -150,7 +156,8 @@ public Object getIngredientUnderMouse(GuiModular guiContainer, new PrecisionLaserEtcherRecipeHandler(), new SatelliteBuilderRecipeHandler(), new FuelingStationRecipeHandler(), - new Co2ScrubberRecipeHandler() + new Co2ScrubberRecipeHandler(), + new StationAssemblerRecipeHandler() ); registry.addRecipes(RollingMachineRecipeMaker.getMachineRecipes(jeiHelpers, TileRollingMachine.class), rollingMachineUUID); @@ -167,7 +174,7 @@ public Object getIngredientUnderMouse(GuiModular guiContainer, registry.addRecipes(SatelliteBuilderRecipeMaker.getMachineRecipes(jeiHelpers, TileSatelliteBuilder.class), satelliteBuilderUUID); registry.addRecipes(FuelingStationRecipeMaker.getMachineRecipes(jeiHelpers, TileFuelingStation.class), fuelingStationUUID); registry.addRecipes(Co2ScrubberRecipeMaker.getRecipes(jeiHelpers), co2ScrubberUUID); - + registry.addRecipes(StationAssemblerRecipeMaker.getMachineRecipes(jeiHelpers, TileStationAssembler.class),stationAssemblerUUID); registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockRollingMachine), rollingMachineUUID); registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockLathe), latheUUID); @@ -181,7 +188,9 @@ public Object getIngredientUnderMouse(GuiModular guiContainer, registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockCentrifuge), centrifugeUUID); registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockPrecisionLaserEngraver), precisionLaserEngraverUUID); registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockSatelliteBuilder), satelliteBuilderUUID); - + // Station Assembler catalyst + registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockStationBuilder), stationAssemblerUUID); + registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryItems.itemSpaceStationChip), stationAssemblerUUID); // Co2 Scrubber catalysts registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockCO2Scrubber), co2ScrubberUUID); registry.addRecipeCatalyst(new ItemStack(AdvancedRocketryBlocks.blockOxygenVent), co2ScrubberUUID); From 55185add8f2af404dabc1c618b2831374358f11e Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 12 Nov 2025 15:27:42 +0100 Subject: [PATCH 210/424] Implement StationAssemblerCategory for JEI integration --- .../StationAssemblerCategory.java | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerCategory.java diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerCategory.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerCategory.java new file mode 100644 index 000000000..0b3bfcff8 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/stationAssembler/StationAssemblerCategory.java @@ -0,0 +1,156 @@ +package zmaster587.advancedRocketry.integration.jei.stationAssembler; + +import mezz.jei.api.IGuiHelper; +import mezz.jei.api.gui.IGuiItemStackGroup; +import mezz.jei.api.gui.IRecipeLayout; +import mezz.jei.api.gui.IDrawable; +import mezz.jei.api.gui.IDrawableAnimated; +import mezz.jei.api.gui.IDrawableAnimated.StartDirection; +import mezz.jei.api.gui.IDrawableStatic; +import mezz.jei.api.ingredients.IIngredients; +import mezz.jei.api.recipe.IRecipeCategory; +import net.minecraft.client.Minecraft; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import zmaster587.advancedRocketry.integration.jei.ARPlugin; +import zmaster587.libVulpes.LibVulpes; + +/** + * Compact layout, mirroring the simple two-input / two-output flow: + * Inputs: [Satellite Loader (meta 1)] [Station Chip] + * Outputs: [Packed Station] [Station Chip (when new station)] + */ +public class StationAssemblerCategory implements IRecipeCategory { + + private final IDrawable background; + private final IDrawable icon; + private final IDrawable slotFrame; + private static final int BG_W = 180; + private static final int BG_H = 90; + + private static final ResourceLocation ROCKET_BUILDER_PNG = + new ResourceLocation("advancedrocketry", "textures/gui/rocketBuilder.png"); + + private static final int PB_BACK_U = 76, PB_BACK_V = 93, PB_BACK_W = 8, PB_BACK_H = 52; + private static final int PB_FILL_U = 176, PB_FILL_V = 15, PB_FILL_W = 2, PB_FILL_H = 38; + private static final int PB_INSET_X = 3, PB_INSET_Y = 2; + private static final int ANIM_MS = 100; + private final IDrawable backBar; // background frame (8x52) + private final IDrawableStatic fillStatic; // fill slice (2x38) + private final IDrawableAnimated fillAnim; // animated fill (bottom→top) + private int _x0, _x1, _y0, _y1; + private final int barX; + private final int barY; + + public StationAssemblerCategory(IGuiHelper gui) { + this.background = gui.createBlankDrawable(BG_W, BG_H); + this.icon = gui.createDrawableIngredient( + new net.minecraft.item.ItemStack(zmaster587.advancedRocketry.api.AdvancedRocketryBlocks.blockStationBuilder)); + this.slotFrame = gui.getSlotDrawable(); + + // build drawables from the exact atlas slices + this.backBar = gui.createDrawable(ROCKET_BUILDER_PNG, PB_BACK_U, PB_BACK_V, PB_BACK_W, PB_BACK_H); + this.fillStatic = gui.createDrawable(ROCKET_BUILDER_PNG, PB_FILL_U, PB_FILL_V, PB_FILL_W, PB_FILL_H); + this.fillAnim = gui.createAnimatedDrawable(fillStatic, ANIM_MS, StartDirection.BOTTOM, /*inverted*/ false); + + // position: right edge, centered Y + this.barX = BG_W - PB_BACK_W; + this.barY = (BG_H - PB_BACK_H) / 2; + } + + @Override public String getUid() { return ARPlugin.stationAssemblerUUID; } + @Override + public String getTitle() { + return new net.minecraft.item.ItemStack( + zmaster587.advancedRocketry.api.AdvancedRocketryBlocks.blockStationBuilder + ).getDisplayName(); + } + @Override public String getModName() { return "Advanced Rocketry"; } + @Override public IDrawable getBackground(){ return background; } + @Override public IDrawable getIcon() { return icon; } + + // keep your BG_W, BG_H, progress bar fields as-is... + + @Override + public void setRecipe(IRecipeLayout layout, StationAssemblerWrapper wrapper, IIngredients ing) { + IGuiItemStackGroup items = layout.getItemStacks(); + + // compact columns; roomy rows + final int SLOT = 18; + final int COL_GAP = 2; // close together horizontally + final int ROW_GAP = 24; // more empty space vertically + + final int widthNeeded = SLOT * 2 + COL_GAP; // 38 + final int heightNeeded = SLOT * 2 + ROW_GAP; // 60 + final int left = (BG_W - widthNeeded) / 2; + final int top = (BG_H - heightNeeded) / 2; + + final int x0 = left; + final int x1 = left + SLOT + COL_GAP; + final int y0 = top; + final int y1 = top + SLOT + ROW_GAP; + + // row 1: [ bay | empty chip ] + items.init(0, true, x0, y0); // bay (Satellite Loader meta 1) + items.init(1, true, x1, y0); // empty chip + + // row 2: [ packed item | programmed chip ] + items.init(2, false, x0, y1); // packed station + items.init(3, false, x1, y1); // programmed chip + + // bind ingredients + java.util.List> inLists = + ing.getInputs(mezz.jei.api.ingredients.VanillaTypes.ITEM); + java.util.List> outLists = + ing.getOutputs(mezz.jei.api.ingredients.VanillaTypes.ITEM); + + if (inLists.size() >= 1) items.set(0, inLists.get(0)); + if (inLists.size() >= 2) items.set(1, inLists.get(1)); + if (outLists.size() >= 1) items.set(2, outLists.get(0)); + if (outLists.size() >= 2) items.set(3, outLists.get(1)); + + // programmed chip: strip original tooltip, show only our hint + items.addTooltipCallback((slot, input, stack, tooltip) -> { + if (slot != 3 || stack == null || stack.isEmpty() + || !(stack.getItem() instanceof zmaster587.advancedRocketry.item.ItemStationChip)) return; + + // Only when chip is unprogrammed + if (zmaster587.advancedRocketry.item.ItemStationChip.getUUID(stack) == 0) { + // Vanilla "unprogrammed" text (with and without gray formatting) + final String vanilla = zmaster587.libVulpes.LibVulpes.proxy.getLocalizedString("msg.unprogrammed"); + final String vanillaGray = net.minecraft.util.text.TextFormatting.GRAY + vanilla; + + // Strip just that line (handle formatting/no-format) + tooltip.removeIf(line -> + line.equals(vanillaGray) || + line.equals(vanilla) || + net.minecraft.util.text.TextFormatting.getTextWithoutFormattingCodes(line).equals(vanilla) + ); + + // Insert our JEI-specific hint + tooltip.add(net.minecraft.util.text.TextFormatting.GRAY + + zmaster587.libVulpes.LibVulpes.proxy.getLocalizedString( + "jei.ar.stationAssembler.newStationChipHint" + ) + ); + } + }); + + + // keep for drawing slot frames + this._x0 = x0; this._x1 = x1; this._y0 = y0; this._y1 = y1; + } + + @Override + public void drawExtras(Minecraft mc) { + // progress bar (exact sprite, right-aligned, centered Y) + backBar.draw(mc, barX, barY); + fillAnim.draw(mc, barX + PB_INSET_X, barY + PB_INSET_Y); + + // draw slot frames at the centered positions + slotFrame.draw(mc, _x0, _y0); + slotFrame.draw(mc, _x1, _y0); + slotFrame.draw(mc, _x0, _y1); + slotFrame.draw(mc, _x1, _y1); + } +} From 403e2aacaad9ce1b4fd29c46c5ca3fc587211636 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 12 Nov 2025 15:42:39 +0100 Subject: [PATCH 211/424] Implement TooltipInjector for item tooltips This class handles tooltips for various items in the Advanced Rocketry mod, mapping registry IDs and suffixes to localization keys, and providing dynamic arguments for formatted tooltip lines. --- .../client/TooltipInjector.java | 522 ++++++++++++++++++ 1 file changed, 522 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/client/TooltipInjector.java diff --git a/src/main/java/zmaster587/advancedRocketry/client/TooltipInjector.java b/src/main/java/zmaster587/advancedRocketry/client/TooltipInjector.java new file mode 100644 index 000000000..b2fa67284 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/client/TooltipInjector.java @@ -0,0 +1,522 @@ +package zmaster587.advancedRocketry.client; + +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.resources.I18n; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.client.event.ModelRegistryEvent; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.lwjgl.input.Keyboard; +import zmaster587.advancedRocketry.api.Constants; +import zmaster587.advancedRocketry.api.ARConfiguration; + +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.FluidRegistry; +import zmaster587.advancedRocketry.api.fuel.FuelRegistry; +import zmaster587.advancedRocketry.api.fuel.FuelRegistry.FuelType; + +import javax.annotation.Nullable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Mod.EventBusSubscriber(modid = Constants.modId, value = Side.CLIENT) +public final class TooltipInjector { + + private TooltipInjector() {} + + /** Maps exact registry IDs -> base tooltip lang key */ + private static final Map KEY_BY_ID = new HashMap<>(); + /** Fallback: maps the unlocalized-name tail -> base tooltip lang key */ + private static final Map KEY_BY_SUFFIX = new HashMap<>(); + /** Optional: dynamic args for formatted lines (usually used in .alt.2) */ + @FunctionalInterface interface ArgProvider { Object[] get(ItemStack s); } + private static final Map ARGS_BY_BASEKEY = new HashMap<>(); + /** For items that need per-stack (e.g., meta) keys */ + private static final Map> KEY_RESOLVER_BY_ID = new HashMap<>(); + + + static { + // ---- CO2 Scrubber ---- + KEY_BY_ID.put("advancedrocketry:scrubber", "tooltip.advancedrocketry.scrubber"); + KEY_BY_SUFFIX.put("scrubber", "tooltip.advancedrocketry.scrubber"); + + // ---- Oxygen Vent ---- + KEY_BY_ID.put("advancedrocketry:oxygenvent", "tooltip.advancedrocketry.oxygenvent"); + KEY_BY_SUFFIX.put("oxygenVent", "tooltip.advancedrocketry.oxygenvent"); + + ARGS_BY_BASEKEY.put("tooltip.advancedrocketry.oxygenvent", + s -> new Object[] { ARConfiguration.getCurrentConfig().oxygenVentSize }); + + // ---- Carbon Scrubber Cartridge ---- + KEY_BY_ID.put("advancedrocketry:carbonscrubbercartridge", "tooltip.advancedrocketry.scrubbercart"); + KEY_BY_SUFFIX.put("carbonScrubberCartridge", "tooltip.advancedrocketry.scrubbercart"); + + // ---- Structure Tower ---- + KEY_BY_ID.put("advancedrocketry:structuretower", "tooltip.advancedrocketry.structuretower"); + KEY_BY_SUFFIX.put("structuretower", "tooltip.advancedrocketry.structuretower"); + + // --- ItemUpgrade (meta-based) 6 Space Suit Components--- + KEY_RESOLVER_BY_ID.put("advancedrocketry:itemupgrade", + s -> "tooltip.advancedrocketry.itemupgrade." + s.getItemDamage()); + KEY_RESOLVER_BY_ID.put("advancedrocketry:item_upgrade", + s -> "tooltip.advancedrocketry.itemupgrade." + s.getItemDamage()); + + // ---- Guidance Computer ---- + KEY_BY_ID.put("advancedrocketry:guidancecomputer", "tooltip.advancedrocketry.guidancecomputer"); + KEY_BY_ID.put("advancedrocketry:guidance_computer", "tooltip.advancedrocketry.guidancecomputer"); // just in case + KEY_BY_SUFFIX.put("guidanceComputer", "tooltip.advancedrocketry.guidancecomputer"); + + // ---- Service Monitor ---- + KEY_BY_ID.put("advancedrocketry:servicemonitor", "tooltip.advancedrocketry.servicemonitor"); + KEY_BY_SUFFIX.put("servicemonitor", "tooltip.advancedrocketry.servicemonitor"); + + // ---- Service Station ---- + KEY_BY_ID.put("advancedrocketry:servicestation", "tooltip.advancedrocketry.servicestation"); + KEY_BY_ID.put("advancedrocketry:serviceStation", "tooltip.advancedrocketry.servicestation"); + KEY_BY_SUFFIX.put("serviceStation", "tooltip.advancedrocketry.servicestation"); + + // ---- Gas Charge Pad ---- + KEY_BY_ID.put("advancedrocketry:oxygenCharger", "tooltip.advancedrocketry.oxygencharger"); + KEY_BY_SUFFIX.put("oxygenCharger", "tooltip.advancedrocketry.oxygencharger"); + + // --- Station Controllers + KEY_BY_ID.put("advancedrocketry:orientationcontroller", "tooltip.advancedrocketry.orientationctrl"); + KEY_BY_SUFFIX.put("orientationcontroller", "tooltip.advancedrocketry.orientationctrl"); + KEY_BY_SUFFIX.put("orientationController", "tooltip.advancedrocketry.orientationctrl"); + + KEY_BY_SUFFIX.put("gravityController", "tooltip.advancedrocketry.gravityctrl"); + KEY_BY_ID.put("advancedrocketry:gravitycontroller", "tooltip.advancedrocketry.gravityctrl"); + KEY_BY_SUFFIX.put("gravitycontroller", "tooltip.advancedrocketry.gravityctrl"); + + KEY_BY_ID.put("advancedrocketry:altitudecontroller", "tooltip.advancedrocketry.altitudectrl"); + KEY_BY_SUFFIX.put("altitudeController", "tooltip.advancedrocketry.altitudectrl"); + KEY_BY_SUFFIX.put("altitudecontroller", "tooltip.advancedrocketry.altitudectrl"); + + // ---- Small Airlock Door (ItemDoor tied to blockAirLock) ---- + KEY_BY_ID.put("advancedrocketry:smallairlockdoor", "tooltip.advancedrocketry.smallairlock"); + // Fallback by unloc tail (you set setUnlocalizedName("smallAirlock")) + KEY_BY_SUFFIX.put("smallAirlock", "tooltip.advancedrocketry.smallairlock"); + + // Planet Selectors + KEY_BY_ID.put("advancedrocketry:planetselector", "tooltip.advancedrocketry.planetselector"); + KEY_BY_SUFFIX.put("planetSelector", "tooltip.advancedrocketry.planetselector"); + + KEY_BY_ID.put("advancedrocketry:planetholoselector", "tooltip.advancedrocketry.planetholoselector"); + KEY_BY_SUFFIX.put("planetHoloSelector", "tooltip.advancedrocketry.planetholoselector"); + + // ---- Station Light ---- + KEY_BY_ID.put("advancedrocketry:circlelight", "tooltip.advancedrocketry.circlelight"); + KEY_BY_SUFFIX.put("circleLight", "tooltip.advancedrocketry.circlelight"); + + // ---- Monitoring Station ---- + KEY_BY_ID.put("advancedrocketry:monitoringstation", "tooltip.advancedrocketry.monitoringstation"); + KEY_BY_ID.put("advancedrocketry:monitoring_station", "tooltip.advancedrocketry.monitoringstation"); + KEY_BY_SUFFIX.put("monitoringstation", "tooltip.advancedrocketry.monitoringstation"); + + // ---- Satellite Builder ---- + KEY_BY_ID.put("advancedrocketry:satellitebuilder", "tooltip.advancedrocketry.satellitebuilder"); + KEY_BY_SUFFIX.put("satelliteBuilder", "tooltip.advancedrocketry.satellitebuilder"); + + // ---- Satellite Control Terminal ---- + KEY_BY_ID.put("advancedrocketry:satellitemonitor", "tooltip.advancedrocketry.satellitemonitor"); + KEY_BY_ID.put("advancedrocketry:satellite_monitor", "tooltip.advancedrocketry.satellitemonitor"); + KEY_BY_SUFFIX.put("satelliteMonitor", "tooltip.advancedrocketry.satellitemonitor"); + + // --- Satellite Primary Function (metas 0..6) + KEY_RESOLVER_BY_ID.put("advancedrocketry:satelliteprimaryfunction", s -> { + switch (s.getMetadata() & 7) { + case 0: return "tooltip.advancedrocketry.satfunc.optical"; + case 1: return "tooltip.advancedrocketry.satfunc.composition"; + case 2: return "tooltip.advancedrocketry.satfunc.mass"; + case 3: return "tooltip.advancedrocketry.satfunc.microwave"; + case 4: return "tooltip.advancedrocketry.satfunc.oremapping"; + case 5: return "tooltip.advancedrocketry.satfunc.biomechanger"; + case 6: return "tooltip.advancedrocketry.satfunc.weather"; + default: return null; + } + }); + // (optional camelCase fallback if you ever see it) + KEY_RESOLVER_BY_ID.put("advancedrocketry:satellitePrimaryFunction", + KEY_RESOLVER_BY_ID.get("advancedrocketry:satelliteprimaryfunction")); + + // --- Satellite Power Source (metas 0..1) + KEY_RESOLVER_BY_ID.put("advancedrocketry:satellitepowersource", s -> { + switch (s.getMetadata() & 1) { + case 0: return "tooltip.advancedrocketry.satpower.0"; // Basic solar + case 1: return "tooltip.advancedrocketry.satpower.1"; // Advanced solar + default: return null; + } + }); + KEY_RESOLVER_BY_ID.put("advancedrocketry:satellitePowerSource", + KEY_RESOLVER_BY_ID.get("advancedrocketry:satellitepowersource")); + + // ---- LibVulpes Battery (meta 0..1) ---- + KEY_RESOLVER_BY_ID.put("libvulpes:battery", s -> "tooltip.libvulpes.battery." + (s.getMetadata() & 1)); + + // ---- ID Chips / Chips ---- + KEY_BY_ID.put("advancedrocketry:satelliteidchip", "tooltip.advancedrocketry.satidchip"); + KEY_BY_SUFFIX.put("satelliteIdChip", "tooltip.advancedrocketry.satidchip"); + + KEY_BY_ID.put("advancedrocketry:planetidchip", "tooltip.advancedrocketry.planetidchip"); + KEY_BY_SUFFIX.put("planetIdChip", "tooltip.advancedrocketry.planetidchip"); + + KEY_BY_ID.put("advancedrocketry:stationchip", "tooltip.advancedrocketry.stationchip"); + KEY_BY_SUFFIX.put("stationChip", "tooltip.advancedrocketry.stationchip"); + // registry sometimes: spaceStationChip + KEY_BY_ID.put("advancedrocketry:spacestationchip", "tooltip.advancedrocketry.stationchip"); + KEY_BY_SUFFIX.put("spaceStationChip", "tooltip.advancedrocketry.stationchip"); + + KEY_BY_ID.put("advancedrocketry:elevatorchip", "tooltip.advancedrocketry.elevatorchip"); + KEY_BY_SUFFIX.put("elevatorChip", "tooltip.advancedrocketry.elevatorchip"); + + KEY_BY_ID.put("advancedrocketry:asteroidchip", "tooltip.advancedrocketry.asteroidchip"); + KEY_BY_SUFFIX.put("asteroidChip", "tooltip.advancedrocketry.asteroidchip"); + + // ---- Energy multiblocks ---- + + // Black Hole Generator + KEY_BY_ID.put("advancedrocketry:blackholegenerator", "tooltip.advancedrocketry.blackholegen"); + KEY_BY_SUFFIX.put("blackholegenerator", "tooltip.advancedrocketry.blackholegen"); + + // Microwave Receiver (note: source uses the misspelling "Reciever"; cover both) + KEY_BY_ID.put("advancedrocketry:microwavereciever", "tooltip.advancedrocketry.microwavereceiver"); + KEY_BY_ID.put("advancedrocketry:microwaveReciever", "tooltip.advancedrocketry.microwavereceiver"); + KEY_BY_SUFFIX.put("microwavereciever", "tooltip.advancedrocketry.microwavereceiver"); + KEY_BY_SUFFIX.put("microwaveReciever", "tooltip.advancedrocketry.microwavereceiver"); + // (optional safety if it ever gets corrected) + KEY_BY_ID.put("advancedrocketry:microwavereceiver", "tooltip.advancedrocketry.microwavereceiver"); + KEY_BY_SUFFIX.put("microwaveReceiver", "tooltip.advancedrocketry.microwavereceiver"); + + // ---- Solar Panel (part of multiblock) ---- + KEY_BY_ID.put("advancedrocketry:solarpanel", "tooltip.advancedrocketry.solarpanel"); + KEY_BY_ID.put("advancedrocketry:solarPanel", "tooltip.advancedrocketry.solarpanel"); // just in case + KEY_BY_SUFFIX.put("solarpanel", "tooltip.advancedrocketry.solarpanel"); + KEY_BY_SUFFIX.put("solarPanel", "tooltip.advancedrocketry.solarpanel"); + + // Solar Array + KEY_BY_ID.put("advancedrocketry:solararray", "tooltip.advancedrocketry.solararray"); + KEY_BY_SUFFIX.put("solararray", "tooltip.advancedrocketry.solararray"); + // Solar Array Panel + KEY_BY_ID.put("advancedrocketry:solararraypanel", "tooltip.advancedrocketry.solararraypanel"); + KEY_BY_SUFFIX.put("solararraypanel", "tooltip.advancedrocketry.solararraypanel"); + + // ---- BlockARHatch (registered as advancedrocketry:loader), meta 0..6 ---- + KEY_RESOLVER_BY_ID.put("advancedrocketry:loader", s -> { + final int v = s.getMetadata() & 7; // strip redstone/state bit + switch (v) { + case 0: return "tooltip.advancedrocketry.hatch.databus"; + case 1: return "tooltip.advancedrocketry.hatch.satellite"; + case 2: return "tooltip.advancedrocketry.hatch.item_unloader"; + case 3: return "tooltip.advancedrocketry.hatch.item_loader"; + case 4: return "tooltip.advancedrocketry.hatch.fluid_unloader"; + case 5: return "tooltip.advancedrocketry.hatch.fluid_loader"; + case 6: return "tooltip.advancedrocketry.hatch.gca"; + default: return null; + } + }); + + // ---- Processing / Machines / Multiblocks---- + KEY_BY_ID.put("advancedrocketry:electricarcfurnace", "tooltip.advancedrocketry.arcfurnace"); + KEY_BY_SUFFIX.put("electricArcFurnace", "tooltip.advancedrocketry.arcfurnace"); + + KEY_BY_ID.put("advancedrocketry:rollingmachine", "tooltip.advancedrocketry.rollingmachine"); + KEY_BY_SUFFIX.put("rollingMachine", "tooltip.advancedrocketry.rollingmachine"); + + KEY_BY_ID.put("advancedrocketry:lathe", "tooltip.advancedrocketry.lathe"); + KEY_BY_SUFFIX.put("lathe", "tooltip.advancedrocketry.lathe"); + + KEY_BY_ID.put("advancedrocketry:crystallizer", "tooltip.advancedrocketry.crystallizer"); + KEY_BY_SUFFIX.put("Crystallizer", "tooltip.advancedrocketry.crystallizer"); // note capital C + + KEY_BY_ID.put("advancedrocketry:cuttingmachine", "tooltip.advancedrocketry.cuttingmachine"); + KEY_BY_SUFFIX.put("cuttingMachine", "tooltip.advancedrocketry.cuttingmachine"); + + KEY_BY_ID.put("advancedrocketry:precisionassemblingmachine", "tooltip.advancedrocketry.precisionassembler"); + KEY_BY_SUFFIX.put("precisionAssemblingMachine", "tooltip.advancedrocketry.precisionassembler"); + + KEY_BY_ID.put("advancedrocketry:electrolyser", "tooltip.advancedrocketry.electrolyser"); + KEY_BY_SUFFIX.put("electrolyser", "tooltip.advancedrocketry.electrolyser"); + + KEY_BY_ID.put("advancedrocketry:chemreactor", "tooltip.advancedrocketry.chemreactor"); + KEY_BY_SUFFIX.put("chemreactor", "tooltip.advancedrocketry.chemreactor"); + + KEY_BY_ID.put("advancedrocketry:precisionlaseretcher","tooltip.advancedrocketry.precisionlaseretcher"); + KEY_BY_SUFFIX.put("precisionlaseretcher", "tooltip.advancedrocketry.precisionlaseretcher"); + + KEY_BY_ID.put("advancedrocketry:observatory", "tooltip.advancedrocketry.observatory"); + KEY_BY_SUFFIX.put("observatory", "tooltip.advancedrocketry.observatory"); + + KEY_BY_ID.put("advancedrocketry:planetanalyser", "tooltip.advancedrocketry.planetanalyser"); + KEY_BY_SUFFIX.put("planetanalyser", "tooltip.advancedrocketry.planetanalyser"); + + KEY_BY_ID.put("advancedrocketry:centrifuge", "tooltip.advancedrocketry.centrifuge"); + KEY_BY_SUFFIX.put("centrifuge", "tooltip.advancedrocketry.centrifuge"); + + // ---- Aux / Huge ---- + KEY_BY_ID.put("advancedrocketry:warpcore", "tooltip.advancedrocketry.warpcore"); + KEY_BY_SUFFIX.put("warpCore", "tooltip.advancedrocketry.warpcore"); + + KEY_BY_ID.put("advancedrocketry:beacon", "tooltip.advancedrocketry.beacon"); + KEY_BY_SUFFIX.put("beacon", "tooltip.advancedrocketry.beacon"); + + KEY_BY_ID.put("advancedrocketry:biomescanner", "tooltip.advancedrocketry.biomescan"); + KEY_BY_SUFFIX.put("biomeScanner", "tooltip.advancedrocketry.biomescan"); + + KEY_BY_ID.put("advancedrocketry:railgun", "tooltip.advancedrocketry.railgun"); + KEY_BY_SUFFIX.put("railgun", "tooltip.advancedrocketry.railgun"); + + KEY_BY_ID.put("advancedrocketry:spaceelevatorcontroller", "tooltip.advancedrocketry.spaceelevatorctrl"); + KEY_BY_SUFFIX.put("spaceElevatorController", "tooltip.advancedrocketry.spaceelevatorctrl"); + + // ---- Building / components ---- + KEY_BY_ID.put("advancedrocketry:concrete", "tooltip.advancedrocketry.concrete"); + KEY_BY_SUFFIX.put("concrete", "tooltip.advancedrocketry.concrete"); + + KEY_BY_ID.put("advancedrocketry:blastbrick", "tooltip.advancedrocketry.blastbrick"); + KEY_BY_ID.put("advancedrocketry:blastBrick", "tooltip.advancedrocketry.blastbrick"); + KEY_BY_SUFFIX.put("blastbrick", "tooltip.advancedrocketry.blastbrick"); + KEY_BY_SUFFIX.put("blastBrick", "tooltip.advancedrocketry.blastbrick"); + + // Machines / misc + KEY_BY_ID.put("advancedrocketry:qcrucible", "tooltip.advancedrocketry.qcrucible"); + KEY_BY_SUFFIX.put("qcrucible", "tooltip.advancedrocketry.qcrucible"); + + KEY_BY_ID.put("advancedrocketry:sawblade", "tooltip.advancedrocketry.sawblade"); + KEY_BY_ID.put("advancedrocketry:sawBlade", "tooltip.advancedrocketry.sawblade"); + KEY_BY_SUFFIX.put("sawblade", "tooltip.advancedrocketry.sawblade"); + KEY_BY_SUFFIX.put("sawBlade", "tooltip.advancedrocketry.sawblade"); + + // Atmosphere Terraformer + KEY_BY_ID.put("advancedrocketry:terraformer", "tooltip.advancedrocketry.atmosterraformer"); + KEY_BY_SUFFIX.put("terraformer", "tooltip.advancedrocketry.atmosterraformer"); + + // Area Gravity Controller + KEY_BY_ID.put("advancedrocketry:gravitymachine", "tooltip.advancedrocketry.gravitymachine"); + KEY_BY_SUFFIX.put("gravityMachine", "tooltip.advancedrocketry.gravitymachine"); + KEY_BY_SUFFIX.put("gravitymachine", "tooltip.advancedrocketry.gravitymachine"); + + // Orbital Laser Drill (space laser) + KEY_BY_ID.put("advancedrocketry:spacelaser", "tooltip.advancedrocketry.spacelaser"); + KEY_BY_SUFFIX.put("spaceLaser", "tooltip.advancedrocketry.spacelaser"); + KEY_BY_SUFFIX.put("spacelaser", "tooltip.advancedrocketry.spacelaser"); + + // ---- Vacuum Laser ---- + KEY_BY_ID.put("advancedrocketry:vacuumlaser", "tooltip.advancedrocketry.vacuumlaser"); + KEY_BY_SUFFIX.put("vacuumLaser", "tooltip.advancedrocketry.vacuumlaser"); + KEY_BY_SUFFIX.put("vacuumlaser", "tooltip.advancedrocketry.vacuumlaser"); + + // ---- Pump ---- + KEY_BY_ID.put("advancedrocketry:pump", "tooltip.advancedrocketry.pump"); + KEY_BY_SUFFIX.put("pump", "tooltip.advancedrocketry.pump"); + + // ---- Assemblers ---- + // Rocket Assembler + KEY_BY_ID.put("advancedrocketry:rocketbuilder", "tooltip.advancedrocketry.rocketassembler"); + KEY_BY_SUFFIX.put("rocketbuilder", "tooltip.advancedrocketry.rocketassembler"); // safety + KEY_BY_SUFFIX.put("rocketAssembler", "tooltip.advancedrocketry.rocketassembler"); + + // Space Station Assembler + KEY_BY_ID.put("advancedrocketry:stationbuilder", "tooltip.advancedrocketry.stationassembler"); + KEY_BY_SUFFIX.put("stationbuilder", "tooltip.advancedrocketry.stationassembler"); + KEY_BY_SUFFIX.put("stationAssembler", "tooltip.advancedrocketry.stationassembler"); + + // Deployable Rocket Assembler (unmanned vehicle) + KEY_BY_ID.put("advancedrocketry:deployablerocketbuilder", "tooltip.advancedrocketry.deployablerocketassembler"); + KEY_BY_SUFFIX.put("deployablerocketbuilder", "tooltip.advancedrocketry.deployablerocketassembler"); + KEY_BY_SUFFIX.put("deployableRocketAssembler", "tooltip.advancedrocketry.deployablerocketassembler"); + + // ---- Fuel Tanks ---- + // Monopropellant Fuel Tank + KEY_BY_ID.put("advancedrocketry:fueltank", "tooltip.advancedrocketry.fueltank"); + KEY_BY_ID.put("advancedrocketry:fuelTank", "tooltip.advancedrocketry.fueltank"); + KEY_BY_SUFFIX.put("fuelTank", "tooltip.advancedrocketry.fueltank"); + + // Bipropellant Fuel Tank + KEY_BY_ID.put("advancedrocketry:bipropellantfueltank", "tooltip.advancedrocketry.bipropfueltank"); + KEY_BY_SUFFIX.put("bipropellantfueltank", "tooltip.advancedrocketry.bipropfueltank"); + + // Oxidizer Fuel Tank + KEY_BY_ID.put("advancedrocketry:oxidizerfueltank", "tooltip.advancedrocketry.oxidizerfueltank"); + KEY_BY_SUFFIX.put("oxidizerfueltank", "tooltip.advancedrocketry.oxidizerfueltank"); + + // Nuclear Fuel Tank + KEY_BY_ID.put("advancedrocketry:nuclearfueltank", "tooltip.advancedrocketry.nuclearfueltank"); + KEY_BY_SUFFIX.put("nuclearfueltank", "tooltip.advancedrocketry.nuclearfueltank"); + + // Monoprop tank + ARGS_BY_BASEKEY.put("tooltip.advancedrocketry.fueltank", + s -> new Object[]{ listFluidsFor(FuelType.LIQUID_MONOPROPELLANT, 6) }); + // Biprop fuel tank + ARGS_BY_BASEKEY.put("tooltip.advancedrocketry.bipropfueltank", + s -> new Object[]{ listFluidsFor(FuelType.LIQUID_BIPROPELLANT, 6) }); + // Oxidizer tank + ARGS_BY_BASEKEY.put("tooltip.advancedrocketry.oxidizerfueltank", + s -> new Object[]{ listFluidsFor(FuelType.LIQUID_OXIDIZER, 6) }); + // Nuclear working fluid tank + ARGS_BY_BASEKEY.put("tooltip.advancedrocketry.nuclearfueltank", + s -> new Object[]{ listFluidsFor(FuelType.NUCLEAR_WORKING_FLUID, 6) }); + + // Example for adding more items later (no code changes beyond these lines): + // KEY_BY_ID.put("advancedrocketry:carbonscrubbercartridge", "tooltip.advancedrocketry.scrubbercart"); + // KEY_BY_SUFFIX.put("carbonScrubberCartridge", "tooltip.advancedrocketry.scrubbercart"); + // ARGS_BY_BASEKEY.put("tooltip.advancedrocketry.scrubbercart", s -> new Object[]{ Math.max(0, s.getMaxDamage() - s.getItemDamage()) }); + } + + @SubscribeEvent + public static void onModels(ModelRegistryEvent e) { /* no-op */ } + + @SubscribeEvent + public static void onTooltip(ItemTooltipEvent e) { + final ItemStack stack = e.getItemStack(); + if (stack.isEmpty()) return; + + final List tooltip = e.getToolTip(); + + // Insert before the advanced "modid:item" line when advanced tooltips are on + final int insertAt = (e.getFlags().isAdvanced() && tooltip.size() > 1) + ? tooltip.size() - 1 + : tooltip.size(); + + final Item item = stack.getItem(); + @Nullable final ResourceLocation id = item.getRegistryName(); + String baseKey = null; + + if (id != null) { + java.util.function.Function res = KEY_RESOLVER_BY_ID.get(id.toString()); + if (res != null) { + baseKey = res.apply(stack); // e.g., tooltip.advancedrocketry.itemupgrade.3 + } + if (baseKey == null) { + baseKey = KEY_BY_ID.get(id.toString()); + } + } + + // Fallback: tail of unlocalized name (1.12 style) + if (baseKey == null) { + final String transKey = item.getUnlocalizedName(stack); + final int dot = transKey.lastIndexOf('.'); + if (dot > 0) { + final String tail = transKey.substring(dot + 1); + baseKey = KEY_BY_SUFFIX.get(tail); + } + } + + if (baseKey != null) { + renderShiftAlt(stack, tooltip, baseKey, insertAt); + } + } + + // ----- Generic renderer for base/shift/alt blocks ----- + @SideOnly(Side.CLIENT) + public static void renderShiftAlt(ItemStack s, List t, String baseKey, int idx) { + final ArgProvider ap = ARGS_BY_BASEKEY.get(baseKey); + final boolean hasShift = I18n.hasKey(baseKey + ".shift.1"); + final boolean hasAlt = I18n.hasKey(baseKey + ".alt.1") || ap != null; + + // Base block: base, base.1, base.2, ... + for (int i = 0; i <= 8; i++) { + final String k = (i == 0) ? baseKey : (baseKey + "." + i); + if (!I18n.hasKey(k)) { + if (i == 0) continue; // no bare base line; try .1 anyway + break; // stop when sequence ends + } + t.add(idx++, TextFormatting.GRAY + (ap != null ? I18n.format(k, ap.get(s)) : I18n.format(k))); + } + + // Shift block (shift.1..N) + if (hasShift) { + if (GuiScreen.isShiftKeyDown()) { + for (int i = 1; i <= 8; i++) { + final String k = baseKey + ".shift." + i; + if (!I18n.hasKey(k)) break; + t.add(idx++, TextFormatting.GRAY + (ap != null ? I18n.format(k, ap.get(s)) : I18n.format(k))); + } + } else if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) { + t.add(idx++, TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + + I18n.format("tooltip.advancedrocketry.hold_shift")); + } + } + + // Alt block (alt.1..N) + if (hasAlt) { + if (isAltDown()) { + for (int i = 1; i <= 8; i++) { + final String k = baseKey + ".alt." + i; + if (!I18n.hasKey(k)) break; + t.add(idx++, TextFormatting.GRAY + (ap != null ? I18n.format(k, ap.get(s)) : I18n.format(k))); + } + } else if (I18n.hasKey("tooltip.advancedrocketry.hold_alt")) { + t.add(idx++, TextFormatting.DARK_GRAY.toString() + TextFormatting.ITALIC + + I18n.format("tooltip.advancedrocketry.hold_alt")); + } + } + } + + + + // ----- Helpers ----- + + @SideOnly(Side.CLIENT) + private static String listFluidsFor(FuelType type, int max) { + java.util.List names = new java.util.ArrayList<>(); + for (net.minecraftforge.fluids.Fluid f : FluidRegistry.getRegisteredFluids().values()) { + try { + if (FuelRegistry.instance.isFuel(type, f)) { + // Localized name (1 bucket) + names.add(new FluidStack(f, 1000).getLocalizedName()); + if (names.size() >= max) break; + } + } catch (Throwable t) { + // be defensive against any odd registry states + } + } + if (names.isEmpty()) return I18n.hasKey("tooltip.advancedrocketry.none") ? I18n.format("tooltip.advancedrocketry.none") : "None"; + // if there are more than max, add an ellipsis + int total = 0; + for (net.minecraftforge.fluids.Fluid f : FluidRegistry.getRegisteredFluids().values()) + if (FuelRegistry.instance.isFuel(type, f)) total++; + String s = String.join(", ", names); + return (total > names.size()) ? (s + ", …") : s; + } + + private static int addIfPresentGray(List t, String key, int idx) { + if (I18n.hasKey(key)) { + t.add(idx, TextFormatting.GRAY + I18n.format(key)); + return idx + 1; + } + return idx; + } + + private static int addIfPresentDarkGray(List t, String key, int idx) { + if (I18n.hasKey(key)) { + t.add(idx, TextFormatting.DARK_GRAY + I18n.format(key)); + return idx + 1; + } + return idx; + } + + private static int addIfPresentDarkGrayFmt(List t, String key, int idx, Object... args) { + if (I18n.hasKey(key)) { + t.add(idx, TextFormatting.DARK_GRAY + I18n.format(key, args)); + return idx + 1; + } + return idx; + } + + @SideOnly(Side.CLIENT) + public static int computeInsertIndex(List tooltip, boolean advanced) { + return (advanced && tooltip.size() > 1) ? tooltip.size() - 1 : tooltip.size(); + } + + @SideOnly(Side.CLIENT) + public static boolean isAltDown() { + return Keyboard.isKeyDown(Keyboard.KEY_LMENU) || Keyboard.isKeyDown(Keyboard.KEY_RMENU); + } +} From e8a2ff8255cadd8af82d78c91997e9fd6b57fa19 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 16 Nov 2025 15:53:18 +0100 Subject: [PATCH 212/424] Implement IMultiblock interface in TileRocketMonitoringStation --- .../TileRocketMonitoringStation.java | 347 +++++++++++++++--- 1 file changed, 297 insertions(+), 50 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java index 15bd688a7..b847aed6a 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java @@ -10,13 +10,14 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumFacing; import net.minecraft.util.ITickable; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.eventhandler.EventPriority; - +import zmaster587.libVulpes.tile.IMultiblock; import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.EntityRocketBase; import zmaster587.advancedRocketry.api.IInfrastructure; @@ -26,8 +27,10 @@ import zmaster587.advancedRocketry.api.satellite.SatelliteBase; import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.advancedRocketry.entity.EntityRocket; +import zmaster587.advancedRocketry.entity.EntityStationDeployedRocket; import zmaster587.advancedRocketry.inventory.TextureResources; - +import zmaster587.advancedRocketry.tile.TileRocketAssemblingMachine; +import zmaster587.advancedRocketry.tile.TileUnmannedVehicleAssembler; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.client.util.IndicatorBarImage; import zmaster587.libVulpes.client.util.ProgressBarImage; @@ -38,6 +41,7 @@ import zmaster587.libVulpes.network.PacketHandler; import zmaster587.libVulpes.network.PacketMachine; import zmaster587.libVulpes.tile.IComparatorOverride; +import zmaster587.libVulpes.util.HashedBlockPosition; import zmaster587.libVulpes.util.IAdjBlockUpdate; import zmaster587.libVulpes.util.INetworkMachine; @@ -48,14 +52,25 @@ public class TileRocketMonitoringStation extends TileEntity implements IModularInventory, ITickable, IAdjBlockUpdate, IInfrastructure, ILinkableTile, INetworkMachine, IButtonInventory, IProgressBar, - IComparatorOverride, IGuiCallback { - // ==== TUNABLE TICK THROTTLES ==== + IComparatorOverride, IGuiCallback, IMultiblock { + // 2–3 ticks for height/vel feels live; 5–10 ticks is fine for fuel. private static final int T_HEIGHTVEL_TICKS = 3; // ~6.7 Hz private static final int T_FUEL_TICKS = 10; // ~2 Hz private static final int T_COMPARATOR_TICKS = 3; // match height cadence // ================================= + // Server-only: assembler-driven claim window + private int expectedRocketId = -1; + private long expectedRocketExpiry = 0L; + + // "this rocket belongs to me" + public void markRocketFromAssembler(EntityRocketBase rocket) { + if (world == null || world.isRemote || rocket == null) return; + this.expectedRocketId = rocket.getEntityId(); + this.expectedRocketExpiry = world.getTotalWorldTime() + 40; // ~2 seconds + } + EntityRocketBase linkedRocket; IMission mission; ModuleText missionText; @@ -73,6 +88,9 @@ public class TileRocketMonitoringStation extends TileEntity private int snapHeight = 0, snapVel = 0; private int snapFuel = 0, snapFuelCap = 0; // active fuel (id=2 semantics) private int snapOx = 0, snapOxCap = 0; // oxidizer (id=6 semantics) + private int lastKnownFuelCap = 0; // active fuel cap (mono/bi/nuclear) + private int lastKnownOxCap = 0; // oxidizer cap + // GUI cached fields (client) boolean was_powered = false; @@ -107,6 +125,33 @@ private void pushState() { } } + private boolean isRocketAllowedForMaster(@Nonnull EntityRocketBase rocket) { + // if something is weird, don't block linking + if (world == null || rocket == null) { + return true; + } + + // Free-floating monitor with no master: no restriction + if (!hasMaster()) { + return true; + } + + TileEntity master = getMasterBlock(); + if (!(master instanceof TileUnmannedVehicleAssembler)) { + // Master is some other assembler type: no SD-only restriction + return true; + } + + // From here: this monitor is owned by an *unmanned* vehicle assembler. + // Only accept SD rockets. + if (rocket instanceof EntityStationDeployedRocket) { + return true; + } + + // Anything else is not allowed for this master + return false; + } + private void clearUiStatus() { uiStatus = 0; lastAbortReason = ""; @@ -130,25 +175,59 @@ public TileRocketMonitoringStation() { } ); } + // --- Master / assembler association --- + private HashedBlockPosition masterBlock = new HashedBlockPosition(0, -1, 0); + + @Override + public boolean hasMaster() { + return masterBlock.y > -1; + } + + @Override + public TileEntity getMasterBlock() { + return world == null ? null : world.getTileEntity( + new BlockPos(masterBlock.x, masterBlock.y, masterBlock.z) + ); + } + + @Override + public void setMasterBlock(BlockPos pos) { + masterBlock = new HashedBlockPosition(pos); + } + + @Override + public void setComplete(BlockPos pos) { + } + + @Override + public void setIncomplete() { + masterBlock.y = -1; + } // --- Lifecycle / bus registration --- @Override public void onLoad() { - if (!world.isRemote && !registeredBus) { - MinecraftForge.EVENT_BUS.register(this); - registeredBus = true; - } - if (!world.isRemote && !initPower) { - boolean now = world.isBlockIndirectlyGettingPowered(pos) > 0; - isPoweredCached = now; - was_powered = now; - initPower = true; - } + if (world == null) return; if (!world.isRemote) { - boolean stale = lastStatusTick == 0L || - (world.getTotalWorldTime() - lastStatusTick) > STATUS_STALE_TICKS; + // Only listen to rocket events if we actually have a rocket + if (linkedRocket != null && !registeredBus) { + MinecraftForge.EVENT_BUS.register(this); + registeredBus = true; + primeSnapshotsFromRocket(); // immediate stats/fuel refresh + } + + if (!initPower) { + boolean now = world.isBlockIndirectlyGettingPowered(pos) > 0; + isPoweredCached = now; + was_powered = now; + initPower = true; + } + + // Status staleness handling unchanged: + boolean stale = lastStatusTick == 0L + || (world.getTotalWorldTime() - lastStatusTick) > STATUS_STALE_TICKS; if (stale || (linkedRocket == null && mission == null)) { clearUiStatus(); @@ -157,22 +236,27 @@ public void onLoad() { pushState(); } } - - } + @Override public void invalidate() { super.invalidate(); - // Unregister bus if (!world.isRemote && registeredBus) { MinecraftForge.EVENT_BUS.unregister(this); registeredBus = false; } - // Preserve original unlink-on-destroy semantics + // Tell the assembler that this infra is gone + if (!world.isRemote && hasMaster()) { + TileEntity master = getMasterBlock(); + if (master instanceof TileRocketAssemblingMachine) { + ((TileRocketAssemblingMachine) master).removeConnectedInfrastructure(this); + } + } + if (linkedRocket != null) { linkedRocket.unlinkInfrastructure(this); unlinkRocket(); @@ -183,17 +267,18 @@ public void invalidate() { } } + @Override public void onChunkUnload() { super.onChunkUnload(); - // IMPORTANT: do NOT unlink here — preserve original behavior: - // this tile remains linked across unload/reload and during flight/space. + // This tile remains linked across unload/reload and during flight/space. if (!world.isRemote && registeredBus) { MinecraftForge.EVENT_BUS.unregister(this); registeredBus = false; } } + // --- Redstone power caching via block neighbor callbacks --- @Deprecated @@ -210,10 +295,10 @@ public void onAdjacentBlockUpdated() { // Update cache first so it stays correct even with no rocket linked isPoweredCached = now; - was_powered = now; // optional if you surface this elsewhere + was_powered = now; if (rising && linkedRocket != null) { - linkedRocket.prepareLaunch(); // only on true 0->1 edge + linkedRocket.prepareLaunch(); markDirty(); } } @@ -234,15 +319,104 @@ public boolean disconnectOnLiftOff() { @Override public boolean linkRocket(EntityRocketBase rocket) { + if (rocket == null || world == null) { + return false; + } + + // If we are bound to an assembler, we only trust: + // - the rocket we already own, or + // - a rocket that the assembler just claimed for us. + if (!world.isRemote && hasMaster()) { + final int rocketId = rocket.getEntityId(); + + boolean allowed = false; + + // 1) Already our rocket? Always allow re-connect (teleports, dim changes). + if (this.linkedRocket != null && this.linkedRocket == rocket) { + allowed = true; + } else { + // 2) Else, require a fresh assembler claim. + boolean haveClaim = + (expectedRocketId == rocketId) && + (world.getTotalWorldTime() <= expectedRocketExpiry); + + if (haveClaim) { + allowed = true; + } + } + + if (!allowed) { + // This rocket has us in its infra list, but assembler did NOT bless it. + // Clean its list and refuse. + rocket.unlinkInfrastructure(this); + System.out.println( + "[Monitor] Rejecting rocket EID=" + rocket.getEntityId() + + " for monitor " + pos + + " (no assembler claim; master-bound monitor)" + ); + return false; + } + if (!isRocketAllowedForMaster(rocket)) { + rocket.unlinkInfrastructure(this); + System.out.println( + "[Monitor] Rejecting rocket EID=" + rocket.getEntityId() + + " for monitor " + pos + + " (rocket type not allowed for this master)" + ); + return false; + } + } + + // From here: either we have no master (free-floating infra), + // or the assembler/owner check passed. this.linkedRocket = rocket; - this.lastComparator = -1; - // Haxy gas mission returning case + // Always listen to events on the server + if (!world.isRemote && !registeredBus) { + MinecraftForge.EVENT_BUS.register(this); + registeredBus = true; + } + + // --- debug: monitor <- rocket link (kept) -------------------------- if (!world.isRemote) { - boolean returning = - (rocket instanceof EntityRocket) - && ((EntityRocket) rocket).isInOrbit() - && ((EntityRocket) rocket).isInFlight(); + final int dim = rocket.world.provider.getDimension(); + final int eid = rocket.getEntityId(); + final double rx = rocket.posX, ry = rocket.posY, rz = rocket.posZ; + + final zmaster587.advancedRocketry.api.fuel.FuelRegistry.FuelType ft = + rocket.getRocketFuelType(); + final int fAmt = (ft != null) ? rocket.getFuelAmount(ft) : 0; + final int fCap = (ft != null) ? rocket.getFuelCapacity(ft) : 0; + + int thrust = -1, weight = -1; + if (rocket instanceof zmaster587.advancedRocketry.entity.EntityRocket) { + try { + zmaster587.advancedRocketry.entity.EntityRocket er = + (zmaster587.advancedRocketry.entity.EntityRocket) rocket; + zmaster587.advancedRocketry.api.StatsRocket stats = er.getRocketStats(); + if (stats != null) { + thrust = (int) stats.getThrust(); + weight = (int) stats.getWeight(); + } + } catch (Throwable t) { /* keep simple */ } + } + + System.out.println( + "[Monitor] Linked @ " + pos + + " -> Rocket EID=" + eid + + " dim=" + dim + + " pos=(" + String.format("%.1f, %.1f, %.1f", rx, ry, rz) + ")" + + " fuel=" + (ft == null ? "NONE" : ft.name()) + " " + fAmt + "/" + fCap + + (thrust >= 0 ? (" thrust=" + thrust) : "") + + (weight >= 0 ? (" weight=" + weight) : "") + ); + + // Fresh snapshot + UI as before + primeSnapshotsFromRocket(); + + boolean returning = (rocket instanceof EntityRocket) + && ((EntityRocket) rocket).isInOrbit() + && ((EntityRocket) rocket).isInFlight(); if (returning) { uiStatus = 4; // deorbiting @@ -253,10 +427,13 @@ public boolean linkRocket(EntityRocketBase rocket) { lastStatusTick = 0L; } } + // ------------------------------------------------------------------- + return true; } + @Override public void unlinkRocket() { linkedRocket = null; @@ -283,11 +460,6 @@ public void unlinkRocket() { @Override public void update() { - // ensure we are listening on the bus --- - if (!world.isRemote && !registeredBus) { - MinecraftForge.EVENT_BUS.register(this); - registeredBus = true; - } if (world.isRemote) return; // One-time prime (in case no neighbor event has fired yet) @@ -316,6 +488,9 @@ public void update() { // Idle fast-exit if (linkedRocket == null) { return; } + if (snapFuelCap == 0 && linkedRocket.getRocketFuelType() != null) { + primeSnapshotsFromRocket(); + } // ---- height + velocity snapshots, every T_HEIGHTVEL_TICKS ---- if (++heightVelTick >= Math.max(1, T_HEIGHTVEL_TICKS)) { heightVelTick = 0; @@ -349,6 +524,8 @@ public void update() { snapOx = linkedRocket.getFuelAmount(FuelRegistry.FuelType.LIQUID_OXIDIZER); snapOxCap = linkedRocket.getFuelCapacity(FuelRegistry.FuelType.LIQUID_OXIDIZER); + + refreshCapsFromRocket(); } } @@ -465,6 +642,17 @@ public void onDataPacket(NetworkManager net, SPacketUpdateTileEntity pkt) { readFromNBT(pkt.getNbtCompound()); } + private void refreshCapsFromRocket() { + if (linkedRocket == null) return; + final zmaster587.advancedRocketry.api.fuel.FuelRegistry.FuelType active = linkedRocket.getRocketFuelType(); + snapFuelCap = (active != null) ? linkedRocket.getFuelCapacity(active) : 0; + snapOxCap = linkedRocket.getFuelCapacity(FuelRegistry.FuelType.LIQUID_OXIDIZER); + + // persist fallbacks so a restart still has sane totals + if (snapFuelCap > 0) lastKnownFuelCap = snapFuelCap; + if (snapOxCap > 0) lastKnownOxCap = snapOxCap; + } + @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); @@ -480,13 +668,23 @@ public void readFromNBT(NBTTagCompound nbt) { uiStatus = nbt.getInteger("uiStatus"); lastStatusTick = nbt.getLong("lastStatusTick"); lastAbortReason = nbt.hasKey("abortReason") ? nbt.getString("abortReason") : ""; + lastKnownFuelCap = nbt.getInteger("lastFuelCap"); + lastKnownOxCap = nbt.getInteger("lastOxCap"); + + if (nbt.hasKey("masterY") && nbt.getInteger("masterY") > -1) { + int mx = nbt.getInteger("masterX"); + int my = nbt.getInteger("masterY"); + int mz = nbt.getInteger("masterZ"); + masterBlock = new HashedBlockPosition(mx, my, mz); + } - // --- client: force GUI labels to refresh next frame --- + // client: force GUI labels to refresh if (world != null && world.isRemote) { - lastUiStatusShown = -1; // guarantees next render tick will reapply the text + lastUiStatusShown = -1; } } + @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); @@ -498,9 +696,18 @@ public NBTTagCompound writeToNBT(NBTTagCompound nbt) { nbt.setInteger("uiStatus", uiStatus); nbt.setLong("lastStatusTick", lastStatusTick); nbt.setString("abortReason", lastAbortReason == null ? "" : lastAbortReason); + nbt.setInteger("lastFuelCap", lastKnownFuelCap); + nbt.setInteger("lastOxCap", lastKnownOxCap); + + if (hasMaster()) { + nbt.setInteger("masterX", masterBlock.x); + nbt.setInteger("masterY", masterBlock.y); + nbt.setInteger("masterZ", masterBlock.z); + } return nbt; } + // --- LibVulpes network bridge --- @Override @@ -540,11 +747,24 @@ else if (id == TAB_SWITCH && !world.isRemote) { getWorld(), pos.getX(), pos.getY(), pos.getZ()); } if (id == 100) { - if (linkedRocket != null) + if (linkedRocket != null) { + System.out.println("[MS] Launch clicked @ " + pos + ", linked? " + (linkedRocket!=null)); + // always re-prime before launch to avoid stale weight/fuel decisions + if (linkedRocket instanceof EntityRocket) { + ((EntityRocket) linkedRocket).recalculateStats(); + } + refreshCapsFromRocket(); + primeSnapshotsFromRocket(); // reflect any last-second loading linkedRocket.prepareLaunch(); + } else { + if (!world.isRemote) { + player.sendMessage(new TextComponentTranslation("msg.monitoringStation.noLinkedRocket")); + } + } } } + // --- GUI / Modules --- @Override public List getModules(int ID, EntityPlayer player) { @@ -817,6 +1037,40 @@ else if (id == 6) oxidizerFuelLevel = progress; } + /** Pulls a full, fresh snapshot from the linked rocket and pushes a TE update. */ + private void primeSnapshotsFromRocket() { + if (world == null || world.isRemote) return; + if (linkedRocket == null) return; + + // 1) make sure the rocket’s internal stats are up to date + if (linkedRocket instanceof EntityRocket) { + ((EntityRocket) linkedRocket).recalculateStats(); // calls storage.recalculateStats(stats) + } + + // 2) fresh fuel types/capacities + final zmaster587.advancedRocketry.api.fuel.FuelRegistry.FuelType active = linkedRocket.getRocketFuelType(); + snapFuel = (active != null) ? linkedRocket.getFuelAmount(active) : 0; + snapFuelCap = (active != null) ? linkedRocket.getFuelCapacity(active) : 0; + + snapOx = linkedRocket.getFuelAmount(zmaster587.advancedRocketry.api.fuel.FuelRegistry.FuelType.LIQUID_OXIDIZER); + snapOxCap = linkedRocket.getFuelCapacity(zmaster587.advancedRocketry.api.fuel.FuelRegistry.FuelType.LIQUID_OXIDIZER); + + // keep persisted fallbacks up to date + if (snapFuelCap > 0) lastKnownFuelCap = snapFuelCap; + if (snapOxCap > 0) lastKnownOxCap = snapOxCap; + + // 3) height/velocity + snapHeight = (int) linkedRocket.posY; + snapVel = (int) (linkedRocket.motionY * 100); + + // 4) make comparator reflect fresh height right away + lastComparator = -1; + world.updateComparatorOutputLevel(pos, world.getBlockState(pos).getBlock()); + + // 5) tell clients now (no waiting for the periodic tick) + pushState(); + } + @Override public int getProgress(int id) { // Client: use client-side cached fields (preserve original mission/height quirk) @@ -838,14 +1092,10 @@ public int getProgress(int id) { @Override public int getTotalProgress(int id) { - if (id == 0) - return ARConfiguration.getCurrentConfig().orbit; - else if (id == 1) - return 1000; - else if (id == 2) - return world.isRemote ? maxFuelLevel : snapFuelCap; - else if (id == 6) - return world.isRemote ? maxFuelLevel : snapOxCap; + if (id == 0) return ARConfiguration.getCurrentConfig().orbit; + if (id == 1) return 1000; + if (id == 2) return (world.isRemote ? maxFuelLevel : (snapFuelCap > 0 ? snapFuelCap : lastKnownFuelCap)); + if (id == 6) return (world.isRemote ? maxFuelLevel : (snapOxCap > 0 ? snapOxCap : lastKnownOxCap)); return 1; } @@ -878,16 +1128,13 @@ public boolean linkMission(IMission mission) { pushState(); } } - - PacketHandler.sendToNearby(new PacketMachine(this, (byte) 1), world.provider.getDimension(), getPos(), 16); return true; } @Override public void unlinkMission() { mission = null; - if (missionText != null) setMissionText(); // guard - PacketHandler.sendToNearby(new PacketMachine(this, (byte) 1), world.provider.getDimension(), getPos(), 16); + if (missionText != null) setMissionText(); } @Override From 51399d315656fabe16d3d4fc31698cf9989cbbbc Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 16 Nov 2025 15:53:43 +0100 Subject: [PATCH 213/424] Add newline at end of TileUnmannedVehicleAssembler.java Fix missing newline at end of file. From c1dd8b384fe1b79c9e24ae89249db97e7c2e182f Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 16 Nov 2025 15:54:05 +0100 Subject: [PATCH 214/424] Implement ITickable in TileRocketAssemblingMachine Added ITickable interface to TileRocketAssemblingMachine and implemented update method for relinking infrastructure. --- .../tile/TileRocketAssemblingMachine.java | 96 +++++++++++-------- 1 file changed, 57 insertions(+), 39 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java index 4620d22ff..26884dc4a 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java @@ -14,6 +14,7 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.ITickable; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; @@ -59,7 +60,7 @@ * changed to complete the rocket structure * Also will be used to "build" the rocket components from the placed frames, control fuel flow etc **/ -public class TileRocketAssemblingMachine extends TileEntityRFConsumer implements IButtonInventory, INetworkMachine, IDataSync, IModularInventory, IProgressBar, ILinkableTile { +public class TileRocketAssemblingMachine extends TileEntityRFConsumer implements ITickable, IButtonInventory, INetworkMachine, IDataSync, IModularInventory, IProgressBar, ILinkableTile { protected static final ResourceLocation backdrop = new ResourceLocation("advancedrocketry", "textures/gui/rocketBuilder.png"); protected static final ProgressBarImage verticalProgressBar = new ProgressBarImage(76, 93, 8, 52, 176, 15, 2, 38, 3, 2, EnumFacing.UP, backdrop); @@ -105,8 +106,9 @@ public void onLoad() { registeredBus = true; } if (!world.isRemote) { - relinkRetries = 10; // up to ~10 seconds - nextRelinkAttempt = world.getTotalWorldTime() + 20; // first retry in 1s + relinkRetries = 15; // give it time + nextRelinkAttempt = world.getTotalWorldTime() + 20; + tryRelinkNow(); // best-effort first shot } if (world.isRemote) return; @@ -118,6 +120,10 @@ public void onLoad() { if (!rockets.isEmpty()) { for (IInfrastructure infra : getConnectedInfrastructure()) { for (EntityRocketBase r : rockets) { + if (infra instanceof zmaster587.advancedRocketry.tile.infrastructure.TileRocketMonitoringStation) { + ((zmaster587.advancedRocketry.tile.infrastructure.TileRocketMonitoringStation) infra) + .markRocketFromAssembler(r); + } r.linkInfrastructure(infra); } } @@ -257,42 +263,6 @@ public int getPowerPerOperation() { @Override public void performFunction() { - // Retry linking infra for up to ~10s, but stop early once ALL are linked - if (!world.isRemote && relinkRetries > 0 && world.getTotalWorldTime() >= nextRelinkAttempt) { - - if (bbCache == null) bbCache = getRocketPadBounds(world, pos); - - int expected = blockPos.size(); // how many infra we remember from NBT - if (expected == 0) { relinkRetries = 0; return; } - int found = 0; // how many are currently loaded & obtainable - - if (bbCache != null) { - final AxisAlignedBB box = bbCache.grow(1.0E-4, 1.0E-4, 1.0E-4); - java.util.List rockets = world.getEntitiesWithinAABB(EntityRocketBase.class, box); - - // Only count + link if a rocket is actually on the pad - if (!rockets.isEmpty()) { - java.util.List infraNow = getConnectedInfrastructure(); // only returns loaded TEs - found = infraNow.size(); - - // Link them all (idempotent in AR) - for (EntityRocketBase r : rockets) { - for (IInfrastructure infra : infraNow) { - r.linkInfrastructure(infra); - } - } - } - } - - // Stop early only when we've linked ALL remembered infra positions - if (found >= expected && expected > 0) { - relinkRetries = 0; // done - } else { - relinkRetries--; // try again next second - nextRelinkAttempt = world.getTotalWorldTime() + 20; - } - } - if (!isScanning()) return; if (progress >= (totalProgress * MAXSCANDELAY)) { @@ -683,9 +653,14 @@ public void assembleRocket() { world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 3); for (IInfrastructure infrastructure : getConnectedInfrastructure()) { + if (infrastructure instanceof zmaster587.advancedRocketry.tile.infrastructure.TileRocketMonitoringStation) { + ((zmaster587.advancedRocketry.tile.infrastructure.TileRocketMonitoringStation) infrastructure) + .markRocketFromAssembler(rocket); + } rocket.linkInfrastructure(infrastructure); } + // Rescan so UI immediately reflects the post-build state scanRocket(world, pos, bbCache); } @@ -1297,9 +1272,14 @@ public void onRocketLand(RocketLandedEvent e) { // Track rocket id and (re)link infra lastRocketID = landed.getEntityId(); for (IInfrastructure infra : getConnectedInfrastructure()) { + if (infra instanceof zmaster587.advancedRocketry.tile.infrastructure.TileRocketMonitoringStation) { + ((zmaster587.advancedRocketry.tile.infrastructure.TileRocketMonitoringStation) infra) + .markRocketFromAssembler(landed); + } landed.linkInfrastructure(infra); } + // Maintain original semantics: only fast-path when exactly one rocket in the pad List rockets = world.getEntitiesWithinAABB(EntityRocket.class, box); if (rockets.size() == 1) { @@ -1351,4 +1331,42 @@ public String getErrorCode() { return code; } } + + @Override + public void update() { + super.update(); // << keep RFConsumer’s normal ticking/performFunction() + if (world.isRemote) return; + + if (relinkRetries > 0 && world.getTotalWorldTime() >= nextRelinkAttempt) { + if (tryRelinkNow()) { + relinkRetries = 0; + } else { + relinkRetries--; + nextRelinkAttempt = world.getTotalWorldTime() + 20; // 1s + } + } + } + + private boolean tryRelinkNow() { + if (bbCache == null) bbCache = getRocketPadBounds(world, pos); + if (bbCache == null) return false; + + AxisAlignedBB box = bbCache.grow(1.0e-4,1.0e-4,1.0e-4); + java.util.List rockets = world.getEntitiesWithinAABB(EntityRocketBase.class, box); + if (rockets.isEmpty()) return false; + + java.util.List infraNow = getConnectedInfrastructure(); + if (infraNow.isEmpty()) return false; + + for (EntityRocketBase r : rockets) { + for (IInfrastructure i : infraNow) { + if (i instanceof zmaster587.advancedRocketry.tile.infrastructure.TileRocketMonitoringStation) { + ((zmaster587.advancedRocketry.tile.infrastructure.TileRocketMonitoringStation) i) + .markRocketFromAssembler(r); + } + r.linkInfrastructure(i); + } + } + return true; + } } From 439aa5219a997ccbdc0e6d50d388642e12bf17f0 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 16 Nov 2025 15:58:07 +0100 Subject: [PATCH 215/424] Refactor TileRocketAssemblingMachine for clarity --- .../tile/TileRocketAssemblingMachine.java | 24 ++++++++----------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java index 26884dc4a..719945150 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileRocketAssemblingMachine.java @@ -325,10 +325,10 @@ public AxisAlignedBB scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { double buffer = 0.0001; AxisAlignedBB bufferedBB = bbCache.grow(buffer, buffer, buffer); List rockets = world.getEntitiesWithinAABB(EntityRocket.class, bufferedBB); - if (rockets.size() == 1){ // only if exactly one rocket is here + if (rockets.size() == 1){ rockets.get(0).recalculateStats(); this.stats = rockets.get(0).stats; - status = ErrorCodes.ALREADY_ASSEMBLED; // to prevent assembly + status = ErrorCodes.ALREADY_ASSEMBLED; return null; } } @@ -514,10 +514,10 @@ public AxisAlignedBB scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { int totalFuelUse = bipropellantfuelUse + nuclearWorkingFluidUse + monopropellantfuelUse; //System.out.println("rocket fuel use:"+totalFuelUse); - // --- Biprop requirement: if any bipropellant thrust exists, require both tanks --- + // Biprop requirement: if any bipropellant thrust exists, require both tanks if (thrustBipropellant > 0) { if (fuelCapacityBipropellant <= 0 || fuelCapacityOxidizer <= 0) { - status = ErrorCodes.NOFUEL; // or a dedicated error if you add one + status = ErrorCodes.NOFUEL; return new AxisAlignedBB(actualMinX, actualMinY, actualMinZ, actualMaxX, actualMaxY, actualMaxZ); } } @@ -563,7 +563,7 @@ public AxisAlignedBB scanRocket(World world, BlockPos pos2, AxisAlignedBB bb) { int maxYi = Math.max(actualMaxY, actualMinY); int maxZi = Math.max(actualMinZ, actualMaxZ); - // IMPORTANT: use BlockPos ctor so the AABB is [min, max+1) in block space + // use BlockPos ctor so the AABB is [min, max+1) in block space return new AxisAlignedBB( new BlockPos(minXi, minYi, minZi), new BlockPos(maxXi, maxYi, maxZi) @@ -610,7 +610,7 @@ public void assembleRocket() { // server only + need a pad cache if (world.isRemote || bbCache == null) return; - // Re-scan to get a *tight* non-air AABB and fresh stats/status + // Re-scan to get a tight non-air AABB and fresh stats/status final AxisAlignedBB scanBB = scanRocket(world, pos, bbCache); if (status != ErrorCodes.SUCCESS || scanBB == null) return; @@ -628,7 +628,7 @@ public void assembleRocket() { final StorageChunk storageChunk; try { storageChunk = StorageChunk.cutWorldBB(world, rocketBB); - } catch (Throwable t) { // covers NegativeArraySizeException & other edge errors + } catch (Throwable t) { // cover NegativeArraySizeException & other edge errors status = ErrorCodes.FAIL_CUT; return; } @@ -1118,7 +1118,7 @@ public int getData(int id) { switch (id) { case 0: - return (int)(getRocketStats().getWeight_NoFuel()*1000);// because it is a float really so take it *1000 + return (int)(getRocketStats().getWeight_NoFuel()*1000); case 1: return getRocketStats().getThrust(); case 2: @@ -1160,7 +1160,6 @@ public int getData(int id) { @Override public void onInventoryButtonPressed(int buttonId) { PacketHandler.sendToServer(new PacketMachine(this, (byte) (buttonId))); - //updateText(); } @Override @@ -1241,7 +1240,6 @@ public void removeConnectedInfrastructure(TileEntity tile) { public List getConnectedInfrastructure() { List list = new LinkedList<>(); - // Don't mutate blockPos here; tiles may not be loaded yet for (HashedBlockPosition position : blockPos) { TileEntity te = world.getTileEntity(position.getBlockPos()); if (te instanceof IInfrastructure) { @@ -1280,7 +1278,7 @@ public void onRocketLand(RocketLandedEvent e) { } - // Maintain original semantics: only fast-path when exactly one rocket in the pad + // only fast-path when exactly one rocket in the pad List rockets = world.getEntitiesWithinAABB(EntityRocket.class, box); if (rockets.size() == 1) { EntityRocket r = rockets.get(0); @@ -1293,8 +1291,6 @@ public void onRocketLand(RocketLandedEvent e) { // Fallback: rescan if something odd happens scanRocket(world, pos, bbCache); } - - // Preserve original networking PacketHandler.sendToPlayersTrackingEntity(new PacketMachine(this, (byte)3), landed); } @@ -1334,7 +1330,7 @@ public String getErrorCode() { @Override public void update() { - super.update(); // << keep RFConsumer’s normal ticking/performFunction() + super.update(); if (world.isRemote) return; if (relinkRetries > 0 && world.getTotalWorldTime() >= nextRelinkAttempt) { From 5c40c623d06efb6c614a43873dfb8cc022f35fba Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 16 Nov 2025 16:07:14 +0100 Subject: [PATCH 216/424] Remove debug logging from TileRocketMonitoringStation Removed debug print statements related to rocket monitoring. --- .../TileRocketMonitoringStation.java | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java index b847aed6a..8630d1b6c 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java @@ -349,20 +349,10 @@ public boolean linkRocket(EntityRocketBase rocket) { // This rocket has us in its infra list, but assembler did NOT bless it. // Clean its list and refuse. rocket.unlinkInfrastructure(this); - System.out.println( - "[Monitor] Rejecting rocket EID=" + rocket.getEntityId() + - " for monitor " + pos + - " (no assembler claim; master-bound monitor)" - ); return false; } if (!isRocketAllowedForMaster(rocket)) { rocket.unlinkInfrastructure(this); - System.out.println( - "[Monitor] Rejecting rocket EID=" + rocket.getEntityId() + - " for monitor " + pos + - " (rocket type not allowed for this master)" - ); return false; } } @@ -377,7 +367,6 @@ public boolean linkRocket(EntityRocketBase rocket) { registeredBus = true; } - // --- debug: monitor <- rocket link (kept) -------------------------- if (!world.isRemote) { final int dim = rocket.world.provider.getDimension(); final int eid = rocket.getEntityId(); @@ -401,16 +390,6 @@ public boolean linkRocket(EntityRocketBase rocket) { } catch (Throwable t) { /* keep simple */ } } - System.out.println( - "[Monitor] Linked @ " + pos + - " -> Rocket EID=" + eid + - " dim=" + dim + - " pos=(" + String.format("%.1f, %.1f, %.1f", rx, ry, rz) + ")" + - " fuel=" + (ft == null ? "NONE" : ft.name()) + " " + fAmt + "/" + fCap + - (thrust >= 0 ? (" thrust=" + thrust) : "") + - (weight >= 0 ? (" weight=" + weight) : "") - ); - // Fresh snapshot + UI as before primeSnapshotsFromRocket(); @@ -427,8 +406,6 @@ public boolean linkRocket(EntityRocketBase rocket) { lastStatusTick = 0L; } } - // ------------------------------------------------------------------- - return true; } @@ -748,7 +725,6 @@ else if (id == TAB_SWITCH && !world.isRemote) { } if (id == 100) { if (linkedRocket != null) { - System.out.println("[MS] Launch clicked @ " + pos + ", linked? " + (linkedRocket!=null)); // always re-prime before launch to avoid stale weight/fuel decisions if (linkedRocket instanceof EntityRocket) { ((EntityRocket) linkedRocket).recalculateStats(); From a1225c9399a9de258bc2fa5c828c8cf3291e3b48 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 16 Nov 2025 16:07:45 +0100 Subject: [PATCH 217/424] Add newline at end of EntityStationDeployedRocket.java Fix missing newline at end of file. From 7fd017e88fdb445e8903ec514a5dad10edc45999 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 16 Nov 2025 16:08:25 +0100 Subject: [PATCH 218/424] Refactor comment for clarity in TileFuelingStation --- .../tile/infrastructure/TileFuelingStation.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java index 2bc3aa5c1..8733f8fd5 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileFuelingStation.java @@ -62,7 +62,7 @@ public class TileFuelingStation extends TileInventoriedRFConsumerTank implements // Cache last emitted redstone to avoid duplicate updates private Boolean lastRs = null; - // Small perf win: cache resolved fluids from rocket stats + // Cache resolved fluids from rocket stats private String lastFuelStr = null, lastOxStr = null, lastWorkStr = null; private Fluid cachedFuelFluid = null, cachedOxFluid = null, cachedWorkFluid = null; From f6e64bd25461a4069d79bc4ede58abb3c66fe2db Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 16 Nov 2025 16:09:47 +0100 Subject: [PATCH 219/424] Fix missing newline at end of TooltipInjector.java From 13acc9b7364380c0c9b988441132728ccad9c21d Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 16 Nov 2025 16:10:16 +0100 Subject: [PATCH 220/424] Refactor language file for item and tile names Updated various item and tile names for clarity and consistency. Adjusted tooltips and descriptions for several components, including solar panels, weather controllers, and hovercraft. --- .../assets/advancedrocketry/lang/en_US.lang | 650 +++++++++++++++++- 1 file changed, 643 insertions(+), 7 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index ca09d5df2..59217f53f 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -136,7 +136,7 @@ tile.precisionlaseretcher.name=Precision Laser Etcher tile.enrichedLavaBlock.name=Enriched Lava Block tile.basalt.name=Basalt tile.landingfloat.name=Landing Float -tile.solararray.name=Solar Array +tile.solararray.name=Solar Array Controller tile.solararraypanel.name=Solar Array Panel tile.serviceStation.name=Service Station @@ -187,12 +187,12 @@ item.itemUpgrade.4.name=Anti-Fog Visor item.itemUpgrade.5.name=Earthbright Visor item.atmAnalyser.name=Atmosphere Analyzer item.biomeChanger.name=Biome Changer Remote -item.weatherController.name=Weather Satellite Remote +item.weatherController.name=Weather Remote item.basicLaserGun.name=Basic Laser Gun item.beaconFinder.name=Beacon Finder item.thermite.name=Thermite item.hovercraft.name=Hovercraft -item.hovercraft.tooltip=Long lasting dilithium power source. It'll probably outlive you. +item.hovercraft.tooltip=Long lasting dilithium Power source. It'll probably outlive you. item.jetPack.name=Suit Jetpack item.pressureTank.0.name=Low Pressure Tank @@ -339,7 +339,7 @@ msg.monitoringStation.deorbiting=Returned from orbit! msg.monitoringStation.landed=Landed msg.monitoringStation.aborted=Aborted! msg.monitoringStation.returningToDock=Returning to dock - +msg.monitoringStation.noLinkedRocket=Not Linked to any Rocket! msg.guidanceComputerHatch.loadingState=Loading State: msg.guidanceComputerHatch.ejectonlanding=Auto Eject Upon Landing @@ -359,7 +359,7 @@ msg.rocketLoader.allowredstoneinput=Allow redstone input msg.rocketLoader.allowredstoneoutput=Allow redstone output msg.rocketLoader.none=None msg.rocketLoader.link=You program the linker with the rocket loader at: -msg.microwaverec.notgenerating=Generating 0 FE/t +msg.microwaverec.notgenerating=Generating 0 RF/t msg.microwaverec.generating=Generating msg.abdp.compositionresearch=Composition Research msg.abdp.distanceresearch=Distance Research @@ -521,11 +521,11 @@ msg.wirelessTransciever.type=Type: %s msg.wirelessTransciever.network=Network: msg.wirelessTransciever.network.unlinked=Unlinked -msg.powerunit.rfpertick=FE/t +msg.powerunit.rfpertick=RF/t msg.linker.error.firstMachine=This must be the first machine to link! msg.linker.program=Coordinates programmed into Linker msg.linker.success=Linked Sucessfully -msg.notenoughpower=Not Enough power! +msg.notenoughpower=Not Enough Power! msg.empty=Empty msg.yes=yes msg.no=no @@ -549,8 +549,644 @@ commands.weather.always_not_clear=This planet is always not clear... commands.weather.cannot_rain=Cannot start a rain here commands.weather.cannot_thunder=Cannot start a thunder here +# Jeistuff jei.sb.satellitepreview=Ready for orbit! jei.sb.copy.source=Source jei.sb.copy.output=New Copy jei.sb.assemblyhint=Atleast one solar panel jei.sb.copychiphint=Make backups! + +jei.ar.fuel.role.monopropellant=Monopropellant Fuel +jei.ar.fuel.role.biprop_fuel=Bipropellant Fuel +jei.ar.fuel.role.oxidizer=Oxidizer +jei.ar.fuel.role.working_fluid=Working Fluid +jei.ar.stationAssembler.newStationChipHint=§cThis Points to the new Station! + +# Generic hint +tooltip.advancedrocketry.hold_shift=Hold §eShift§7 for details +tooltip.advancedrocketry.hold_alt=Hold §eAlt§7 for advanced tips + +# Fuel Tank (monoprop) +tooltip.advancedrocketry.fueltank=§cPart of Rocket +tooltip.advancedrocketry.fueltank.shift.1=§fHolds: §b%s +tooltip.advancedrocketry.fueltank.alt.1=Lets Rockety Rockrock! + +# Bipropellant Fuel Tank +tooltip.advancedrocketry.bipropfueltank=§cPart of Rocket +tooltip.advancedrocketry.bipropfueltank.shift.1=§fHolds: §b%s +tooltip.advancedrocketry.bipropfueltank.alt.1=§fBipropellant Rocket requires §bBipropellant§f and §bOxidizer§f tanks + +# Oxidizer Fuel Tank +tooltip.advancedrocketry.oxidizerfueltank=§cPart of Rocket +tooltip.advancedrocketry.oxidizerfueltank.shift.1=§fHolds: §b%s +tooltip.advancedrocketry.oxidizerfueltank.alt.1=§fBipropellant Rocket requires §bBipropellant§f and §bOxidizer§f tanks + +# Nuclear Fuel Tank +tooltip.advancedrocketry.nuclearfueltank=§cPart of Rocket +tooltip.advancedrocketry.nuclearfueltank.shift.1=§fHolds: §b%s +tooltip.advancedrocketry.nuclearfueltank.alt.1=§fRequires §bNuclear Core§f and §bNuclear Engine + +# Monopropellant Engine +tooltip.advancedrocketry.monopropmotor=§cPart of Rocket +tooltip.advancedrocketry.monopropmotor.shift.1=Uses §bMonopropellant Fuel§7 +tooltip.advancedrocketry.monopropmotor.alt.1=Check Fueling Station JEI-page + +# Nuclear Core +tooltip.advancedrocketry.nuclearcore=§cPart of Rocket +tooltip.advancedrocketry.nuclearcore.shift.1=Needs to be directly on top of a +tooltip.advancedrocketry.nuclearcore.shift.2=Nuclear Engine or another Nuclear Core. +tooltip.advancedrocketry.nuclearcore.alt.1=Vertical placement rules doesn't apply +tooltip.advancedrocketry.nuclearcore.alt.2=for Unmanned Vehicles (Gas Mission rockets) + +# Nuclear rocketengine +tooltip.advancedrocketry.nuclearmotor=§cPart of Rocket §6Allows planetary travel! +tooltip.advancedrocketry.nuclearmotor.shift.1=Uses §bWorking fluid§7 +tooltip.advancedrocketry.nuclearmotor.shift.2=Needs Nuclear Core directly above. +tooltip.advancedrocketry.nuclearmotor.alt.1=Check Fueling Station JEI-page + +# Bipropellant Engine +tooltip.advancedrocketry.bipropmotor=§cPart of Rocket +tooltip.advancedrocketry.bipropmotor.shift.1=Uses §bBipropellant Fuel§7 and §bOxidizer§7 +tooltip.advancedrocketry.bipropmotor.alt.1=Check Fueling Station JEI-page + +# Drill +tooltip.advancedrocketry.drill=§cPart of Rocket +tooltip.advancedrocketry.drill.shift.1=Lowers duration of §6Mining Missions§7 +tooltip.advancedrocketry.drill.shift.2=§bEffect stacks +tooltip.advancedrocketry.drill.alt.1=This rocket is built with Rocket Assembling Machine +tooltip.advancedrocketry.drill.alt.2=Requires a programmed Asteroid Chip + +# Gas Intake +tooltip.advancedrocketry.intake=§cPart of Rocket +tooltip.advancedrocketry.intake.shift.1=Lowers duration of §6Gas Missions§7 +tooltip.advancedrocketry.intake.shift.2=§bEffect stacks +tooltip.advancedrocketry.intake.alt.1=This rocket is built with Unmanned Vehicle Assembler +tooltip.advancedrocketry.intake.alt.2=Launched from Space Station orbiting a Gas giant + +# Seat +tooltip.advancedrocketry.seat=§cPart of rocket +tooltip.advancedrocketry.seat.shift.1=Adds a passenger slot to the rocket + +# Guidance Computer +tooltip.advancedrocketry.guidancecomputer=§cPart of Rocket +tooltip.advancedrocketry.guidancecomputer.shift.1=Insert a §cChip§7 or programmed §cLinker§7 +tooltip.advancedrocketry.guidancecomputer.alt.1=Remember to tell rocket which planet to target +tooltip.advancedrocketry.guidancecomputer.alt.2=when deploying Satellites or Space Station into orbit + +# Service Monitor +tooltip.advancedrocketry.servicemonitor=§cPart of Rocket +tooltip.advancedrocketry.servicemonitor.shift.1=Enables damage view +tooltip.advancedrocketry.servicemonitor.shift.2=in rocket GUI +tooltip.advancedrocketry.servicemonitor.alt.1=WIP +tooltip.advancedrocketry.servicemonitor.alt.2= + +# Docking Pad (landingPad) +tooltip.advancedrocketry.landingpad=Replace the launchpad’s center block with this +tooltip.advancedrocketry.landingpad.shift.1=§cLinker§7 can store this block's exact position (dimension-aware). +tooltip.advancedrocketry.landingpad.shift.2=Insert in §4Guidance Computer§7 to land here. +tooltip.advancedrocketry.landingpad.alt.1=Place a programmed Linker in the Docking Pad. +tooltip.advancedrocketry.landingpad.alt.2=Rockets launched from this pad will fly to the Linker’s saved coordinates (used for automation). +tooltip.advancedrocketry.landingpad.alt.3=if there is nothing in the rocket's guidance computer. + +# Launch Pad +tooltip.advancedrocketry.launchpad=Base for Launch Pad platform. +tooltip.advancedrocketry.launchpad.shift.1=Place Launch Pad blocks in a flat square. +tooltip.advancedrocketry.launchpad.shift.2=3x3, 4x4, 5x5, .... +tooltip.advancedrocketry.launchpad.alt.1=§bAdd Structure Tower (minimum 4 high, starting at same y as Launch Pad) +tooltip.advancedrocketry.launchpad.alt.2=§fRocket/Station Assembler will connect automatically + +# Structure Tower +tooltip.advancedrocketry.structuretower=Vertical support for the Launch Pad platform. +tooltip.advancedrocketry.structuretower.shift.1=Tower must be minimum 4 blocks. +tooltip.advancedrocketry.structuretower.shift.2=Bottom block must touch the Launch Pad. +tooltip.advancedrocketry.structuretower.alt.1=Main block for Unmanned Vehicle Assembler structure +tooltip.advancedrocketry.structuretower.alt.2=Check wiki for more info. + +# Terraformer +tooltip.advancedrocketry.terraformer=Terraform +tooltip.advancedrocketry.terraformer.shift.1=Terraform stuff +tooltip.advancedrocketry.terraformer.shift.2= +tooltip.advancedrocketry.terraformer.alt.1=Terraform stuff +tooltip.advancedrocketry.terraformer.alt.2= + +# Rocket Monitoring Station +tooltip.advancedrocketry.monitoringstation=§cInfrastructure +tooltip.advancedrocketry.monitoringstation.shift.1=Launch with Redstone Signal! +tooltip.advancedrocketry.monitoringstation.shift.2=§fLink to §4Rocket Assembler/Dockingpad§f or §4Rocket +tooltip.advancedrocketry.monitoringstation.alt.1=§bMissions becomes active when orbit reached! + +# Satellite Terminal +tooltip.advancedrocketry.satellitemonitor=Communicates with Satellites +tooltip.advancedrocketry.satellitemonitor.shift.1=Insert Satellite Chip +tooltip.advancedrocketry.satellitemonitor.shift.2=Download Data +tooltip.advancedrocketry.satellitemonitor.alt.1=§fTransfer and Auto-Download Data with Wireless Tranciever or Data Unit + +# Satellite Builder +tooltip.advancedrocketry.satellitebuilder=Assembles Satellites +tooltip.advancedrocketry.satellitebuilder.shift.1=Also Copy Chips/Remotes. +tooltip.advancedrocketry.satellitebuilder.shift.2=§bMust be on top of a Power Plug! +tooltip.advancedrocketry.satellitebuilder.alt.1=Insert chassis, Chip/Remote +tooltip.advancedrocketry.satellitebuilder.alt.2=core component + other components + + +### Infrastructure +## BlockARHatch + +# TileDataBus +tooltip.advancedrocketry.hatch.databus=Capacity: §62000 §7Data +tooltip.advancedrocketry.hatch.databus.shift.1=§bCan only hold one type of Data + +# TileSatelliteHatch +tooltip.advancedrocketry.hatch.satellite=§cPart of Rocket +tooltip.advancedrocketry.hatch.satellite.shift.1=Used to put payloads in orbit +tooltip.advancedrocketry.hatch.satellite.shift.2=Remember to set target planet for orbit! +tooltip.advancedrocketry.hatch.satellite.alt.1=§fUsed in §4Station Assembler§f to pack and store the Station + +# TileRocketUnloader +tooltip.advancedrocketry.hatch.item_unloader=§cInfrastructure +tooltip.advancedrocketry.hatch.item_unloader.shift.1=Emits redstone when empty +tooltip.advancedrocketry.hatch.item_unloader.alt.1=§fLink to §4Rocket Assembler/Dockingpad§f or §4Rocket +tooltip.advancedrocketry.hatch.item_unloader.alt.2=§fRockets landing here will auto-link to this. + +# TileRocketLoader +tooltip.advancedrocketry.hatch.item_loader=§cInfrastructure +tooltip.advancedrocketry.hatch.item_loader.shift.1=Emits redstone when full +tooltip.advancedrocketry.hatch.item_loader.alt.1=§fLink to §4Rocket Assembler/Dockingpad§f or §4Rocket +tooltip.advancedrocketry.hatch.item_loader.alt.2=§fRockets landing here will auto-link to this. + +# TileRocketFluidUnloader +tooltip.advancedrocketry.hatch.fluid_unloader=§cInfrastructure +tooltip.advancedrocketry.hatch.fluid_unloader.shift.1=Emits redstone when empty +tooltip.advancedrocketry.hatch.fluid_unloader.alt.1=§fLink to §4Rocket Assembler/Dockingpad§f or §4Rocket +tooltip.advancedrocketry.hatch.fluid_unloader.alt.2=§fRockets landing here will auto-link to this. + +# TileRocketFluidLoader +tooltip.advancedrocketry.hatch.fluid_loader=§cInfrastructure +tooltip.advancedrocketry.hatch.fluid_loader.shift.1=Emits redstone when full +tooltip.advancedrocketry.hatch.fluid_loader.alt.1=§fLink to §4Rocket Assembler/Dockingpad§f or §4Rocket +tooltip.advancedrocketry.hatch.fluid_loader.alt.2=§fRockets landing here will auto-link to this. + +# Guidance Computer Access +tooltip.advancedrocketry.hatch.gca=§cInfrastructure +tooltip.advancedrocketry.hatch.gca.shift.1=Emits redstone when empty +tooltip.advancedrocketry.hatch.gca.alt.1=§fLink to §4Rocket Assembler/Dockingpad§f or §4Rocket +tooltip.advancedrocketry.hatch.gca.alt.2=§fRockets landing here will auto-link to this. + +## /BlockARHatch + +# Fueling Station +tooltip.advancedrocketry.fuelingstation=§cInfrastructure +tooltip.advancedrocketry.fuelingstation.shift.1=Emits redstone when full +tooltip.advancedrocketry.fuelingstation.shift.2=if station has same fueltype. +tooltip.advancedrocketry.fuelingstation.alt.1=§fLink to §4Rocket Assembler/Dockingpad§f or §4Rocket +tooltip.advancedrocketry.fuelingstation.alt.2=§fRockets landing here will auto-link to this. + +# Service Station +tooltip.advancedrocketry.servicestation=§cInfrastructure +tooltip.advancedrocketry.servicestation.shift.1=Repair rocket +tooltip.advancedrocketry.servicestation.shift.2=§o(WIP) +tooltip.advancedrocketry.fuelingstation.alt.1=§fLink to §4Rocket Assembler/Dockingpad§f or §4Rocket + +## // Infrastructure + +# Pressurized Fluid Tank +tooltip.advancedrocketry.fluidtank.shift.1=§cConnects to tanks above or below to make a bigger tank + +# Wireless Transciever +tooltip.advancedrocketry.transceiver=Transfers §6Data +tooltip.advancedrocketry.transceiver.shift.1=Use §cLinker§7 to create Networks +tooltip.advancedrocketry.transceiver.shift.2=Supports multiple Tranceivers +tooltip.advancedrocketry.transceiver.alt.1=§fExtractmode toggles autodownload from Terminal +tooltip.advancedrocketry.transceiver.alt.2=(reinsert chip if stale) + +# Atmosphere Detector +tooltip.advancedrocketry.atmosphereDetector=Emits redstone based on Atmosphere +tooltip.advancedrocketry.atmosphereDetector.shift.1=Select wanted Atmosphere +tooltip.advancedrocketry.atmosphereDetector.shift.2=emits if the condition is true +tooltip.advancedrocketry.atmosphereDetector.alt.1=Can detect: air, vacuum, +tooltip.advancedrocketry.atmosphereDetector.alt.2=low O₂, No O₂, very hot and more. + +# Station Light +tooltip.advancedrocketry.circlelight=Always on +tooltip.advancedrocketry.circlelight.shift.1=Does not require +tooltip.advancedrocketry.circlelight.shift.2=Power or Redstone + +# Gas Charge Pad +tooltip.advancedrocketry.oxygencharger=Charges Space Suit O₂ and H₂ +tooltip.advancedrocketry.oxygencharger.shift.1=Stand on pad to refill +tooltip.advancedrocketry.oxygencharger.alt.1=Does not require Power + +# Docking Port +tooltip.advancedrocketry.dockingport=Marks a station module docking point +tooltip.advancedrocketry.dockingport.shift.1=On the station: set a unique “My ID” +tooltip.advancedrocketry.dockingport.shift.2=On the new module: set “Target ID” +tooltip.advancedrocketry.dockingport.alt.1=Build new module in Station Builder +tooltip.advancedrocketry.dockingport.alt.2=clamp faces must face each other + +# Pipe Seal +tooltip.advancedrocketry.pipeseal=Airtight holes! +tooltip.advancedrocketry.pipeseal.shift.1=Seal a 1×1 gap by framing it with this +tooltip.advancedrocketry.pipeseal.shift.2=§bRequires 4 blocks per hole +tooltip.advancedrocketry.pipeseal.alt.1=Allows pipes through while keeping O₂ in +tooltip.advancedrocketry.pipeseal.alt.2=Entities can pass through the opening + +# Planet Selector (full-screen) +tooltip.advancedrocketry.planetselector=Browse Spacebodies +tooltip.advancedrocketry.planetselector.shift.1=Opens full-screen planet UI. +tooltip.advancedrocketry.planetselector.shift.2=Browse systems, planets and moons +tooltip.advancedrocketry.planetselector.alt.1=Allows you to remotely set a +tooltip.advancedrocketry.planetselector.alt.2=planet destination for warp controller. + +# Holographic Planet Selector +tooltip.advancedrocketry.planetholoselector=Holographic Spacebody Display +tooltip.advancedrocketry.planetholoselector.shift.1=Makes holographs in-world +tooltip.advancedrocketry.planetholoselector.alt.1="Functions the as planet selector +tooltip.advancedrocketry.planetholoselector.alt.2=but with a 3D holographic display" + +# Orientation Controller +tooltip.advancedrocketry.orientationctrl=§cSpace Station Controller +tooltip.advancedrocketry.orientationctrl.shift.1=Customize Angular Velocity +tooltip.advancedrocketry.orientationctrl.alt.1=§bCosmetic only§7 + +# Gravity Controller +tooltip.advancedrocketry.gravityctrl=§cSpace Station Controller +tooltip.advancedrocketry.gravityctrl.shift.1=Artificial gravity! +tooltip.advancedrocketry.gravityctrl.alt.1=§bCosmetic only§7 +tooltip.advancedrocketry.gravityctrl.alt.2=Redstone control + +# Altitude Controller +tooltip.advancedrocketry.altitudectrl=§cSpace Station Controller +tooltip.advancedrocketry.altitudectrl.shift.1=Customize orbital height +tooltip.advancedrocketry.altitudectrl.alt.1=§bCosmetic only§7 +tooltip.advancedrocketry.altitudectrl.alt.2=Redstone control + +# Co2Scrubber +tooltip.advancedrocketry.scrubber=Place next to Oxygen Vent +tooltip.advancedrocketry.scrubber.shift.1=Reduces Oxygen use (max 2) +tooltip.advancedrocketry.scrubber.alt.1=Each scrubber halves O₂ use, increases Power use. +tooltip.advancedrocketry.scrubber.alt.2=With 2 Scrubbers Oxygen Vent won't use Oxygen. + +# Oxygen Vent +tooltip.advancedrocketry.oxygenvent=Creates breathable air in sealed rooms. +tooltip.advancedrocketry.oxygenvent.shift.1=Requires Power and Oxygen. +tooltip.advancedrocketry.oxygenvent.shift.2=Place inside enclosed area. +tooltip.advancedrocketry.oxygenvent.alt.1=Use CO2 Scrubber instead of oxygen. +tooltip.advancedrocketry.oxygenvent.alt.2=Range: %s blocks radius. + +# Airlock Door +tooltip.advancedrocketry.smallairlock=Airtight door! +tooltip.advancedrocketry.smallairlock.shift.1=Not airtight, leaks when open +tooltip.advancedrocketry.smallairlock.alt.1=Build a proper airlock +tooltip.advancedrocketry.smallairlock.alt.2=using 2 doors + +# Warp Controller +tooltip.advancedrocketry.warpcontroller=Turns the station into a §6Starship +tooltip.advancedrocketry.warpcontroller.shift.1=Place §4Warp Controller§7 + §4Warp Core§7 on a space station +tooltip.advancedrocketry.warpcontroller.shift.2=Warp between planets and solar systems +tooltip.advancedrocketry.warpcontroller.alt.1=UI shows location, destinations, and warp fuel +tooltip.advancedrocketry.warpcontroller.alt.2=(You made it this far! check wiki bro) + +# CarbonScrubberCartridge +tooltip.advancedrocketry.scrubbercart=Used in CO₂ Scrubber +tooltip.advancedrocketry.scrubbercart.shift.1=Purifies air while at cost of durability. +tooltip.advancedrocketry.atmanalyzer.alt.1=Should last more than 24h + +# Seal Detector +tooltip.advancedrocketry.sealdetector=Detects if a block is airtight +tooltip.advancedrocketry.sealdetector.shift.1=§fRight Click on block to use + +# Lens +tooltip.advancedrocketry.lens=§cPart of Observatory +tooltip.advancedrocketry.lens.shift.1=§bUse Holo-Projector! + +## SPACE SUIT + COMPONENTS + +# Suit Working Station +tooltip.advancedrocketry.suitworkingstation=Install/remove §5Space Suit Components +tooltip.advancedrocketry.suitworkingstation.shift.1=Works with Space Suit armor +tooltip.advancedrocketry.suitworkingstation.shift.2=(Helmet/Chest/Legs/Boots) +tooltip.advancedrocketry.suitworkingstation.alt.1=Does not require Power + +# Jetpack +tooltip.advancedrocketry.jetpack=§5Space Suit Component +tooltip.advancedrocketry.jetpack.shift.1=§dSlot: Chest§7 + +# AtmosphereAnalyzer +tooltip.advancedrocketry.atmanalyzer=§5Space Suit ComponentRight Click to check atmosphere. +tooltip.advancedrocketry.atmanalyzer.shift.1=§fRight Click to check atmosphere. +tooltip.advancedrocketry.atmanalyzer.shift.2=§dSlot: Helmet§7 +tooltip.advancedrocketry.atmanalyzer.alt.1=Breathable? Depends on atmosphere +tooltip.advancedrocketry.atmanalyzer.alt.2=Shows type and pressure + +# BeaconFinder +tooltip.advancedrocketry.beaconfinder=§5Space Suit Component +tooltip.advancedrocketry.beaconfinder.shift.1=§fShows a HUD arrow toward AR beacons in this dimension +tooltip.advancedrocketry.beaconfinder.shift.2=§dSlot: Helmet§7 +tooltip.advancedrocketry.beaconfinder.alt.1=Arrow offset is relative to your facing +tooltip.advancedrocketry.beaconfinder.alt.2=Works only in AR dimensions that have registered beacons. + +# PressureTank +tooltip.advancedrocketry.pressuretank.shift.1=§dSlot: Chest§7 +tooltip.advancedrocketry.pressuretank.alt.1=§fStores Oxygen for suit +tooltip.advancedrocketry.pressuretank.alt.2=§fStores Hydrogen for Jetpack + +## Item Upgrade +# 0 = Hover +tooltip.advancedrocketry.itemupgrade.0=§5Space Suit Component +tooltip.advancedrocketry.itemupgrade.0.shift.1=§fEnables Jetpack hover mode +tooltip.advancedrocketry.itemupgrade.0.shift.2=§dSlot: Helmet§7 +tooltip.advancedrocketry.itemupgrade.0.alt.1=Requires a Jetpack installed in the chestplate. +tooltip.advancedrocketry.itemupgrade.0.alt.2=Stacking has no additional effect. + +# 1 = Flight Speed Control Upgrade +tooltip.advancedrocketry.itemupgrade.1=§5Space Suit Component +tooltip.advancedrocketry.itemupgrade.1.shift.1=§fBoosts Jetpack flight speed +tooltip.advancedrocketry.itemupgrade.1.shift.2=§dSlot: Helmet§7 +tooltip.advancedrocketry.itemupgrade.1.alt.1=Requires a Jetpack installed in the chestplate. +tooltip.advancedrocketry.itemupgrade.1.alt.2=§bEffect Stacks! + +# 2 = Bionic Leg Upgrade (speed) +tooltip.advancedrocketry.itemupgrade.2=§5Space Suit Component +tooltip.advancedrocketry.itemupgrade.2.shift.1=§fLeg upgrade: increases walk speed +tooltip.advancedrocketry.itemupgrade.2.shift.2=§dSlot: Legs§7 +tooltip.advancedrocketry.itemupgrade.2.alt.1=Sprint to activate +tooltip.advancedrocketry.itemupgrade.2.alt.2=Stacks with multiple modules. + +# 3 = Padded Landing Boots Upgrade (no fall damage; config-aware) +tooltip.advancedrocketry.itemupgrade.3=§5Space Suit Component +tooltip.advancedrocketry.itemupgrade.3.shift.1=§fEliminates fall damage +tooltip.advancedrocketry.itemupgrade.3.shift.2=§dSlot: Feet§7 +tooltip.advancedrocketry.itemupgrade.3.alt.1= +tooltip.advancedrocketry.itemupgrade.3.alt.2=Stacking has no additional effect. + +# 4 = Antifog Visor Upgrade +tooltip.advancedrocketry.itemupgrade.4=§5Space Suit Component +tooltip.advancedrocketry.itemupgrade.4.shift.1=WIP if u know what this does contact me +tooltip.advancedrocketry.itemupgrade.4.shift.2=§dSlot: Helmet§7 +tooltip.advancedrocketry.itemupgrade.4.alt.1=See through fog on high pressure planets +tooltip.advancedrocketry.itemupgrade.4.alt.2=Stacking has no additional effect. + +# 5 = Earthbright Visor +tooltip.advancedrocketry.itemupgrade.5=§5Space Suit Component +tooltip.advancedrocketry.itemupgrade.5.shift.1=WIP if u know what this does contact me +tooltip.advancedrocketry.itemupgrade.5.shift.2=§dSlot: Helmet§7 +tooltip.advancedrocketry.itemupgrade.5.alt.1= +tooltip.advancedrocketry.itemupgrade.5.alt.2=Stacking has no additional effect. + +## Satellite Components +# Primary Function payloads +tooltip.advancedrocketry.satfunc.optical=§5Satellite Core Component +tooltip.advancedrocketry.satfunc.optical.shift.1=§bCollects Distance Data§7 +tooltip.advancedrocketry.satfunc.optical.shift.2=§oDownload Data in Satellite Terminal +tooltip.advancedrocketry.satfunc.optical.alt.1=Combine with Satellite Chip +tooltip.advancedrocketry.satfunc.optical.alt.2=when assembling + +tooltip.advancedrocketry.satfunc.composition=§5Satellite Core Component +tooltip.advancedrocketry.satfunc.composition.shift.1=§bCollects Composition Data§7 +tooltip.advancedrocketry.satfunc.composition.shift.2=§oDownload data in Satellite Terminal +tooltip.advancedrocketry.satfunc.composition.alt.1=Combine with Satellite Chip +tooltip.advancedrocketry.satfunc.composition.alt.2=when assembling + +tooltip.advancedrocketry.satfunc.mass=§5Satellite Core Component +tooltip.advancedrocketry.satfunc.mass.shift.1=§bCollects Mass Data§7 +tooltip.advancedrocketry.satfunc.mass.shift.2=§oDownload data in Satellite Terminal +tooltip.advancedrocketry.satfunc.mass.alt.1=Combine with Satellite Chip +tooltip.advancedrocketry.satfunc.mass.alt.2=when assembling + +tooltip.advancedrocketry.satfunc.microwave=§5Satellite Core Component +tooltip.advancedrocketry.satfunc.microwave.shift.1=§bGenerates Power in Space§7 +tooltip.advancedrocketry.satfunc.microwave.shift.2=§oNeeds Microwave Receiver (5x5 Multiblock) +tooltip.advancedrocketry.satfunc.microwave.alt.1=Combine with Satellite Chip +tooltip.advancedrocketry.satfunc.microwave.alt.2=when assembling + +tooltip.advancedrocketry.satfunc.oremapping=§5Satellite Core Component +tooltip.advancedrocketry.satfunc.oremapping.shift.1=§bScans the planet for Ore§7 +tooltip.advancedrocketry.satfunc.oremapping.alt.1=Combine with Ore Scanner +tooltip.advancedrocketry.satfunc.oremapping.alt.2=when assembling + +tooltip.advancedrocketry.satfunc.biomechanger=§5Satellite Core Component +tooltip.advancedrocketry.satfunc.biomechanger.shift.1=§bAdjusts biomes§7 +tooltip.advancedrocketry.satfunc.biomechanger.alt.1=Combine with Biome Changer Remote +tooltip.advancedrocketry.satfunc.biomechanger.alt.2=when assembling + +tooltip.advancedrocketry.satfunc.weather=§5Satellite Core Component +tooltip.advancedrocketry.satfunc.weather.shift.1=§bDoes some weather stuff! +tooltip.advancedrocketry.satfunc.weather.alt.1=Combine with Weather Remote +tooltip.advancedrocketry.satfunc.weather.alt.2=when assembling + +# Power Sources +tooltip.advancedrocketry.satpower.0=§5Satellite Component +tooltip.advancedrocketry.satpower.0.shift.1=§fGenerates §c4 §fRF/t§7 +tooltip.advancedrocketry.satpower.0.shift.2=§oSatellites requires atleast 1 powergen + +tooltip.advancedrocketry.satpower.1=§5Satellite Component +tooltip.advancedrocketry.satpower.1.shift.1=§fGenerates §c40 §fRF/t§7 +tooltip.advancedrocketry.satpower.1.shift.2=§oSatellites requires atleast 1 powergen + +# LibVulpes Batteries +tooltip.libvulpes.battery.0=§5Satellite Component§7 +tooltip.libvulpes.battery.0.shift.1=Increases Powerstorage +tooltip.libvulpes.battery.0.shift.2=§fCapacity: §c10.000 §fRF§7 + +tooltip.libvulpes.battery.1=§5Satellite Component +tooltip.libvulpes.battery.1.shift.1=Increases Powerstorage +tooltip.libvulpes.battery.1.shift.2=§fCapacity: §c40.000 §fRF§7 + +# Data Unit +tooltip.advancedrocketry.itemdataunit.shift.1=§fIncrease Satellite Data Storage by 1000 +tooltip.advancedrocketry.itemdataunit.alt.1=§fWorks as Datastorage in inventory aswell + +## Chips / remotes +# Asteroid Chip +tooltip.advancedrocketry.asteroidchip.shift.1=§bUsed for Mining Missions§7 +tooltip.advancedrocketry.asteroidchip.shift.2=§fProgram in §cObservatory +tooltip.advancedrocketry.asteroidchip.alt.1=§4Insert programmed Chip in Guidance Computer§7 + +# Station Chip +tooltip.advancedrocketry.stationchip=§bMake Backups! +tooltip.advancedrocketry.stationchip.shift.1=§fProgram in Space Station Assembler +tooltip.advancedrocketry.stationchip.alt.1=§4Insert programmed Chip in Guidance Computer§7 + +# Planet Chip +tooltip.advancedrocketry.planetidchip.shift.1=§fInsert Chip in §4Guidance Computer§7 +tooltip.advancedrocketry.planetidchip.shift.2=§fSet destination in Rocket GUI to program it. +tooltip.advancedrocketry.planetidchip.alt.1=§4Doublecheck that this is programmed before Launch! + +# Satellite Chip +tooltip.advancedrocketry.satidchip=§bMake Backups! +tooltip.advancedrocketry.satidchip.shift.1=§fStores a satellite’s ID. +tooltip.advancedrocketry.satidchip.alt.1=§4Use in Satellite Monitor to link or in the Microwave Receiver Multiblock (Input hatch). §8 (Planet: resolves if put in Terminal) + +# Elevator Chip +tooltip.advancedrocketry.elevatorchip=Space Elevator Chip +tooltip.advancedrocketry.elevatorchip.shift.1=§fLinks an elevator pad/destination. + + +## Multiblocks + +# Black Hole Generator +tooltip.advancedrocketry.blackholegen=Generates Power from compressed mass +tooltip.advancedrocketry.blackholegen.shift.1=§bUse Holo-Projector! + +# Microwave Receiver +tooltip.advancedrocketry.microwavereceiver=Receives Power from Solar Satellites +tooltip.advancedrocketry.microwavereceiver.shift.1=5x5 Multiblock +tooltip.advancedrocketry.microwavereceiver.shift.2=§bUse Holo-Projector! +tooltip.advancedrocketry.microwavereceiver.alt.1=§fSolar Satellites are built with §bMicrowave Transmitter§f and §bSatellite Chip +tooltip.advancedrocketry.microwavereceiver.alt.2=§8RF/t = (sum Satellites RF/t) * (2 * AtmospheredensityFactor) + +# Solar Panel (part of Microwave Receiver) +tooltip.advancedrocketry.solarpanel=§cPart of Multiblock +tooltip.advancedrocketry.solarpanel.shift.1=5x5 Multiblock +tooltip.advancedrocketry.solarpanel.shift.2=§o§f(Microwave Receiver) +tooltip.advancedrocketry.solarpanel.shift.3=§bUse Holo-Projector! + +# Solar Array Controller +tooltip.advancedrocketry.solararray=Generates Power from sunlight +tooltip.advancedrocketry.solararray.shift.1=Requires 63x Solar Array Panels +tooltip.advancedrocketry.solararray.shift.2=§bUse Holo-Projector! +tooltip.advancedrocketry.solararray.alt.1= + +# Solar Array Panel +tooltip.advancedrocketry.solararraypanel=§cPart of Multiblock +tooltip.advancedrocketry.solararraypanel.shift.1=Requires 63x Solar Array Panels and Controller +tooltip.advancedrocketry.solararraypanel.shift.2=§bUse Holo-Projector! +tooltip.advancedrocketry.solararray.alt.1= + +# Solar Generator +tooltip.advancedrocketry.solargenerator=Basic Solar Panel +tooltip.advancedrocketry.solargenerator.shift.1=§fGenerates §c2 §fRF/t§7 + +# Arc Furnace +tooltip.advancedrocketry.arcfurnace=Smelts at extreme temperatures +tooltip.advancedrocketry.arcfurnace.shift.1=§bUse Holo-Projector! + +# Rolling Machine +tooltip.advancedrocketry.rollingmachine=Rolls plates and foils +tooltip.advancedrocketry.rollingmachine.shift.1=§bUse Holo-Projector! + +# Lathe +tooltip.advancedrocketry.lathe=Turns rods and shafts +tooltip.advancedrocketry.lathe.shift.1=§bUse Holo-Projector! + +# Crystallizer +tooltip.advancedrocketry.crystallizer=Grows high-purity crystals +tooltip.advancedrocketry.crystallizer.shift.1=§bUse Holo-Projector! + +# Cutting Machine +tooltip.advancedrocketry.cuttingmachine=Precision cutting of materials +tooltip.advancedrocketry.cuttingmachine.shift.1=§bUse Holo-Projector! + +# Precision Assembler +tooltip.advancedrocketry.precisionassembler=Automates complex assembly +tooltip.advancedrocketry.precisionassembler.shift.1=§bUse Holo-Projector! + +# Electrolyser +tooltip.advancedrocketry.electrolyser=Splits compounds via electrolysis +tooltip.advancedrocketry.electrolyser.shift.1=§bUse Holo-Projector! + +# Chemical Reactor +tooltip.advancedrocketry.chemreactor=Processes chemical reactions +tooltip.advancedrocketry.chemreactor.shift.1=§bUse Holo-Projector! + +# Precision Laser Etcher +tooltip.advancedrocketry.precisionlaseretcher=Laser-etches fine circuits +tooltip.advancedrocketry.precisionlaseretcher.shift.1=§bUse Holo-Projector! + +# Observatory +tooltip.advancedrocketry.observatory=Analyzes celestial bodies +tooltip.advancedrocketry.observatory.shift.1=§fUsed for §6Mining Missions +tooltip.advancedrocketry.observatory.shift.2=§bUse Holo-Projector! +tooltip.advancedrocketry.observatory.alt.1=§fInsert §cAsteroid Chip + + +# Planet Analyser +tooltip.advancedrocketry.planetanalyser=Processes planet scan data +tooltip.advancedrocketry.planetanalyser.shift.1=§bUse Holo-Projector! + +# Centrifuge +tooltip.advancedrocketry.centrifuge=Separates by density +tooltip.advancedrocketry.centrifuge.shift.1=§bUse Holo-Projector! + +# Warp Core +tooltip.advancedrocketry.warpcore=Core for §6Starship +tooltip.advancedrocketry.warpcore.shift.1=§bUse Holo-Projector! + +# Beacon +tooltip.advancedrocketry.beacon=Long-range signal beacon +tooltip.advancedrocketry.beacon.shift.1=§bUse Holo-Projector! + +# Biome Scanner +tooltip.advancedrocketry.biomescan=Scans planetary biomes +tooltip.advancedrocketry.biomescan.shift.1=§bUse Holo-Projector! + +# Railgun +tooltip.advancedrocketry.railgun=Shoots Items into space +tooltip.advancedrocketry.railgun.shift.1=§bUse Holo-Projector! +tooltip.advancedrocketry.railgun.alt.1="The railgun is not powerful enough to transport item stacks between planets and its range is limited to bodies within the same system" + +# Space Elevator Controller +tooltip.advancedrocketry.spaceelevatorctrl=Controls the Space Elevator +tooltip.advancedrocketry.spaceelevatorctrl.shift.1=§bUse Holo-Projector! + +# Atmosphere Terraformer +tooltip.advancedrocketry.atmosterraformer=Changes Atmospheric pressure on an entire planet planet +tooltip.advancedrocketry.atmosterraformer.shift.1=§bUse Holo-Projector! +tooltip.advancedrocketry.atmosterraformer.alt.1=Increase and decrease the atmosphere pressure by using connected §cBiome changing remote. + +# Area Gravity Controller +tooltip.advancedrocketry.gravitymachine=Manipulates Gravity +tooltip.advancedrocketry.gravitymachine.shift.1=§fCan also affect the direction of Gravity +tooltip.advancedrocketry.gravitymachine.shift.2=§bUse Holo-Projector! + +# Orbital Last Drill +tooltip.advancedrocketry.spacelaser=§cSpace Station Multiblock +tooltip.advancedrocketry.spacelaser.shift.1=§bUse Holo-Projector! + +# Force Field Projector +tooltip.advancedrocketry.forcefieldprojector=Projeccts up to 32 blocks away! +tooltip.advancedrocketry.forcefieldprojector.shift.1=Activate with Redstone + +# Vacuum Laser +tooltip.advancedrocketry.vacuumlaser=§cPart of Multiblock +tooltip.advancedrocketry.vacuumlaser.shift.1=§bUse Holo-Projector! + + +# Pump +tooltip.advancedrocketry.pump=Searches for fluid directly below +tooltip.advancedrocketry.pump.shift.1=§cPulls from the connected pool within 64 blocks. +tooltip.advancedrocketry.pump.alt.1=§fAutoejects to nearby tank +tooltip.advancedrocketry.pump.alt.2=Redstone turns it off + +# Parts for Multiblock +tooltip.advancedrocketry.concrete=§cPart of Multiblock +tooltip.advancedrocketry.concrete.shift.1=§bUse Holo-Projector! +tooltip.advancedrocketry.blastbrick=§cPart of Multiblock +tooltip.advancedrocketry.blastbrick.shift.1=§bUse Holo-Projector! +tooltip.advancedrocketry.qcrucible=§cPart of Multiblock +tooltip.advancedrocketry.qcrucible.shift.1=§bUse Holo-Projector! +tooltip.advancedrocketry.sawblade=§cPart of Multiblock +tooltip.advancedrocketry.sawblade.shift.1=§bUse Holo-Projector! + +## Assemblers +# Rocket Assembler +tooltip.advancedrocketry.rocketassembler=§cBuilds Rockets +tooltip.advancedrocketry.rocketassembler.shift.1=§bRequires Launch Pad + Structure Tower Structure +tooltip.advancedrocketry.rocketassembler.shift.2=§fConnecting all infrastructure to this lets them autoconnect to Rocket on Pad +tooltip.advancedrocketry.rocketassembler.alt.1=§fPlace this 1 block higher than Launch Pad, connecting lower corners and facing opposite of the Launch Pad square + +# Station Assembler +tooltip.advancedrocketry.stationassembler=§cPacks Space Stations down for Launch! +tooltip.advancedrocketry.stationassembler.shift.1=§bRequires Launch Pad + Structure Tower Structure +tooltip.advancedrocketry.stationassembler.alt.1=§fPlace this 1 block higher than Launch Pad, connecting lower corners and facing opposite of the Launch Pad square + +# Packet Station +tooltip.advancedrocketry.packedstructure=Insert in §cSatellite Bay§7 to put in Orbit! +tooltip.advancedrocketry.packedstructure.shift.1=§eRemember to tell Rocket what planet it should deplay payload into Orbit! + +# Deployable Rocket Assembler +tooltip.advancedrocketry.deployablerocketassembler=§cBuilds Rockets on Space Stations +tooltip.advancedrocketry.deployablerocketassembler.shift.1=§bRequires Structure Tower blocks +tooltip.advancedrocketry.deployablerocketassembler.shift.2=§fUsed for §6Gas Missions§7 +tooltip.advancedrocketry.deployablerocketassembler.alt.1=§fPlace this in the middle of upside down T facing outwards in space, then a horizontal support outwards from the top of tower. +tooltip.advancedrocketry.deployablerocketassembler.alt.2=Check wiki if unsure! From d7857cf27a9d85d6e7cfa5da5c3ccd81c615edad Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:27:47 +0100 Subject: [PATCH 221/424] Refactor item information display in ItemData --- .../java/zmaster587/advancedRocketry/item/ItemData.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemData.java b/src/main/java/zmaster587/advancedRocketry/item/ItemData.java index ccd62a615..4de0f0af9 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemData.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemData.java @@ -98,18 +98,17 @@ public void addInformation(@Nonnull ItemStack stack, @Nullable World world, List DataStorage data = getDataStorage(stack); - // 1) Type: + // Type: list.add(TextFormatting.DARK_PURPLE + "Space Suit Component"); String typeText = net.minecraft.client.resources.I18n.format(data.getDataType().toString()); list.add(net.minecraft.util.text.TextFormatting.WHITE + "Type: " + typeText); - - // 2) §fData stored: §6 §f/§6 + // Data: list.add(net.minecraft.util.text.TextFormatting.WHITE + "Data stored: " + net.minecraft.util.text.TextFormatting.GOLD + data.getData() + net.minecraft.util.text.TextFormatting.WHITE + " / " + net.minecraft.util.text.TextFormatting.GOLD + data.getMaxData()); - // 3) Hold Shift for more info + // Hold Shift for more info if (net.minecraft.client.gui.GuiScreen.isShiftKeyDown()) { list.add(net.minecraft.util.text.TextFormatting.GRAY + net.minecraft.client.resources.I18n.format("tooltip.advancedrocketry.itemdataunit.shift.1")); @@ -119,5 +118,4 @@ public void addInformation(@Nonnull ItemStack stack, @Nullable World world, List net.minecraft.client.resources.I18n.format("tooltip.advancedrocketry.hold_shift")); } } - } From fef59f59e2dc332901e5151e7ea33b49a48e836b Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:28:49 +0100 Subject: [PATCH 222/424] Clean up renderScreen method in ItemPressureTank --- .../advancedRocketry/item/components/ItemPressureTank.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java b/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java index 39007f1b0..163ace625 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java +++ b/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java @@ -117,14 +117,11 @@ public boolean isAllowedInSlot(@Nonnull ItemStack stack, EntityEquipmentSlot slo @SideOnly(Side.CLIENT) public void renderScreen(@Nonnull ItemStack componentStack, List modules, RenderGameOverlayEvent event, Gui gui) { // TODO Auto-generated method stub - } - - + @Override public ICapabilityProvider initCapabilities(@Nonnull ItemStack stack, NBTTagCompound nbt) { return new TankCapabilityItemStack(stack, getCapacity(stack)); } - } From a1df6d81494128859bc77ecdc54b37f52c66f4d6 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:30:36 +0100 Subject: [PATCH 223/424] Reorganize imports and clean up BlockTransciever --- .../advancedRocketry/block/BlockTransciever.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java b/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java index a7a966723..9eb0d0f61 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockTransciever.java @@ -1,7 +1,5 @@ package zmaster587.advancedRocketry.block; -import javax.annotation.Nonnull; - import net.minecraft.block.state.BlockStateContainer; import net.minecraft.block.state.IBlockState; import net.minecraft.client.util.ITooltipFlag; @@ -21,13 +19,10 @@ import zmaster587.libVulpes.block.BlockTile; import zmaster587.advancedRocketry.client.TooltipInjector; +import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.List; - - - - public class BlockTransciever extends BlockTile { public static final PropertyDirection FACING = PropertyDirection.create("facing"); @@ -75,8 +70,6 @@ public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, Bloc public BlockRenderLayer getBlockLayer() { return BlockRenderLayer.CUTOUT_MIPPED; } - // If this still errors in your mappings, rename the method to: - // public BlockRenderLayer getRenderLayer() { return BlockRenderLayer.CUTOUT_MIPPED; } @Override protected BlockStateContainer createBlockState() { From 9a91ffe48312fc1ed19094d7a74fe175cf1f49bc Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:32:14 +0100 Subject: [PATCH 224/424] Refactor ItemBlockFluidTank by removing imports Removed unused imports and cleaned up comments. --- .../advancedRocketry/item/ItemBlockFluidTank.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java b/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java index 4b19ff280..2f05015fd 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java @@ -24,15 +24,9 @@ import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.tile.TileFluidTank; -import net.minecraftforge.fml.relauncher.Side; -import net.minecraftforge.fml.relauncher.SideOnly; - import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; - -import org.lwjgl.input.Keyboard; - import java.util.List; public class ItemBlockFluidTank extends ItemBlock { @@ -64,7 +58,7 @@ public void addInformation(@Nonnull ItemStack stack, @Nullable World world, List list.add("Fluid: " + fluidName); list.add("Level: " + amount + "/" + capMb + " mB"); - // --- SHIFT for more info (adds two short lines) --- + // --- SHIFT for more info --- if (GuiScreen.isShiftKeyDown()) { list.add(TextFormatting.GRAY + I18n.format("tooltip.advancedrocketry.fluidtank.shift.1")); } else if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) { @@ -95,7 +89,6 @@ public boolean placeBlockAt(@Nonnull ItemStack stack, EntityPlayer player, World return true; } - public void fill(@Nonnull ItemStack stack, FluidStack fluid) { NBTTagCompound nbt; FluidTank tank = new FluidTank(getCapMb()); From 62c87d41d597b49accbed701ce01a3b9774313ea Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:39:04 +0100 Subject: [PATCH 225/424] Remove unnecessary blank lines in BlockForceFieldProjector --- .../advancedRocketry/block/BlockForceFieldProjector.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockForceFieldProjector.java b/src/main/java/zmaster587/advancedRocketry/block/BlockForceFieldProjector.java index 513c5e741..19405aa88 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockForceFieldProjector.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockForceFieldProjector.java @@ -1,7 +1,6 @@ package zmaster587.advancedRocketry.block; import java.util.List; - import javax.annotation.Nullable; import net.minecraft.block.material.Material; @@ -48,5 +47,4 @@ public void addInformation(ItemStack stack, @Nullable World world, List int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.forcefieldprojector", insertAt); } - } From f0344b9e2d6804c0ec579fb50902ace8fe0af47b Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:40:16 +0100 Subject: [PATCH 226/424] Fix formatting in BlockSolarGenerator.java From 8e4dd413e458080adcb4b9346e586cac9161c7de Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:42:02 +0100 Subject: [PATCH 227/424] Fix formatting in BlockNuclearCore.java From 17a38342c21483e5191c7b7d34652b68b114e362 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:43:06 +0100 Subject: [PATCH 228/424] Refactor comment for visual tag generation --- .../java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java b/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java index d2fbad2d1..2c2ee55ac 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemAsteroidChip.java @@ -113,7 +113,7 @@ public void addInformation(@Nonnull ItemStack stack, World world, List l final long disp = makeDisplayId(id, type); final String hex = Long.toUnsignedString(disp, 16).toUpperCase(); - // Fixed-length visual tag (avoid lookalikes by using N=6 chars) + // Fixed-length visual tag final int N = 6; final String shortHex = (hex.length() > N) ? hex.substring(hex.length() - N) : hex; From 9fc62c3b9009109bef298240f76009a448068dc9 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:43:53 +0100 Subject: [PATCH 229/424] Fix missing newline at end of ItemPlanetIdentificationChip.java From 16dae64ae805795275e95eda41968aaec84f780f Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:44:32 +0100 Subject: [PATCH 230/424] Fix formatting issue in BlockRocketMotor.java From 546755d87c412652f1fea449cdde498b5a11408e Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:45:16 +0100 Subject: [PATCH 231/424] Add newline at end of BlockBipropellantRocketMotor.java Fix missing newline at end of file. From 3801a2395b57b20c1e2b3170dca865a8a55f1b0a Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:46:17 +0100 Subject: [PATCH 232/424] Add newline at end of Co2ScrubberWrapper.java Added a newline at the end of the file for consistency. From 5c73fb7502cc9b5d216ec04ec4ea0263d7d99379 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:46:39 +0100 Subject: [PATCH 233/424] Fix missing newline at end of Co2ScrubberRecipeMaker.java Added a newline at the end of the file. From dcc99e3a78a616be94b2aacf228e85ed3d0dee98 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:47:08 +0100 Subject: [PATCH 234/424] Fix recipe validation logic in Co2ScrubberRecipeHandler From 0db3f06d946771aa15bb44713393bb80b6895806 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:47:37 +0100 Subject: [PATCH 235/424] Remove commented code and clean up formatting --- .../integration/jei/co2scrubber/Co2ScrubberCategory.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberCategory.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberCategory.java index 6aac19c5c..298b201bc 100644 --- a/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberCategory.java +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/co2scrubber/Co2ScrubberCategory.java @@ -17,7 +17,6 @@ public class Co2ScrubberCategory implements IRecipeCategory private final IDrawable icon; private final IDrawable slot; - // Compact like your fueling station: 150x40 public Co2ScrubberCategory(IGuiHelper gui) { this.bg = gui.createBlankDrawable(150, 40); this.icon = gui.createDrawableIngredient(new ItemStack(AdvancedRocketryBlocks.blockCO2Scrubber)); @@ -43,7 +42,6 @@ public void setRecipe(IRecipeLayout layout, Co2ScrubberWrapper wrapper, IIngredi items.set(1, new ItemStack(AdvancedRocketryBlocks.blockOxygenVent)); } - @Override public void drawExtras(Minecraft mc) { // Draw the slot frame behind the cartridge From d5b68fb13043a16e8cae12faae34fa78f760b880 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:48:35 +0100 Subject: [PATCH 236/424] Add newline at end of BlockPressurizedFluidTank.java Fix formatting by adding a newline at the end of the file. From 40fe80340951f468158ac54b567c8fc197ff6a44 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:49:35 +0100 Subject: [PATCH 237/424] Add newline at end of BlockTileRedstoneEmitter.java Fix formatting by adding a newline at the end of the file. From ab92fedc20c5a1e50ca6f77b04fd4e50c4a1bb85 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:50:30 +0100 Subject: [PATCH 238/424] Define supported data types in MultiData Add supported data types for MultiData class --- .../advancedRocketry/world/util/MultiData.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/world/util/MultiData.java b/src/main/java/zmaster587/advancedRocketry/world/util/MultiData.java index f523f032d..27b4178d5 100644 --- a/src/main/java/zmaster587/advancedRocketry/world/util/MultiData.java +++ b/src/main/java/zmaster587/advancedRocketry/world/util/MultiData.java @@ -19,6 +19,14 @@ public MultiData() { reset(); } + private static final java.util.EnumSet SUPPORTED_TYPES = + java.util.EnumSet.of( + DataStorage.DataType.COMPOSITION, + DataStorage.DataType.MASS, + DataStorage.DataType.DISTANCE + ); + + public void reset() { for (DataStorage.DataType type : DataStorage.DataType.values()) { if (type != DataStorage.DataType.UNDEFINED) @@ -91,4 +99,4 @@ public void readFromNBT(NBTTagCompound nbt) { } } } -} \ No newline at end of file +} From 1ff2944a528d3b068ec395131942834273901c06 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:51:49 +0100 Subject: [PATCH 239/424] Clean up BlockLinkedHorizontalTexture.java Remove unnecessary blank lines and fix formatting. --- .../advancedRocketry/block/BlockLinkedHorizontalTexture.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockLinkedHorizontalTexture.java b/src/main/java/zmaster587/advancedRocketry/block/BlockLinkedHorizontalTexture.java index 5c5e574ba..aee2caf69 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockLinkedHorizontalTexture.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockLinkedHorizontalTexture.java @@ -135,5 +135,4 @@ private static boolean isAltDown() { return false; } } - } From d9c8bbe3f0bf8b014aa30fd0e27b455ee09bbe32 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:52:42 +0100 Subject: [PATCH 240/424] Remove unnecessary comment in FuelingStationWrapper --- .../integration/jei/fuelingStation/FuelingStationWrapper.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationWrapper.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationWrapper.java index 2f0af02ef..2c5811be2 100644 --- a/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationWrapper.java +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationWrapper.java @@ -84,7 +84,6 @@ public ItemStack getRoleTankStack() { } } - // keep this helper; category uses it conditionally public ItemStack getFilledContainer() { ItemStack is = net.minecraftforge.fluids.FluidUtil.getFilledBucket(fluid); return is == null ? ItemStack.EMPTY : is; From 6fedd10b235ae8be274853e154a826537d4a36de Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:53:10 +0100 Subject: [PATCH 241/424] Remove commented code in FuelingStationRecipeMaker --- .../jei/fuelingStation/FuelingStationRecipeMaker.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationRecipeMaker.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationRecipeMaker.java index 76bc797ec..ab6af1c14 100644 --- a/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationRecipeMaker.java +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationRecipeMaker.java @@ -35,7 +35,6 @@ private static void add(List list, } } - // Optional: keep this to match your existing makers public static List getMachineRecipes(IJeiHelpers helpers, Class ignored) { return getRecipes(helpers); } From 24304a8ea87bbe18d703358f7a6198b71188111b Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:53:28 +0100 Subject: [PATCH 242/424] Add newline at end of FuelingStationRecipeHandler.java Fix formatting by adding a newline at the end of the file. From 6f4c16c2567fd92d1d0752f28f93679a34b489e0 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:54:06 +0100 Subject: [PATCH 243/424] Remove commented-out code in drawExtras method --- .../jei/fuelingStation/FuelingStationCategory.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationCategory.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationCategory.java index 1124851b1..240586afe 100644 --- a/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationCategory.java +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/fuelingStation/FuelingStationCategory.java @@ -90,9 +90,8 @@ public void setRecipe(IRecipeLayout layout, FuelingStationWrapper wrapper, IIngr @Override public void drawExtras(Minecraft mc) { - // Draw tank bezel and slot frames so it looks like the real GUI - tankFrame.draw(mc, 27, 2); // 14x54 bezel - slotFrame.draw(mc, 45, 6); // bucket slot + tankFrame.draw(mc, 27, 2); + slotFrame.draw(mc, 45, 6); } } From f5e1a476bf595cfa2a53cd58788c30b90e0be1ad Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:54:52 +0100 Subject: [PATCH 244/424] Add newline at end of BlockLandingPad.java Fix missing newline at end of file in BlockLandingPad.java From 75f362129dd30e8b820bba88262ccd47992b1dc4 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:55:25 +0100 Subject: [PATCH 245/424] Fix formatting and add newline at end of file From 8c41706f08b218937460f98f30877a0228a72913 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:55:55 +0100 Subject: [PATCH 246/424] Fix formatting issue in ItemSealDetector.java From dc592bbea6a8281cd797549f1cb0138c3004d039 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:57:31 +0100 Subject: [PATCH 247/424] Add tooltip support to BlockDoor2 --- .../java/zmaster587/advancedRocketry/block/BlockDoor2.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockDoor2.java b/src/main/java/zmaster587/advancedRocketry/block/BlockDoor2.java index e6012eb75..f02831f46 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockDoor2.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockDoor2.java @@ -3,6 +3,7 @@ import net.minecraft.block.BlockDoor; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Items; import net.minecraft.item.Item; @@ -14,9 +15,13 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.advancedRocketry.api.AdvancedRocketryItems; +import zmaster587.advancedRocketry.client.TooltipInjector; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import javax.annotation.ParametersAreNullableByDefault; + +import java.util.List; import java.util.Random; public class BlockDoor2 extends BlockDoor { @@ -45,5 +50,5 @@ public boolean onBlockActivated(World worldIn, BlockPos pos, IBlockState state, EntityPlayer playerIn, EnumHand hand, EnumFacing side, float hitX, float hitY, float hitZ) { return false; - } + } } From c31bb9ba76a1360a780a9be2dbe39f7855bb3c1c Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:57:59 +0100 Subject: [PATCH 248/424] Fix formatting and remove unnecessary line --- src/main/java/zmaster587/advancedRocketry/block/BlockDoor2.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockDoor2.java b/src/main/java/zmaster587/advancedRocketry/block/BlockDoor2.java index f02831f46..cd569c4cf 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockDoor2.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockDoor2.java @@ -37,7 +37,6 @@ public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state) { return new ItemStack(AdvancedRocketryItems.itemSmallAirlockDoor); } - @Override @Nonnull public Item getItemDropped(IBlockState state, Random rand, int fortune) { From fe1d65223a95d59cb7afb6fee9828c90434209a0 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:58:49 +0100 Subject: [PATCH 249/424] Fix formatting and remove unnecessary newline --- .../zmaster587/advancedRocketry/block/BlockWarpController.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockWarpController.java b/src/main/java/zmaster587/advancedRocketry/block/BlockWarpController.java index 227058aa7..016e09722 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockWarpController.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockWarpController.java @@ -16,7 +16,6 @@ import zmaster587.libVulpes.block.BlockTile; import java.util.List; - import javax.annotation.Nonnull; import javax.annotation.Nullable; From 71513392f52e4efbcfade5f1db7a9bbdb66098b3 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 08:59:41 +0100 Subject: [PATCH 250/424] Fix formatting and remove unnecessary whitespace --- .../zmaster587/advancedRocketry/block/BlockTileTerraformer.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockTileTerraformer.java b/src/main/java/zmaster587/advancedRocketry/block/BlockTileTerraformer.java index 55f038c9a..e4967cba4 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockTileTerraformer.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockTileTerraformer.java @@ -37,7 +37,6 @@ import zmaster587.libVulpes.util.IAdjBlockUpdate; import java.util.List; - import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -177,5 +176,4 @@ public void addInformation(ItemStack stack, @Nullable World world, List int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.terraformer", insertAt); } - } From e5cd6910d555992e66cf5fee5c154ed18734b592 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:00:21 +0100 Subject: [PATCH 251/424] Remove extra newline in BlockSeal.java --- src/main/java/zmaster587/advancedRocketry/block/BlockSeal.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockSeal.java b/src/main/java/zmaster587/advancedRocketry/block/BlockSeal.java index f19828940..a34786b89 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockSeal.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockSeal.java @@ -209,5 +209,4 @@ public void addInformation(ItemStack stack, @Nullable World world, List int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.pipeseal", insertAt); } - } From ca13e7e8eb9657b33e1c23adfdc4af8ae301e5bd Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:01:22 +0100 Subject: [PATCH 252/424] Fix missing newline at end of ItemBiomeChanger.java From be0e7e72f470535be4580b00d78efb6035e4cf85 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:02:13 +0100 Subject: [PATCH 253/424] Remove unnecessary newline at end of BlockSuitWorkstation.java --- .../zmaster587/advancedRocketry/block/BlockSuitWorkstation.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockSuitWorkstation.java b/src/main/java/zmaster587/advancedRocketry/block/BlockSuitWorkstation.java index 84cca8f0e..cea44cc89 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockSuitWorkstation.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockSuitWorkstation.java @@ -69,5 +69,4 @@ public void addInformation(ItemStack stack, @Nullable World world, List int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.suitworkingstation", insertAt); } - } From c7ed0e5b5e7f6f1b51eff419bddd825c9e43197f Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:02:49 +0100 Subject: [PATCH 254/424] Fix formatting by removing extra newlines --- .../zmaster587/advancedRocketry/block/BlockRedstoneEmitter.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockRedstoneEmitter.java b/src/main/java/zmaster587/advancedRocketry/block/BlockRedstoneEmitter.java index 94131b83a..dc4a78830 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockRedstoneEmitter.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockRedstoneEmitter.java @@ -105,5 +105,4 @@ public void addInformation(ItemStack stack, @Nullable World world, List public boolean canProvidePower(IBlockState state) { return true; } - } From e9e3e4ba6fd3651a1fca8d79b9d2d427b7d6641c Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:03:27 +0100 Subject: [PATCH 255/424] Add newline at end of TileAtmosphereDetector.java Fix missing newline at end of file. From 50a7256bba9c9b20256cea487cf91ba136835803 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:05:48 +0100 Subject: [PATCH 256/424] Fix formatting in BlockLens.java From 808653c000898f7a2ebaa831d3c0f9d6cb900a6f Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:06:15 +0100 Subject: [PATCH 257/424] Fix formatting and add tooltip information for BlockSeat --- src/main/java/zmaster587/advancedRocketry/block/BlockSeat.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockSeat.java b/src/main/java/zmaster587/advancedRocketry/block/BlockSeat.java index 0e3a63004..71d3d565c 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockSeat.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockSeat.java @@ -119,5 +119,4 @@ public void addInformation(ItemStack stack, @Nullable World world, List int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.seat", insertAt); } - } From b6defb33b1c112f9c51ed424581d175265fe72d4 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:06:48 +0100 Subject: [PATCH 258/424] Fix formatting by removing extra newlines --- src/main/java/zmaster587/advancedRocketry/block/BlockIntake.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockIntake.java b/src/main/java/zmaster587/advancedRocketry/block/BlockIntake.java index 652466352..af0b222e0 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockIntake.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockIntake.java @@ -32,5 +32,4 @@ public void addInformation(ItemStack stack, @Nullable World world, List public int getIntakeAmt(IBlockState state) { return 1; } - } From 20f6cfbbccdff2b95113d72b98bf1ae5d483c814 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:07:18 +0100 Subject: [PATCH 259/424] Remove unnecessary newline and fix formatting --- .../java/zmaster587/advancedRocketry/block/BlockMiningDrill.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockMiningDrill.java b/src/main/java/zmaster587/advancedRocketry/block/BlockMiningDrill.java index db5141062..13b4fc1db 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockMiningDrill.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockMiningDrill.java @@ -44,5 +44,4 @@ public void addInformation(ItemStack stack, @Nullable World world, List public int powerConsumption() { return 0; } - } From acdee5bc680e5cac7027d78208edf61a07c2c8a1 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:07:58 +0100 Subject: [PATCH 260/424] Remove unnecessary newline and clean up code --- .../zmaster587/advancedRocketry/item/ItemAtmosphereAnalzer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemAtmosphereAnalzer.java b/src/main/java/zmaster587/advancedRocketry/item/ItemAtmosphereAnalzer.java index eec4f7ef9..06f01c537 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemAtmosphereAnalzer.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemAtmosphereAnalzer.java @@ -159,5 +159,4 @@ public void renderScreen(@Nonnull ItemStack componentStack, List modu public ResourceIcon getComponentIcon(@Nonnull ItemStack armorStack) { return null; } - } From 510571ab3c603e6f2a7982d0ec8e6712d83a6c78 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:09:12 +0100 Subject: [PATCH 261/424] Fix formatting by removing trailing newline Removed unnecessary newline at the end of the file. --- .../advancedRocketry/mission/MissionResourceCollection.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/mission/MissionResourceCollection.java b/src/main/java/zmaster587/advancedRocketry/mission/MissionResourceCollection.java index 6b4e20c68..8126abccf 100644 --- a/src/main/java/zmaster587/advancedRocketry/mission/MissionResourceCollection.java +++ b/src/main/java/zmaster587/advancedRocketry/mission/MissionResourceCollection.java @@ -198,5 +198,4 @@ public void unlinkInfrastructure(IInfrastructure tile) { HashedBlockPosition pos = new HashedBlockPosition(((TileEntity) tile).getPos()); infrastructureCoords.remove(pos); } - } From c02861788f6de64c36a95a88f30efd4ed87cf877 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:10:04 +0100 Subject: [PATCH 262/424] Add newline at end of EntityStationDeployedRocket.java Fix missing newline at end of file. From 7d7a59f5d12c5e52e9ae881b6d5882a095b117be Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:11:56 +0100 Subject: [PATCH 263/424] Add newline at end of TileUnmannedVehicleAssembler.java Fix missing newline at end of file From c2e1c89b08d286a1e6aa82be2d5bc2a75a99f226 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:12:24 +0100 Subject: [PATCH 264/424] Fix missing newline at end of TileSatelliteTerminal.java From 36e526dc20a1092eac15f5790c0046dabb7c054a Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:13:34 +0100 Subject: [PATCH 265/424] Refactor TileWirelessTransciever code structure --- .../tile/cables/TileWirelessTransciever.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java b/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java index b44255465..69a3c44ba 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/cables/TileWirelessTransciever.java @@ -33,8 +33,6 @@ import zmaster587.libVulpes.network.PacketMachine; import zmaster587.libVulpes.util.INetworkMachine; - - import javax.annotation.Nonnull; import java.util.LinkedList; import java.util.List; @@ -277,7 +275,7 @@ public List getModules(int id, EntityPlayer player) { list.add(toggleSwitch); list.add(netIdLabel); - // Bar-only UI (no buttons/slots). Place it where you want it. + // Bar-only UI list.add(new ModuleWirelessBufferBar(14, 22, uiBuffer)); return list; @@ -461,7 +459,7 @@ public void update() { // Resolve front for either 6-way or legacy block EnumFacing front = resolveFront(state); - EnumFacing facing = front.getOpposite(); // keep existing IO semantics + EnumFacing facing = front.getOpposite(); TileEntity neighbor = world.getTileEntity(getPos().offset(facing)); if (neighbor == null || neighbor instanceof TileWirelessTransciever) return; if (!(neighbor instanceof IDataHandler)) return; @@ -537,6 +535,4 @@ public void invalidate() { super.invalidate(); } - - } From c4cd7c78a10a850893f15b7c3bb8066d97543854 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:14:31 +0100 Subject: [PATCH 266/424] Fix missing newline at end of StatsRocket.java Add missing newline at the end of the file From 4b8f6dc5f6841d3f3778db311eb92a55cda8a5b2 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:19:40 +0100 Subject: [PATCH 267/424] Add newline at end of WeightEngine.java Fix formatting issue by adding a newline at the end of the file. From d56faae3c51f446130efc09437083c735ea2bcfc Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:20:55 +0100 Subject: [PATCH 268/424] Update TileFluidTank.java --- .../java/zmaster587/advancedRocketry/tile/TileFluidTank.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileFluidTank.java b/src/main/java/zmaster587/advancedRocketry/tile/TileFluidTank.java index 8cde1f94f..c0843e49f 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileFluidTank.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileFluidTank.java @@ -366,8 +366,4 @@ else if (dir == EnumFacing.UP) { exitColumnOp(); } } - - - - } From 46b3ee077b2237f409c0dc37dc02184d9f6a5662 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:22:28 +0100 Subject: [PATCH 269/424] Refactor DataStorage.java formatting Removed an empty line and fixed the closing brace formatting. --- src/main/java/zmaster587/advancedRocketry/api/DataStorage.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/api/DataStorage.java b/src/main/java/zmaster587/advancedRocketry/api/DataStorage.java index ac53852fc..c99849801 100644 --- a/src/main/java/zmaster587/advancedRocketry/api/DataStorage.java +++ b/src/main/java/zmaster587/advancedRocketry/api/DataStorage.java @@ -168,7 +168,6 @@ public void readFromNBT(NBTTagCompound nbt) { } } - public enum DataType { UNDEFINED, DISTANCE, From dbf0fe2fbaf1cb86845b7229b45845f4fc436716 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:23:07 +0100 Subject: [PATCH 270/424] Fix missing newline at end of ItemSatellite.java Added a newline at the end of the file. From bc25c2366c6f4198676b7cac23c534d2ea508110 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 17 Nov 2025 09:23:34 +0100 Subject: [PATCH 271/424] Fix missing newline in ItemSatelliteIdentificationChip.java Add missing newline at end of file From 255e9a45fbad077ff8d38d334601c6ccaaef2ae4 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 20 Nov 2025 19:39:19 +0100 Subject: [PATCH 272/424] Implement tooltip for ItemJackHammer Added tooltip information for ItemJackHammer. --- .../advancedRocketry/item/ItemJackHammer.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemJackHammer.java b/src/main/java/zmaster587/advancedRocketry/item/ItemJackHammer.java index 6aa3551b3..560f3554d 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemJackHammer.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemJackHammer.java @@ -4,14 +4,22 @@ import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemTool; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.oredict.OreDictionary; import zmaster587.advancedRocketry.api.MaterialGeode; +import zmaster587.advancedRocketry.client.TooltipInjector; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; + +import java.util.List; import java.util.Set; public class ItemJackHammer extends ItemTool { @@ -40,4 +48,12 @@ public float getDestroySpeed(@Nonnull ItemStack stack, IBlockState state) { public boolean canHarvestBlock(IBlockState blockIn) { return true; } + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.jackhammer", insertAt); + } + } From 1d07d610245359a4a431260620aa704c6197aa70 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 20 Nov 2025 19:39:42 +0100 Subject: [PATCH 273/424] Add tooltip support to BlockThermiteTorch Implement tooltip information for Thermite Torch. --- .../block/BlockThermiteTorch.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/block/BlockThermiteTorch.java b/src/main/java/zmaster587/advancedRocketry/block/BlockThermiteTorch.java index 3c5aedd3a..266895ca5 100644 --- a/src/main/java/zmaster587/advancedRocketry/block/BlockThermiteTorch.java +++ b/src/main/java/zmaster587/advancedRocketry/block/BlockThermiteTorch.java @@ -1,7 +1,23 @@ package zmaster587.advancedRocketry.block; +import java.util.List; + +import javax.annotation.Nullable; + import net.minecraft.block.BlockTorch; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import zmaster587.advancedRocketry.client.TooltipInjector; public class BlockThermiteTorch extends BlockTorch { + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.thermitetorch", insertAt); + } } From 4fa3b38453bc98901880bacc5291b630192a9b26 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 20 Nov 2025 19:40:15 +0100 Subject: [PATCH 274/424] Add tooltip information to ItemThermite --- .../advancedRocketry/item/ItemThermite.java | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemThermite.java b/src/main/java/zmaster587/advancedRocketry/item/ItemThermite.java index a17a52453..9b0368631 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemThermite.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemThermite.java @@ -1,9 +1,17 @@ package zmaster587.advancedRocketry.item; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import zmaster587.advancedRocketry.client.TooltipInjector; + +import java.util.List; import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class ItemThermite extends Item { @@ -11,5 +19,11 @@ public class ItemThermite extends Item { public int getItemBurnTime(@Nonnull ItemStack itemStack) { return 6000; } - + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.thermite", insertAt); + } + } From 001151069751eb18a671b849fcbb455e31c3d7e7 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 20 Nov 2025 19:40:39 +0100 Subject: [PATCH 275/424] Update hovercraft tooltip localization key --- .../java/zmaster587/advancedRocketry/item/ItemHovercraft.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemHovercraft.java b/src/main/java/zmaster587/advancedRocketry/item/ItemHovercraft.java index f6c2c96ae..cb7bea633 100755 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemHovercraft.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemHovercraft.java @@ -101,6 +101,6 @@ public ActionResult onItemRightClick(World worldIn, EntityPlayer play @Override public void addInformation(@Nonnull ItemStack stack, World worldIn, List tooltip, ITooltipFlag flagIn) { - tooltip.add(LibVulpes.proxy.getLocalizedString("item.hovercraft.tooltip")); + tooltip.add(LibVulpes.proxy.getLocalizedString("tooltip.advancedrocketry.hovercraft")); } } From 1e001e6e436e4fd43f3259a034ef88889b575f64 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 20 Nov 2025 20:36:12 +0100 Subject: [PATCH 276/424] Refactor addInformation method parameters and logic --- .../item/ItemWeatherController.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemWeatherController.java b/src/main/java/zmaster587/advancedRocketry/item/ItemWeatherController.java index a3360f947..a574b1f30 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemWeatherController.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemWeatherController.java @@ -56,19 +56,23 @@ public List getModules(int id, EntityPlayer player) { } @Override - public void addInformation(@Nonnull ItemStack stack, World player, List list, ITooltipFlag arg5) { + public void addInformation(@Nonnull ItemStack stack, World world, List list, ITooltipFlag flag) { - SatelliteBase sat = SatelliteRegistry.getSatellite(stack); + // If unprogrammed, let the superclass handle the "unprogrammed" tooltip + if (!stack.hasTagCompound()) { + super.addInformation(stack, world, list, flag); + return; + } + SatelliteBase sat = SatelliteRegistry.getSatellite(stack); SatelliteWeatherController mapping = null; + if (sat instanceof SatelliteWeatherController) mapping = (SatelliteWeatherController) sat; - if (!stack.hasTagCompound()) - list.add(LibVulpes.proxy.getLocalizedString("msg.unprogrammed")); - else if (mapping == null) + if (mapping == null) { list.add(LibVulpes.proxy.getLocalizedString("msg.biomechanger.nosat")); - else if (mapping.getDimensionId() == player.provider.getDimension()) { + } else if (mapping.getDimensionId() == world.provider.getDimension()) { list.add(LibVulpes.proxy.getLocalizedString("msg.connected")); if (mapping.mode_id == 0) list.add("mode: rain - Fills small basins in the terrain with water"); @@ -76,10 +80,12 @@ else if (mapping.getDimensionId() == player.provider.getDimension()) { list.add("mode: dry - Drys all water in a radius of 16"); if (mapping.mode_id == 2) list.add("mode: flood - Floods area with a radius of 16 with water"); - } else + } else { list.add(LibVulpes.proxy.getLocalizedString("msg.notconnected")); + } - super.addInformation(stack, player, list, arg5); + // Still let the parent add its usual info (except "unprogrammed", which we handled above) + super.addInformation(stack, world, list, flag); } From b09a64079ce41e7b807866604d8354b9f6aa9cfa Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 20 Nov 2025 20:36:30 +0100 Subject: [PATCH 277/424] Refactor addInformation method in ItemBiomeChanger --- .../item/ItemBiomeChanger.java | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemBiomeChanger.java b/src/main/java/zmaster587/advancedRocketry/item/ItemBiomeChanger.java index eb460113d..220c408d2 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemBiomeChanger.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemBiomeChanger.java @@ -64,27 +64,29 @@ public List getModules(int id, EntityPlayer player) { } @Override - public void addInformation(@Nonnull ItemStack stack, World player, List list, ITooltipFlag arg5) { + public void addInformation(@Nonnull ItemStack stack, World world, List list, ITooltipFlag flag) { SatelliteBase sat = SatelliteRegistry.getSatellite(stack); + SatelliteBiomeChanger mapping = sat instanceof SatelliteBiomeChanger ? (SatelliteBiomeChanger) sat : null; - SatelliteBiomeChanger mapping = null; - if (sat instanceof SatelliteBiomeChanger) - mapping = (SatelliteBiomeChanger) sat; + // If unprogrammed, let the superclass handle the "unprogrammed" tooltip so it only shows once + if (!stack.hasTagCompound()) { + super.addInformation(stack, world, list, flag); + return; + } - if (!stack.hasTagCompound()) - list.add(LibVulpes.proxy.getLocalizedString("msg.unprogrammed")); - else if (mapping == null) + if (mapping == null) { list.add(LibVulpes.proxy.getLocalizedString("msg.biomechanger.nosat")); - else if (mapping.getDimensionId() == player.provider.getDimension()) { + } else if (mapping.getDimensionId() == world.provider.getDimension()) { list.add(LibVulpes.proxy.getLocalizedString("msg.connected")); - if (mapping.getBiome()!=null) + if (mapping.getBiome() != null) list.add(LibVulpes.proxy.getLocalizedString("msg.biomechanger.selBiome") + mapping.getBiome().getBiomeName()); list.add(LibVulpes.proxy.getLocalizedString("msg.biomechanger.numBiome") + mapping.discoveredBiomes().size()); - } else + } else { list.add(LibVulpes.proxy.getLocalizedString("msg.notconnected")); + } - super.addInformation(stack, player, list, arg5); + super.addInformation(stack, world, list, flag); } From 162b68e5f4d95e4319e9cae2712e33bfb25eb88a Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 20 Nov 2025 20:37:57 +0100 Subject: [PATCH 278/424] removed internal energy since its not used this tile uses the satellites rf, waila/oneprobe showing rf is just confusing also fixed typo in GUI --- .../satellite/TileTerraformingTerminal.java | 54 ++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileTerraformingTerminal.java b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileTerraformingTerminal.java index 4a80d0de4..8a1a8eed1 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileTerraformingTerminal.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileTerraformingTerminal.java @@ -8,6 +8,8 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.world.biome.BiomeProvider; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.energy.CapabilityEnergy; import net.minecraftforge.fml.relauncher.Side; import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; @@ -31,6 +33,7 @@ import zmaster587.libVulpes.network.PacketMachine; import zmaster587.libVulpes.tile.TileInventoriedRFConsumer; import zmaster587.libVulpes.util.INetworkMachine; +import zmaster587.libVulpes.cap.TeslaHandler; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -65,7 +68,7 @@ public int[] getSlotsForFace(@Nullable EnumFacing side) { @Override public String getModularInventoryName() { - return AdvancedRocketryBlocks.blockSatelliteControlCenter.getLocalizedName(); + return AdvancedRocketryBlocks.blockTerraformingTerminal.getLocalizedName(); } @Override @@ -209,14 +212,14 @@ public void updateInventoryInfo() { BigDecimal bd = new BigDecimal(randomblocks_per_tick); bd = bd.setScale(2, RoundingMode.HALF_UP); - moduleText.setText("terraforming planet...\n" + - "\nPower generation:" + sat_power_per_tick + - "\nBlocks per tick:" + bd); + moduleText.setText("Terraforming planet...\n" + + "\nPower generation: " + sat_power_per_tick + + "\nBlocks per tick: " + bd); } else if (hasValidBiomeChanger()) { - moduleText.setText("provide redstone signal\nto start the process"); + moduleText.setText("Provide redstone signal\nto start the process"); } else { - moduleText.setText("place a biome remote here\nto make the satellite terraform\nthe entire planet"); + moduleText.setText("\nPlace a Biome Changer Remote\nhere to make the Satellite\nterraform the entire planet"); } } @@ -265,6 +268,45 @@ public NBTTagCompound writeToNBT(NBTTagCompound nbt) { return nbt; } + @Override + public boolean canConnectEnergy(EnumFacing side) { + return false; + } + + @Override + public boolean canReceive() { + return false; + } + + @Override + public int getEnergyStored(EnumFacing side) { + return 0; + } + + @Override + public int getMaxEnergyStored(EnumFacing side) { + return 0; + } + + @Override + public boolean hasCapability(Capability capability, @Nullable EnumFacing facing) { + // Hide Forge Energy capability + if (capability == CapabilityEnergy.ENERGY) return false; + // Hide any Tesla capability the base class would expose + if (TeslaHandler.hasTeslaCapability(this, capability)) return false; + return super.hasCapability(capability, facing); + } + + @Override + @Nullable + public T getCapability(Capability capability, @Nullable EnumFacing facing) { + // Don’t provide energy handlers to probes/pipes + if (capability == CapabilityEnergy.ENERGY) return null; + if (TeslaHandler.hasTeslaCapability(this, capability)) return null; + return super.getCapability(capability, facing); + } + + @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); From 18b5b084d363a91e919fdebad3106db84bcdafbc Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 20 Nov 2025 20:56:20 +0100 Subject: [PATCH 279/424] Correct mode descriptions to use proper casing --- .../advancedRocketry/item/ItemWeatherController.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemWeatherController.java b/src/main/java/zmaster587/advancedRocketry/item/ItemWeatherController.java index a574b1f30..f2b0dc64a 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemWeatherController.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemWeatherController.java @@ -75,11 +75,11 @@ public void addInformation(@Nonnull ItemStack stack, World world, List l } else if (mapping.getDimensionId() == world.provider.getDimension()) { list.add(LibVulpes.proxy.getLocalizedString("msg.connected")); if (mapping.mode_id == 0) - list.add("mode: rain - Fills small basins in the terrain with water"); + list.add("Mode: rain - Fills small basins in the terrain with water"); if (mapping.mode_id == 1) - list.add("mode: dry - Drys all water in a radius of 16"); + list.add("Mode: dry - Drys all water in a radius of 16"); if (mapping.mode_id == 2) - list.add("mode: flood - Floods area with a radius of 16 with water"); + list.add("Mode: flood - Floods area with a radius of 16 with water"); } else { list.add(LibVulpes.proxy.getLocalizedString("msg.notconnected")); } From 0aa7ed1a9a32e08672d55aeb779991b92bc5d1dd Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 20 Nov 2025 20:59:11 +0100 Subject: [PATCH 280/424] Correct capitalization in weather mode descriptions --- .../advancedRocketry/item/ItemWeatherController.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemWeatherController.java b/src/main/java/zmaster587/advancedRocketry/item/ItemWeatherController.java index f2b0dc64a..e29e11504 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemWeatherController.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemWeatherController.java @@ -75,11 +75,11 @@ public void addInformation(@Nonnull ItemStack stack, World world, List l } else if (mapping.getDimensionId() == world.provider.getDimension()) { list.add(LibVulpes.proxy.getLocalizedString("msg.connected")); if (mapping.mode_id == 0) - list.add("Mode: rain - Fills small basins in the terrain with water"); + list.add("Mode: Rain - Fills small basins in the terrain with water"); if (mapping.mode_id == 1) - list.add("Mode: dry - Drys all water in a radius of 16"); + list.add("Mode: Dry - Drys all water in a radius of 16"); if (mapping.mode_id == 2) - list.add("Mode: flood - Floods area with a radius of 16 with water"); + list.add("Mode: Flood - Floods area with a radius of 16 with water"); } else { list.add(LibVulpes.proxy.getLocalizedString("msg.notconnected")); } From 83085a138b92d158ca815e844ae0fda936380bad Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 20 Nov 2025 21:32:12 +0100 Subject: [PATCH 281/424] Update modVersion in gradle.properties small tooltip polish --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index b16343f8a..6eff6a358 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ org.gradle.daemon=false # Project mcVersion=1.12.2 forgeVersion=14.23.5.2860 -modVersion=2.2.1 +modVersion=2.2.1-1 archiveBase=AdvancedRocketry startGitRev=8e676bd From 9bf54259107aab1c1583981708fcc5afdb2ec646 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 20 Nov 2025 21:51:22 +0100 Subject: [PATCH 282/424] Implement tooltip for Basic Laser Gun Added tooltip information for the Basic Laser Gun. --- .../item/tools/ItemBasicLaserGun.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/item/tools/ItemBasicLaserGun.java b/src/main/java/zmaster587/advancedRocketry/item/tools/ItemBasicLaserGun.java index 2e50ef406..ca58000fe 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/tools/ItemBasicLaserGun.java +++ b/src/main/java/zmaster587/advancedRocketry/item/tools/ItemBasicLaserGun.java @@ -5,6 +5,7 @@ import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; +import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; @@ -17,11 +18,15 @@ import net.minecraft.util.math.*; import net.minecraft.util.math.RayTraceResult.Type; import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import zmaster587.advancedRocketry.AdvancedRocketry; +import zmaster587.advancedRocketry.client.TooltipInjector; import zmaster587.advancedRocketry.util.AudioRegistry; import zmaster587.libVulpes.LibVulpes; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import java.util.List; import java.util.WeakHashMap; @@ -249,4 +254,12 @@ public ActionResult onItemRightClick(World worldIn, EntityPlayer play } return new ActionResult<>(EnumActionResult.PASS, stack); } + + @SideOnly(Side.CLIENT) + @Override + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + int insertAt = TooltipInjector.computeInsertIndex(tooltip, flag.isAdvanced()); + TooltipInjector.renderShiftAlt(stack, tooltip, "tooltip.advancedrocketry.lasergun", insertAt); + } + } From c8beca2088415746030261422e075cd759e8a047 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 20 Nov 2025 21:51:45 +0100 Subject: [PATCH 283/424] Add tooltips for new remote and crafting items --- .../client/TooltipInjector.java | 45 ++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/client/TooltipInjector.java b/src/main/java/zmaster587/advancedRocketry/client/TooltipInjector.java index b2fa67284..3ee9cf119 100644 --- a/src/main/java/zmaster587/advancedRocketry/client/TooltipInjector.java +++ b/src/main/java/zmaster587/advancedRocketry/client/TooltipInjector.java @@ -316,10 +316,53 @@ private TooltipInjector() {} KEY_BY_ID.put("advancedrocketry:pump", "tooltip.advancedrocketry.pump"); KEY_BY_SUFFIX.put("pump", "tooltip.advancedrocketry.pump"); + // ---- Remotes ---- + KEY_BY_ID.put("advancedrocketry:biomechanger", "tooltip.advancedrocketry.biomechangerremote"); + KEY_BY_SUFFIX.put("biomechanger", "tooltip.advancedrocketry.biomechangerremote"); + + KEY_BY_ID.put("advancedrocketry:weathercontroller", "tooltip.advancedrocketry.weathercontrollerremote"); + KEY_BY_SUFFIX.put("weathercontroller", "tooltip.advancedrocketry.weathercontrollerremote"); + + KEY_BY_ID.put("advancedrocketry:orescanner", "tooltip.advancedrocketry.orescanner"); + KEY_BY_SUFFIX.put("orescanner", "tooltip.advancedrocketry.orescanner"); + + + + // ---- Crafting items ---- + // Iron Saw Blade + KEY_BY_ID.put("advancedrocketry:sawbladeiron", "tooltip.advancedrocketry.sawbladeiron"); + KEY_BY_SUFFIX.put("sawbladeiron", "tooltip.advancedrocketry.sawbladeiron"); + + // Wafer + KEY_BY_ID.put("advancedrocketry:wafer", "tooltip.advancedrocketry.wafer"); + KEY_BY_SUFFIX.put("wafer", "tooltip.advancedrocketry.wafer"); + + // Circuit Plate + KEY_BY_ID.put("advancedrocketry:itemcircuitplate", "tooltip.advancedrocketry.circuitplate"); + KEY_BY_SUFFIX.put("itemcircuitplate", "tooltip.advancedrocketry.circuitplate"); + KEY_BY_SUFFIX.put("circuitplate", "tooltip.advancedrocketry.circuitplate"); + + // itemLens + KEY_BY_ID.put("advancedrocketry:lens", "tooltip.advancedrocketry.itemlens"); + KEY_BY_SUFFIX.put("lens", "tooltip.advancedrocketry.itemlens"); + + // Integrated Circuit (IC) + KEY_BY_ID.put("advancedrocketry:ic", "tooltip.advancedrocketry.circuitic"); + KEY_BY_SUFFIX.put("ic", "tooltip.advancedrocketry.circuitic"); + KEY_BY_SUFFIX.put("circuitIC", "tooltip.advancedrocketry.circuitic"); + + // Misc parts + KEY_BY_ID.put("advancedrocketry:miscpart", "tooltip.advancedrocketry.miscpart"); + KEY_BY_SUFFIX.put("miscpart", "tooltip.advancedrocketry.miscpart"); + + KEY_BY_ID.put("advancedrocketry:misc", "tooltip.advancedrocketry.misc"); + KEY_BY_SUFFIX.put("misc", "tooltip.advancedrocketry.misc"); + + // ---- Assemblers ---- // Rocket Assembler KEY_BY_ID.put("advancedrocketry:rocketbuilder", "tooltip.advancedrocketry.rocketassembler"); - KEY_BY_SUFFIX.put("rocketbuilder", "tooltip.advancedrocketry.rocketassembler"); // safety + KEY_BY_SUFFIX.put("rocketbuilder", "tooltip.advancedrocketry.rocketassembler"); KEY_BY_SUFFIX.put("rocketAssembler", "tooltip.advancedrocketry.rocketassembler"); // Space Station Assembler From c0bc69d002fed91ae73d57b42a90a0ffa46a2747 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 20 Nov 2025 21:54:56 +0100 Subject: [PATCH 284/424] Refine item tooltips and messages in en_US.lang Updated tooltips for various items and messages to improve clarity and consistency. --- .../assets/advancedrocketry/lang/en_US.lang | 114 ++++++++++++------ 1 file changed, 78 insertions(+), 36 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index 59217f53f..c6b05361b 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -192,7 +192,7 @@ item.basicLaserGun.name=Basic Laser Gun item.beaconFinder.name=Beacon Finder item.thermite.name=Thermite item.hovercraft.name=Hovercraft -item.hovercraft.tooltip=Long lasting dilithium Power source. It'll probably outlive you. + item.jetPack.name=Suit Jetpack item.pressureTank.0.name=Low Pressure Tank @@ -529,11 +529,11 @@ msg.notenoughpower=Not Enough Power! msg.empty=Empty msg.yes=yes msg.no=no -msg.connected=connected -msg.notconnected=not connected +msg.connected=Connected +msg.notconnected=Not Connected msg.unprogrammed=Unprogrammed msg.programfail=Programming Failed -msg.modules=modules +msg.modules=Modules: msg.na=N/A msg.entityDeployedRocket.notGasGiant=No Gas Here msg.noOxygen=Warning: Atmosphere lacks oxygen! @@ -663,11 +663,11 @@ tooltip.advancedrocketry.structuretower.alt.1=Main block for Unmanned Vehicle As tooltip.advancedrocketry.structuretower.alt.2=Check wiki for more info. # Terraformer -tooltip.advancedrocketry.terraformer=Terraform -tooltip.advancedrocketry.terraformer.shift.1=Terraform stuff -tooltip.advancedrocketry.terraformer.shift.2= -tooltip.advancedrocketry.terraformer.alt.1=Terraform stuff -tooltip.advancedrocketry.terraformer.alt.2= +tooltip.advancedrocketry.terraformer=Terraform the entire planet! +tooltip.advancedrocketry.terraformer.shift.1=§fUse with §cBiome Changer Satellite +tooltip.advancedrocketry.terraformer.shift.2=§fSatellite has to orbit this planet +tooltip.advancedrocketry.terraformer.alt.1=§fInsert §cBiome Changer Remote +tooltip.advancedrocketry.terraformer.alt.2=§fPowered by Satellite # Rocket Monitoring Station tooltip.advancedrocketry.monitoringstation=§cInfrastructure @@ -754,10 +754,10 @@ tooltip.advancedrocketry.fluidtank.shift.1=§cConnects to tanks above or below t # Wireless Transciever tooltip.advancedrocketry.transceiver=Transfers §6Data -tooltip.advancedrocketry.transceiver.shift.1=Use §cLinker§7 to create Networks -tooltip.advancedrocketry.transceiver.shift.2=Supports multiple Tranceivers +tooltip.advancedrocketry.transceiver.shift.1=§fUse §cLinker§f to create Networks +tooltip.advancedrocketry.transceiver.shift.2=§fSupports multiple Tranceivers tooltip.advancedrocketry.transceiver.alt.1=§fExtractmode toggles autodownload from Terminal -tooltip.advancedrocketry.transceiver.alt.2=(reinsert chip if stale) +tooltip.advancedrocketry.transceiver.alt.2=§o(reinsert chip if stale) # Atmosphere Detector tooltip.advancedrocketry.atmosphereDetector=Emits redstone based on Atmosphere @@ -848,7 +848,7 @@ tooltip.advancedrocketry.warpcontroller.alt.2=(You made it this far! check wiki # CarbonScrubberCartridge tooltip.advancedrocketry.scrubbercart=Used in CO₂ Scrubber -tooltip.advancedrocketry.scrubbercart.shift.1=Purifies air while at cost of durability. +tooltip.advancedrocketry.scrubbercart.shift.1=Purifies air at the cost of durability. tooltip.advancedrocketry.atmanalyzer.alt.1=Should last more than 24h # Seal Detector @@ -872,9 +872,9 @@ tooltip.advancedrocketry.jetpack=§5Space Suit Component tooltip.advancedrocketry.jetpack.shift.1=§dSlot: Chest§7 # AtmosphereAnalyzer -tooltip.advancedrocketry.atmanalyzer=§5Space Suit ComponentRight Click to check atmosphere. -tooltip.advancedrocketry.atmanalyzer.shift.1=§fRight Click to check atmosphere. -tooltip.advancedrocketry.atmanalyzer.shift.2=§dSlot: Helmet§7 +tooltip.advancedrocketry.atmanalyzer=§5Space Suit Component +tooltip.advancedrocketry.atmanalyzer.1=§fRight Click in hand to check atmosphere. +tooltip.advancedrocketry.atmanalyzer.shift.1=§dSlot: Helmet§7 tooltip.advancedrocketry.atmanalyzer.alt.1=Breathable? Depends on atmosphere tooltip.advancedrocketry.atmanalyzer.alt.2=Shows type and pressure @@ -901,14 +901,14 @@ tooltip.advancedrocketry.itemupgrade.0.alt.2=Stacking has no additional effect. # 1 = Flight Speed Control Upgrade tooltip.advancedrocketry.itemupgrade.1=§5Space Suit Component tooltip.advancedrocketry.itemupgrade.1.shift.1=§fBoosts Jetpack flight speed -tooltip.advancedrocketry.itemupgrade.1.shift.2=§dSlot: Helmet§7 +tooltip.advancedrocketry.itemupgrade.1.shift.2=§dSlot: Leggings§7 tooltip.advancedrocketry.itemupgrade.1.alt.1=Requires a Jetpack installed in the chestplate. tooltip.advancedrocketry.itemupgrade.1.alt.2=§bEffect Stacks! # 2 = Bionic Leg Upgrade (speed) tooltip.advancedrocketry.itemupgrade.2=§5Space Suit Component -tooltip.advancedrocketry.itemupgrade.2.shift.1=§fLeg upgrade: increases walk speed -tooltip.advancedrocketry.itemupgrade.2.shift.2=§dSlot: Legs§7 +tooltip.advancedrocketry.itemupgrade.2.shift.1=§fIncreases walk speed +tooltip.advancedrocketry.itemupgrade.2.shift.2=§dSlot: Leggings§7 tooltip.advancedrocketry.itemupgrade.2.alt.1=Sprint to activate tooltip.advancedrocketry.itemupgrade.2.alt.2=Stacks with multiple modules. @@ -916,22 +916,19 @@ tooltip.advancedrocketry.itemupgrade.2.alt.2=Stacks with multiple modules. tooltip.advancedrocketry.itemupgrade.3=§5Space Suit Component tooltip.advancedrocketry.itemupgrade.3.shift.1=§fEliminates fall damage tooltip.advancedrocketry.itemupgrade.3.shift.2=§dSlot: Feet§7 -tooltip.advancedrocketry.itemupgrade.3.alt.1= -tooltip.advancedrocketry.itemupgrade.3.alt.2=Stacking has no additional effect. +tooltip.advancedrocketry.itemupgrade.3.alt.1=Stacking has no additional effect. # 4 = Antifog Visor Upgrade tooltip.advancedrocketry.itemupgrade.4=§5Space Suit Component -tooltip.advancedrocketry.itemupgrade.4.shift.1=WIP if u know what this does contact me +tooltip.advancedrocketry.itemupgrade.4.shift.1=§fSee through fog on high pressure planets tooltip.advancedrocketry.itemupgrade.4.shift.2=§dSlot: Helmet§7 -tooltip.advancedrocketry.itemupgrade.4.alt.1=See through fog on high pressure planets -tooltip.advancedrocketry.itemupgrade.4.alt.2=Stacking has no additional effect. +tooltip.advancedrocketry.itemupgrade.4.alt.1=Stacking has no additional effect. # 5 = Earthbright Visor tooltip.advancedrocketry.itemupgrade.5=§5Space Suit Component -tooltip.advancedrocketry.itemupgrade.5.shift.1=WIP if u know what this does contact me +tooltip.advancedrocketry.itemupgrade.5.shift.1=§fAdjusts the lightlevels on distant worlds tooltip.advancedrocketry.itemupgrade.5.shift.2=§dSlot: Helmet§7 -tooltip.advancedrocketry.itemupgrade.5.alt.1= -tooltip.advancedrocketry.itemupgrade.5.alt.2=Stacking has no additional effect. +tooltip.advancedrocketry.itemupgrade.5.alt.1=Stacking has no additional effect. ## Satellite Components # Primary Function payloads @@ -966,13 +963,29 @@ tooltip.advancedrocketry.satfunc.oremapping.alt.2=when assembling tooltip.advancedrocketry.satfunc.biomechanger=§5Satellite Core Component tooltip.advancedrocketry.satfunc.biomechanger.shift.1=§bAdjusts biomes§7 -tooltip.advancedrocketry.satfunc.biomechanger.alt.1=Combine with Biome Changer Remote -tooltip.advancedrocketry.satfunc.biomechanger.alt.2=when assembling +tooltip.advancedrocketry.satfunc.biomechanger.alt.1=Combine with Biome Changer Remote when assembling +tooltip.advancedrocketry.satfunc.biomechanger.alt.2=Requires Power generation and storage! tooltip.advancedrocketry.satfunc.weather=§5Satellite Core Component tooltip.advancedrocketry.satfunc.weather.shift.1=§bDoes some weather stuff! -tooltip.advancedrocketry.satfunc.weather.alt.1=Combine with Weather Remote -tooltip.advancedrocketry.satfunc.weather.alt.2=when assembling +tooltip.advancedrocketry.satfunc.weather.alt.1=Combine with Weather Remote when assembling + +# Weather Remote +tooltip.advancedrocketry.weathercontrollerremote=§bShift-Right Click to open GUI +tooltip.advancedrocketry.weathercontrollerremote.shift.1=§fRight-click in hand to use +tooltip.advancedrocketry.weathercontrollerremote.alt.1=Combine with Weather Controller when assembling + +# Biome Changer Remote +tooltip.advancedrocketry.biomechangerremote=§bShift-Right Click to open GUI +tooltip.advancedrocketry.biomechangerremote.shift.1=§fRight-click in hand to transform a 20×20 area +tooltip.advancedrocketry.biomechangerremote.shift.2=§f"Scan Biome" stores the Biome you're standing in to satellite’s memory. +tooltip.advancedrocketry.biomechangerremote.alt.1=§6Satellite needs alot of power +tooltip.advancedrocketry.biomechangerremote.alt.2=§fUsed in §cTerraforming Terminal§f and§c Atmosphere Terraformer + +# Ore Scanner +tooltip.advancedrocketry.orescanner=§bRight-Click to open GUI +tooltip.advancedrocketry.orescanner.shift.1=§fIf satellite has at least §63,000 data§f storage, the Ore Scanner can filter by type. +tooltip.advancedrocketry.orescanner.alt.1=§fScan range depends on the satellite's energy generation # Power Sources tooltip.advancedrocketry.satpower.0=§5Satellite Component @@ -1021,9 +1034,7 @@ tooltip.advancedrocketry.satidchip.alt.1=§4Use in Satellite Monitor to link or tooltip.advancedrocketry.elevatorchip=Space Elevator Chip tooltip.advancedrocketry.elevatorchip.shift.1=§fLinks an elevator pad/destination. - ## Multiblocks - # Black Hole Generator tooltip.advancedrocketry.blackholegen=Generates Power from compressed mass tooltip.advancedrocketry.blackholegen.shift.1=§bUse Holo-Projector! @@ -1045,13 +1056,11 @@ tooltip.advancedrocketry.solarpanel.shift.3=§bUse Holo-Projector! tooltip.advancedrocketry.solararray=Generates Power from sunlight tooltip.advancedrocketry.solararray.shift.1=Requires 63x Solar Array Panels tooltip.advancedrocketry.solararray.shift.2=§bUse Holo-Projector! -tooltip.advancedrocketry.solararray.alt.1= # Solar Array Panel tooltip.advancedrocketry.solararraypanel=§cPart of Multiblock tooltip.advancedrocketry.solararraypanel.shift.1=Requires 63x Solar Array Panels and Controller tooltip.advancedrocketry.solararraypanel.shift.2=§bUse Holo-Projector! -tooltip.advancedrocketry.solararray.alt.1= # Solar Generator tooltip.advancedrocketry.solargenerator=Basic Solar Panel @@ -1098,6 +1107,7 @@ tooltip.advancedrocketry.observatory=Analyzes celestial bodies tooltip.advancedrocketry.observatory.shift.1=§fUsed for §6Mining Missions tooltip.advancedrocketry.observatory.shift.2=§bUse Holo-Projector! tooltip.advancedrocketry.observatory.alt.1=§fInsert §cAsteroid Chip +tooltip.advancedrocketry.observatory.alt.2=§fNeeds §6Distance Data§f to operate (operates only at night) # Planet Analyser @@ -1111,6 +1121,7 @@ tooltip.advancedrocketry.centrifuge.shift.1=§bUse Holo-Projector! # Warp Core tooltip.advancedrocketry.warpcore=Core for §6Starship tooltip.advancedrocketry.warpcore.shift.1=§bUse Holo-Projector! +tooltip.advancedrocketry.warpcore.alt.1=§6Starship §7needs §4Warp Controller§7 + §4Warp Core§7 # Beacon tooltip.advancedrocketry.beacon=Long-range signal beacon @@ -1132,7 +1143,7 @@ tooltip.advancedrocketry.spaceelevatorctrl.shift.1=§bUse Holo-Projector! # Atmosphere Terraformer tooltip.advancedrocketry.atmosterraformer=Changes Atmospheric pressure on an entire planet planet tooltip.advancedrocketry.atmosterraformer.shift.1=§bUse Holo-Projector! -tooltip.advancedrocketry.atmosterraformer.alt.1=Increase and decrease the atmosphere pressure by using connected §cBiome changing remote. +tooltip.advancedrocketry.atmosterraformer.alt.1=Increase and decrease the Atmospheric pressure by using connected §cBiome Changer Remote. # Area Gravity Controller tooltip.advancedrocketry.gravitymachine=Manipulates Gravity @@ -1190,3 +1201,34 @@ tooltip.advancedrocketry.deployablerocketassembler.shift.1=§bRequires Structure tooltip.advancedrocketry.deployablerocketassembler.shift.2=§fUsed for §6Gas Missions§7 tooltip.advancedrocketry.deployablerocketassembler.alt.1=§fPlace this in the middle of upside down T facing outwards in space, then a horizontal support outwards from the top of tower. tooltip.advancedrocketry.deployablerocketassembler.alt.2=Check wiki if unsure! + +# Hovercraft +tooltip.advancedrocketry.hovercraft=Long lasting dilithium Power source. It'll probably outlive you. + +# Thermite +tooltip.advancedrocketry.thermite=Known for generating intense heat! + +# Thermite Torch +tooltip.advancedrocketry.thermitetorch=Burns without oxygen +tooltip.advancedrocketry.thermitetorch.shift.1=§fUsed in low or no Atmosphere + +# Jackhammer +tooltip.advancedrocketry.jackhammer=§cVery Fast Mining Tool +tooltip.advancedrocketry.jackhammer.1=It'll probably outlive you, (if you change bolts) +tooltip.advancedrocketry.jackhammer.shift.1=§fRepair with §6Titanium Rod +tooltip.advancedrocketry.jackhammer.alt.1=§fHarvestlevel: §bDiamond + +# Basic basicLaserGun +tooltip.advancedrocketry.lasergun=§cRanged Mining Tool +tooltip.advancedrocketry.lasergun.shift.1=§dInfinite uses +tooltip.advancedrocketry.lasergun.alt.1=§fHarvestlevel: §bDiamond +tooltip.advancedrocketry.lasergun.alt.2=§fRange: §b50 blocks + +## Crafting items +tooltip.advancedrocketry.sawbladeiron=§3Crafting Item +tooltip.advancedrocketry.wafer=§3Crafting Item +tooltip.advancedrocketry.circuitplate=§3Crafting Item +tooltip.advancedrocketry.circuitic=§3Crafting Item +tooltip.advancedrocketry.miscpart=§3Crafting Item +tooltip.advancedrocketry.itemlens=§3Crafting Item +tooltip.advancedrocketry.misc=§3Crafting Item From a882636235c0a221170ce64be45591579a6b78d6 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 20 Nov 2025 21:56:23 +0100 Subject: [PATCH 285/424] Add newline at end of TooltipInjector.java Fix missing newline at end of TooltipInjector.java From 6c029701936efdde40bd43c65341a5e5a327f88f Mon Sep 17 00:00:00 2001 From: ZetaY <34602681+ZHAY10086@users.noreply.github.com> Date: Fri, 28 Nov 2025 16:09:53 +0800 Subject: [PATCH 286/424] Update zh_CN.lang --- .../assets/advancedrocketry/lang/zh_CN.lang | 1286 +++++++++++++---- 1 file changed, 1002 insertions(+), 284 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index 6d5379489..71ebbe4d1 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -1,71 +1,71 @@ itemGroup.advancedRocketry=高级火箭 -itemGroup.advancedRocketryOres=高级火箭矿物 - -death.attack.Vacuum=%1$s 因真空暴露死亡 -death.attack.Vacuum.player=%1$s 因真空暴露死亡 -death.attack.OxygenToxicity=%1$s 死于氧气中毒 -death.attack.OxygenToxicity.player=%1$s 死于氧气中毒 -death.attack.LowOxygen=%1$s 死于缺氧 -death.attack.LowOxygen.player=%1$s 死于缺氧 -death.attack.Heat=%1$s 死于高温暴露 -death.attack.Heat.player=%1$s 死于高温暴露 +itemGroup.advancedRocketryOres=高级火箭丨矿石 + +death.attack.Vacuum=%1$s因为失压而死 +death.attack.Vacuum.player=%1$s因为失压而死 +death.attack.OxygenToxicity=%1$s因氧气中毒而死 +death.attack.OxygenToxicity.player=%1$s因氧气中毒而死 +death.attack.LowOxygen=%1$s 因缺氧而死 +death.attack.LowOxygen.player=%1$s因缺氧而死 +death.attack.Heat=%1$s因过热而死 +death.attack.Heat.player=%1$s因过热而死 entity.advancedRocketry.rocket.name=火箭 entity.rocket.name=火箭 +entity.deployedRocket.name=火箭 entity.hovercraft.name=气垫船 -tile.landingPad.name=着陆平台 +tile.landingPad.name=着陆台 tile.seat.name=座位 tile.pad.name=发射台 tile.servicestation.name=服务站 -tile.servicemonitor.name=服务监控器 -tile.invhatch.name=储物舱口 +tile.servicemonitor.name=服务监测器 +tile.invhatch.name=存储舱口 tile.structuretower.name=结构塔 tile.rocketAssembler.name=火箭组装机 tile.turf.name=月面土 tile.turfDark.name=暗月面土 tile.cuttingMachine.name=切割机 -tile.sawBlade.name=电锯 -tile.controlComp.name=任务控制电脑 -tile.precisionAssemblingMachine.name=精确组装机 +tile.sawBlade.name=锯片组件 +tile.precisionAssemblingMachine.name=精密组装机 tile.spaceLaser.name=轨道激光钻 tile.Crystallizer.name=结晶器 tile.blastBrick.name=隔热砖 tile.blastFurnaceController.name=隔热高炉控制器 -tile.fuelStation.name=燃油站 +tile.fuelStation.name=加油站 tile.loader.0.name=数据总线 -tile.loader.1.name=卫星舱 +tile.loader.1.name=卫星仓 tile.loader.2.name=火箭卸载器 tile.loader.3.name=火箭装载器 -tile.loader.4.name=火箭液体卸载器 -tile.loader.5.name=火箭液体装载器 -tile.loader.6.name=导航电脑访问舱口 +tile.loader.4.name=火箭流体卸载器 +tile.loader.5.name=火箭流体装载器 +tile.loader.6.name=导航计算机访问舱口 tile.observatory.name=瞭望台 tile.satelliteBuilder.name=卫星建造机 -tile.rocket.name=单推进剂火箭发动机 -tile.bipropellantrocket.name=双燃料火箭发动机 +tile.rocket.name=单组元推进剂火箭发动机 +tile.bipropellantrocket.name=双组元推进剂火箭发动机 tile.nuclearrocket.name=核热火箭发动机 -tile.fuelTank.name=液体燃料箱 -tile.bipropellantfueltank.name=双燃料燃料箱 +tile.fuelTank.name=单组元推进剂燃料箱 +tile.bipropellantfueltank.name=双组元推进剂燃料箱 tile.oxidizerfueltank.name=氧化剂燃料箱 -tile.nuclearfueltank.name=核热工作燃料箱 -tile.nuclearcore.name=核热裂变核心 +tile.nuclearfueltank.name=核热工质箱 +tile.nuclearcore.name=核热裂变堆芯 tile.monitoringstation.name=火箭监测站 tile.satelliteMonitor.name=卫星终端 -tile.terraformingTerminal.name=地形改造终端 -tile.lightwoodlog.name=轻木原木 -tile.lightwoodsapling.name=轻木种子 -tile.lightwoodleaves.name=轻木叶子 +tile.terraformingTerminal.name=环境改造终端 +tile.lightwoodlog.name=轻树木 +tile.lightwoodsapling.name=轻树树苗 +tile.lightwoodleaves.name=轻树树叶 tile.lightwoodplanks.name=轻木木板 tile.chipStorage.name=卫星ID储存器 tile.planetanalyser.name=天体数据处理器 tile.lunaranalyser.name=月球分析器 -tile.guidanceComputer.name=导航电脑 +tile.guidanceComputer.name=导航计算机 tile.electricArcFurnace.name=电弧高炉 -tile.hotDryturf.name=氧化铁砂 +tile.hotDryturf.name=氧化铁沙 tile.concrete.name=混凝土 tile.lathe.name=车床 tile.rollingMachine.name=卷板机 -tile.planetSelector.name=星球选择器 +tile.planetSelector.name=行星选择器 tile.blockHandPress.name=小型压板器 tile.placeHolder.name=机器 tile.stationAssembler.name=太空站组装机 @@ -73,7 +73,7 @@ tile.electrolyser.name=电解器 tile.chemreactor.name=化学反应器 tile.scrubber.name=二氧化碳净化器 tile.oxygenVent.name=氧气排放口 -tile.liquidHatch.name=液体口 +tile.liquidHatch.name=流体舱口 tile.rocketFuelBlock.name=火箭燃料 tile.hydrogenFluidBlock.name=氢气 tile.oxygenFluidBlock.name=氧气 @@ -83,73 +83,73 @@ tile.dockingPad.name=停靠台 tile.stationmonitor.name=跃迁控制器 tile.warpCore.name=跃迁核心 tile.atmosphereDetector.name=大气检测机 -tile.unlittorch.name=扑灭的火把 +tile.unlittorch.name=熄灭的火把 tile.geode.name=晶簇方块 tile.electricMushroom.name=电蘑菇 -tile.charcoallog.name=碳化树 +tile.charcoallog.name=碳化原木 tile.vitrifiedSand.name=玻璃化沙子 -tile.ruby.name=红宝石方块 -tile.emerald.name=绿宝石方块 -tile.sapphire.name=蓝宝石方块 +tile.ruby.name=红水晶方块 +tile.emerald.name=绿水晶方块 +tile.sapphire.name=蓝水晶方块 tile.citrine.name=黄水晶方块 -tile.wulfentite.name=钼铅矿方块 +tile.wulfentite.name=橙水晶方块 tile.amethyst.name=紫水晶方块 -tile.gravityControl.name=重力控制器 +tile.gravityControl.name=空间站重力控制器 tile.drill.name=钻头 -tile.dataPipe.name=数据线 -tile.liquidPipe.name=液体管道 +tile.dataPipe.name=数据线(弃用) +tile.liquidPipe.name=流体管道(弃用) tile.rfOutput.name=RF输出端口 tile.microwaveReciever.name=微波接收器 tile.solarPanel.name=太阳能板 tile.suitWorkStation.name=太空服调节台 tile.orientationControl.name=方向控制器 tile.biomeScanner.name=生物群系扫描仪 -tile.atmoshereTerraformer.name=大气修改器 -tile.deployableRocketAssembler.name=无人飞船组装器 -tile.pressurizedTank.name=压力槽 +tile.atmoshereTerraformer.name=大气改造器 +tile.deployableRocketAssembler.name=无人载具组装器 +tile.pressurizedTank.name=加压储罐 tile.gasIntake.name=气体收集器 tile.atmosphereTerraformer.name=大气改造器 tile.circleLight.name=空间站光源 -tile.energyPipe.name=能量管道 +tile.energyPipe.name=能量管道(弃用) tile.solarGenerator.name=太阳能发电机 -tile.stationMarker.name=空间站停靠点 +tile.stationMarker.name=空间站对接口 tile.qcrucible.name=石英坩埚 tile.altitudeController.name=海拔控制器 tile.railgun.name=轨道炮 -tile.advRocket.name=高级单推进剂火箭发动机 -tile.advbipropellantRocket.name=高级双推进剂火箭发动机 +tile.advRocket.name=高级单组元推进剂火箭发动机 +tile.advbipropellantRocket.name=高级双组元推进剂火箭发动机 tile.planetHoloSelector.name=全息行星选择器 tile.lens.name=透镜 -tile.forceField.name=力场方块 +tile.forceField.name=力场 tile.forceFieldProjector.name=力场投射器 tile.vacuumLaser.name=真空室高功率激光发射器 -tile.gravityMachine.name=重力控制器 +tile.gravityMachine.name=区域重力控制器 tile.pipeSeal.name=密封管 tile.spaceElevatorController.name=太空电梯 -tile.beacon.name=灯塔 -tile.thermiteTorch.name=铝热管 +tile.beacon.name=信标 +tile.thermiteTorch.name=铝热剂火把 tile.wirelessTransciever.name=无线收发器 -tile.blackholegenerator.name=黑洞发生器 +tile.blackholegenerator.name=黑洞发电机 tile.pump.name=流体泵 tile.centrifuge.name=离心机 -tile.precisionlaseretcher.name=精密激光刻蚀机 +tile.precisionlaseretcher.name=精密激光刻蚀器 tile.enrichedLavaBlock.name=浓缩熔岩块 tile.basalt.name=玄武岩 -tile.landingfloat.name=着陆浮标 -tile.solararray.name=太阳能电池 -tile.solararraypanel.name=太阳能电池板 +tile.landingfloat.name=着陆浮筒 +tile.solararray.name=太阳能阵列控制器 +tile.solararraypanel.name=阵列太阳能板 tile.serviceStation.name=服务站 item.lens.0.name=基础透镜 -item.wafer.0.name=硅晶片 -item.circuitplate.0.name=基础电路板 -item.circuitplate.1.name=高级电路板 -item.circuitIC.0.name=基础芯片 -item.circuitIC.1.name=跟踪芯片 -item.circuitIC.2.name=高级芯片 -item.circuitIC.3.name=控制芯片板 -item.circuitIC.4.name=物品IO芯片板 -item.circuitIC.5.name=液体IO芯片板 +item.wafer.0.name=硅晶圆 +item.circuitplate.0.name=基础电路基板 +item.circuitplate.1.name=高级电路基板 +item.circuitIC.0.name=基础电路 +item.circuitIC.1.name=跟踪电路 +item.circuitIC.2.name=高级电路 +item.circuitIC.3.name=控制电路板 +item.circuitIC.4.name=物品IO电路板 +item.circuitIC.5.name=流体IO电路板 item.OreScanner.name=矿物扫描仪 item.dataUnit.0.name=数据存储单元 item.sawBlade.0.name=铁锯片 @@ -160,55 +160,55 @@ item.satellitePrimaryFunction.0.name=光学传感器 item.satellitePrimaryFunction.1.name=成分传感器 item.satellitePrimaryFunction.2.name=质量检测器 item.satellitePrimaryFunction.3.name=微波传输器 -item.satellitePrimaryFunction.4.name=矿物扫描仪 -item.satellitePrimaryFunction.5.name=生物群落修改器 +item.satellitePrimaryFunction.4.name=矿物映射器 +item.satellitePrimaryFunction.5.name=生物群系变换器 item.satellitePrimaryFunction.6.name=天气控制器 item.satelliteIdChip.name=卫星ID芯片 item.planetIdChip.name=星球ID芯片 -item.asteroidChip.name=小行星ID芯片 +item.asteroidChip.name=小行星芯片 item.miscpart.0.name=用户界面 item.miscpart.1.name=碳砖 item.station.name=空间站容器 item.stationChip.name=空间站ID芯片 -item.stationchip.openmenu=蹲下右键打开配置菜单 +item.stationchip.openmenu=潜行右击以打开配置菜单 item.spaceHelmet.name=太空头盔 item.spaceChest.name=太空胸甲 -item.spaceLeggings.name=太空裤子 -item.spaceBoots.name=太空鞋 +item.spaceLeggings.name=太空护腿 +item.spaceBoots.name=太空靴子 item.smallAirlock.name=小气密门 -item.carbonScrubberCartridge.name=碳收集器 +item.carbonScrubberCartridge.name=集炭滤芯 item.jackhammer.name=气锤 item.sealDetector.name=气密检测器 -item.itemUpgrade.0.name=盘旋升级 +item.itemUpgrade.0.name=悬停升级 item.itemUpgrade.1.name=飞行速度控制升级 item.itemUpgrade.2.name=仿生腿升级 item.itemUpgrade.3.name=降落缓冲鞋 -item.itemUpgrade.4.name=雾镜 -item.itemUpgrade.5.name=地球反光遮挡板 +item.itemUpgrade.4.name=防雾护目镜 +item.itemUpgrade.5.name=类地天光护目镜 item.atmAnalyser.name=大气分析器 -item.biomeChanger.name=生物群系改变器遥控终端 -item.weatherController.name=气象卫星控制器 +item.biomeChanger.name=生物群系变换器遥控终端 +item.weatherController.name=天气遥控终端 item.basicLaserGun.name=基础激光枪 -item.beaconFinder.name=灯塔探测器 +item.beaconFinder.name=信标定位器 item.thermite.name=铝热剂 item.hovercraft.name=气垫船 -item.hovercraft.tooltip=持久二锂电源,它可能会比你活得长 + item.jetPack.name=飞行背包 -item.pressureTank.0.name=低压槽 -item.pressureTank.1.name=压力槽 -item.pressureTank.2.name=高压槽 -item.pressureTank.3.name=超高压槽 +item.pressureTank.0.name=低压储罐 +item.pressureTank.1.name=气压储罐 +item.pressureTank.2.name=高压储罐 +item.pressureTank.3.name=超高压储罐 item.elevatorChip.name=太空电梯芯片 -container.satellite=卫星舱 +container.satellite=卫星仓 container.monitoringstation=监测站 -container.invhatch=储存舱口 +container.invhatch=存储舱口 material.TitaniumAluminide.name=钛铝合金 material.TitaniumIridium.name=钛铱合金 -enchantment.spaceBreathing=严实的封口 +enchantment.spaceBreathing=气密密封 data.undefined.name=一些随机数据 data.distance.name=距离 @@ -225,292 +225,1010 @@ fluid.rocketFuel=火箭燃料 fluid.enrichedLava=浓缩熔岩 mission.asteroidmining.name=小行星采矿 -mission.gascollection.name=气体收集 +mission.gascollection.name=气体采集 -error.rocket.cannotGetThere=无法到达目标 -error.rocket.destinationNotExist=无法发射:目标不存在 -error.rocket.notSameSystem=无法发射:目标不在同一星球系统内 +error.rocket.notEnoughMissionFuel=燃料不足! +error.rocket.tooHeavy=火箭过重,无法发射(推力不足)。 +error.rocket.cannotGetThere=无法从当前位置抵达所选目的地。 +error.rocket.destinationNotExist=所选空间站不存在。 +error.rocket.notSameSystem=星际航行需要核动力火箭和有效的路径。 +error.rocket.partsWornOut=关键部件损坏,发射中止。 +error.rocket.aborted=发射中止。 advancement.holographic=全息 -advancement.holographic.desc=合成一个全息投射器 +advancement.holographic.desc=合成一个全息投影器 advancement.flattening=压扁 -advancement.flattening.desc=制作一个小压板机 -advancement.feelTheHeat=感受热量 +advancement.flattening.desc=制作一个小型压板器 +advancement.feelTheHeat=感受热量! advancement.feelTheHeat.desc=合成一个电弧高炉 -advancement.electrifying=电击 +advancement.electrifying=电激! advancement.electrifying.desc=合成一个电解器 -advancement.spinDoctor=旋转的医生 +advancement.spinDoctor=舆论导向专家 advancement.spinDoctor.desc=合成一个机床 -advancement.rollin=卷起来 +advancement.rollin=Rollin' advancement.rollin.desc=合成一个卷板机 -advancement.crystalline=晶体 +advancement.crystalline=结晶 advancement.crystalline.desc=合成一个结晶器 advancement.warp=跃迁 -advancement.warp.desc=制作一个跃迁核心 -advancement.moonLanding=登录月球 -advancement.moonLanding.desc=登录月球 -advancement.oneSmallStep=一小步 -advancement.oneSmallStep.desc=第一个到达月球 -advancement.weReallyWentToTheMoon=我们真的登上了月球! -advancement.weReallyWentToTheMoon.desc=找到月球上的阿波罗11着陆点 +advancement.warp.desc=建造一个跃迁核心 +advancement.moonLanding=登月! +advancement.moonLanding.desc=登陆月球 +advancement.oneSmallStep=一小步…… +advancement.oneSmallStep.desc=第一个到达月球! +advancement.weReallyWentToTheMoon=我们真的*去过*月球! +advancement.weReallyWentToTheMoon.desc=找到月球上的阿波罗11号着陆点 advancement.dilithium=双锂 -advancement.dilithium.desc=找到双锂矿 -advancement.givingItAllShesGot=全都在这里了 -advancement.givingItAllShesGot.desc=开上一艘可以跃迁的飞船 -advancement.flightOfThePhoenix=凤凰飞翔 -advancement.flightOfThePhoenix.desc=建造并起飞第一艘可以跃迁的飞船 +advancement.dilithium.desc=找到双锂矿石 +advancement.givingItAllShesGot=已经尽全力了! +advancement.givingItAllShesGot.desc=乘坐具有跃迁能力的飞船飞行 +advancement.flightOfThePhoenix=凤凰劫 +advancement.flightOfThePhoenix.desc=建造并起飞第一艘具备跃迁能力的飞船 advancement.beerOnTheSun=太阳上的成人饮料 -advancement.beerOnTheSun.desc=你需要更多的TNT才能到达轨道 -advancement.suitedUp=穿好了 +advancement.beerOnTheSun.desc=你需要更多的TNT才能进入轨道 +advancement.suitedUp=穿上制服 advancement.suitedUp.desc=穿好全套太空服 -key.controls.advancedrocketry=高级火箭 +key.controls.advancedrocketry=高级火箭(Advanced Rocketry) key.openRocketUI=打开火箭界面 -key.toggleJetpack=开关喷气背包 -key.togglercs=切换反作用控制系统 -key.turnRocketLeft=左转 -key.turnRocketRight=右转 -key.turnRocketUp=上移 -key.turnRocketDown=下移 +key.toggleJetpack=开关飞行背包 +key.togglercs=切换RCS(反作用控制系统) +key.turnRocketLeft=向左旋转载具 +key.turnRocketRight=向右旋转载具 +key.turnRocketUp=向上移动载具 +key.turnRocketDown=向下移动载具 -enchantment.advancedrocketry.spacebreathing.desc=可以让盔甲形成密封 +enchantment.advancedrocketry.spacebreathing.desc=令盔甲部件形成气密密封 -machine.tooltip.smallplatepress=需要下面有两块黑曜石才能运作 +machine.tooltip.smallplatepress=需要下方两格处存在黑曜石才可工作 -msg.crystalliser.gravityTooHigh=重力不够低 -msg.observetory.scan.tooltip=扫描新的小行星,将消耗100个距离数据 +msg.crystalliser.gravityTooHigh=重力过高! +msg.observetory.scan.tooltip=扫描新的小行星,消耗100距离数据 msg.observetory.scan.button=扫描! msg.observetory.text.asteroids=小行星 msg.observetory.text.composition=成分 msg.observetory.text.processdiscovery=扫描进度 -msg.observetory.text.observabledistance=可观测距离: -msg.observetory.text.missionTime=任务时间: +msg.observetory.text.observabledistance=可观测距离: +msg.observetory.text.missionTime=任务时间: +msg.observetory.req.open=瞭望台必须满足开放条件(夜晚、天气晴朗、可观测天空)或位于空间站中! +msg.observetory.print.already=此小行星已存在对应芯片! msg.tooltip.data=数据 msg.tooltip.asteroidselection=小行星选择 -msg.label.name=名字 -msg.label.clear=发射 -msg.label.add=添加新的 +msg.label.name=名称 +msg.label.clear=清除 +msg.label.add=添加新行星 msg.label.rename=重命名 msg.label.delete=删除 msg.label.noneSelected=未选择目的地 msg.label.selectDst=选择目的地 msg.label.destName=目的地名称 msg.label.coords=坐标 -msg.spaceElevator.button.summon=调运舱体 -msg.spaceElevator.sameDimensionError=无法连接同一星球上的两部电梯! -msg.spaceElevator.linkNotGeostationaryError=空间站未处于地球静止轨道! -msg.spaceElevator.tetherWouldBreakError=空间站必须直立静止才能接收系链! -msg.spaceElevator.linkCannotChangeError=已连接的电梯系链不能改变位置! -msg.spaceElevator.newDstAdded=锚定缆索连接成功! -msg.spaceElevator.ascentReady=准备升空 -msg.spaceElevator.warning.anchored0=该电梯锚定缆索已 -msg.spaceElevator.warning.anchored1=锚定了空间站! -msg.spaceElevator.warning.unanchored=该电梯没有锚定缆索 +msg.spaceElevator.button.summon=呼唤太空舱 +msg.spaceElevator.sameDimensionError=无法在同一行星上连接两部电梯! +msg.spaceElevator.linkNotGeostationaryError=空间站不在同步轨道上! +msg.spaceElevator.tetherWouldBreakError=空间站必须保持垂直静止状态才能接收系绳! +msg.spaceElevator.linkCannotChangeError=电梯系绳在已链接状态下不可变更位置! +msg.spaceElevator.newDstAdded=电梯系绳已链接! +msg.spaceElevator.ascentReady=准备开始上升 +msg.spaceElevator.warning.anchored0=当前电梯系绳已 +msg.spaceElevator.warning.anchored1=成功锚定空间站! +msg.spaceElevator.warning.unanchored=当前电梯尚未连接系绳 msg.spaceElevator.turnedOff=电梯已关闭 -msg.fuelingStation.link=你将位于以下位置的燃油站对链接器进行编程 -msg.monitoringStation.missionProgressNA=任务进展: N/A -msg.monitoringStation.link=你将位于以下位置的监控站对链接器进行编程 -msg.monitoringStation.progress= 进度: -msg.guidanceComputerHatch.loadingState=加载状态: -msg.guidanceComputerHatch.ejectonlanding=着陆时自动弹射 -msg.guidanceComputerHatch.ejectonsatlanding=允许弹射卫星芯片 -msg.guidanceComputerHatch.ejectonplanetlanding=允许弹射行星芯片 -msg.guidanceComputerHatch.ejectonstationlanding=允许弹射空间站芯片 -msg.guidanceComputerHatch.link=你将位于以下位置的流体装载机对链接器进行编程 -msg.fluidLoader.loadingState=加载状态: -msg.fluidLoader.allowLoading=允许加载: +msg.fuelingStation.link=已将加油站写入链接器,位置: + +msg.monitoringStation.buttonLaunch=发射! +msg.monitoringStation.missionProgressNA=任务进度:N/A +msg.monitoringStation.missionNoActiveMission=无激活任务…… +msg.monitoringStation.mission.type.gas=气体采集任务 +msg.monitoringStation.mission.type.ore=小行星采矿任务 +msg.monitoringStation.mission.target.default=收获:(待定) +msg.monitoringStation.mission.targetPrefix=收获: +msg.monitoringStation.mission.Asteroid.target.default=小行星: +msg.monitoringStation.mission.Asteroid.targetPrefix=小行星: +msg.monitoringStation.mission.asteroidIdPrefix=类型: +msg.monitoringStation.mission.plannedAmountPrefix=数量: +msg.monitoringStation.mission.plannedAmountPending=数量:(待定) +msg.monitoringStation.mission.asteroidType=小行星类型:(显示在芯片/任务上) +msg.monitoringStation.link=已将监控站写入链接器,位置: +msg.monitoringStation.progress=ETA: +msg.monitoringStation.progress=进度: +msg.monitoringStation.prelaunch=启动中…… +msg.monitoringStation.launching=发射中! +msg.monitoringStation.orbit=已进入轨道! +msg.monitoringStation.deorbiting=已返回轨道! +msg.monitoringStation.landed=已着陆 +msg.monitoringStation.aborted=已中止! +msg.monitoringStation.returningToDock=返回停靠点 +msg.monitoringStation.noLinkedRocket=未链接任何火箭! + +msg.guidanceComputerHatch.loadingState=装载状态: +msg.guidanceComputerHatch.ejectonlanding=着陆时自动弹出 +msg.guidanceComputerHatch.ejectonsatlanding=允许弹出卫星芯片 +msg.guidanceComputerHatch.ejectonplanetlanding=允许弹出行星芯片 +msg.guidanceComputerHatch.ejectonstationlanding=允许弹出太空站芯片 +msg.guidanceComputerHatch.link=已将流体装载器写入链接器,位置: +msg.fluidLoader.loadingState=装载状态: +msg.fluidLoader.allowLoading=允许装载: msg.fluidLoader.allowredstoneinput=允许红石输入 msg.fluidLoader.allowredstoneoutput=允许红石输出 msg.fluidLoader.none=无 -msg.fluidLoader.link=你将位于以下位置的流体装载机对链接器进行编程: -msg.rocketLoader.loadingState=载入状态: -msg.rocketLoader.allowLoading=允许加载: +msg.fluidLoader.link=已将流体装载器写入链接器,位置: +msg.rocketLoader.loadingState=装载状态: +msg.rocketLoader.allowLoading=允许装载: msg.rocketLoader.allowredstoneinput=允许红石输入 msg.rocketLoader.allowredstoneoutput=允许红石输出 msg.rocketLoader.none=无 -msg.rocketLoader.link=你将位于以下位置的火箭加载器对链接器进行编程: -msg.microwaverec.notgenerating=生成 0 FE/t -msg.microwaverec.generating=正在生成 -msg.abdp.compositionresearch=合成研究 +msg.rocketLoader.link=已将火箭装载器写入链接器,位置: +msg.microwaverec.notgenerating=产能 0 FE/t +msg.microwaverec.generating=产能 +msg.abdp.compositionresearch=成分研究 msg.abdp.distanceresearch=距离研究 msg.abdp.massresearch=质量研究 msg.terraformer.atminc=增加大气压 msg.terraformer.atmdec=减少大气压 msg.terraformer.running=运行中 -msg.terraformer.missingbiome=缺少生物群落改变器链接 -msg.terraformer.outofgas=停止: 气体储备不足 +msg.terraformer.missingbiome=缺失生物群系变换器链接 +msg.terraformer.outofgas=已中止:气体耗尽 msg.terraformer.notrunning=未运行 msg.terraformer.status=状态 msg.terraformer.pressure=气压 -msg.biomescanner.gas=是啊,时髦,不是吗? -msg.biomescanner.star=如果我的传感器有遮阳帘就好了 -msg.gravitycontroller.radius=半径: -msg.gravitycontroller.targetgrav=目标重力: -msg.gravitycontroller.none=未设置 -msg.gravitycontroller.activeset=激活: 设置 -msg.gravitycontroller.activeadd=激活: 添加 -msg.gravitycontroller.targetdir.1=目标 -> +msg.biomescanner.gas=呀哈哈哈,是气体,不是么? +msg.biomescanner.star=要是我的传感器有遮阳板就好了 +msg.gravitycontroller.radius=半径: +msg.gravitycontroller.targetgrav=目标重力: +msg.gravitycontroller.none=复位 +msg.gravitycontroller.activeset=激活:设置 +msg.gravitycontroller.activeadd=激活:添加 +msg.gravitycontroller.targetdir.1=目标-> msg.gravitycontroller.targetdir.2=方向 -msg.railgun.transfermin=最小传送尺寸 +msg.railgun.transfermin=最小传输尺寸 msg.spacelaser.reset=重置 -msg.satctrlcenter.toofar=太远 -msg.satctrlcenter.nolink=无链接... -msg.satctrlcenter.info=信息: +msg.satctrlcenter.toofar=距离过远 +msg.satctrlcenter.nolink=无链接…… +msg.satctrlcenter.info=信息: msg.satctrlcenter.destroysat=摧毁卫星 -msg.satctrlcenter.connect=连接! -msg.satbuilder.writesecondchip=写入第二芯片 -msg.dockingport.target=目标 Id -msg.dockingport.me=我的 Id +msg.satctrlcenter.connect=下载 +msg.satctrlcenter.autodl_hint=无线收发器自动下载(提取) +msg.satbuilder.writesecondchip=写入副芯片 +msg.dockingport.target=目标ID +msg.dockingport.me=本端ID msg.planetholo.size=全息图尺寸: -msg.stationaltctrl.maxaltrate=最大高度变化率: -msg.stationaltctrl.tgtalt=目标高度: -msg.stationaltctrl.alt=高度: -msg.stationgravctrl.maxaltrate=最大重力变化率: -msg.stationgravctrl.tgtalt=目标重力: -msg.stationgravctrl.alt=模拟重力: -msg.stationorientctrl.alt=角速度: -msg.stationorientctrl.tgtalt=目标角速度: +msg.stationaltctrl.maxaltrate=最大海拔变化率: +msg.stationaltctrl.tgtalt=目标海拔: +msg.stationaltctrl.alt=海拔: +msg.stationgravctrl.maxaltrate=最大重力变化率: +msg.stationgravctrl.tgtalt=目标重力: +msg.stationgravctrl.alt=人造重力: +msg.stationorientctrl.alt=角速度: +msg.stationorientctrl.tgtalt=目标角速度: msg.warpmon.tab.warp=跃迁选择 msg.warpmon.tab.data=数据 -msg.warpmon.tab.tracking=行星跟踪 +msg.warpmon.tab.tracking=行星追踪 msg.warpmon.selectplanet=选择行星 msg.warpmon.corestatus=核心状态: -msg.warpmon.anchored=空间站已锚定! -msg.warpmon.nowhere=无处可去 +msg.warpmon.anchored=空间站已锚定! +msg.warpmon.nowhere=无可用目的地 msg.warpmon.missingart=缺少工件 -msg.warpmon.ready=准备就绪! +msg.warpmon.ready=就绪! msg.warpmon.notready=未就绪 -msg.warpmon.warp=跃迁! -msg.warpmon.fuelcost=燃料成本: -msg.warpmon.fuel=燃料: -msg.warpmon.dest=目的地: +msg.warpmon.warp=跃迁! +msg.warpmon.fuelcost=燃料消耗: +msg.warpmon.fuel=燃料: +msg.warpmon.dest=目的地: msg.warpmon.na=N/A msg.warpmon.search=搜索行星 -msg.warpmon.chip=芯片编程 -msg.warpmon.datareq=每种数据类型需要100个 +msg.warpmon.chip=从芯片载入程序 +msg.warpmon.datareq=需各类数据各100 msg.warpmon.artifact=工件 -msg.rocketbuilder.success=可以发射了! -msg.rocketbuilder.nofuel=燃料容量不够! -msg.rocketbuilder.noseat=缺少座位或卫星舱! -msg.rocketbuilder.noengines=你没有足够的推力! -msg.rocketbuilder.noguidance=缺少导航电脑 +msg.rocketbuilder.success=可以发射! +msg.rocketbuilder.nofuel=燃料容量不足! +msg.rocketbuilder.noseat=缺少座位或卫星仓! +msg.rocketbuilder.noengines=推力不足! +msg.rocketbuilder.noguidance=缺少导航计算机 msg.rocketbuilder.unscanned=火箭未扫描 -msg.rocketbuilder.success_station=准备就绪! -msg.rocketbuilder.empty=这里什么都没有 -msg.rocketbuilder.finished=建造完成! -msg.rocketbuild.invalidblock=无效块! -msg.rocketbuilder.incompletestructure=无效的发射台结构! -msg.rocketbuilder.nosatellitehatch=缺少卫星舱 +msg.rocketbuilder.unscanned_station=等待扫描 +msg.rocketbuilder.success_station=就绪! +msg.rocketbuilder.fail_cut=搭建失败:区域已变更 +msg.rocketbuilder.empty=区域为空 +msg.rocketbuilder.finished=搭建完成! +msg.rocketbuild.invalidblock=无效方块! +msg.rocketbuilder.incompletestructure=发射台结构无效! +msg.rocketbuilder.nosatellitehatch=缺少卫星仓 msg.rocketbuilder.nosatellitechip=缺少芯片 msg.rocketbuilder.outputblocked=输出槽被阻塞 msg.rocketbuilder.thrust=推力 msg.rocketbuilder.weight=重量 msg.rocketbuilder.fuel=燃料 -msg.rocketbuilder.acc=飞行控制中心 +msg.rocketbuilder.acc=加速度 msg.rocketbuilder.build=建造 msg.rocketbuilder.scan=扫描 -msg.rocketbuild.combinedthrust=燃料类型不能组合! -msg.rocketbuilder.alreadyassembled=火箭已组装 +msg.rocketbuild.combinedthrust=燃料类型不能混合使用! +msg.rocketbuilder.alreadyassembled=火箭已组装完成 +msg.rocketbuilder.nointake=缺少气体收集器! +msg.rocketbuilder.notank=Missing Fluidtank! msg.solar.collectingEnergy=收集能量: msg.solar.cannotcollectEnergy=无法收集能量 msg.asteroidChip.asteroid=小行星 -msg.atmanal.atmtype=大气类型: -msg.atmanal.canbreathe=可呼吸: +msg.asteroidChip.type=类型: +msg.atmanal.atmtype=大气类型: +msg.atmanal.canbreathe=是否可呼吸: msg.biomechanger.scan=扫描生物群系 msg.biomechanger.nosat=卫星尚未发射 -msg.biomechanger.selBiome=选中生物群系: -msg.biomechanger.numBiome=扫描的生物群系数量: +msg.biomechanger.selBiome=选择的生物群系: +msg.biomechanger.numBiome=已扫描生物群系数: msg.itemorescanner.nosat=卫星尚未发射 -msg.itemorescanner.maxzoom=最大缩放: -msg.itemorescanner.filter=可过滤矿石: -msg.itemorescanner.value=值: -msg.itemplanetidchip.planetname=星球名: -msg.itemplanetidchip.stationid=站台 Id: -msg.itemplanetidchip.artifacts=工件: -msg.vent.trace=氧迹检测 - -msg.serviceStation.destroyProbNA=销毁概率: N/A -msg.serviceStation.destroyProb=销毁概率 +msg.itemorescanner.maxzoom=最大缩放: +msg.itemorescanner.filter=可过滤矿石: +msg.itemorescanner.value=值: +msg.itemplanetidchip.planetname=行星名称: +msg.itemplanetidchip.stationid=空间站ID: +msg.itemplanetidchip.artifacts=工件: +msg.vent.trace=氧气追踪 +msg.serviceStation.destroyProbNA=破坏概率:N/A +msg.serviceStation.destroyProb=破坏概率 msg.serviceStation.serviceProgress=服务进度 -msg.serviceStation.serviceProgressNA=服务进度: N/A -msg.serviceStation.wornMotorsText=引擎 +msg.serviceStation.serviceProgressNA=服务进度:N/A +msg.serviceStation.wornMotorsText=发动机 msg.serviceStation.wornSeatsText=座位 -msg.serviceStation.wornTanksText=油箱 -msg.serviceStation.assemblerScan=扫描装配器 -msg.serviceStation.link=你将位于以下位置的服务站对链接器进行编程: - -msg.itemsatellite.pwr=电源存储: -msg.itemsatellite.nopwr=无电源存储 -msg.itemsatellite.pwrgen=发电: -msg.itemsatellite.nopwrgen=无发电! -msg.itemsatellite.microwavestatus=收集电能 -msg.itemsatellite.data=数据存储: -msg.itemsatellite.nodata=无数据存储! -msg.itemsatellite.empty=空机箱 -msg.itemsatellite.weight=机箱重量: +msg.serviceStation.wornTanksText=燃料箱 +msg.serviceStation.assemblerScan=扫描组装机 +msg.serviceStation.link=已将服务站写入链接器,位置: + +msg.itemsatellite.pwr=能量存储: +msg.itemsatellite.nopwr=无能量存储 +msg.itemsatellite.pwrgen=能量产出: +msg.itemsatellite.nopwrgen=无能量产出! +msg.itemsatellite.microwavestatus=收集能量 +msg.itemsatellite.data=数据存储: +msg.itemsatellite.nodata=无数据存储! +msg.itemsatellite.empty=空框架 +msg.itemsatellite.weight=框架重量: msg.itemsatellite.noweight=重量计算错误 +msg.itemsatellite.unassembled=未组装(预览) -msg.brokenstage.text=销毁阶段 -msg.itemsatchip.id=ID: -msg.itemsatchip.planet=行星: +msg.brokenstage.text=摧毁阶段 + +msg.itemsatchip.id=ID: +msg.itemsatchip.planet=行星: msg.itemsatchip.planetunk=行星: 未知 -msg.itemsatchip.sat=卫星: -msg.itemsatchip.satlost=卫星: 失去联系 -msg.sealdetector.sealed=应能很好地密封 -msg.sealdetector.notsealmat=材料不会密封 -msg.sealdetector.notsealblock=阻挡物不会保持密封 -msg.sealdetector.notfullblock=空气会绕开此方块 -msg.sealdetector.fluid=空气会渗透此方块 -msg.sealdetector.other=空气会在此方块处泄露 -msg.stationchip.sation=站台 -msg.entity.rocket.descend.1=按空格键下降! -msg.entity.rocket.descend.2=自动下降 -msg.entity.rocket.ascend.1=按空格键起飞! -msg.entity.rocket.ascend.2=目的地: -msg.entity.rocket.launch=在T区发射 - -msg.entity.rocket.launch2=按空格键终止发射 -msg.entity.rocket.station=发射站 -msg.entity.rocket.pad=平台: +msg.itemsatchip.sat=卫星: +msg.itemsatchip.satlost=卫星:失去联系 +msg.sealdetector.sealed=应该能保持良好密封。 +msg.sealdetector.notsealmat=材料无法保持密封。 +msg.sealdetector.notsealblock=方块无法保持密封。 +msg.sealdetector.notfullblock=空气会从这个方块通过。 +msg.sealdetector.fluid=空气会从这个方块中冒泡通过。 +msg.sealdetector.other=空气会从这个方块泄漏。 +msg.stationchip.sation=空间站 +msg.entity.rocket.descend.1=按空格键降落! +msg.entity.rocket.descend.2=自动降落倒计时: +msg.entity.rocket.ascend.1=按空格键发射! +msg.entity.rocket.ascend.2=目的地: +msg.entity.rocket.launch=发射倒计时: +msg.entity.rocket.launch2=按[空格键]中止 +msg.entity.rocket.station=空间站 +msg.entity.rocket.pad=发射台: msg.entity.rocket.disass=解体 msg.entity.rocket.seldst=选择目的地 -msg.entity.rocket.clear=发射 -msg.entity.rocket.rcs=反作用控制系统模式 +msg.entity.rocket.clear=清除 +msg.entity.rocket.rcs=RCS模式 msg.entity.rocket.none=未选择 msg.wirelessTransciever.extract=提取 +msg.wirelessTransciever.insert=插入 +msg.wirelessTransciever.type=类型: +msg.wirelessTransciever.network=网络: +msg.wirelessTransciever.network.unlinked=未链接 -msg.powerunit.rfpertick=FE/t -msg.linker.error.firstMachine=这必须是第一台要链接的机器! -msg.linker.program=坐标已编入链接器 -msg.linker.success=链接成功 -msg.notenoughpower=电量不足! +msg.powerunit.rfpertick=RF/t +msg.linker.error.firstMachine=这台机器必须第一个被链接! +msg.linker.program=坐标已写入链接器 +msg.linker.success=已成功链接 +msg.notenoughpower=能量不足! msg.empty=空 msg.yes=是 msg.no=否 msg.connected=已连接 -msg.notconnected=未连接 -msg.unprogrammed=未编程 -msg.programfail=编程失败 -msg.modules=模块 +msg.notconnected=未链接 +msg.unprogrammed=未编写 +msg.programfail=编写失败 +msg.modules=模块: msg.na=N/A -msg.entityDeployedRocket.notGasGiant=这里没有气体 -msg.noOxygen=警告: 氧气浓度不足! -msg.tooHot=警告: 大气过热! -msg.tooDense=警告: 大气压过高! -msg.muchTooDense=警告: 大气压达到临界压力! +msg.entityDeployedRocket.notGasGiant=没有气体 +msg.noOxygen=警告:大气缺氧! +msg.tooHot=警告:大气过热! +msg.tooDense=警告:大气压力过高! +msg.muchTooDense=警告:大气压力极高! -msg.chat.nostation1=你在空间站醒来时,有一种挥之不去的感觉,那就是你那影响深远的太空行走遭到了某位狐神长老的鄙视,如果你再次尝试并期望得到不同的结果,那将是愚蠢的 -msg.chat.nostation2=也许你应该考虑一下,不要再逾越明确的逻辑和绝对的界限,然后决定这是个好主意,出了问题也不是你的错 -msg.chat.nostation3=你必须在空间站上才能来到这个时空,而现在还没有空间站! +msg.chat.nostation1=你在空间站醒来,隐约觉得上次那场深空漫步似乎触怒了某位年长的狐神,若想重蹈覆辙且期待能有不同的结果,实属不智 +msg.chat.nostation2=也许你应该在再次越过明确合理且绝对的界限之前先思考一下,而不是在事情出错后自认为是个好主意且不是你的错 +msg.chat.nostation3=你必须在空间站上才能进入此维度,但目前尚未建造任何空间站! -commands.weather.always_not_clear=这个星球的天气总是阴暗... -commands.weather.cannot_rain=这里无法启动降雨 -commands.weather.cannot_thunder=这里无法启动雷暴 +commands.weather.always_not_clear=这颗星球从未晴朗过…… +commands.weather.cannot_rain=此处无法降雨 +commands.weather.cannot_thunder=此处无法降下雷暴 -jei.sb.satellitepreview=准备进入轨道! +# Jeistuff +jei.sb.satellitepreview=已做好入轨准备! jei.sb.copy.source=来源 jei.sb.copy.output=新副本 -jei.sb.assemblyhint=至少一个太阳能电池板 -jei.sb.copychiphint=请做好备份! +jei.sb.assemblyhint=至少需要一块太阳能板 +jei.sb.copychiphint=记得做好备份! + +jei.ar.fuel.role.monopropellant=单组元推进剂燃料 +jei.ar.fuel.role.biprop_fuel=双组元推进剂燃料 +jei.ar.fuel.role.oxidizer=氧化剂 +jei.ar.fuel.role.working_fluid=工质 +jei.ar.stationAssembler.newStationChipHint=§c此芯片指向新的空间站! + +# Generic hint +tooltip.advancedrocketry.hold_shift=按住§eShift§7查看详细信息 +tooltip.advancedrocketry.hold_alt=按住§eAlt§7查看高级提示 + +# Fuel Tank (monoprop) +tooltip.advancedrocketry.fueltank=§c火箭的组成部分 +tooltip.advancedrocketry.fueltank.shift.1=§f可容纳:§b%s +tooltip.advancedrocketry.fueltank.alt.1=让我们摇滚冲天! + +# Bipropellant Fuel Tank +tooltip.advancedrocketry.bipropfueltank=§c火箭的组成部分 +tooltip.advancedrocketry.bipropfueltank.shift.1=§f可容纳:§b%s +tooltip.advancedrocketry.bipropfueltank.alt.1=§f双组元推进剂火箭需要§b双组元推进剂§f和§b氧化剂§f燃料箱 + +# Oxidizer Fuel Tank +tooltip.advancedrocketry.oxidizerfueltank=§c火箭的组成部分 +tooltip.advancedrocketry.oxidizerfueltank.shift.1=§f可容纳:§b%s +tooltip.advancedrocketry.oxidizerfueltank.alt.1=§f双组元推进剂火箭需要§b双组元推进剂§f和§b氧化剂§f燃料箱 + +# Nuclear Fuel Tank +tooltip.advancedrocketry.nuclearfueltank=§c火箭的组成部分 +tooltip.advancedrocketry.nuclearfueltank.shift.1=§f可容纳:§b%s +tooltip.advancedrocketry.nuclearfueltank.alt.1=§f需要§b核热堆芯§f和§b核热发动机 + +# Monopropellant Engine +tooltip.advancedrocketry.monopropmotor=§c火箭的组成部分 +tooltip.advancedrocketry.monopropmotor.shift.1=使用§b单组元推进剂燃料§7 +tooltip.advancedrocketry.monopropmotor.alt.1=查看加油站的JEI页面 + +# Nuclear Core +tooltip.advancedrocketry.nuclearcore=§c火箭的组成部分 +tooltip.advancedrocketry.nuclearcore.shift.1=必须直接放置在核热发动机 +tooltip.advancedrocketry.nuclearcore.shift.2=或其他核热堆芯正上方。 +tooltip.advancedrocketry.nuclearcore.alt.1=垂直放置规则不适用于 +tooltip.advancedrocketry.nuclearcore.alt.2=无人载具(气体任务火箭) + +# Nuclear rocketengine +tooltip.advancedrocketry.nuclearmotor=§c火箭的组成部分 §6可进行星际航行! +tooltip.advancedrocketry.nuclearmotor.shift.1=使用§b工质§7 +tooltip.advancedrocketry.nuclearmotor.shift.2=正上方需存在核热堆芯。 +tooltip.advancedrocketry.nuclearmotor.alt.1=查看加油站的JEI页面 + +# Bipropellant Engine +tooltip.advancedrocketry.bipropmotor=§c火箭的组成部分 +tooltip.advancedrocketry.bipropmotor.shift.1=使用§b双组元推进剂燃料§7和§b氧化剂§7 +tooltip.advancedrocketry.bipropmotor.alt.1=查看加油站的JEI页面 + +# Drill +tooltip.advancedrocketry.drill=§c火箭的组成部分 +tooltip.advancedrocketry.drill.shift.1=缩短§6采矿任务§7的所需时间 +tooltip.advancedrocketry.drill.shift.2=§b效果可叠加 +tooltip.advancedrocketry.drill.alt.1=此火箭需通过火箭组装机搭建 +tooltip.advancedrocketry.drill.alt.2=需要一个已编程的小行星芯片 + +# Gas Intake +tooltip.advancedrocketry.intake=§c火箭的组成部分 +tooltip.advancedrocketry.intake.shift.1=缩短§6气体任务§7的所需时间 +tooltip.advancedrocketry.intake.shift.2=§b效果可叠加 +tooltip.advancedrocketry.intake.alt.1=此火箭需通过无人载具组装机搭建 +tooltip.advancedrocketry.intake.alt.2=从绕气态巨行星运行的空间站发射 + +# Seat +tooltip.advancedrocketry.seat=§c火箭的组成部分 +tooltip.advancedrocketry.seat.shift.1=为火箭增加一个乘客位 + +# Guidance Computer +tooltip.advancedrocketry.guidancecomputer=§c火箭的组成部分 +tooltip.advancedrocketry.guidancecomputer.shift.1=放入§c芯片§7或已编程的§c链接器§7 +tooltip.advancedrocketry.guidancecomputer.alt.1=部署卫星或空间站至轨道时 +tooltip.advancedrocketry.guidancecomputer.alt.2=记得设定火箭的目标行星 + +# Service Monitor +tooltip.advancedrocketry.servicemonitor=§c火箭的组成部分 +tooltip.advancedrocketry.servicemonitor.shift.1=在火箭界面中 +tooltip.advancedrocketry.servicemonitor.shift.2=启用损伤视图 +tooltip.advancedrocketry.servicemonitor.alt.1=未完成 +tooltip.advancedrocketry.servicemonitor.alt.2= + +# Docking Pad (landingPad) +tooltip.advancedrocketry.landingpad=使用此方块替换发射台结构的中心方块 +tooltip.advancedrocketry.landingpad.shift.1=§c链接器§7能够存储此方块的精确位置(包括维度信息)。 +tooltip.advancedrocketry.landingpad.shift.2=将其放入§4导航计算机§7以在此着陆。 +tooltip.advancedrocketry.landingpad.alt.1=在停靠台中放入一个已编程的链接器。 +tooltip.advancedrocketry.landingpad.alt.2=从此停靠台发射的火箭会飞往链接器中保存的坐标(用于实现自动化)。 +tooltip.advancedrocketry.landingpad.alt.3=如果火箭的导航计算机中没有其他目标信息。 + +# Launch Pad +tooltip.advancedrocketry.launchpad=发射台平台的基础方块。 +tooltip.advancedrocketry.launchpad.shift.1=以方形平台形状放置发射台方块。 +tooltip.advancedrocketry.launchpad.shift.2=3x3、4x4、5x5…… +tooltip.advancedrocketry.launchpad.alt.1=§b添加结构塔(最低高度4格,起始方块需与发射台y坐标相同) +tooltip.advancedrocketry.launchpad.alt.2=§f火箭/空间站组装机将自动连接 + +# Structure Tower +tooltip.advancedrocketry.structuretower=发射台平台的垂直支架。 +tooltip.advancedrocketry.structuretower.shift.1=结构塔最低高度为4格。 +tooltip.advancedrocketry.structuretower.shift.2=底部方块必须与发射台相连。 +tooltip.advancedrocketry.structuretower.alt.1=无人载具组装机的主要方块 +tooltip.advancedrocketry.structuretower.alt.2=查看维基了解更多信息。 + +# Terraformer +tooltip.advancedrocketry.terraformer=改变整颗行星的地形环境! +tooltip.advancedrocketry.terraformer.shift.1=§f需与§c生物群系变换器卫星§f搭配使用 +tooltip.advancedrocketry.terraformer.shift.2=§f卫星必须环绕对应行星运行 +tooltip.advancedrocketry.terraformer.alt.1=§f放入§c生物群系变换器遥控终端 +tooltip.advancedrocketry.terraformer.alt.2=§f由卫星提供能源 + +# Rocket Monitoring Station +tooltip.advancedrocketry.monitoringstation=§c基础设备 +tooltip.advancedrocketry.monitoringstation.shift.1=通过红石信号发射! +tooltip.advancedrocketry.monitoringstation.shift.2=§f需连接至§4火箭组装机/停靠台§f或§4火箭本体 +tooltip.advancedrocketry.monitoringstation.alt.1=§b到达轨道后任务即会激活! + +# Satellite Terminal +tooltip.advancedrocketry.satellitemonitor=用于与卫星通信 +tooltip.advancedrocketry.satellitemonitor.shift.1=放入卫星芯片 +tooltip.advancedrocketry.satellitemonitor.shift.2=下载数据 +tooltip.advancedrocketry.satellitemonitor.alt.1=§f通过无线收发器或数据单元传输并自动下载数据 + +# Satellite Builder +tooltip.advancedrocketry.satellitebuilder=用于组装卫星 +tooltip.advancedrocketry.satellitebuilder.shift.1=也可创建芯片/遥控终端副本。 +tooltip.advancedrocketry.satellitebuilder.shift.2=§b必须放置在能量输入口顶部! +tooltip.advancedrocketry.satellitebuilder.alt.1=放入框架、芯片/遥控终端 +tooltip.advancedrocketry.satellitebuilder.alt.2=核心组件+其他组件 + + +### Infrastructure +## BlockARHatch + +# TileDataBus +tooltip.advancedrocketry.hatch.databus=容量:§62000§7数据 +tooltip.advancedrocketry.hatch.databus.shift.1=§b只能保存一种类型的数据 + +# TileSatelliteHatch +tooltip.advancedrocketry.hatch.satellite=§c火箭的组成部分 +tooltip.advancedrocketry.hatch.satellite.shift.1=用于将有效载荷送入轨道 +tooltip.advancedrocketry.hatch.satellite.shift.2=记得设定轨道的目标行星! +tooltip.advancedrocketry.hatch.satellite.alt.1=§f可在§4空间站组装机§f中用于封装和存储空间站 + +# TileRocketUnloader +tooltip.advancedrocketry.hatch.item_unloader=§c基础设备 +tooltip.advancedrocketry.hatch.item_unloader.shift.1=空载时发出红石信号 +tooltip.advancedrocketry.hatch.item_unloader.alt.1=§f需连接至§4火箭组装机/停靠台§f或§4火箭本体 +tooltip.advancedrocketry.hatch.item_unloader.alt.2=§f在此降落的火箭将自动建立连接。 + +# TileRocketLoader +tooltip.advancedrocketry.hatch.item_loader=§c基础设备 +tooltip.advancedrocketry.hatch.item_loader.shift.1=满载时发出红石信号 +tooltip.advancedrocketry.hatch.item_loader.alt.1=§f需连接至§4火箭组装机/停靠台§f或§4火箭本体 +tooltip.advancedrocketry.hatch.item_loader.alt.2=§f在此降落的火箭将自动建立连接。 + +# TileRocketFluidUnloader +tooltip.advancedrocketry.hatch.fluid_unloader=§c基础设备 +tooltip.advancedrocketry.hatch.fluid_unloader.shift.1=空载时发出红石信号 +tooltip.advancedrocketry.hatch.fluid_unloader.alt.1=§f需连接至§4火箭组装机/停靠台§f或§4火箭本体 +tooltip.advancedrocketry.hatch.fluid_unloader.alt.2=§f在此降落的火箭将自动建立连接。 + +# TileRocketFluidLoader +tooltip.advancedrocketry.hatch.fluid_loader=§c基础设备 +tooltip.advancedrocketry.hatch.fluid_loader.shift.1=满载时发出红石信号 +tooltip.advancedrocketry.hatch.fluid_loader.alt.1=§f需连接至§4火箭组装机/停靠台§f或§4火箭本体 +tooltip.advancedrocketry.hatch.fluid_loader.alt.2=§f在此降落的火箭将自动建立连接。 + +# Guidance Computer Access +tooltip.advancedrocketry.hatch.gca=§c基础设备 +tooltip.advancedrocketry.hatch.gca.shift.1=空载时发出红石信号 +tooltip.advancedrocketry.hatch.gca.alt.1=§f需连接至§4火箭组装机/停靠台§f或§4火箭本体 +tooltip.advancedrocketry.hatch.gca.alt.2=§f在此降落的火箭将自动建立连接。 + +## /BlockARHatch + +# Fueling Station +tooltip.advancedrocketry.fuelingstation=§c基础设备 +tooltip.advancedrocketry.fuelingstation.shift.1=当空间站燃料类型相同时 +tooltip.advancedrocketry.fuelingstation.shift.2=满载时发出红石信号。 +tooltip.advancedrocketry.fuelingstation.alt.1=§f需连接至§4火箭组装机/停靠台§f或§4火箭本体 +tooltip.advancedrocketry.fuelingstation.alt.2=§f在此降落的火箭将自动建立连接。 + +# Service Station +tooltip.advancedrocketry.servicestation=§c基础设备 +tooltip.advancedrocketry.servicestation.shift.1=修复火箭 +tooltip.advancedrocketry.servicestation.shift.2=§o(未完成) +tooltip.advancedrocketry.fuelingstation.alt.1=§f需连接至§4火箭组装机/停靠台§f或§4火箭本体 + +## // Infrastructure + +# Pressurized Fluid Tank +tooltip.advancedrocketry.fluidtank.shift.1=§c与上下的储罐连接构成大型储罐 + +# Wireless Transciever +tooltip.advancedrocketry.transceiver=传输§6数据 +tooltip.advancedrocketry.transceiver.shift.1=§f使用§c链接器§f创建网络 +tooltip.advancedrocketry.transceiver.shift.2=§f支持连接多个收发器 +tooltip.advancedrocketry.transceiver.alt.1=§f提取模式可切换终端的自动下载功能 +tooltip.advancedrocketry.transceiver.alt.2=§o(如数据过期请重新放入芯片) + +# Atmosphere Detector +tooltip.advancedrocketry.atmosphereDetector=根据大气环境发出红石信号 +tooltip.advancedrocketry.atmosphereDetector.shift.1=选择需要检测的大气类型 +tooltip.advancedrocketry.atmosphereDetector.shift.2=条件符合时即会发射信号 +tooltip.advancedrocketry.atmosphereDetector.alt.1=可检测:空气、真空、 +tooltip.advancedrocketry.atmosphereDetector.alt.2=低氧气、无氧气、高温等多种状态 + +# Station Light +tooltip.advancedrocketry.circlelight=总是发光 +tooltip.advancedrocketry.circlelight.shift.1=不需要 +tooltip.advancedrocketry.circlelight.shift.2=能量或信号 + +# Gas Charge Pad +tooltip.advancedrocketry.oxygencharger=为太空服装填氧气和氢气 +tooltip.advancedrocketry.oxygencharger.shift.1=站在装填台上填充气体 +tooltip.advancedrocketry.oxygencharger.alt.1=不需要能量 + +# Docking Port +tooltip.advancedrocketry.dockingport=标记空间站模块的对接点 +tooltip.advancedrocketry.dockingport.shift.1=在空间站上:设置唯一的“本端ID” +tooltip.advancedrocketry.dockingport.shift.2=在新模块上:设置“目标ID” +tooltip.advancedrocketry.dockingport.alt.1=在太空站组装机中构建新模块 +tooltip.advancedrocketry.dockingport.alt.2=夹具面必须相互对准 + +# Pipe Seal +tooltip.advancedrocketry.pipeseal=具有气密性的孔洞! +tooltip.advancedrocketry.pipeseal.shift.1=用此方块框住1×1孔洞即可实现密封 +tooltip.advancedrocketry.pipeseal.shift.2=§b每个孔洞需要4个方块 +tooltip.advancedrocketry.pipeseal.alt.1=允许管道穿过的同时防止内部氧气泄露 +tooltip.advancedrocketry.pipeseal.alt.2=实体可通过此类开口穿行 + +# Planet Selector (full-screen) +tooltip.advancedrocketry.planetselector=浏览星体 +tooltip.advancedrocketry.planetselector.shift.1=开启全屏行星UI。 +tooltip.advancedrocketry.planetselector.shift.2=浏览星系、行星与天然卫星 +tooltip.advancedrocketry.planetselector.alt.1=可远程设置跃迁控制器的 +tooltip.advancedrocketry.planetselector.alt.2=行星目的地 + +# Holographic Planet Selector +tooltip.advancedrocketry.planetholoselector=全息星体显示器 +tooltip.advancedrocketry.planetholoselector.shift.1=在世界中生成全息投影 +tooltip.advancedrocketry.planetholoselector.alt.1=“功能与行星选择器相同 +tooltip.advancedrocketry.planetholoselector.alt.2=但采用3D全息投影显示” + +# Orientation Controller +tooltip.advancedrocketry.orientationctrl=§c空间站控制器 +tooltip.advancedrocketry.orientationctrl.shift.1=自定义角速度 +tooltip.advancedrocketry.orientationctrl.alt.1=§b仅影响视觉效果§7 + +# Gravity Controller +tooltip.advancedrocketry.gravityctrl=§c空间站控制器 +tooltip.advancedrocketry.gravityctrl.shift.1=人造重力! +tooltip.advancedrocketry.gravityctrl.alt.1=§b仅影响视觉效果§7 +tooltip.advancedrocketry.gravityctrl.alt.2=红石控制 + +# Altitude Controller +tooltip.advancedrocketry.altitudectrl=§c空间站控制器 +tooltip.advancedrocketry.altitudectrl.shift.1=自定义轨道高度 +tooltip.advancedrocketry.altitudectrl.alt.1=§b仅影响视觉效果§7 +tooltip.advancedrocketry.altitudectrl.alt.2=红石控制 + +# Co2Scrubber +tooltip.advancedrocketry.scrubber=与氧气排放口相邻放置 +tooltip.advancedrocketry.scrubber.shift.1=减少氧气消耗(最多2个) +tooltip.advancedrocketry.scrubber.alt.1=每个净化器可令氧气消耗减半,增加能量消耗。 +tooltip.advancedrocketry.scrubber.alt.2=使用2个净化器时,氧气排放口将不消耗氧气。 + +# Oxygen Vent +tooltip.advancedrocketry.oxygenvent=在密闭房间中产出可呼吸的空气。 +tooltip.advancedrocketry.oxygenvent.shift.1=需要能量和氧气。 +tooltip.advancedrocketry.oxygenvent.shift.2=放置在封闭区域内。 +tooltip.advancedrocketry.oxygenvent.alt.1=可使用二氧化碳净化器代替氧气供应。 +tooltip.advancedrocketry.oxygenvent.alt.2=范围:%s格半径。 + +# Airlock Door +tooltip.advancedrocketry.smallairlock=气密门! +tooltip.advancedrocketry.smallairlock.shift.1=非完全气密,打开时会泄漏 +tooltip.advancedrocketry.smallairlock.alt.1=使用两扇门 +tooltip.advancedrocketry.smallairlock.alt.2=建造一个合适的气闸 + +# Warp Controller +tooltip.advancedrocketry.warpcontroller=将空间站转变为§6星际飞船 +tooltip.advancedrocketry.warpcontroller.shift.1=在空间站上放置§4跃迁控制器§7和§4跃迁核心 +tooltip.advancedrocketry.warpcontroller.shift.2=在行星和太阳系之间进行跃迁旅行 +tooltip.advancedrocketry.warpcontroller.alt.1=界面中会显示位置、目的地和跃迁燃料 +tooltip.advancedrocketry.warpcontroller.alt.2=(你已经做到了!去看看Wiki吧伙计) + +# CarbonScrubberCartridge +tooltip.advancedrocketry.scrubbercart=用于二氧化碳净化器 +tooltip.advancedrocketry.scrubbercart.shift.1=消耗耐久净化空气。 +tooltip.advancedrocketry.atmanalyzer.alt.1=应该能使用超过24小时 + +# Seal Detector +tooltip.advancedrocketry.sealdetector=检测方块是否具有气密性 +tooltip.advancedrocketry.sealdetector.shift.1=§f右击方块使用 + +# Lens +tooltip.advancedrocketry.lens=§c瞭望台的组成部分 +tooltip.advancedrocketry.lens.shift.1=§b使用全息投影器! + +## SPACE SUIT + COMPONENTS + +# Suit Working Station +tooltip.advancedrocketry.suitworkingstation=安装/移除§5太空服组件 +tooltip.advancedrocketry.suitworkingstation.shift.1=适用于太空服盔甲 +tooltip.advancedrocketry.suitworkingstation.shift.2=(头盔/胸甲/护腿/靴子) +tooltip.advancedrocketry.suitworkingstation.alt.1=不需要能量 + +# Jetpack +tooltip.advancedrocketry.jetpack=§5太空服组件 +tooltip.advancedrocketry.jetpack.shift.1=§d槽位:胸甲§7 + +# AtmosphereAnalyzer +tooltip.advancedrocketry.atmanalyzer=§5太空服组件 +tooltip.advancedrocketry.atmanalyzer.1=§f手持此物品右击来检查大气。 +tooltip.advancedrocketry.atmanalyzer.shift.1=§d槽位:头盔§7 +tooltip.advancedrocketry.atmanalyzer.alt.1=是否可呼吸?取决于大气 +tooltip.advancedrocketry.atmanalyzer.alt.2=显示类型与气压 + +# BeaconFinder +tooltip.advancedrocketry.beaconfinder=§5太空服组件 +tooltip.advancedrocketry.beaconfinder.shift.1=§f显示指向此维度中高级火箭模组信标的HUD箭头 +tooltip.advancedrocketry.beaconfinder.shift.2=§d槽位:头盔§7 +tooltip.advancedrocketry.beaconfinder.alt.1=箭头偏移量相对于你的朝向 +tooltip.advancedrocketry.beaconfinder.alt.2=仅在已注册信标的高级火箭模组维度中工作。 + +# PressureTank +tooltip.advancedrocketry.pressuretank.shift.1=§d槽位:胸甲§7 +tooltip.advancedrocketry.pressuretank.alt.1=§f为太空服储存氧气 +tooltip.advancedrocketry.pressuretank.alt.2=§f为飞行背包储存氢气 + +## Item Upgrade +# 0 = Hover +tooltip.advancedrocketry.itemupgrade.0=§5太空服组件 +tooltip.advancedrocketry.itemupgrade.0.shift.1=§f启用飞行背包的悬停模式 +tooltip.advancedrocketry.itemupgrade.0.shift.2=§d槽位:头盔§7 +tooltip.advancedrocketry.itemupgrade.0.alt.1=需要在胸甲中安装飞行背包。 +tooltip.advancedrocketry.itemupgrade.0.alt.2=无额外叠加效果。 + +# 1 = Flight Speed Control Upgrade +tooltip.advancedrocketry.itemupgrade.1=§5太空服组件 +tooltip.advancedrocketry.itemupgrade.1.shift.1=§f提升飞行背包的飞行速度 +tooltip.advancedrocketry.itemupgrade.1.shift.2=§d槽位:护腿§7 +tooltip.advancedrocketry.itemupgrade.1.alt.1=需要在胸甲中安装飞行背包。 +tooltip.advancedrocketry.itemupgrade.1.alt.2=§b效果可堆叠! + +# 2 = Bionic Leg Upgrade (speed) +tooltip.advancedrocketry.itemupgrade.2=§5太空服组件 +tooltip.advancedrocketry.itemupgrade.2.shift.1=§f增加行走速度 +tooltip.advancedrocketry.itemupgrade.2.shift.2=§d槽位:护腿§7 +tooltip.advancedrocketry.itemupgrade.2.alt.1=疾跑以激活 +tooltip.advancedrocketry.itemupgrade.2.alt.2=可与多个模块叠加效果。 + +# 3 = Padded Landing Boots Upgrade (no fall damage; config-aware) +tooltip.advancedrocketry.itemupgrade.3=§5太空服组件 +tooltip.advancedrocketry.itemupgrade.3.shift.1=§f消除摔落伤害 +tooltip.advancedrocketry.itemupgrade.3.shift.2=§d槽位:靴子§7 +tooltip.advancedrocketry.itemupgrade.3.alt.1=无额外叠加效果。 + +# 4 = Antifog Visor Upgrade +tooltip.advancedrocketry.itemupgrade.4=§5太空服组件 +tooltip.advancedrocketry.itemupgrade.4.shift.1=§f看透高气压行星上的迷雾 +tooltip.advancedrocketry.itemupgrade.4.shift.2=§d槽位:头盔§7 +tooltip.advancedrocketry.itemupgrade.4.alt.1=无额外叠加效果。 + +# 5 = Earthbright Visor +tooltip.advancedrocketry.itemupgrade.5=§5太空服组件 +tooltip.advancedrocketry.itemupgrade.5.shift.1=§f调整遥远世界的光照水平 +tooltip.advancedrocketry.itemupgrade.5.shift.2=§d槽位:头盔§7 +tooltip.advancedrocketry.itemupgrade.5.alt.1=无额外叠加效果。 + +## Satellite Components +# Primary Function payloads +tooltip.advancedrocketry.satfunc.optical=§5卫星核心组件 +tooltip.advancedrocketry.satfunc.optical.shift.1=§b收集距离数据§7 +tooltip.advancedrocketry.satfunc.optical.shift.2=§o通过卫星终端下载数据 +tooltip.advancedrocketry.satfunc.optical.alt.1=组装时 +tooltip.advancedrocketry.satfunc.optical.alt.2=与卫星芯片结合 + +tooltip.advancedrocketry.satfunc.composition=§5卫星核心组件 +tooltip.advancedrocketry.satfunc.composition.shift.1=§b收集成分数据§7 +tooltip.advancedrocketry.satfunc.composition.shift.2=§o通过卫星终端下载数据 +tooltip.advancedrocketry.satfunc.composition.alt.1=组装时 +tooltip.advancedrocketry.satfunc.composition.alt.2=与卫星芯片结合 + +tooltip.advancedrocketry.satfunc.mass=§5卫星核心组件 +tooltip.advancedrocketry.satfunc.mass.shift.1=§b收集质量数据§7 +tooltip.advancedrocketry.satfunc.mass.shift.2=§o通过卫星终端下载数据 +tooltip.advancedrocketry.satfunc.mass.alt.1=组装时 +tooltip.advancedrocketry.satfunc.mass.alt.2=与卫星芯片结合 + +tooltip.advancedrocketry.satfunc.microwave=§5卫星核心组件 +tooltip.advancedrocketry.satfunc.microwave.shift.1=§b在太空中产出能量§7 +tooltip.advancedrocketry.satfunc.microwave.shift.2=§o需要微波接收器(5x5多方块结构) +tooltip.advancedrocketry.satfunc.microwave.alt.1=组装时 +tooltip.advancedrocketry.satfunc.microwave.alt.2=与卫星芯片结合 + +tooltip.advancedrocketry.satfunc.oremapping=§5卫星核心组件 +tooltip.advancedrocketry.satfunc.oremapping.shift.1=§b扫描行星上的矿物§7 +tooltip.advancedrocketry.satfunc.oremapping.alt.1=组装时 +tooltip.advancedrocketry.satfunc.oremapping.alt.2=与卫星芯片结合 + +tooltip.advancedrocketry.satfunc.biomechanger=§5卫星核心组件 +tooltip.advancedrocketry.satfunc.biomechanger.shift.1=§b调节生物群系§7 +tooltip.advancedrocketry.satfunc.biomechanger.alt.1=组装时与生物群系变换器遥控终端结合 +tooltip.advancedrocketry.satfunc.biomechanger.alt.2=需要能量产出和存储组件! + +tooltip.advancedrocketry.satfunc.weather=§5卫星核心组件 +tooltip.advancedrocketry.satfunc.weather.shift.1=§b处理天气相关事项! +tooltip.advancedrocketry.satfunc.weather.alt.1=组装时与天气遥控终端结合 + +# Weather Remote +tooltip.advancedrocketry.weathercontrollerremote=§bShift-右击打开界面 +tooltip.advancedrocketry.weathercontrollerremote.shift.1=§f手持此物品右击来使用 +tooltip.advancedrocketry.weathercontrollerremote.alt.1=组装时与天气控制器结合 + +# Biome Changer Remote +tooltip.advancedrocketry.biomechangerremote=§bShift-右击打开界面 +tooltip.advancedrocketry.biomechangerremote.shift.1=§f手持此物品右击来转换20x20的区域 +tooltip.advancedrocketry.biomechangerremote.shift.2=§f“扫描生物群系”会将所在的生物群系储存在卫星的内存中。 +tooltip.advancedrocketry.biomechangerremote.alt.1=§6卫星需要大量能量 +tooltip.advancedrocketry.biomechangerremote.alt.2=§f用于§c环境改造终端§f和§c大气改造器 + +# Ore Scanner +tooltip.advancedrocketry.orescanner=§b右击打开界面 +tooltip.advancedrocketry.orescanner.shift.1=§f若卫星的数据存储容量大于等于§63,000§f,矿物扫描仪可以按类型过滤。 +tooltip.advancedrocketry.orescanner.alt.1=§f扫描范围取决于卫星的能量产出 + +# Power Sources +tooltip.advancedrocketry.satpower.0=§5卫星组件 +tooltip.advancedrocketry.satpower.0.shift.1=§f产能:§c4 §fRF/t§7 +tooltip.advancedrocketry.satpower.0.shift.2=§o卫星需要至少1个产能组件 + +tooltip.advancedrocketry.satpower.1=§5卫星组件 +tooltip.advancedrocketry.satpower.1.shift.1=§f产能:§c40 §fRF/t§7 +tooltip.advancedrocketry.satpower.1.shift.2=§o卫星需要至少1个产能组件 + +# LibVulpes Batteries +tooltip.libvulpes.battery.0=§5卫星组件§7 +tooltip.libvulpes.battery.0.shift.1=增加能量存储 +tooltip.libvulpes.battery.0.shift.2=§f容量:§c10.000 §fRF§7 + +tooltip.libvulpes.battery.1=§5卫星组件 +tooltip.libvulpes.battery.1.shift.1=增加能量存储 +tooltip.libvulpes.battery.1.shift.2=§f容量:§c40.000 §fRF§7 + +# Data Unit +tooltip.advancedrocketry.itemdataunit.shift.1=§f令卫星数据存储量增加1000 +tooltip.advancedrocketry.itemdataunit.alt.1=§f也可在物品栏中作为数据存储器使用 + +## Chips / remotes +# Asteroid Chip +tooltip.advancedrocketry.asteroidchip.shift.1=§b用于采矿任务§7 +tooltip.advancedrocketry.asteroidchip.shift.2=§f在§c瞭望台§f中编程 +tooltip.advancedrocketry.asteroidchip.alt.1=§4将已编程的芯片放入导航计算机§7 + +# Station Chip +tooltip.advancedrocketry.stationchip=§b记得做好备份! +tooltip.advancedrocketry.stationchip.shift.1=§f在空间站组装器中编程 +tooltip.advancedrocketry.stationchip.alt.1=§4将已编程的芯片放入导航计算机§7 + +# Planet Chip +tooltip.advancedrocketry.planetidchip.shift.1=§f将芯片放入§4导航计算机§7 +tooltip.advancedrocketry.planetidchip.shift.2=§f在火箭界面中设置目的地进行编程。 +tooltip.advancedrocketry.planetidchip.alt.1=§4发射前请仔细检查是否已完成编程! + +# Satellite Chip +tooltip.advancedrocketry.satidchip=§b记得做好备份! +tooltip.advancedrocketry.satidchip.shift.1=§f储存卫星的ID。 +tooltip.advancedrocketry.satidchip.alt.1=§4在卫星终端中使用以进行链接,或在微波接收器多方块结构(输入舱口)中使用。§8(行星:放入终端时解析信息) + +# Elevator Chip +tooltip.advancedrocketry.elevatorchip=太空电梯芯片 +tooltip.advancedrocketry.elevatorchip.shift.1=§f链接电梯平台/目的地。 + +## Multiblocks +# Black Hole Generator +tooltip.advancedrocketry.blackholegen=通过压缩质量产出能量 +tooltip.advancedrocketry.blackholegen.shift.1=§b使用全息投影器! + +# Microwave Receiver +tooltip.advancedrocketry.microwavereceiver=接收来自太阳能卫星的能量 +tooltip.advancedrocketry.microwavereceiver.shift.1=5x5多方块结构 +tooltip.advancedrocketry.microwavereceiver.shift.2=§b使用全息投影器! +tooltip.advancedrocketry.microwavereceiver.alt.1=§f使用§b微波传输器§f和§b卫星芯片§f来建造太阳能卫星 +tooltip.advancedrocketry.microwavereceiver.alt.2=§8产能 = 卫星产能总和 * (2 * 大气密度系数) + +# Solar Panel (part of Microwave Receiver) +tooltip.advancedrocketry.solarpanel=§c多方块结构的组成部分 +tooltip.advancedrocketry.solarpanel.shift.1=5x5多方块结构 +tooltip.advancedrocketry.solarpanel.shift.2=§o§f(微波接收器) +tooltip.advancedrocketry.solarpanel.shift.3=§b使用全息投影器! + +# Solar Array Controller +tooltip.advancedrocketry.solararray=利用阳光产出能量 +tooltip.advancedrocketry.solararray.shift.1=需要63个阵列太阳能板 +tooltip.advancedrocketry.solararray.shift.2=§b使用全息投影器! + +# Solar Array Panel +tooltip.advancedrocketry.solararraypanel=§c多方块结构的组成部分 +tooltip.advancedrocketry.solararraypanel.shift.1=需要63个阵列太阳能板和控制器 +tooltip.advancedrocketry.solararraypanel.shift.2=§b使用全息投影器! + +# Solar Generator +tooltip.advancedrocketry.solargenerator=基础太阳能板 +tooltip.advancedrocketry.solargenerator.shift.1=§f产能:§c2 §fRF/t§7 + +# Arc Furnace +tooltip.advancedrocketry.arcfurnace=通过极端温度熔炼物质 +tooltip.advancedrocketry.arcfurnace.shift.1=§b使用全息投影器! + +# Rolling Machine +tooltip.advancedrocketry.rollingmachine=加工板材与箔材 +tooltip.advancedrocketry.rollingmachine.shift.1=§b使用全息投影器! + +# Lathe +tooltip.advancedrocketry.lathe=车削加工杆件与轴类零件 +tooltip.advancedrocketry.lathe.shift.1=§b使用全息投影器! + +# Crystallizer +tooltip.advancedrocketry.crystallizer=生长高纯度晶体 +tooltip.advancedrocketry.crystallizer.shift.1=§b使用全息投影器! + +# Cutting Machine +tooltip.advancedrocketry.cuttingmachine=对材料进行精密切割 +tooltip.advancedrocketry.cuttingmachine.shift.1=§b使用全息投影器! + +# Precision Assembler +tooltip.advancedrocketry.precisionassembler=自动化完成复杂组装 +tooltip.advancedrocketry.precisionassembler.shift.1=§b使用全息投影器! + +# Electrolyser +tooltip.advancedrocketry.electrolyser=通过电解工艺分解化合物 +tooltip.advancedrocketry.electrolyser.shift.1=§b使用全息投影器! + +# Chemical Reactor +tooltip.advancedrocketry.chemreactor=处理化学反应 +tooltip.advancedrocketry.chemreactor.shift.1=§b使用全息投影器! + +# Precision Laser Etcher +tooltip.advancedrocketry.precisionlaseretcher=通过激光刻蚀精密电路 +tooltip.advancedrocketry.precisionlaseretcher.shift.1=§b使用全息投影器! + +# Observatory +tooltip.advancedrocketry.observatory=分析天体 +tooltip.advancedrocketry.observatory.shift.1=§f用于§6采矿任务 +tooltip.advancedrocketry.observatory.shift.2=§b使用全息投影器! +tooltip.advancedrocketry.observatory.alt.1=§f放入§c卫星芯片 +tooltip.advancedrocketry.observatory.alt.2=§f需要§6距离数据§f才能运作(仅在夜间工作) + + +# Planet Analyser +tooltip.advancedrocketry.planetanalyser=处理行星扫描数据 +tooltip.advancedrocketry.planetanalyser.shift.1=§b使用全息投影器! + +# Centrifuge +tooltip.advancedrocketry.centrifuge=按密度分离物质 +tooltip.advancedrocketry.centrifuge.shift.1=§b使用全息投影器! + +# Warp Core +tooltip.advancedrocketry.warpcore=§6星际飞船§f的核心 +tooltip.advancedrocketry.warpcore.shift.1=§b使用全息投影器! +tooltip.advancedrocketry.warpcore.alt.1=§6星际飞船§7需要§4跃迁控制器§7+§4跃迁核心§7 + +# Beacon +tooltip.advancedrocketry.beacon=远程信标 +tooltip.advancedrocketry.beacon.shift.1=§b使用全息投影器! + +# Biome Scanner +tooltip.advancedrocketry.biomescan=扫描行星的生物群系 +tooltip.advancedrocketry.biomescan.shift.1=§b使用全息投影器! + +# Railgun +tooltip.advancedrocketry.railgun=将物品发射到太空 +tooltip.advancedrocketry.railgun.shift.1=§b使用全息投影器! +tooltip.advancedrocketry.railgun.alt.1=“轨道炮的威力不足以在行星间运输物品,其射程仅限于同一行星系内的天体” + +# Space Elevator Controller +tooltip.advancedrocketry.spaceelevatorctrl=用于控制太空电梯 +tooltip.advancedrocketry.spaceelevatorctrl.shift.1=§b使用全息投影器! + +# Atmosphere Terraformer +tooltip.advancedrocketry.atmosterraformer=改变整颗行星上的大气压 +tooltip.advancedrocketry.atmosterraformer.shift.1=§b使用全息投影器! +tooltip.advancedrocketry.atmosterraformer.alt.1=通过连接的§c生物群系变换器遥控终端§f增加和减少大气压。 + +# Area Gravity Controller +tooltip.advancedrocketry.gravitymachine=操纵重力 +tooltip.advancedrocketry.gravitymachine.shift.1=§f也可影响重力的方向 +tooltip.advancedrocketry.gravitymachine.shift.2=§b使用全息投影器! + +# Orbital Last Drill +tooltip.advancedrocketry.spacelaser=§c空间站多方块 +tooltip.advancedrocketry.spacelaser.shift.1=§b使用全息投影器! + +# Force Field Projector +tooltip.advancedrocketry.forcefieldprojector=最远可投射32格距离! +tooltip.advancedrocketry.forcefieldprojector.shift.1=使用红石信号激活 + +# Vacuum Laser +tooltip.advancedrocketry.vacuumlaser=§c多方块结构的组成部分 +tooltip.advancedrocketry.vacuumlaser.shift.1=§b使用全息投影器! + + +# Pump +tooltip.advancedrocketry.pump=搜索下方的流体 +tooltip.advancedrocketry.pump.shift.1=§c可从64格范围内的相连流体池中抽取。 +tooltip.advancedrocketry.pump.alt.1=§f自动弹出到附近储罐 +tooltip.advancedrocketry.pump.alt.2=使用红石信号关闭 + +# Parts for Multiblock +tooltip.advancedrocketry.concrete=§c多方块结构的组成部分 +tooltip.advancedrocketry.concrete.shift.1=§b使用全息投影器! +tooltip.advancedrocketry.blastbrick=§c多方块结构的组成部分 +tooltip.advancedrocketry.blastbrick.shift.1=§b使用全息投影器! +tooltip.advancedrocketry.qcrucible=§c多方块结构的组成部分 +tooltip.advancedrocketry.qcrucible.shift.1=§b使用全息投影器! +tooltip.advancedrocketry.sawblade=§c多方块结构的组成部分 +tooltip.advancedrocketry.sawblade.shift.1=§b使用全息投影器! + +## Assemblers +# Rocket Assembler +tooltip.advancedrocketry.rocketassembler=§c搭建火箭 +tooltip.advancedrocketry.rocketassembler.shift.1=§b需要发射台+结构塔结构 +tooltip.advancedrocketry.rocketassembler.shift.2=§f将所有基础设备连接至此方块,使它们自动与发射台上的火箭连接 +tooltip.advancedrocketry.rocketassembler.alt.1=§f将此方块放置在比发射台高1格的位置,连接底部边角且朝向与发射台方块相反 + +# Station Assembler +tooltip.advancedrocketry.stationassembler=§c将空间站打包以便发射! +tooltip.advancedrocketry.stationassembler.shift.1=§b需要发射台+结构塔结构 +tooltip.advancedrocketry.stationassembler.alt.1=§f将此方块放置在比发射台高1格的位置,连接底部边角且朝向与发射台方块相反 + +# Packet Station +tooltip.advancedrocketry.packedstructure=放入§c卫星舱§7以送入轨道! +tooltip.advancedrocketry.packedstructure.shift.1=§e记得告诉火箭应该将有效载荷部署到哪个行星的轨道! + +# Deployable Rocket Assembler +tooltip.advancedrocketry.deployablerocketassembler=§c在空间站中搭建火箭 +tooltip.advancedrocketry.deployablerocketassembler.shift.1=§b需要结构塔方块 +tooltip.advancedrocketry.deployablerocketassembler.shift.2=§f用于§6气体任务§7 +tooltip.advancedrocketry.deployablerocketassembler.alt.1=§f将此方块放置在倒T形结构的中间,朝向太空外部,然后从塔顶向外延伸出水平支撑。 +tooltip.advancedrocketry.deployablerocketassembler.alt.2=如果不确定,请查看Wiki! + +# Hovercraft +tooltip.advancedrocketry.hovercraft=使用持久耐用的双锂动力源。可能比你的寿命还长。 + +# Thermite +tooltip.advancedrocketry.thermite=以产生高温而闻名! + +# Thermite Torch +tooltip.advancedrocketry.thermitetorch=即便没有氧气也可燃烧 +tooltip.advancedrocketry.thermitetorch.shift.1=§f适用于大气环境稀薄或缺失的情况 + +# Jackhammer +tooltip.advancedrocketry.jackhammer=§c极速挖掘工具 +tooltip.advancedrocketry.jackhammer.1=这东西估计能比你活得还久(只要勤换螺栓的话) +tooltip.advancedrocketry.jackhammer.shift.1=§f使用§6钛棒§f修复 +tooltip.advancedrocketry.jackhammer.alt.1=§f挖掘等级:§b钻石 + +# Basic basicLaserGun +tooltip.advancedrocketry.lasergun=§c远程挖掘工具 +tooltip.advancedrocketry.lasergun.shift.1=§d无限耐久 +tooltip.advancedrocketry.lasergun.alt.1=§f挖掘等级:§b钻石 +tooltip.advancedrocketry.lasergun.alt.2=§f范围:§b50格 + +## Crafting items +tooltip.advancedrocketry.sawbladeiron=§3合成用物品 +tooltip.advancedrocketry.wafer=§3合成用物品 +tooltip.advancedrocketry.circuitplate=§3合成用物品 +tooltip.advancedrocketry.circuitic=§3合成用物品 +tooltip.advancedrocketry.miscpart=§3合成用物品 +tooltip.advancedrocketry.itemlens=§3合成用物品 +tooltip.advancedrocketry.misc=§3合成用物品 From 45a5e4e26601b2b5e5ace2f85e88717bb71a8823 Mon Sep 17 00:00:00 2001 From: ZetaY <34602681+ZHAY10086@users.noreply.github.com> Date: Fri, 28 Nov 2025 16:14:57 +0800 Subject: [PATCH 287/424] Update zh_CN.lang --- src/main/resources/assets/advancedrocketry/lang/zh_CN.lang | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index 71ebbe4d1..e3f375713 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -164,7 +164,7 @@ item.satellitePrimaryFunction.4.name=矿物映射器 item.satellitePrimaryFunction.5.name=生物群系变换器 item.satellitePrimaryFunction.6.name=天气控制器 item.satelliteIdChip.name=卫星ID芯片 -item.planetIdChip.name=星球ID芯片 +item.planetIdChip.name=行星ID芯片 item.asteroidChip.name=小行星芯片 item.miscpart.0.name=用户界面 item.miscpart.1.name=碳砖 @@ -545,7 +545,7 @@ msg.chat.nostation1=你在空间站醒来,隐约觉得上次那场深空漫步 msg.chat.nostation2=也许你应该在再次越过明确合理且绝对的界限之前先思考一下,而不是在事情出错后自认为是个好主意且不是你的错 msg.chat.nostation3=你必须在空间站上才能进入此维度,但目前尚未建造任何空间站! -commands.weather.always_not_clear=这颗星球从未晴朗过…… +commands.weather.always_not_clear=这颗行星从未晴朗过…… commands.weather.cannot_rain=此处无法降雨 commands.weather.cannot_thunder=此处无法降下雷暴 From eee500da53dc54b4af01cab2c2ab3dba9496b81a Mon Sep 17 00:00:00 2001 From: ZetaY <34602681+ZHAY10086@users.noreply.github.com> Date: Sun, 7 Dec 2025 23:19:52 +0800 Subject: [PATCH 288/424] Fix translation for 'Space Station' in Chinese --- src/main/resources/assets/advancedrocketry/lang/zh_CN.lang | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index e3f375713..6d7da9937 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -68,7 +68,7 @@ tile.rollingMachine.name=卷板机 tile.planetSelector.name=行星选择器 tile.blockHandPress.name=小型压板器 tile.placeHolder.name=机器 -tile.stationAssembler.name=太空站组装机 +tile.stationAssembler.name=空间站组装机 tile.electrolyser.name=电解器 tile.chemreactor.name=化学反应器 tile.scrubber.name=二氧化碳净化器 @@ -346,7 +346,7 @@ msg.guidanceComputerHatch.loadingState=装载状态: msg.guidanceComputerHatch.ejectonlanding=着陆时自动弹出 msg.guidanceComputerHatch.ejectonsatlanding=允许弹出卫星芯片 msg.guidanceComputerHatch.ejectonplanetlanding=允许弹出行星芯片 -msg.guidanceComputerHatch.ejectonstationlanding=允许弹出太空站芯片 +msg.guidanceComputerHatch.ejectonstationlanding=允许弹出空间站芯片 msg.guidanceComputerHatch.link=已将流体装载器写入链接器,位置: msg.fluidLoader.loadingState=装载状态: msg.fluidLoader.allowLoading=允许装载: @@ -780,7 +780,7 @@ tooltip.advancedrocketry.oxygencharger.alt.1=不需要能量 tooltip.advancedrocketry.dockingport=标记空间站模块的对接点 tooltip.advancedrocketry.dockingport.shift.1=在空间站上:设置唯一的“本端ID” tooltip.advancedrocketry.dockingport.shift.2=在新模块上:设置“目标ID” -tooltip.advancedrocketry.dockingport.alt.1=在太空站组装机中构建新模块 +tooltip.advancedrocketry.dockingport.alt.1=在空间站组装机中构建新模块 tooltip.advancedrocketry.dockingport.alt.2=夹具面必须相互对准 # Pipe Seal From 35ddc33f7d59e7b16dab43a8adef6680371b0a08 Mon Sep 17 00:00:00 2001 From: ZetaY <34602681+ZHAY10086@users.noreply.github.com> Date: Mon, 8 Dec 2025 00:18:18 +0800 Subject: [PATCH 289/424] Update zh_CN.lang --- .../assets/advancedrocketry/lang/zh_CN.lang | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index 6d7da9937..786efe2a2 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -19,7 +19,7 @@ tile.seat.name=座位 tile.pad.name=发射台 tile.servicestation.name=服务站 tile.servicemonitor.name=服务监测器 -tile.invhatch.name=存储舱口 +tile.invhatch.name=存储仓 tile.structuretower.name=结构塔 tile.rocketAssembler.name=火箭组装机 tile.turf.name=月面土 @@ -33,12 +33,12 @@ tile.blastBrick.name=隔热砖 tile.blastFurnaceController.name=隔热高炉控制器 tile.fuelStation.name=加油站 tile.loader.0.name=数据总线 -tile.loader.1.name=卫星仓 +tile.loader.1.name=卫星舱 tile.loader.2.name=火箭卸载器 tile.loader.3.name=火箭装载器 tile.loader.4.name=火箭流体卸载器 tile.loader.5.name=火箭流体装载器 -tile.loader.6.name=导航计算机访问舱口 +tile.loader.6.name=导航计算机访问仓 tile.observatory.name=瞭望台 tile.satelliteBuilder.name=卫星建造机 tile.rocket.name=单组元推进剂火箭发动机 @@ -73,7 +73,7 @@ tile.electrolyser.name=电解器 tile.chemreactor.name=化学反应器 tile.scrubber.name=二氧化碳净化器 tile.oxygenVent.name=氧气排放口 -tile.liquidHatch.name=流体舱口 +tile.liquidHatch.name=流体仓 tile.rocketFuelBlock.name=火箭燃料 tile.hydrogenFluidBlock.name=氢气 tile.oxygenFluidBlock.name=氧气 @@ -201,9 +201,9 @@ item.pressureTank.2.name=高压储罐 item.pressureTank.3.name=超高压储罐 item.elevatorChip.name=太空电梯芯片 -container.satellite=卫星仓 +container.satellite=卫星舱 container.monitoringstation=监测站 -container.invhatch=存储舱口 +container.invhatch=存储仓 material.TitaniumAluminide.name=钛铝合金 material.TitaniumIridium.name=钛铱合金 @@ -423,7 +423,7 @@ msg.warpmon.datareq=需各类数据各100 msg.warpmon.artifact=工件 msg.rocketbuilder.success=可以发射! msg.rocketbuilder.nofuel=燃料容量不足! -msg.rocketbuilder.noseat=缺少座位或卫星仓! +msg.rocketbuilder.noseat=缺少座位或卫星舱! msg.rocketbuilder.noengines=推力不足! msg.rocketbuilder.noguidance=缺少导航计算机 msg.rocketbuilder.unscanned=火箭未扫描 @@ -434,7 +434,7 @@ msg.rocketbuilder.empty=区域为空 msg.rocketbuilder.finished=搭建完成! msg.rocketbuild.invalidblock=无效方块! msg.rocketbuilder.incompletestructure=发射台结构无效! -msg.rocketbuilder.nosatellitehatch=缺少卫星仓 +msg.rocketbuilder.nosatellitehatch=缺少卫星舱 msg.rocketbuilder.nosatellitechip=缺少芯片 msg.rocketbuilder.outputblocked=输出槽被阻塞 msg.rocketbuilder.thrust=推力 @@ -1028,7 +1028,7 @@ tooltip.advancedrocketry.planetidchip.alt.1=§4发射前请仔细检查是否已 # Satellite Chip tooltip.advancedrocketry.satidchip=§b记得做好备份! tooltip.advancedrocketry.satidchip.shift.1=§f储存卫星的ID。 -tooltip.advancedrocketry.satidchip.alt.1=§4在卫星终端中使用以进行链接,或在微波接收器多方块结构(输入舱口)中使用。§8(行星:放入终端时解析信息) +tooltip.advancedrocketry.satidchip.alt.1=§4在卫星终端中使用以进行链接,或在微波接收器多方块结构(输入仓)中使用。§8(行星:放入终端时解析信息) # Elevator Chip tooltip.advancedrocketry.elevatorchip=太空电梯芯片 From 69891ec94b9afc89bb80c8301b72fad3cfacb540 Mon Sep 17 00:00:00 2001 From: ZetaY <34602681+ZHAY10086@users.noreply.github.com> Date: Mon, 8 Dec 2025 00:19:38 +0800 Subject: [PATCH 290/424] Update zh_CN.lang --- .../resources/assets/advancedrocketry/lang/zh_CN.lang | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index 786efe2a2..a8ca3d79e 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -33,7 +33,7 @@ tile.blastBrick.name=隔热砖 tile.blastFurnaceController.name=隔热高炉控制器 tile.fuelStation.name=加油站 tile.loader.0.name=数据总线 -tile.loader.1.name=卫星舱 +tile.loader.1.name=卫星仓 tile.loader.2.name=火箭卸载器 tile.loader.3.name=火箭装载器 tile.loader.4.name=火箭流体卸载器 @@ -201,7 +201,7 @@ item.pressureTank.2.name=高压储罐 item.pressureTank.3.name=超高压储罐 item.elevatorChip.name=太空电梯芯片 -container.satellite=卫星舱 +container.satellite=卫星仓 container.monitoringstation=监测站 container.invhatch=存储仓 @@ -423,7 +423,7 @@ msg.warpmon.datareq=需各类数据各100 msg.warpmon.artifact=工件 msg.rocketbuilder.success=可以发射! msg.rocketbuilder.nofuel=燃料容量不足! -msg.rocketbuilder.noseat=缺少座位或卫星舱! +msg.rocketbuilder.noseat=缺少座位或卫星仓! msg.rocketbuilder.noengines=推力不足! msg.rocketbuilder.noguidance=缺少导航计算机 msg.rocketbuilder.unscanned=火箭未扫描 @@ -434,7 +434,7 @@ msg.rocketbuilder.empty=区域为空 msg.rocketbuilder.finished=搭建完成! msg.rocketbuild.invalidblock=无效方块! msg.rocketbuilder.incompletestructure=发射台结构无效! -msg.rocketbuilder.nosatellitehatch=缺少卫星舱 +msg.rocketbuilder.nosatellitehatch=缺少卫星仓 msg.rocketbuilder.nosatellitechip=缺少芯片 msg.rocketbuilder.outputblocked=输出槽被阻塞 msg.rocketbuilder.thrust=推力 @@ -1192,7 +1192,7 @@ tooltip.advancedrocketry.stationassembler.shift.1=§b需要发射台+结构塔 tooltip.advancedrocketry.stationassembler.alt.1=§f将此方块放置在比发射台高1格的位置,连接底部边角且朝向与发射台方块相反 # Packet Station -tooltip.advancedrocketry.packedstructure=放入§c卫星舱§7以送入轨道! +tooltip.advancedrocketry.packedstructure=放入§c卫星仓§7以送入轨道! tooltip.advancedrocketry.packedstructure.shift.1=§e记得告诉火箭应该将有效载荷部署到哪个行星的轨道! # Deployable Rocket Assembler From 590044f36d5fceed1becf5b8c325b7f36ab4fc4c Mon Sep 17 00:00:00 2001 From: ZHAY10086 Date: Fri, 12 Dec 2025 01:20:51 +0800 Subject: [PATCH 291/424] update --- .../assets/advancedrocketry/lang/zh_CN.lang | 239 ++++++++++++++---- 1 file changed, 194 insertions(+), 45 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index e3f375713..c160b9507 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -19,7 +19,7 @@ tile.seat.name=座位 tile.pad.name=发射台 tile.servicestation.name=服务站 tile.servicemonitor.name=服务监测器 -tile.invhatch.name=存储舱口 +tile.invhatch.name=存储仓 tile.structuretower.name=结构塔 tile.rocketAssembler.name=火箭组装机 tile.turf.name=月面土 @@ -32,15 +32,16 @@ tile.Crystallizer.name=结晶器 tile.blastBrick.name=隔热砖 tile.blastFurnaceController.name=隔热高炉控制器 tile.fuelStation.name=加油站 +tile.databusbig.name=高级数据总线 tile.loader.0.name=数据总线 tile.loader.1.name=卫星仓 tile.loader.2.name=火箭卸载器 tile.loader.3.name=火箭装载器 tile.loader.4.name=火箭流体卸载器 tile.loader.5.name=火箭流体装载器 -tile.loader.6.name=导航计算机访问舱口 +tile.loader.6.name=导航计算机访问仓 tile.observatory.name=瞭望台 -tile.satelliteBuilder.name=卫星建造机 +tile.satelliteBuilder.name=卫星组装机 tile.rocket.name=单组元推进剂火箭发动机 tile.bipropellantrocket.name=双组元推进剂火箭发动机 tile.nuclearrocket.name=核热火箭发动机 @@ -73,7 +74,7 @@ tile.electrolyser.name=电解器 tile.chemreactor.name=化学反应器 tile.scrubber.name=二氧化碳净化器 tile.oxygenVent.name=氧气排放口 -tile.liquidHatch.name=流体舱口 +tile.liquidHatch.name=流体仓 tile.rocketFuelBlock.name=火箭燃料 tile.hydrogenFluidBlock.name=氢气 tile.oxygenFluidBlock.name=氧气 @@ -139,6 +140,7 @@ tile.landingfloat.name=着陆浮筒 tile.solararray.name=太阳能阵列控制器 tile.solararraypanel.name=阵列太阳能板 tile.serviceStation.name=服务站 +tile.orbitalRegistry.name=轨道注册站 item.lens.0.name=基础透镜 item.wafer.0.name=硅晶圆 @@ -203,20 +205,23 @@ item.elevatorChip.name=太空电梯芯片 container.satellite=卫星仓 container.monitoringstation=监测站 -container.invhatch=存储舱口 +container.invhatch=存储仓 material.TitaniumAluminide.name=钛铝合金 material.TitaniumIridium.name=钛铱合金 enchantment.spaceBreathing=气密密封 -data.undefined.name=一些随机数据 +data.undefined.name=未定义 data.distance.name=距离 data.humidity.name=湿度 data.temperature.name=温度 data.composition.name=成分 data.atmospheredensity.name=大气密度 data.mass.name=质量 +data.label.type=类型: +data.label.data=数据 + fluid.oxygen=氧气 fluid.hydrogen=氢气 @@ -229,11 +234,13 @@ mission.gascollection.name=气体采集 error.rocket.notEnoughMissionFuel=燃料不足! error.rocket.tooHeavy=火箭过重,无法发射(推力不足)。 -error.rocket.cannotGetThere=无法从当前位置抵达所选目的地。 +error.rocket.cannotGetThere=无法抵达所选目的地。(你在尝试登陆气态巨行星?) error.rocket.destinationNotExist=所选空间站不存在。 -error.rocket.notSameSystem=星际航行需要核动力火箭和有效的路径。 error.rocket.partsWornOut=关键部件损坏,发射中止。 error.rocket.aborted=发射中止。 +error.rocket.gatedArtifactMissing=缺失工件。(玩家物品栏中) +error.rocket.outsideStarSystem=星际航行需要星际飞船。 +error.rocket.outsidePlanetarySystem=行星航行需要核动力火箭。 advancement.holographic=全息 advancement.holographic.desc=合成一个全息投影器 @@ -245,7 +252,7 @@ advancement.electrifying=电激! advancement.electrifying.desc=合成一个电解器 advancement.spinDoctor=舆论导向专家 advancement.spinDoctor.desc=合成一个机床 -advancement.rollin=Rollin' +advancement.rollin=卷起来! advancement.rollin.desc=合成一个卷板机 advancement.crystalline=结晶 advancement.crystalline.desc=合成一个结晶器 @@ -265,7 +272,7 @@ advancement.flightOfThePhoenix=凤凰劫 advancement.flightOfThePhoenix.desc=建造并起飞第一艘具备跃迁能力的飞船 advancement.beerOnTheSun=太阳上的成人饮料 advancement.beerOnTheSun.desc=你需要更多的TNT才能进入轨道 -advancement.suitedUp=穿上制服 +advancement.suitedUp=穿戴整齐 advancement.suitedUp.desc=穿好全套太空服 @@ -311,8 +318,8 @@ msg.spaceElevator.tetherWouldBreakError=空间站必须保持垂直静止状态 msg.spaceElevator.linkCannotChangeError=电梯系绳在已链接状态下不可变更位置! msg.spaceElevator.newDstAdded=电梯系绳已链接! msg.spaceElevator.ascentReady=准备开始上升 -msg.spaceElevator.warning.anchored0=当前电梯系绳已 -msg.spaceElevator.warning.anchored1=成功锚定空间站! +msg.spaceElevator.warning.anchored0=当前电梯系绳 +msg.spaceElevator.warning.anchored1=已成功锚定空间站! msg.spaceElevator.warning.unanchored=当前电梯尚未连接系绳 msg.spaceElevator.turnedOff=电梯已关闭 msg.fuelingStation.link=已将加油站写入链接器,位置: @@ -331,12 +338,11 @@ msg.monitoringStation.mission.plannedAmountPrefix=数量: msg.monitoringStation.mission.plannedAmountPending=数量:(待定) msg.monitoringStation.mission.asteroidType=小行星类型:(显示在芯片/任务上) msg.monitoringStation.link=已将监控站写入链接器,位置: -msg.monitoringStation.progress=ETA: -msg.monitoringStation.progress=进度: +msg.monitoringStation.progress=剩余时间: msg.monitoringStation.prelaunch=启动中…… msg.monitoringStation.launching=发射中! msg.monitoringStation.orbit=已进入轨道! -msg.monitoringStation.deorbiting=已返回轨道! +msg.monitoringStation.deorbiting=已从轨道返回! msg.monitoringStation.landed=已着陆 msg.monitoringStation.aborted=已中止! msg.monitoringStation.returningToDock=返回停靠点 @@ -356,12 +362,19 @@ msg.fluidLoader.none=无 msg.fluidLoader.link=已将流体装载器写入链接器,位置: msg.rocketLoader.loadingState=装载状态: msg.rocketLoader.allowLoading=允许装载: -msg.rocketLoader.allowredstoneinput=允许红石输入 -msg.rocketLoader.allowredstoneoutput=允许红石输出 -msg.rocketLoader.none=无 +msg.rocketLoader.none=已禁用(绿色) +msg.rocketLoader.allowredstoneoutput=红石输出(蓝色) +msg.rocketLoader.allowredstoneinput=红石输入(红色) msg.rocketLoader.link=已将火箭装载器写入链接器,位置: -msg.microwaverec.notgenerating=产能 0 FE/t +advancedrocketry.sideselector.direction.bottom=底部 +advancedrocketry.sideselector.direction.top=顶部 +advancedrocketry.sideselector.direction.north=北部 +advancedrocketry.sideselector.direction.south=南部 +advancedrocketry.sideselector.direction.west=西部 +advancedrocketry.sideselector.direction.east=东部 +msg.microwaverec.notgenerating=产能 0 RF/t msg.microwaverec.generating=产能 +msg.abdp.research=研究 msg.abdp.compositionresearch=成分研究 msg.abdp.distanceresearch=距离研究 msg.abdp.massresearch=质量研究 @@ -373,7 +386,15 @@ msg.terraformer.outofgas=已中止:气体耗尽 msg.terraformer.notrunning=未运行 msg.terraformer.status=状态 msg.terraformer.pressure=气压 -msg.biomescanner.gas=呀哈哈哈,是气体,不是么? +msg.terraformingterminal.terraforming=正在改造行星…… +msg.terraformingterminal.powergen=能量产出: +msg.terraformingterminal.blockspertick=每刻处理方块: +msg.terraformingterminal.needredstone.line1=提供红石信号 +msg.terraformingterminal.needredstone.line2=启动改造流程 +msg.terraformingterminal.insertchip.line1=在此处放入生物群系 +msg.terraformingterminal.insertchip.line2=变换器遥控终端来让 +msg.terraformingterminal.insertchip.line3=卫星改造整颗行星 +msg.biomescanner.gas=哈,是气体环境,对吧? msg.biomescanner.star=要是我的传感器有遮阳板就好了 msg.gravitycontroller.radius=半径: msg.gravitycontroller.targetgrav=目标重力: @@ -384,6 +405,13 @@ msg.gravitycontroller.targetdir.1=目标-> msg.gravitycontroller.targetdir.2=方向 msg.railgun.transfermin=最小传输尺寸 msg.spacelaser.reset=重置 +msg.spacelaser.notarget1=未找到目标! +msg.spacelaser.notarget2=降落并勘察该区域! +msg.spacelaser.voidmining.line1=正在开采 +msg.spacelaser.voidmining.line2=下方行星的内部物质 +msg.spacelaser.voidcobble=销毁圆石 +msg.spacelaser.voidcobble.on=销毁圆石:开 +msg.spacelaser.voidcobble.off=销毁圆石:关 msg.satctrlcenter.toofar=距离过远 msg.satctrlcenter.nolink=无链接…… msg.satctrlcenter.info=信息: @@ -416,6 +444,7 @@ msg.warpmon.warp=跃迁! msg.warpmon.fuelcost=燃料消耗: msg.warpmon.fuel=燃料: msg.warpmon.dest=目的地: +msg.warpmon.orbit=轨道环绕: msg.warpmon.na=N/A msg.warpmon.search=搜索行星 msg.warpmon.chip=从芯片载入程序 @@ -446,7 +475,7 @@ msg.rocketbuilder.scan=扫描 msg.rocketbuild.combinedthrust=燃料类型不能混合使用! msg.rocketbuilder.alreadyassembled=火箭已组装完成 msg.rocketbuilder.nointake=缺少气体收集器! -msg.rocketbuilder.notank=Missing Fluidtank! +msg.rocketbuilder.notank=缺少流体储罐! msg.solar.collectingEnergy=收集能量: msg.solar.cannotcollectEnergy=无法收集能量 msg.asteroidChip.asteroid=小行星 @@ -465,6 +494,7 @@ msg.itemplanetidchip.planetname=行星名称: msg.itemplanetidchip.stationid=空间站ID: msg.itemplanetidchip.artifacts=工件: msg.vent.trace=氧气追踪 + msg.serviceStation.destroyProbNA=破坏概率:N/A msg.serviceStation.destroyProb=破坏概率 msg.serviceStation.serviceProgress=服务进度 @@ -515,12 +545,26 @@ msg.entity.rocket.seldst=选择目的地 msg.entity.rocket.clear=清除 msg.entity.rocket.rcs=RCS模式 msg.entity.rocket.none=未选择 +msg.entity.rocket.openGuiHint=按%s以打开火箭GUI msg.wirelessTransciever.extract=提取 msg.wirelessTransciever.insert=插入 -msg.wirelessTransciever.type=类型: +msg.wirelessTransciever.type=类型:%s msg.wirelessTransciever.network=网络: msg.wirelessTransciever.network.unlinked=未链接 +msg.advancedrocketry.planetselector.up=<< 上一级 +msg.advancedrocketry.planetselector.select=选择 +msg.advancedrocketry.planetselector.planet.list=行星列表 +msg.advancedrocketry.planetselector.atm.tooltip=%b -> %a个地球大气压 +msg.advancedrocketry.planetselector.mass.tooltip=%b -> %a个地球质量 +msg.advancedrocketry.planetselector.distance.tooltip=%b -> %a相对距离单位 +msg.advancedrocketry.planetselector.star.tooltip.name=名称:%s +msg.advancedrocketry.planetselector.star.tooltip.number.of.planets=行星数量:%d +msg.advancedrocketry.planetselector.planet.tooltip.name=%s +msg.advancedrocketry.planetselector.planet.tooltip.moons.count=天然卫星:%d + + + msg.powerunit.rfpertick=RF/t msg.linker.error.firstMachine=这台机器必须第一个被链接! msg.linker.program=坐标已写入链接器 @@ -545,6 +589,65 @@ msg.chat.nostation1=你在空间站醒来,隐约觉得上次那场深空漫步 msg.chat.nostation2=也许你应该在再次越过明确合理且绝对的界限之前先思考一下,而不是在事情出错后自认为是个好主意且不是你的错 msg.chat.nostation3=你必须在空间站上才能进入此维度,但目前尚未建造任何空间站! +msg.orbitalregistry.tab.satellites=卫星: +msg.orbitalregistry.tab.stations=空间站: +msg.orbitalregistry.text.details=详细信息: +msg.orbitalregistry.text.satellites=卫星 +msg.orbitalregistry.text.stations=空间站 +msg.orbitalregistry.text.nosel=选择一个对象 +msg.orbitalregistry.text.notfound=未找到 +msg.orbitalregistry.scan.tooltip=更新此列表 +msg.orbitalregistry.writechip.ok=点击编程芯片! +msg.orbitalregistry.writechip.no=无法为此对象编程 +msg.orbitalregistry.writechip=编程芯片 + + +# List entry +msg.orbitalregistry.text.listentry=ID + +# StationDetails +msg.orbitalregistry.text.type.starshiplist=§6星际飞船 +msg.orbitalregistry.text.type.starship=星际飞船 +msg.orbitalregistry.text.type.station=空间站 +msg.orbitalregistry.text.id=ID: +msg.orbitalregistry.text.type=类型: +msg.orbitalregistry.text.dimid=维度: +msg.orbitalregistry.text.dimid.none=无 +msg.orbitalregistry.text.orbit=轨道环绕: +msg.orbitalregistry.text.orbit.unlaunched=未入轨! +msg.orbitalregistry.text.freepads=空闲着陆台: +msg.orbitalregistry.text.anchored=已锚定: +msg.orbitalregistry.text.anchored.yes=是 +msg.orbitalregistry.text.anchored.no=否 +msg.orbitalregistry.text.system=星系: +msg.orbitalregistry.text.system.none=无 +msg.orbitalregistry.text.system.unknown=未知 +# SatelliteDetails power fields +msg.orbitalregistry.text.sat.pwrgen=能量产出: +msg.orbitalregistry.text.sat.pwrstore=能量存储: +msg.orbitalregistry.text.sat.maxdata=最大数据量: + +# Orbital Registry – satellite type names +msg.orbitalregistry.sat.name.optical=望远镜 +msg.orbitalregistry.sat.name.density=密度 +msg.orbitalregistry.sat.name.composition=成分 +msg.orbitalregistry.sat.name.mass=质量 +msg.orbitalregistry.sat.name.solarEnergy=太阳能 +msg.orbitalregistry.sat.name.oreScanner=矿物扫描仪 +msg.orbitalregistry.sat.name.biomeChanger=生物群系变换器 +msg.orbitalregistry.sat.name.weatherController=天气 + +msg.orbitalregistry.writechip.hint.insert=放入芯片进行写入 +msg.orbitalregistry.writechip.hint.select=从列表中选择一个条目 +msg.orbitalregistry.writechip.hint.output=需先清空输出槽位 +msg.orbitalregistry.writechip.hint.sat.or.stationchip=放入空间站芯片 +msg.orbitalregistry.writechip.hint.sat.or.idchip=放入卫星ID芯片或控制器 +msg.orbitalregistry.writechip.hint.sat.badcontroller=该卫星不接受此芯片,请使用对应的控制器! +msg.orbitalregistry.writechip.hint.sat.orescanner.only=矿石扫描仪仅能链接至矿石勘探卫星 +msg.orbitalregistry.writechip.hint.station.unlaunched=该空间站尚未进入轨道 + + + commands.weather.always_not_clear=这颗行星从未晴朗过…… commands.weather.cannot_rain=此处无法降雨 commands.weather.cannot_thunder=此处无法降下雷暴 @@ -588,7 +691,7 @@ tooltip.advancedrocketry.nuclearfueltank.alt.1=§f需要§b核热堆芯§f和§b # Monopropellant Engine tooltip.advancedrocketry.monopropmotor=§c火箭的组成部分 -tooltip.advancedrocketry.monopropmotor.shift.1=使用§b单组元推进剂燃料§7 +tooltip.advancedrocketry.monopropmotor.shift.1=§f使用§b单组元推进剂燃料 tooltip.advancedrocketry.monopropmotor.alt.1=查看加油站的JEI页面 # Nuclear Core @@ -599,26 +702,26 @@ tooltip.advancedrocketry.nuclearcore.alt.1=垂直放置规则不适用于 tooltip.advancedrocketry.nuclearcore.alt.2=无人载具(气体任务火箭) # Nuclear rocketengine -tooltip.advancedrocketry.nuclearmotor=§c火箭的组成部分 §6可进行星际航行! -tooltip.advancedrocketry.nuclearmotor.shift.1=使用§b工质§7 +tooltip.advancedrocketry.nuclearmotor=§c火箭的组成部分 §6可进行行星航行! +tooltip.advancedrocketry.nuclearmotor.shift.1=§f使用§b工质 tooltip.advancedrocketry.nuclearmotor.shift.2=正上方需存在核热堆芯。 tooltip.advancedrocketry.nuclearmotor.alt.1=查看加油站的JEI页面 # Bipropellant Engine tooltip.advancedrocketry.bipropmotor=§c火箭的组成部分 -tooltip.advancedrocketry.bipropmotor.shift.1=使用§b双组元推进剂燃料§7和§b氧化剂§7 +tooltip.advancedrocketry.bipropmotor.shift.1=§f使用§b双组元推进剂燃料§7和§b氧化剂 tooltip.advancedrocketry.bipropmotor.alt.1=查看加油站的JEI页面 # Drill tooltip.advancedrocketry.drill=§c火箭的组成部分 -tooltip.advancedrocketry.drill.shift.1=缩短§6采矿任务§7的所需时间 +tooltip.advancedrocketry.drill.shift.1=缩短§6采矿任务§f的所需时间 tooltip.advancedrocketry.drill.shift.2=§b效果可叠加 tooltip.advancedrocketry.drill.alt.1=此火箭需通过火箭组装机搭建 tooltip.advancedrocketry.drill.alt.2=需要一个已编程的小行星芯片 # Gas Intake tooltip.advancedrocketry.intake=§c火箭的组成部分 -tooltip.advancedrocketry.intake.shift.1=缩短§6气体任务§7的所需时间 +tooltip.advancedrocketry.intake.shift.1=缩短§6气体任务§f的所需时间 tooltip.advancedrocketry.intake.shift.2=§b效果可叠加 tooltip.advancedrocketry.intake.alt.1=此火箭需通过无人载具组装机搭建 tooltip.advancedrocketry.intake.alt.2=从绕气态巨行星运行的空间站发射 @@ -673,7 +776,7 @@ tooltip.advancedrocketry.terraformer.alt.2=§f由卫星提供能源 tooltip.advancedrocketry.monitoringstation=§c基础设备 tooltip.advancedrocketry.monitoringstation.shift.1=通过红石信号发射! tooltip.advancedrocketry.monitoringstation.shift.2=§f需连接至§4火箭组装机/停靠台§f或§4火箭本体 -tooltip.advancedrocketry.monitoringstation.alt.1=§b到达轨道后任务即会激活! +tooltip.advancedrocketry.monitoringstation.alt.1=§b任务将在进入轨道后激活! # Satellite Terminal tooltip.advancedrocketry.satellitemonitor=用于与卫星通信 @@ -688,13 +791,26 @@ tooltip.advancedrocketry.satellitebuilder.shift.2=§b必须放置在能量输入 tooltip.advancedrocketry.satellitebuilder.alt.1=放入框架、芯片/遥控终端 tooltip.advancedrocketry.satellitebuilder.alt.2=核心组件+其他组件 +# Orbital Registry +tooltip.advancedrocketry.orbitalregistry=追踪太空中的人造物体 +tooltip.advancedrocketry.orbitalregistry.shift.1=§f可写入新芯片! +tooltip.advancedrocketry.orbitalregistry.shift.2= +tooltip.advancedrocketry.orbitalregistry.alt.1=§f在§4卫星终端§f中使用芯片以销毁卫星 +tooltip.advancedrocketry.orbitalregistry.alt.2= + ### Infrastructure ## BlockARHatch +# TileDataBusBig +tooltip.advancedrocketry.databusbig.header=§c总线与单元 +tooltip.advancedrocketry.databusbig.shift.1=§b只能保存一种类型的数据 +tooltip.advancedrocketry.databusbig.alt.1=§b破坏时保留数据,可作为物品或方块使用 + # TileDataBus tooltip.advancedrocketry.hatch.databus=容量:§62000§7数据 tooltip.advancedrocketry.hatch.databus.shift.1=§b只能保存一种类型的数据 +tooltip.advancedrocketry.hatch.databus.alt.1=§f破坏时清空数据 # TileSatelliteHatch tooltip.advancedrocketry.hatch.satellite=§c火箭的组成部分 @@ -750,6 +866,9 @@ tooltip.advancedrocketry.fuelingstation.alt.1=§f需连接至§4火箭组装机/ ## // Infrastructure # Pressurized Fluid Tank +tooltip.advancedrocketry.fluidtank.empty=空 +tooltip.advancedrocketry.fluidtank.fluid=流体: +tooltip.advancedrocketry.fluidtank.level=液位: tooltip.advancedrocketry.fluidtank.shift.1=§c与上下的储罐连接构成大型储罐 # Wireless Transciever @@ -811,8 +930,7 @@ tooltip.advancedrocketry.orientationctrl.alt.1=§b仅影响视觉效果§7 # Gravity Controller tooltip.advancedrocketry.gravityctrl=§c空间站控制器 tooltip.advancedrocketry.gravityctrl.shift.1=人造重力! -tooltip.advancedrocketry.gravityctrl.alt.1=§b仅影响视觉效果§7 -tooltip.advancedrocketry.gravityctrl.alt.2=红石控制 +tooltip.advancedrocketry.gravityctrl.alt.1=红石控制 # Altitude Controller tooltip.advancedrocketry.altitudectrl=§c空间站控制器 @@ -856,7 +974,7 @@ tooltip.advancedrocketry.sealdetector=检测方块是否具有气密性 tooltip.advancedrocketry.sealdetector.shift.1=§f右击方块使用 # Lens -tooltip.advancedrocketry.lens=§c瞭望台的组成部分 +tooltip.advancedrocketry.lens=§c多方块的组成部分 tooltip.advancedrocketry.lens.shift.1=§b使用全息投影器! ## SPACE SUIT + COMPONENTS @@ -896,7 +1014,7 @@ tooltip.advancedrocketry.itemupgrade.0=§5太空服组件 tooltip.advancedrocketry.itemupgrade.0.shift.1=§f启用飞行背包的悬停模式 tooltip.advancedrocketry.itemupgrade.0.shift.2=§d槽位:头盔§7 tooltip.advancedrocketry.itemupgrade.0.alt.1=需要在胸甲中安装飞行背包。 -tooltip.advancedrocketry.itemupgrade.0.alt.2=无额外叠加效果。 +tooltip.advancedrocketry.itemupgrade.0.alt.2=§f潜行+开关飞行背包键来激活 # 1 = Flight Speed Control Upgrade tooltip.advancedrocketry.itemupgrade.1=§5太空服组件 @@ -959,7 +1077,7 @@ tooltip.advancedrocketry.satfunc.microwave.alt.2=与卫星芯片结合 tooltip.advancedrocketry.satfunc.oremapping=§5卫星核心组件 tooltip.advancedrocketry.satfunc.oremapping.shift.1=§b扫描行星上的矿物§7 tooltip.advancedrocketry.satfunc.oremapping.alt.1=组装时 -tooltip.advancedrocketry.satfunc.oremapping.alt.2=与卫星芯片结合 +tooltip.advancedrocketry.satfunc.oremapping.alt.2=与矿物扫描仪结合 tooltip.advancedrocketry.satfunc.biomechanger=§5卫星核心组件 tooltip.advancedrocketry.satfunc.biomechanger.shift.1=§b调节生物群系§7 @@ -974,6 +1092,10 @@ tooltip.advancedrocketry.satfunc.weather.alt.1=组装时与天气遥控终端结 tooltip.advancedrocketry.weathercontrollerremote=§bShift-右击打开界面 tooltip.advancedrocketry.weathercontrollerremote.shift.1=§f手持此物品右击来使用 tooltip.advancedrocketry.weathercontrollerremote.alt.1=组装时与天气控制器结合 +tooltip.advancedrocketry.weathercontrollerremote.mode.rain=§e模式:降雨——使用水填充地形中的小洼地 +tooltip.advancedrocketry.weathercontrollerremote.mode.dry=§e模式:干旱——蒸发半径16格内的所有水源 +tooltip.advancedrocketry.weathercontrollerremote.mode.flood=§e模式:洪水——用水淹没半径16格的区域 + # Biome Changer Remote tooltip.advancedrocketry.biomechangerremote=§bShift-右击打开界面 @@ -1006,6 +1128,9 @@ tooltip.libvulpes.battery.1.shift.1=增加能量存储 tooltip.libvulpes.battery.1.shift.2=§f容量:§c40.000 §fRF§7 # Data Unit +tooltip.advancedrocketry.itemdata.header=§5太空服组件 +tooltip.advancedrocketry.itemdata.type=§f类型: +tooltip.advancedrocketry.itemdata.data=§f数据存储量: tooltip.advancedrocketry.itemdataunit.shift.1=§f令卫星数据存储量增加1000 tooltip.advancedrocketry.itemdataunit.alt.1=§f也可在物品栏中作为数据存储器使用 @@ -1014,13 +1139,17 @@ tooltip.advancedrocketry.itemdataunit.alt.1=§f也可在物品栏中作为数据 tooltip.advancedrocketry.asteroidchip.shift.1=§b用于采矿任务§7 tooltip.advancedrocketry.asteroidchip.shift.2=§f在§c瞭望台§f中编程 tooltip.advancedrocketry.asteroidchip.alt.1=§4将已编程的芯片放入导航计算机§7 +tooltip.advancedrocketry.asteroidchip.alt.2=§f任务完成后会返还芯片 # Station Chip tooltip.advancedrocketry.stationchip=§b记得做好备份! -tooltip.advancedrocketry.stationchip.shift.1=§f在空间站组装器中编程 +tooltip.advancedrocketry.stationchip.shift.1=§f在空间站组装机中编程 +tooltip.advancedrocketry.stationchip.shift.2=§c在卫星组装机中复制 tooltip.advancedrocketry.stationchip.alt.1=§4将已编程的芯片放入导航计算机§7 +tooltip.advancedrocketry.stationchip.namelabel=名称: # Planet Chip +tooltip.advancedrocketry.planetidchip=§b可重复编程! tooltip.advancedrocketry.planetidchip.shift.1=§f将芯片放入§4导航计算机§7 tooltip.advancedrocketry.planetidchip.shift.2=§f在火箭界面中设置目的地进行编程。 tooltip.advancedrocketry.planetidchip.alt.1=§4发射前请仔细检查是否已完成编程! @@ -1028,7 +1157,9 @@ tooltip.advancedrocketry.planetidchip.alt.1=§4发射前请仔细检查是否已 # Satellite Chip tooltip.advancedrocketry.satidchip=§b记得做好备份! tooltip.advancedrocketry.satidchip.shift.1=§f储存卫星的ID。 -tooltip.advancedrocketry.satidchip.alt.1=§4在卫星终端中使用以进行链接,或在微波接收器多方块结构(输入舱口)中使用。§8(行星:放入终端时解析信息) +tooltip.advancedrocketry.satidchip.shift.2=§c在卫星组装机中复制 +tooltip.advancedrocketry.satidchip.alt.1=§4在卫星终端中使用以进行链接,或在微波接收器多方块结构(输入仓)中使用。 +tooltip.advancedrocketry.satidchip.alt.2=§8(行星:放入终端时解析信息) # Elevator Chip tooltip.advancedrocketry.elevatorchip=太空电梯芯片 @@ -1106,12 +1237,24 @@ tooltip.advancedrocketry.precisionlaseretcher.shift.1=§b使用全息投影器 tooltip.advancedrocketry.observatory=分析天体 tooltip.advancedrocketry.observatory.shift.1=§f用于§6采矿任务 tooltip.advancedrocketry.observatory.shift.2=§b使用全息投影器! -tooltip.advancedrocketry.observatory.alt.1=§f放入§c卫星芯片 +tooltip.advancedrocketry.observatory.alt.1=§f放入§c小行星芯片 tooltip.advancedrocketry.observatory.alt.2=§f需要§6距离数据§f才能运作(仅在夜间工作) +# LibVulpes Hatches and Coal Generator +tooltip.advancedrocketry.libvulpes.hatch=§c多方块结构的组成部分 +tooltip.advancedrocketry.libvulpes.hatch.shift.1=§b使用全息投影器! +tooltip.advancedrocketry.libvulpes.forgepoweroutput=§c多方块结构的组成部分 +tooltip.advancedrocketry.libvulpes.forgepoweroutput.shift.1=§b使用全息投影器! +tooltip.advancedrocketry.libvulpes.forgepowerinput=§c多方块结构的组成部分 +tooltip.advancedrocketry.libvulpes.forgepowerinput.shift.1=§b使用全息投影器! +tooltip.advancedrocketry.libvulpes.creativepowerbattery=§d无限能源 +tooltip.advancedrocketry.libvulpes.creativepowerbattery.shift.1=§c多方块结构的组成部分 +tooltip.advancedrocketry.libvulpes.creativepowerbattery.shift.2=§b使用全息投影器! +tooltip.advancedrocketry.libvulpes.coalgenerator=§c燃烧固体燃料 + # Planet Analyser -tooltip.advancedrocketry.planetanalyser=处理行星扫描数据 +tooltip.advancedrocketry.planetanalyser=处理数据并写入小行星芯片 tooltip.advancedrocketry.planetanalyser.shift.1=§b使用全息投影器! # Centrifuge @@ -1143,7 +1286,7 @@ tooltip.advancedrocketry.spaceelevatorctrl.shift.1=§b使用全息投影器! # Atmosphere Terraformer tooltip.advancedrocketry.atmosterraformer=改变整颗行星上的大气压 tooltip.advancedrocketry.atmosterraformer.shift.1=§b使用全息投影器! -tooltip.advancedrocketry.atmosterraformer.alt.1=通过连接的§c生物群系变换器遥控终端§f增加和减少大气压。 +tooltip.advancedrocketry.atmosterraformer.alt.1=§f通过连接的§c生物群系变换器遥控终端§f增加和减少大气压。 # Area Gravity Controller tooltip.advancedrocketry.gravitymachine=操纵重力 @@ -1153,10 +1296,11 @@ tooltip.advancedrocketry.gravitymachine.shift.2=§b使用全息投影器! # Orbital Last Drill tooltip.advancedrocketry.spacelaser=§c空间站多方块 tooltip.advancedrocketry.spacelaser.shift.1=§b使用全息投影器! +tooltip.advancedrocketry.spacelaser.alt.1=§f需要红石信号来运行 # Force Field Projector tooltip.advancedrocketry.forcefieldprojector=最远可投射32格距离! -tooltip.advancedrocketry.forcefieldprojector.shift.1=使用红石信号激活 +tooltip.advancedrocketry.forcefieldprojector.shift.1=§f使用红石信号激活 # Vacuum Laser tooltip.advancedrocketry.vacuumlaser=§c多方块结构的组成部分 @@ -1178,6 +1322,11 @@ tooltip.advancedrocketry.qcrucible=§c多方块结构的组成部分 tooltip.advancedrocketry.qcrucible.shift.1=§b使用全息投影器! tooltip.advancedrocketry.sawblade=§c多方块结构的组成部分 tooltip.advancedrocketry.sawblade.shift.1=§b使用全息投影器! +tooltip.libvulpes.structuremachine=§c多方块结构的组成部分 +tooltip.libvulpes.structuremachine.shift.1=§b使用全息投影器! +tooltip.libvulpes.advstructuremachine=§c多方块结构的组成部分 +tooltip.libvulpes.advstructuremachine.shift.1=§b使用全息投影器! + ## Assemblers # Rocket Assembler @@ -1192,8 +1341,8 @@ tooltip.advancedrocketry.stationassembler.shift.1=§b需要发射台+结构塔 tooltip.advancedrocketry.stationassembler.alt.1=§f将此方块放置在比发射台高1格的位置,连接底部边角且朝向与发射台方块相反 # Packet Station -tooltip.advancedrocketry.packedstructure=放入§c卫星舱§7以送入轨道! -tooltip.advancedrocketry.packedstructure.shift.1=§e记得告诉火箭应该将有效载荷部署到哪个行星的轨道! +tooltip.advancedrocketry.packedstructure=放入§c卫星仓§7以送入轨道! +tooltip.advancedrocketry.packedstructure.shift.1=§e发射前记得要设置火箭的目标行星! # Deployable Rocket Assembler tooltip.advancedrocketry.deployablerocketassembler=§c在空间站中搭建火箭 @@ -1210,11 +1359,11 @@ tooltip.advancedrocketry.thermite=以产生高温而闻名! # Thermite Torch tooltip.advancedrocketry.thermitetorch=即便没有氧气也可燃烧 -tooltip.advancedrocketry.thermitetorch.shift.1=§f适用于大气环境稀薄或缺失的情况 +tooltip.advancedrocketry.thermitetorch.shift.1=§f适用于大气稀薄或真空环境 # Jackhammer tooltip.advancedrocketry.jackhammer=§c极速挖掘工具 -tooltip.advancedrocketry.jackhammer.1=这东西估计能比你活得还久(只要勤换螺栓的话) +tooltip.advancedrocketry.jackhammer.1=这东西估计能比你活得还久(当然,得记得换螺栓) tooltip.advancedrocketry.jackhammer.shift.1=§f使用§6钛棒§f修复 tooltip.advancedrocketry.jackhammer.alt.1=§f挖掘等级:§b钻石 @@ -1231,4 +1380,4 @@ tooltip.advancedrocketry.circuitplate=§3合成用物品 tooltip.advancedrocketry.circuitic=§3合成用物品 tooltip.advancedrocketry.miscpart=§3合成用物品 tooltip.advancedrocketry.itemlens=§3合成用物品 -tooltip.advancedrocketry.misc=§3合成用物品 +tooltip.advancedrocketry.misc=§3合成用物品 \ No newline at end of file From 71ac79b71552d0728c18c0dc0f5a082c84314003 Mon Sep 17 00:00:00 2001 From: ZetaY <34602681+ZHAY10086@users.noreply.github.com> Date: Fri, 12 Dec 2025 02:17:23 +0800 Subject: [PATCH 292/424] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20zh=5FCN.lang?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/assets/advancedrocketry/lang/zh_CN.lang | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index 0a5225c29..e2b5de8e4 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -861,7 +861,6 @@ tooltip.advancedrocketry.fuelingstation.alt.2=§f在此降落的火箭将自动 tooltip.advancedrocketry.servicestation=§c基础设备 tooltip.advancedrocketry.servicestation.shift.1=修复火箭 tooltip.advancedrocketry.servicestation.shift.2=§o(未完成) -tooltip.advancedrocketry.fuelingstation.alt.1=§f需连接至§4火箭组装机/停靠台§f或§4火箭本体 ## // Infrastructure From 3dad441611e7731b463259ccfec358ede35de188 Mon Sep 17 00:00:00 2001 From: ZetaY <34602681+ZHAY10086@users.noreply.github.com> Date: Sat, 13 Dec 2025 01:01:40 +0800 Subject: [PATCH 293/424] Update zh_CN.lang --- src/main/resources/assets/advancedrocketry/lang/zh_CN.lang | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index e2b5de8e4..486d4b260 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -162,7 +162,7 @@ item.satellitePrimaryFunction.0.name=光学传感器 item.satellitePrimaryFunction.1.name=成分传感器 item.satellitePrimaryFunction.2.name=质量检测器 item.satellitePrimaryFunction.3.name=微波传输器 -item.satellitePrimaryFunction.4.name=矿物映射器 +item.satellitePrimaryFunction.4.name=矿物测绘器 item.satellitePrimaryFunction.5.name=生物群系变换器 item.satellitePrimaryFunction.6.name=天气控制器 item.satelliteIdChip.name=卫星ID芯片 @@ -1379,4 +1379,4 @@ tooltip.advancedrocketry.circuitplate=§3合成用物品 tooltip.advancedrocketry.circuitic=§3合成用物品 tooltip.advancedrocketry.miscpart=§3合成用物品 tooltip.advancedrocketry.itemlens=§3合成用物品 -tooltip.advancedrocketry.misc=§3合成用物品 \ No newline at end of file +tooltip.advancedrocketry.misc=§3合成用物品 From 214c0f8fe3039f56cef100fd531847a94176682e Mon Sep 17 00:00:00 2001 From: ZetaY <34602681+ZHAY10086@users.noreply.github.com> Date: Sat, 13 Dec 2025 01:16:37 +0800 Subject: [PATCH 294/424] Update zh_CN.lang --- src/main/resources/assets/advancedrocketry/lang/zh_CN.lang | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index 486d4b260..b516eac04 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -5,7 +5,7 @@ death.attack.Vacuum=%1$s因为失压而死 death.attack.Vacuum.player=%1$s因为失压而死 death.attack.OxygenToxicity=%1$s因氧气中毒而死 death.attack.OxygenToxicity.player=%1$s因氧气中毒而死 -death.attack.LowOxygen=%1$s 因缺氧而死 +death.attack.LowOxygen=%1$s因缺氧而死 death.attack.LowOxygen.player=%1$s因缺氧而死 death.attack.Heat=%1$s因过热而死 death.attack.Heat.player=%1$s因过热而死 @@ -808,7 +808,7 @@ tooltip.advancedrocketry.databusbig.shift.1=§b只能保存一种类型的数据 tooltip.advancedrocketry.databusbig.alt.1=§b破坏时保留数据,可作为物品或方块使用 # TileDataBus -tooltip.advancedrocketry.hatch.databus=容量:§62000§7数据 +tooltip.advancedrocketry.hatch.databus=容量:§62000§7 数据 tooltip.advancedrocketry.hatch.databus.shift.1=§b只能保存一种类型的数据 tooltip.advancedrocketry.hatch.databus.alt.1=§f破坏时清空数据 From ac10e212d7126f0d63f365f9cfabdeeb413ee706 Mon Sep 17 00:00:00 2001 From: ZHAY10086 Date: Sat, 13 Dec 2025 12:44:26 +0800 Subject: [PATCH 295/424] correct planet definition --- .../assets/advancedrocketry/lang/zh_CN.lang | 60 +++++++++---------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index b516eac04..74bab1bfd 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -66,7 +66,7 @@ tile.hotDryturf.name=氧化铁沙 tile.concrete.name=混凝土 tile.lathe.name=车床 tile.rollingMachine.name=卷板机 -tile.planetSelector.name=行星选择器 +tile.planetSelector.name=星球选择器 tile.blockHandPress.name=小型压板器 tile.placeHolder.name=机器 tile.stationAssembler.name=空间站组装机 @@ -119,7 +119,7 @@ tile.altitudeController.name=海拔控制器 tile.railgun.name=轨道炮 tile.advRocket.name=高级单组元推进剂火箭发动机 tile.advbipropellantRocket.name=高级双组元推进剂火箭发动机 -tile.planetHoloSelector.name=全息行星选择器 +tile.planetHoloSelector.name=全息星球选择器 tile.lens.name=透镜 tile.forceField.name=力场 tile.forceFieldProjector.name=力场投射器 @@ -166,7 +166,7 @@ item.satellitePrimaryFunction.4.name=矿物测绘器 item.satellitePrimaryFunction.5.name=生物群系变换器 item.satellitePrimaryFunction.6.name=天气控制器 item.satelliteIdChip.name=卫星ID芯片 -item.planetIdChip.name=行星ID芯片 +item.planetIdChip.name=星球ID芯片 item.asteroidChip.name=小行星芯片 item.miscpart.0.name=用户界面 item.miscpart.1.name=碳砖 @@ -304,7 +304,7 @@ msg.tooltip.data=数据 msg.tooltip.asteroidselection=小行星选择 msg.label.name=名称 msg.label.clear=清除 -msg.label.add=添加新行星 +msg.label.add=新增 msg.label.rename=重命名 msg.label.delete=删除 msg.label.noneSelected=未选择目的地 @@ -351,7 +351,7 @@ msg.monitoringStation.noLinkedRocket=未链接任何火箭! msg.guidanceComputerHatch.loadingState=装载状态: msg.guidanceComputerHatch.ejectonlanding=着陆时自动弹出 msg.guidanceComputerHatch.ejectonsatlanding=允许弹出卫星芯片 -msg.guidanceComputerHatch.ejectonplanetlanding=允许弹出行星芯片 +msg.guidanceComputerHatch.ejectonplanetlanding=允许弹出星球芯片 msg.guidanceComputerHatch.ejectonstationlanding=允许弹出空间站芯片 msg.guidanceComputerHatch.link=已将流体装载器写入链接器,位置: msg.fluidLoader.loadingState=装载状态: @@ -386,14 +386,14 @@ msg.terraformer.outofgas=已中止:气体耗尽 msg.terraformer.notrunning=未运行 msg.terraformer.status=状态 msg.terraformer.pressure=气压 -msg.terraformingterminal.terraforming=正在改造行星…… +msg.terraformingterminal.terraforming=正在改造星球…… msg.terraformingterminal.powergen=能量产出: msg.terraformingterminal.blockspertick=每刻处理方块: msg.terraformingterminal.needredstone.line1=提供红石信号 msg.terraformingterminal.needredstone.line2=启动改造流程 msg.terraformingterminal.insertchip.line1=在此处放入生物群系 msg.terraformingterminal.insertchip.line2=变换器遥控终端来让 -msg.terraformingterminal.insertchip.line3=卫星改造整颗行星 +msg.terraformingterminal.insertchip.line3=卫星改造整颗星球 msg.biomescanner.gas=哈,是气体环境,对吧? msg.biomescanner.star=要是我的传感器有遮阳板就好了 msg.gravitycontroller.radius=半径: @@ -408,7 +408,7 @@ msg.spacelaser.reset=重置 msg.spacelaser.notarget1=未找到目标! msg.spacelaser.notarget2=降落并勘察该区域! msg.spacelaser.voidmining.line1=正在开采 -msg.spacelaser.voidmining.line2=下方行星的内部物质 +msg.spacelaser.voidmining.line2=下方星球的内部物质 msg.spacelaser.voidcobble=销毁圆石 msg.spacelaser.voidcobble.on=销毁圆石:开 msg.spacelaser.voidcobble.off=销毁圆石:关 @@ -432,8 +432,8 @@ msg.stationorientctrl.alt=角速度: msg.stationorientctrl.tgtalt=目标角速度: msg.warpmon.tab.warp=跃迁选择 msg.warpmon.tab.data=数据 -msg.warpmon.tab.tracking=行星追踪 -msg.warpmon.selectplanet=选择行星 +msg.warpmon.tab.tracking=星球追踪 +msg.warpmon.selectplanet=选择星球 msg.warpmon.corestatus=核心状态: msg.warpmon.anchored=空间站已锚定! msg.warpmon.nowhere=无可用目的地 @@ -446,7 +446,7 @@ msg.warpmon.fuel=燃料: msg.warpmon.dest=目的地: msg.warpmon.orbit=轨道环绕: msg.warpmon.na=N/A -msg.warpmon.search=搜索行星 +msg.warpmon.search=搜索星球 msg.warpmon.chip=从芯片载入程序 msg.warpmon.datareq=需各类数据各100 msg.warpmon.artifact=工件 @@ -490,7 +490,7 @@ msg.itemorescanner.nosat=卫星尚未发射 msg.itemorescanner.maxzoom=最大缩放: msg.itemorescanner.filter=可过滤矿石: msg.itemorescanner.value=值: -msg.itemplanetidchip.planetname=行星名称: +msg.itemplanetidchip.planetname=星球名称: msg.itemplanetidchip.stationid=空间站ID: msg.itemplanetidchip.artifacts=工件: msg.vent.trace=氧气追踪 @@ -521,8 +521,8 @@ msg.itemsatellite.unassembled=未组装(预览) msg.brokenstage.text=摧毁阶段 msg.itemsatchip.id=ID: -msg.itemsatchip.planet=行星: -msg.itemsatchip.planetunk=行星: 未知 +msg.itemsatchip.planet=星球: +msg.itemsatchip.planetunk=星球: 未知 msg.itemsatchip.sat=卫星: msg.itemsatchip.satlost=卫星:失去联系 msg.sealdetector.sealed=应该能保持良好密封。 @@ -554,7 +554,7 @@ msg.wirelessTransciever.network.unlinked=未链接 msg.advancedrocketry.planetselector.up=<< 上一级 msg.advancedrocketry.planetselector.select=选择 -msg.advancedrocketry.planetselector.planet.list=行星列表 +msg.advancedrocketry.planetselector.planet.list=星球列表 msg.advancedrocketry.planetselector.atm.tooltip=%b -> %a个地球大气压 msg.advancedrocketry.planetselector.mass.tooltip=%b -> %a个地球质量 msg.advancedrocketry.planetselector.distance.tooltip=%b -> %a相对距离单位 @@ -648,7 +648,7 @@ msg.orbitalregistry.writechip.hint.station.unlaunched=该空间站尚未进入 -commands.weather.always_not_clear=这颗行星从未晴朗过…… +commands.weather.always_not_clear=这颗星球从未晴朗过…… commands.weather.cannot_rain=此处无法降雨 commands.weather.cannot_thunder=此处无法降下雷暴 @@ -734,7 +734,7 @@ tooltip.advancedrocketry.seat.shift.1=为火箭增加一个乘客位 tooltip.advancedrocketry.guidancecomputer=§c火箭的组成部分 tooltip.advancedrocketry.guidancecomputer.shift.1=放入§c芯片§7或已编程的§c链接器§7 tooltip.advancedrocketry.guidancecomputer.alt.1=部署卫星或空间站至轨道时 -tooltip.advancedrocketry.guidancecomputer.alt.2=记得设定火箭的目标行星 +tooltip.advancedrocketry.guidancecomputer.alt.2=记得设定火箭的目标星球 # Service Monitor tooltip.advancedrocketry.servicemonitor=§c火箭的组成部分 @@ -766,9 +766,9 @@ tooltip.advancedrocketry.structuretower.alt.1=无人载具组装机的主要方 tooltip.advancedrocketry.structuretower.alt.2=查看维基了解更多信息。 # Terraformer -tooltip.advancedrocketry.terraformer=改变整颗行星的地形环境! +tooltip.advancedrocketry.terraformer=改变整颗星球的地形环境! tooltip.advancedrocketry.terraformer.shift.1=§f需与§c生物群系变换器卫星§f搭配使用 -tooltip.advancedrocketry.terraformer.shift.2=§f卫星必须环绕对应行星运行 +tooltip.advancedrocketry.terraformer.shift.2=§f卫星必须环绕对应星球运行 tooltip.advancedrocketry.terraformer.alt.1=§f放入§c生物群系变换器遥控终端 tooltip.advancedrocketry.terraformer.alt.2=§f由卫星提供能源 @@ -815,7 +815,7 @@ tooltip.advancedrocketry.hatch.databus.alt.1=§f破坏时清空数据 # TileSatelliteHatch tooltip.advancedrocketry.hatch.satellite=§c火箭的组成部分 tooltip.advancedrocketry.hatch.satellite.shift.1=用于将有效载荷送入轨道 -tooltip.advancedrocketry.hatch.satellite.shift.2=记得设定轨道的目标行星! +tooltip.advancedrocketry.hatch.satellite.shift.2=记得设定轨道的目标星球! tooltip.advancedrocketry.hatch.satellite.alt.1=§f可在§4空间站组装机§f中用于封装和存储空间站 # TileRocketUnloader @@ -910,15 +910,15 @@ tooltip.advancedrocketry.pipeseal.alt.2=实体可通过此类开口穿行 # Planet Selector (full-screen) tooltip.advancedrocketry.planetselector=浏览星体 -tooltip.advancedrocketry.planetselector.shift.1=开启全屏行星UI。 +tooltip.advancedrocketry.planetselector.shift.1=开启全屏星球UI。 tooltip.advancedrocketry.planetselector.shift.2=浏览星系、行星与天然卫星 tooltip.advancedrocketry.planetselector.alt.1=可远程设置跃迁控制器的 -tooltip.advancedrocketry.planetselector.alt.2=行星目的地 +tooltip.advancedrocketry.planetselector.alt.2=目标星球 # Holographic Planet Selector tooltip.advancedrocketry.planetholoselector=全息星体显示器 tooltip.advancedrocketry.planetholoselector.shift.1=在世界中生成全息投影 -tooltip.advancedrocketry.planetholoselector.alt.1=“功能与行星选择器相同 +tooltip.advancedrocketry.planetholoselector.alt.1=“功能与星球选择器相同 tooltip.advancedrocketry.planetholoselector.alt.2=但采用3D全息投影显示” # Orientation Controller @@ -959,7 +959,7 @@ tooltip.advancedrocketry.smallairlock.alt.2=建造一个合适的气闸 # Warp Controller tooltip.advancedrocketry.warpcontroller=将空间站转变为§6星际飞船 tooltip.advancedrocketry.warpcontroller.shift.1=在空间站上放置§4跃迁控制器§7和§4跃迁核心 -tooltip.advancedrocketry.warpcontroller.shift.2=在行星和太阳系之间进行跃迁旅行 +tooltip.advancedrocketry.warpcontroller.shift.2=在行星和恒星系之间进行跃迁旅行 tooltip.advancedrocketry.warpcontroller.alt.1=界面中会显示位置、目的地和跃迁燃料 tooltip.advancedrocketry.warpcontroller.alt.2=(你已经做到了!去看看Wiki吧伙计) @@ -1037,7 +1037,7 @@ tooltip.advancedrocketry.itemupgrade.3.alt.1=无额外叠加效果。 # 4 = Antifog Visor Upgrade tooltip.advancedrocketry.itemupgrade.4=§5太空服组件 -tooltip.advancedrocketry.itemupgrade.4.shift.1=§f看透高气压行星上的迷雾 +tooltip.advancedrocketry.itemupgrade.4.shift.1=§f看透高气压星球上的迷雾 tooltip.advancedrocketry.itemupgrade.4.shift.2=§d槽位:头盔§7 tooltip.advancedrocketry.itemupgrade.4.alt.1=无额外叠加效果。 @@ -1074,7 +1074,7 @@ tooltip.advancedrocketry.satfunc.microwave.alt.1=组装时 tooltip.advancedrocketry.satfunc.microwave.alt.2=与卫星芯片结合 tooltip.advancedrocketry.satfunc.oremapping=§5卫星核心组件 -tooltip.advancedrocketry.satfunc.oremapping.shift.1=§b扫描行星上的矿物§7 +tooltip.advancedrocketry.satfunc.oremapping.shift.1=§b扫描星球上的矿物§7 tooltip.advancedrocketry.satfunc.oremapping.alt.1=组装时 tooltip.advancedrocketry.satfunc.oremapping.alt.2=与矿物扫描仪结合 @@ -1158,7 +1158,7 @@ tooltip.advancedrocketry.satidchip=§b记得做好备份! tooltip.advancedrocketry.satidchip.shift.1=§f储存卫星的ID。 tooltip.advancedrocketry.satidchip.shift.2=§c在卫星组装机中复制 tooltip.advancedrocketry.satidchip.alt.1=§4在卫星终端中使用以进行链接,或在微波接收器多方块结构(输入仓)中使用。 -tooltip.advancedrocketry.satidchip.alt.2=§8(行星:放入终端时解析信息) +tooltip.advancedrocketry.satidchip.alt.2=§8(星球:放入终端时解析信息) # Elevator Chip tooltip.advancedrocketry.elevatorchip=太空电梯芯片 @@ -1270,7 +1270,7 @@ tooltip.advancedrocketry.beacon=远程信标 tooltip.advancedrocketry.beacon.shift.1=§b使用全息投影器! # Biome Scanner -tooltip.advancedrocketry.biomescan=扫描行星的生物群系 +tooltip.advancedrocketry.biomescan=扫描星球的生物群系 tooltip.advancedrocketry.biomescan.shift.1=§b使用全息投影器! # Railgun @@ -1283,7 +1283,7 @@ tooltip.advancedrocketry.spaceelevatorctrl=用于控制太空电梯 tooltip.advancedrocketry.spaceelevatorctrl.shift.1=§b使用全息投影器! # Atmosphere Terraformer -tooltip.advancedrocketry.atmosterraformer=改变整颗行星上的大气压 +tooltip.advancedrocketry.atmosterraformer=改变整颗星球的大气压 tooltip.advancedrocketry.atmosterraformer.shift.1=§b使用全息投影器! tooltip.advancedrocketry.atmosterraformer.alt.1=§f通过连接的§c生物群系变换器遥控终端§f增加和减少大气压。 @@ -1341,7 +1341,7 @@ tooltip.advancedrocketry.stationassembler.alt.1=§f将此方块放置在比发 # Packet Station tooltip.advancedrocketry.packedstructure=放入§c卫星仓§7以送入轨道! -tooltip.advancedrocketry.packedstructure.shift.1=§e发射前记得要设置火箭的目标行星! +tooltip.advancedrocketry.packedstructure.shift.1=§e发射前记得要设置火箭的目标星球! # Deployable Rocket Assembler tooltip.advancedrocketry.deployablerocketassembler=§c在空间站中搭建火箭 From cae55b7b6a388eb9477cd1f63dbc28500a49599d Mon Sep 17 00:00:00 2001 From: ZHAY10086 Date: Sat, 13 Dec 2025 13:32:17 +0800 Subject: [PATCH 296/424] small change --- src/main/resources/assets/advancedrocketry/lang/zh_CN.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index 74bab1bfd..ff016c39f 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -545,7 +545,7 @@ msg.entity.rocket.seldst=选择目的地 msg.entity.rocket.clear=清除 msg.entity.rocket.rcs=RCS模式 msg.entity.rocket.none=未选择 -msg.entity.rocket.openGuiHint=按%s以打开火箭GUI +msg.entity.rocket.openGuiHint=按%s键打开火箭GUI msg.wirelessTransciever.extract=提取 msg.wirelessTransciever.insert=插入 msg.wirelessTransciever.type=类型:%s From 665432918482d37119476feebb25addb53fb516f Mon Sep 17 00:00:00 2001 From: ZHAY10086 Date: Sat, 13 Dec 2025 13:41:02 +0800 Subject: [PATCH 297/424] chip --- src/main/resources/assets/advancedrocketry/lang/zh_CN.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index ff016c39f..dcbfed334 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -418,7 +418,7 @@ msg.satctrlcenter.info=信息: msg.satctrlcenter.destroysat=摧毁卫星 msg.satctrlcenter.connect=下载 msg.satctrlcenter.autodl_hint=无线收发器自动下载(提取) -msg.satbuilder.writesecondchip=写入副芯片 +msg.satbuilder.writesecondchip=写入第二芯片 msg.dockingport.target=目标ID msg.dockingport.me=本端ID msg.planetholo.size=全息图尺寸: From d31be0e3acc6c2fc931ac701c5f5a697c2ebb97d Mon Sep 17 00:00:00 2001 From: ZHAY10086 Date: Sat, 13 Dec 2025 16:02:51 +0800 Subject: [PATCH 298/424] Data Unit Tooltip --- src/main/resources/assets/advancedrocketry/lang/zh_CN.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index dcbfed334..110ad11b1 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -1127,7 +1127,7 @@ tooltip.libvulpes.battery.1.shift.1=增加能量存储 tooltip.libvulpes.battery.1.shift.2=§f容量:§c40.000 §fRF§7 # Data Unit -tooltip.advancedrocketry.itemdata.header=§5太空服组件 +tooltip.advancedrocketry.itemdata.header=§5卫星组件 tooltip.advancedrocketry.itemdata.type=§f类型: tooltip.advancedrocketry.itemdata.data=§f数据存储量: tooltip.advancedrocketry.itemdataunit.shift.1=§f令卫星数据存储量增加1000 From e4669fddef3fd860477521f1f3898fbf3639e659 Mon Sep 17 00:00:00 2001 From: ZHAY10086 Date: Sat, 13 Dec 2025 17:18:08 +0800 Subject: [PATCH 299/424] update --- .../assets/advancedrocketry/lang/zh_CN.lang | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index 110ad11b1..d689a69e9 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -194,6 +194,13 @@ item.basicLaserGun.name=基础激光枪 item.beaconFinder.name=信标定位器 item.thermite.name=铝热剂 item.hovercraft.name=气垫船 +item.satellite.opticaltelescope=光学望远镜 +item.satellite.composition=成分扫描器 +item.satellite.massscanner=质量扫描器 +item.satellite.solar=太阳能 +item.satellite.oremapper=矿物测绘器 +item.satellite.biomechanger=生物群系变换器 +item.satellite.weather=天气卫星 item.jetPack.name=飞行背包 @@ -298,8 +305,26 @@ msg.observetory.text.composition=成分 msg.observetory.text.processdiscovery=扫描进度 msg.observetory.text.observabledistance=可观测距离: msg.observetory.text.missionTime=任务时间: +msg.observetory.text.time=时间: msg.observetory.req.open=瞭望台必须满足开放条件(夜晚、天气晴朗、可观测天空)或位于空间站中! msg.observetory.print.already=此小行星已存在对应芯片! + +# Atmosphere detector GUI labels +msg.atmosphere.air=正常空气 +msg.atmosphere.pressurizedair=加压空气 +msg.atmosphere.lowo2=低氧 +msg.atmosphere.vacuum=真空 +msg.atmosphere.highpressure=高压 +msg.atmosphere.superhighpressure=超高压 +msg.atmosphere.veryhot=高温 +msg.atmosphere.superheated=过热 +msg.atmosphere.noo2=无氧 +msg.atmosphere.highpressurenoo2=高压无氧 +msg.atmosphere.superhighpressurenoo2=超高压无氧 +msg.atmosphere.veryhotnoo2=高温无氧 +msg.atmosphere.superheatednooxygen=过热无氧 + + msg.tooltip.data=数据 msg.tooltip.asteroidselection=小行星选择 msg.label.name=名称 @@ -417,6 +442,8 @@ msg.satctrlcenter.nolink=无链接…… msg.satctrlcenter.info=信息: msg.satctrlcenter.destroysat=摧毁卫星 msg.satctrlcenter.connect=下载 +msg.satctrlcenter.data=数据: +msg.satctrlcenter.power=能量产出: msg.satctrlcenter.autodl_hint=无线收发器自动下载(提取) msg.satbuilder.writesecondchip=写入第二芯片 msg.dockingport.target=目标ID @@ -653,6 +680,8 @@ commands.weather.cannot_rain=此处无法降雨 commands.weather.cannot_thunder=此处无法降下雷暴 # Jeistuff +jei.machinerecipe.power=能量: +jei.machinerecipe.time=时间: jei.sb.satellitepreview=已做好入轨准备! jei.sb.copy.source=来源 jei.sb.copy.output=新副本 From 40baaf6c010c99a2e0173c247706ec6a7c5c2291 Mon Sep 17 00:00:00 2001 From: ZHAY10086 Date: Sat, 13 Dec 2025 17:18:13 +0800 Subject: [PATCH 300/424] remove blank --- src/main/resources/assets/advancedrocketry/lang/zh_CN.lang | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index d689a69e9..0d62703a9 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -1408,4 +1408,4 @@ tooltip.advancedrocketry.circuitplate=§3合成用物品 tooltip.advancedrocketry.circuitic=§3合成用物品 tooltip.advancedrocketry.miscpart=§3合成用物品 tooltip.advancedrocketry.itemlens=§3合成用物品 -tooltip.advancedrocketry.misc=§3合成用物品 +tooltip.advancedrocketry.misc=§3合成用物品 \ No newline at end of file From 3e1b16caa8e45c5350a774da5136477b4cc5b4ab Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 11:39:32 +0100 Subject: [PATCH 301/424] Update modVersion from 2.2.1-1 to 2.2.2 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 6eff6a358..163fe0461 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,7 +4,7 @@ org.gradle.daemon=false # Project mcVersion=1.12.2 forgeVersion=14.23.5.2860 -modVersion=2.2.1-1 +modVersion=2.2.2 archiveBase=AdvancedRocketry startGitRev=8e676bd From adf5fe09903214070d26588d4599b4c4f9679280 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 11:43:22 +0100 Subject: [PATCH 302/424] Add orbitalregistry.json blockstate configuration --- .../blockstates/orbitalregistry.json | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/main/resources/assets/advancedrocketry/blockstates/orbitalregistry.json diff --git a/src/main/resources/assets/advancedrocketry/blockstates/orbitalregistry.json b/src/main/resources/assets/advancedrocketry/blockstates/orbitalregistry.json new file mode 100644 index 000000000..dd6a128b9 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/blockstates/orbitalregistry.json @@ -0,0 +1,20 @@ +{ + "forge_marker": 1, + "defaults": { + "transform": "forge:default-block", + "model": "advancedrocketry:orbitalRegistry" + }, + "variants": { + "facing=north,state=false": [{}], + "facing=south,state=false": { "model": "advancedrocketry:orbitalRegistry", "y": 180 }, + "facing=west,state=false": { "model": "advancedrocketry:orbitalRegistry", "y": 270 }, + "facing=east,state=false": { "model": "advancedrocketry:orbitalRegistry", "y": 90 }, + + "facing=north,state=true": [{}], + "facing=south,state=true": { "model": "advancedrocketry:orbitalRegistry", "y": 180 }, + "facing=west,state=true": { "model": "advancedrocketry:orbitalRegistry", "y": 270 }, + "facing=east,state=true": { "model": "advancedrocketry:orbitalRegistry", "y": 90 }, + + "inventory": [{}] + } +} From b39b1afe641278e3e9aabaf1239df605dabe5bd7 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 11:44:47 +0100 Subject: [PATCH 303/424] Add orbitalregistry.json model for orbital registry --- .../assets/advancedrocketry/models/item/orbitalregistry.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/main/resources/assets/advancedrocketry/models/item/orbitalregistry.json diff --git a/src/main/resources/assets/advancedrocketry/models/item/orbitalregistry.json b/src/main/resources/assets/advancedrocketry/models/item/orbitalregistry.json new file mode 100644 index 000000000..33b944c0c --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/models/item/orbitalregistry.json @@ -0,0 +1,3 @@ +{ + "parent": "advancedrocketry:block/orbitalRegistry" +} From 025745118f541de72c5004b25d7f1c535e666d28 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 11:46:22 +0100 Subject: [PATCH 304/424] Add files via upload --- .../textures/blocks/orbitalregistry.png | Bin 0 -> 640 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/main/resources/assets/advancedrocketry/textures/blocks/orbitalregistry.png diff --git a/src/main/resources/assets/advancedrocketry/textures/blocks/orbitalregistry.png b/src/main/resources/assets/advancedrocketry/textures/blocks/orbitalregistry.png new file mode 100644 index 0000000000000000000000000000000000000000..66e68a7cbe7f1a0d4bd21cedfdba6b6b32cec80d GIT binary patch literal 640 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBufiR<}hF1enLwjaOL`j6Nk5zJhu3lnFep0GlMQ#C5H3Nf< zeMLcHa&~HoLQ-maW}dD3``!E16*5z7)x%AF4SWlnQ!_F>s)|yBtNcQetFn_VQ`GJ4 zc)4sUtbiuurj{fsROII56ON0GHI_ zN%^HEwo0X?nJHFjiD{-uDJiD9Nr}cOx`u`+iMoj?#)i5n#>Oe;riK zGN53Bhi+;fFi6XRVW%@?1~)L=n><|{LoEEy25;nTFyJW`4Ca5x`b>-ct61NImcA45 zrMl8xUfv61H;8C{d~jr1k`u?tsBXC<5{#2L9l|I21h4xgx>?R;kKAgDzPGR1^()Re z98njne_YD8Ugyc5{W?7H0iqZ7edaM)#grc?qLHgp=%9QgjJMT8h#{fs{!Od)()a?V X=YqMdCmk<+0VM-ZS3j3^P6 Date: Sat, 13 Dec 2025 11:47:29 +0100 Subject: [PATCH 305/424] Add orbitalregistry.json model for block --- .../advancedrocketry/models/block/orbitalregistry.json | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/main/resources/assets/advancedrocketry/models/block/orbitalregistry.json diff --git a/src/main/resources/assets/advancedrocketry/models/block/orbitalregistry.json b/src/main/resources/assets/advancedrocketry/models/block/orbitalregistry.json new file mode 100644 index 000000000..855beb1cd --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/models/block/orbitalregistry.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/orientable", + "textures": { + "top": "libvulpes:blocks/machinegeneric", + "front": "advancedrocketry:blocks/orbitalregistry", + "side": "libvulpes:blocks/machinegeneric" + } +} From e61fd1289664296b8856284c3c78029f9f68d08f Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 11:48:13 +0100 Subject: [PATCH 306/424] Refactor rocket dismantle event handling --- .../tile/station/TileLandingPad.java | 28 +++++++++++++------ 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/station/TileLandingPad.java b/src/main/java/zmaster587/advancedRocketry/tile/station/TileLandingPad.java index 5e1d5c20a..2242ad73a 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/station/TileLandingPad.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/station/TileLandingPad.java @@ -179,22 +179,32 @@ public void onRocketLaunch(RocketPreLaunchEvent event) { @SubscribeEvent public void onRocketDismantle(RocketDismantleEvent event) { - if (!world.isRemote && world.provider.getDimension() == ARConfiguration.getCurrentConfig().spaceDimId) { + if (world == null || world.isRemote || world.provider == null) return; + if (world.provider.getDimension() != ARConfiguration.getCurrentConfig().spaceDimId) return; - EntityRocketBase rocket = (EntityRocketBase) event.getEntity(); - AxisAlignedBB bbCache = new AxisAlignedBB(this.getPos().add(-1, 0, -1), this.getPos().add(1, 2, 1)); + // Make sure this is actually a rocket + if (!(event.getEntity() instanceof EntityRocketBase)) return; - if (bbCache.intersects(rocket.getEntityBoundingBox())) { + EntityRocketBase rocket = (EntityRocketBase) event.getEntity(); + AxisAlignedBB rocketBB = rocket.getEntityBoundingBox(); + if (rocketBB == null) return; // don't explode if some mod messes with AABBs - ISpaceObject spaceObj = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); + AxisAlignedBB bbCache = new AxisAlignedBB( + this.getPos().add(-1, 0, -1), + this.getPos().add(1, 2, 1) + ); - if (spaceObj instanceof SpaceStationObject) { - ((SpaceStationObject) spaceObj).setPadStatus(pos, false); - } - } + if (!bbCache.intersects(rocketBB)) return; + + ISpaceObject spaceObj = + SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); + + if (spaceObj instanceof SpaceStationObject) { + ((SpaceStationObject) spaceObj).setPadStatus(pos, false); } } + public void registerTileWithStation(World world, BlockPos pos) { if (!world.isRemote && world.provider.getDimension() == ARConfiguration.getCurrentConfig().spaceDimId) { ISpaceObject spaceObj = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); From c28b34d7b7aac6e242a8181f03f5e9cddaa2ad8c Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 11:49:00 +0100 Subject: [PATCH 307/424] Enhance deconstructRocket with error logging Added error handling for RocketDismantleEvent to log exceptions. --- .../advancedRocketry/api/EntityRocketBase.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/api/EntityRocketBase.java b/src/main/java/zmaster587/advancedRocketry/api/EntityRocketBase.java index 685b5ae2e..ea5440d79 100644 --- a/src/main/java/zmaster587/advancedRocketry/api/EntityRocketBase.java +++ b/src/main/java/zmaster587/advancedRocketry/api/EntityRocketBase.java @@ -3,6 +3,7 @@ import net.minecraft.entity.Entity; import net.minecraft.world.World; import net.minecraftforge.common.MinecraftForge; +import zmaster587.advancedRocketry.AdvancedRocketry; import zmaster587.advancedRocketry.api.fuel.FuelRegistry; import zmaster587.advancedRocketry.api.stations.ISpaceObject; import zmaster587.libVulpes.util.HashedBlockPosition; @@ -140,8 +141,16 @@ public void onOrbitReached() { /** * Deconstructs the rocket, replacing it with actual blocks + * Log and continue even if event handlers throw exceptions */ public void deconstructRocket() { - MinecraftForge.EVENT_BUS.post(new RocketEvent.RocketDismantleEvent(this)); + try { + MinecraftForge.EVENT_BUS.post(new RocketEvent.RocketDismantleEvent(this)); + } catch (Throwable t) { + AdvancedRocketry.logger.error( + "RocketDismantleEvent handler threw for rocket {}, continuing deconstruction anyway", + this, t + ); + } } } From 19fe3615f8a3f754be9b1aae97992e6483b3610e Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 11:49:36 +0100 Subject: [PATCH 308/424] Improve key input handling for rocket launch Refactor key input handling for rocket controls. --- .../advancedRocketry/client/KeyBindings.java | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/client/KeyBindings.java b/src/main/java/zmaster587/advancedRocketry/client/KeyBindings.java index bd7a10a12..b4549e571 100644 --- a/src/main/java/zmaster587/advancedRocketry/client/KeyBindings.java +++ b/src/main/java/zmaster587/advancedRocketry/client/KeyBindings.java @@ -44,6 +44,10 @@ public static void init() { ClientRegistry.registerKeyBinding(turnRocketUp); ClientRegistry.registerKeyBinding(turnRocketDown); } + //Getters for keybindings + public static KeyBinding getOpenRocketUI() { + return openRocketUI; + } @SubscribeEvent public void onKeyInput(InputEvent.KeyInputEvent event) { @@ -62,14 +66,22 @@ public void onKeyInput(InputEvent.KeyInputEvent event) { PacketHandler.sendToServer(new PacketEntity(rocket, (byte)EntityRocket.PacketType.LAUNCH.ordinal())); rocket.launch(); }*/ - + if (player.getRidingEntity() != null && player.getRidingEntity() instanceof EntityRocket) { EntityRocket rocket = (EntityRocket) player.getRidingEntity(); + /* spacehammercode : janky in large packs if (Minecraft.getMinecraft().inGameHasFocus && player.equals(Minecraft.getMinecraft().player)) { if (!rocket.isInFlight() && Keyboard.isKeyDown(Keyboard.KEY_SPACE)) { rocket.prepareLaunch(); } + */ + if (Minecraft.getMinecraft().inGameHasFocus && player.equals(Minecraft.getMinecraft().player)) { + if (!rocket.isInFlight() + && Keyboard.getEventKey() == Keyboard.KEY_SPACE + && Keyboard.getEventKeyState()) { + rocket.prepareLaunch(); + } rocket.onTurnLeft(turnRocketLeft.isKeyDown()); rocket.onTurnRight(turnRocketRight.isKeyDown()); rocket.onUp(turnRocketUp.isKeyDown()); @@ -113,4 +125,4 @@ public void onKeyInput(InputEvent.KeyInputEvent event) { PacketHandler.sendToServer(new PacketChangeKeyState(Keyboard.KEY_SPACE, prevState)); } } -} \ No newline at end of file +} From a556d49e875899a0611e7d0016a18b4001f320ca Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 11:51:08 +0100 Subject: [PATCH 309/424] Implement hint for opening Rocket UI Added a hint for opening the Rocket UI down right corner --- .../event/RocketEventHandler.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/event/RocketEventHandler.java b/src/main/java/zmaster587/advancedRocketry/event/RocketEventHandler.java index a28d54afe..716da05de 100644 --- a/src/main/java/zmaster587/advancedRocketry/event/RocketEventHandler.java +++ b/src/main/java/zmaster587/advancedRocketry/event/RocketEventHandler.java @@ -13,6 +13,8 @@ import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.settings.GameSettings; import net.minecraft.entity.Entity; import net.minecraft.init.Blocks; import net.minecraft.inventory.EntityEquipmentSlot; @@ -38,6 +40,7 @@ import zmaster587.advancedRocketry.api.RocketEvent; import zmaster587.advancedRocketry.api.armor.IFillableArmor; import zmaster587.advancedRocketry.atmosphere.AtmosphereHandler; +import zmaster587.advancedRocketry.client.KeyBindings; import zmaster587.advancedRocketry.client.render.ClientDynamicTexture; import zmaster587.advancedRocketry.client.render.planet.RenderPlanetarySky; import zmaster587.advancedRocketry.dimension.DimensionManager; @@ -58,6 +61,7 @@ public class RocketEventHandler extends Gui { + private static final int getImgSize = 512; private static final int outerImgSize = getImgSize / 8; private static final int numTicksToDisplay = 100; @@ -141,6 +145,30 @@ public void onScreenRender(RenderGameOverlayEvent.Post event) { vertPos++; } } + // New bottom-right hint + Minecraft mc = Minecraft.getMinecraft(); + if (mc.currentScreen == null) { // no GUI open + FontRenderer fontRenderer = mc.fontRenderer; + String keyName = GameSettings.getKeyDisplayString( + KeyBindings.getOpenRocketUI().getKeyCode() + ); + String hint = I18n.format("msg.entity.rocket.openGuiHint", keyName); + + int scaledW = event.getResolution().getScaledWidth(); + int scaledH = event.getResolution().getScaledHeight(); + int textWidth = fontRenderer.getStringWidth(hint); + int textHeight = fontRenderer.FONT_HEIGHT; + + float scale = 1.0F; + float x = (scaledW - 4 - textWidth * scale) / scale; + float y = (scaledH - 4 - textHeight * scale) / scale; + + GL11.glPushMatrix(); + GL11.glScalef(scale, scale, scale); + fontRenderer.drawStringWithShadow(hint, x, y, 0xFFFFFF); + GL11.glPopMatrix(); + } + } //Draw the O2 Bar if needed From 850021abe9e6b85be31172bde2e8796ba1e0f04a Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 11:51:54 +0100 Subject: [PATCH 310/424] Clamp weather duration values to avoid exceptions --- .../world/provider/WorldProviderPlanet.java | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/world/provider/WorldProviderPlanet.java b/src/main/java/zmaster587/advancedRocketry/world/provider/WorldProviderPlanet.java index f71ef4689..64783da5e 100644 --- a/src/main/java/zmaster587/advancedRocketry/world/provider/WorldProviderPlanet.java +++ b/src/main/java/zmaster587/advancedRocketry/world/provider/WorldProviderPlanet.java @@ -147,13 +147,20 @@ public void updateWeather() { world.getWorldInfo().setRaining(true); } + // Clamp to avoid IllegalArgumentException in Random#nextInt(0 or negative) + final int thunderProlong = props.thunderProlongationLength > 0 ? props.thunderProlongationLength : 12000; + final int thunderStart = props.thunderStartLength > 0 ? props.thunderStartLength : 168000; + final int rainProlong = props.rainProlongationLength > 0 ? props.rainProlongationLength : 12000; + final int rainStart = props.rainStartLength > 0 ? props.rainStartLength : 168000; + + int k2 = world.getWorldInfo().getThunderTime(); if (k2 <= 0) { if (world.getWorldInfo().isThundering()) { - world.getWorldInfo().setThunderTime(world.rand.nextInt(getDimensionProperties().thunderProlongationLength) + 3600); + world.getWorldInfo().setThunderTime(world.rand.nextInt(thunderProlong) + 3600); } else { - world.getWorldInfo().setThunderTime(world.rand.nextInt(getDimensionProperties().thunderStartLength) + 12000); + world.getWorldInfo().setThunderTime(world.rand.nextInt(thunderStart) + 12000); } } else { --k2; @@ -168,9 +175,9 @@ public void updateWeather() { if (l2 <= 0) { if (world.getWorldInfo().isRaining()) { - world.getWorldInfo().setRainTime(world.rand.nextInt(getDimensionProperties().rainProlongationLength) + 12000); + world.getWorldInfo().setRainTime(world.rand.nextInt(rainProlong) + 12000); } else { - world.getWorldInfo().setRainTime(world.rand.nextInt(getDimensionProperties().rainStartLength) + 12000); + world.getWorldInfo().setRainTime(world.rand.nextInt(rainStart) + 12000); } } else { --l2; @@ -182,6 +189,7 @@ public void updateWeather() { } } + world.prevThunderingStrength = world.thunderingStrength; if (world.getWorldInfo().isThundering()) { From b7de8ea5d1aa84453944608f7da076945783db28 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 11:52:35 +0100 Subject: [PATCH 311/424] Improve world notification and weather data handling Added null check for world before notifying neighbors and updated weather info loading with key checks. --- .../dimension/DimensionProperties.java | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/dimension/DimensionProperties.java b/src/main/java/zmaster587/advancedRocketry/dimension/DimensionProperties.java index 4a3f7bfe6..645f70ad0 100644 --- a/src/main/java/zmaster587/advancedRocketry/dimension/DimensionProperties.java +++ b/src/main/java/zmaster587/advancedRocketry/dimension/DimensionProperties.java @@ -1082,7 +1082,9 @@ public void tick() { BlockPos p = i.pos.getBlockPos(); iterator_2.remove(); // Safe removal during iteration World world = (net.minecraftforge.common.DimensionManager.getWorld(getId())); - world.notifyNeighborsOfStateChange(p, world.getBlockState(p).getBlock(), false); + if (world != null) { + world.notifyNeighborsOfStateChange(p, world.getBlockState(p).getBlock(), false); + } } } @@ -1627,12 +1629,28 @@ public void readFromNBT(NBTTagCompound nbt) { volcanoFrequencyMultiplier = nbt.getFloat("volcanoFrequencyMultiplier"); // Custom weather info - rainStartLength = nbt.getInteger("rainStartLength"); - thunderStartLength = nbt.getInteger("thunderStartLength"); - rainProlongationLength = nbt.getInteger("rainProlongationLength"); - thunderProlongationLength = nbt.getInteger("thunderProlongationLength"); - rainMarker = nbt.getInteger("rainMarker"); - thunderMarker = nbt.getInteger("thunderMarker"); + if (nbt.hasKey("rainStartLength", NBT.TAG_INT)) + rainStartLength = nbt.getInteger("rainStartLength"); + if (nbt.hasKey("thunderStartLength", NBT.TAG_INT)) + thunderStartLength = nbt.getInteger("thunderStartLength"); + if (nbt.hasKey("rainProlongationLength", NBT.TAG_INT)) + rainProlongationLength = nbt.getInteger("rainProlongationLength"); + if (nbt.hasKey("thunderProlongationLength", NBT.TAG_INT)) + thunderProlongationLength = nbt.getInteger("thunderProlongationLength"); + + if (nbt.hasKey("rainMarker", NBT.TAG_INT)) + rainMarker = nbt.getInteger("rainMarker"); + if (nbt.hasKey("thunderMarker", NBT.TAG_INT)) + thunderMarker = nbt.getInteger("thunderMarker"); + + // Sanity clamp + if (rainStartLength <= 0) rainStartLength = 168000; + if (thunderStartLength <= 0) thunderStartLength = 168000; + if (rainProlongationLength <= 0) rainProlongationLength = 12000; + if (thunderProlongationLength <= 0) thunderProlongationLength = 12000; + // Clamp markers to documented range + rainMarker = MathHelper.clamp(rainMarker, -1, 1); + thunderMarker = MathHelper.clamp(thunderMarker, -1, 1); //Hierarchy From 70bb76424c4c31c8df13d09ae6860fd427d52f2c Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 11:54:04 +0100 Subject: [PATCH 312/424] Add crafting recipe for orbital registry --- .../recipes/orbitalregistry.json | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/main/resources/assets/advancedrocketry/recipes/orbitalregistry.json diff --git a/src/main/resources/assets/advancedrocketry/recipes/orbitalregistry.json b/src/main/resources/assets/advancedrocketry/recipes/orbitalregistry.json new file mode 100644 index 000000000..d628c62b7 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/orbitalregistry.json @@ -0,0 +1,45 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": + [ + "oso", + "cbc", + "rpr" + ], + "key": + { + "s": + { + "item": "advancedrocketry:misc", + "data": 0 + }, + "o": + { + "item": "advancedrocketry:satelliteprimaryfunction", + "data": 0 + }, + "b": + { + "item": "libvulpes:structuremachine" + }, + "c": + { + "type": "forge:ore_dict", + "ore": "stickCopper" + }, + "p": + { + "type": "forge:ore_dict", + "ore": "itemBattery" + }, + "r": + { + "item": "minecraft:comparator" + } + }, + "result": + { + "item": "advancedrocketry:orbitalregistry", + "count": 1 + } +} From c26e2a3fb7de375017d246ea90f693e7118acf3f Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 11:55:16 +0100 Subject: [PATCH 313/424] Fix typo in altitude variable name --- .../advancedRocketry/stations/SpaceStationObject.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/stations/SpaceStationObject.java b/src/main/java/zmaster587/advancedRocketry/stations/SpaceStationObject.java index fc6b65544..0be61dc0c 100644 --- a/src/main/java/zmaster587/advancedRocketry/stations/SpaceStationObject.java +++ b/src/main/java/zmaster587/advancedRocketry/stations/SpaceStationObject.java @@ -707,7 +707,7 @@ public void writeToNbt(NBTTagCompound nbt) { nbt.setInteger("posX", posX); nbt.setInteger("posY", posZ); nbt.setBoolean("created", created); - nbt.setInteger("alitude", altitude); + nbt.setInteger("altitude", altitude); nbt.setInteger("spawnX", spawnLocation.x); nbt.setInteger("spawnY", spawnLocation.y); nbt.setInteger("spawnZ", spawnLocation.z); From 73d0e900b448b6784520352723ed7d1813bbadd0 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 11:56:07 +0100 Subject: [PATCH 314/424] Fix typo in altitude variable name --- .../zmaster587/advancedRocketry/stations/SpaceObjectBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/stations/SpaceObjectBase.java b/src/main/java/zmaster587/advancedRocketry/stations/SpaceObjectBase.java index b20962060..b74086e33 100644 --- a/src/main/java/zmaster587/advancedRocketry/stations/SpaceObjectBase.java +++ b/src/main/java/zmaster587/advancedRocketry/stations/SpaceObjectBase.java @@ -254,7 +254,7 @@ public void writeToNbt(NBTTagCompound nbt) { nbt.setInteger("id", getId()); nbt.setInteger("posX", posX); nbt.setInteger("posY", posY); - nbt.setInteger("alitude", altitude); + nbt.setInteger("altitude", altitude); nbt.setInteger("spawnX", spawnLocation.x); nbt.setInteger("spawnY", spawnLocation.y); nbt.setInteger("spawnZ", spawnLocation.z); From 031f2dd62f0b272b8282e146d54cfe083a321e26 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:00:19 +0100 Subject: [PATCH 315/424] Add new block definitions for orbital registry and data bus --- .../zmaster587/advancedRocketry/api/AdvancedRocketryBlocks.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/api/AdvancedRocketryBlocks.java b/src/main/java/zmaster587/advancedRocketry/api/AdvancedRocketryBlocks.java index ad05c0b22..f56dd0119 100644 --- a/src/main/java/zmaster587/advancedRocketry/api/AdvancedRocketryBlocks.java +++ b/src/main/java/zmaster587/advancedRocketry/api/AdvancedRocketryBlocks.java @@ -109,4 +109,6 @@ public class AdvancedRocketryBlocks { public static Block blockRocketFire; public static Block blockServiceMonitor; public static Block blockInvHatch; + public static Block blockOrbitalRegistry; + public static Block blockDataBusBig; } From 3cb68f364e7313c182392eb56ecd3cbb36af1ad5 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:01:11 +0100 Subject: [PATCH 316/424] Add databusbig.json model file --- .../assets/advancedrocketry/models/item/databusbig.json | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 src/main/resources/assets/advancedrocketry/models/item/databusbig.json diff --git a/src/main/resources/assets/advancedrocketry/models/item/databusbig.json b/src/main/resources/assets/advancedrocketry/models/item/databusbig.json new file mode 100644 index 000000000..28454a208 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/models/item/databusbig.json @@ -0,0 +1,3 @@ +{ + "parent": "advancedrocketry:block/databusbig" +} From 2d1c89f690fa1509ab1465639b520175a683189e Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:02:00 +0100 Subject: [PATCH 317/424] Add databusbig.json model for data hatch block --- .../assets/advancedrocketry/models/block/databusbig.json | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/main/resources/assets/advancedrocketry/models/block/databusbig.json diff --git a/src/main/resources/assets/advancedrocketry/models/block/databusbig.json b/src/main/resources/assets/advancedrocketry/models/block/databusbig.json new file mode 100644 index 000000000..cf285526e --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/models/block/databusbig.json @@ -0,0 +1,6 @@ +{ + "parent": "block/cube_all", + "textures": { + "all": "advancedrocketry:blocks/dataHatchbig" + } +} From 253626bd401d0d31636712c34f5fb95ba57b7f14 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:03:08 +0100 Subject: [PATCH 318/424] Add TileDataBusBig class with increased capacity --- .../tile/hatch/TileDataBusBig.java | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/tile/hatch/TileDataBusBig.java diff --git a/src/main/java/zmaster587/advancedRocketry/tile/hatch/TileDataBusBig.java b/src/main/java/zmaster587/advancedRocketry/tile/hatch/TileDataBusBig.java new file mode 100644 index 000000000..e8854bba9 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/tile/hatch/TileDataBusBig.java @@ -0,0 +1,39 @@ +package zmaster587.advancedRocketry.tile.hatch; + +import net.minecraft.nbt.NBTTagCompound; + +public class TileDataBusBig extends TileDataBus { + + private static final int MULT = 4; + + public TileDataBusBig() { + super(); + enforceBigCapacity(); + } + + public TileDataBusBig(int number) { + super(number); + enforceBigCapacity(); + } + + private void enforceBigCapacity() { + int max = BASE_MAX_DATA * MULT; + + this.data.setMaxData(max); + + if (this.data.getData() > max) { + this.data.setData(max, this.data.getDataType()); + } + } + + @Override + public String getModularInventoryName() { + return "tile.databusbig.name"; + } + + @Override + protected void readFromNBTHelper(NBTTagCompound nbtTagCompound) { + super.readFromNBTHelper(nbtTagCompound); + enforceBigCapacity(); + } +} From 14a239412485c23fd4a86bbb439d351e05313d0d Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:04:19 +0100 Subject: [PATCH 319/424] Add files via upload --- .../textures/blocks/datahatchbig.png | Bin 0 -> 2591 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/main/resources/assets/advancedrocketry/textures/blocks/datahatchbig.png diff --git a/src/main/resources/assets/advancedrocketry/textures/blocks/datahatchbig.png b/src/main/resources/assets/advancedrocketry/textures/blocks/datahatchbig.png new file mode 100644 index 0000000000000000000000000000000000000000..add83418e7cdc9b00b0ff6bf391c125ccebcb108 GIT binary patch literal 2591 zcmY*ac|6ox8~5p zWy*Fb_gX^67V1WWWV@lbDrhJ&{<%oo3 zjG1$n!{dwbd}S{FZy1Zi5Px4Q$ICL@<8ic;DVIRU{k&u^bDMqU?D};GIb>nIf5p*X zM3ovkl|k8&qpSgC4%mEgNzQZAy4scWyn)(8hAWrwOF$v9|CJU_Q6;Tr;gg(k`-~!0 z;=A7No49VE#LDO;ctputxp=ZcU~sPs<&t}8o;2@}qhYn*7v8;~H>h}*yI4y1={p<#G2mYuvs}cfPG`wr#fJ&gfw6kpS6d~k^WrIuH)O??|q#) zx$Hmn>yk5%x%4yd5=QVf+GQVzr}wr#FELW;Y-4rbPI3b%yG~X{uIcpaf!Ifpr469r zC-8!;q9(uNv<{6jIW-7@1tw_Wkrb znrRZ?4S5FZ!$l*xl*SUp`&{%3M@BD+-*Moxl;|9P8~VPhsQLBzcX0;N_<4sEu^}gk z7>nEYK_78qtMlQb;&Uk)rO64-5f$*`#n%@$UG+Oj*gQV8=J~rP`P8by{Q5vfqcKW!up46N(yGcmuy3WA;v7~hg1sg~M9yCqzscolP<%a@al zYHD_+1F9;+IPc`+bMph+Z%TMB&v}eblbK#S@Xd*lq{;JJWl=HGA)^=t9oBx5G<~Kv zU+IcwUne**2_?S@;*f6uzjF3LW90QTog6a7T{Mw~b(K}3hETdKy1vMsMd*u;KVh(; zPWYlhJXgABxu`@KWpOttKYSAwbT?_D|AmNCc~-P~Q|1|Zy|Pl-P*02Mfk%g4=9udr z7o4pppA_HbKQ{^2nqzQOI1r@tZdQIXMRu%3)Y2)faX;yK_4hnsyiFP*H%65SlUV&} zkVaX3wGt<T3$fcS3l;8 z3@%${DeO7!*u;-)f=RO|i5iCT;$(MAcw}64zqs9{)j1Xj{@!K8m0`K{AQqBPnG9J^ z#HE)%PyQgppa-72;h7;hY;P8&m$2z1?0UV|Q@h|eVDx zPUmo~!rqy>_yeASU&2_~QT5C)K{?6-t#;ZX5=t^0@LV9g_8)G2^-bmDW@^h<6dH~W zm{c6z74?x8xgMK1#w_ZcTM9c!XX?j?)r1#TelkR#0K-#SEqNcOhTY=hthx6zz+(KV z-&kxvM1LbyYcn|(UbH@i;yv%jow`l;zMVoL}Z$qe+$V?Q?qEw@EjS)pXuw> z$(@l4TY{EmPnU$&GPDr4rjcpsytQth;W@0E$ajg~-Pz?w>MS&doePx9Dch*BS|_?p zi9${?bROi&2?mrW@Eff{lpU5jE2l6*3R@oG$sd)DHASZch`3fXm;~bOnnZ=39{civ zm0%tsr=EN+>x9FFo$oM$!JV9g4C`H&z1VE;fLY9@nZHNs)$JD_CDwSvYPgcC-&g!& zG+s?6>yL@2r}ey<)$;tNYe5){?wvNAm)eX)Lc0$h2mwL@7RkAW+@ z>ey=9h9a>3c&i8^)+xfy866RbHoz#G7z^+jQDJNk!B{d%o*EoPAi=0`g})uc*!m$1 zQ7|?lVsJ1=^YcG;uvc&ee=<1~27yp06b*{DMhMXl0yQu&fM{w#w6xUOJJd-V z)vu*nsW@1R3-0&N>wkFn{Z13*puk58b7F(DWgPoyOJD$qVa0XN+lVETCC>1s)W*b@T&WE5ie=X!8{C!`M7Ix+}Kl{Y}1-2%acmMzZ literal 0 HcmV?d00001 From f636a9473e5a4dea998c42eaa84a878a6aa21b03 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:05:03 +0100 Subject: [PATCH 320/424] Add Big Data Bus Block and related registrations --- .../advancedRocketry/AdvancedRocketry.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/AdvancedRocketry.java b/src/main/java/zmaster587/advancedRocketry/AdvancedRocketry.java index ffb6b7127..93e38a8a7 100644 --- a/src/main/java/zmaster587/advancedRocketry/AdvancedRocketry.java +++ b/src/main/java/zmaster587/advancedRocketry/AdvancedRocketry.java @@ -58,6 +58,7 @@ import zmaster587.advancedRocketry.block.*; import zmaster587.advancedRocketry.block.inventory.BlockInvHatch; import zmaster587.advancedRocketry.block.multiblock.BlockARHatch; +import zmaster587.advancedRocketry.block.multiblock.BlockDataBusBig; import zmaster587.advancedRocketry.block.plant.BlockLightwoodLeaves; import zmaster587.advancedRocketry.block.plant.BlockLightwoodPlanks; import zmaster587.advancedRocketry.block.plant.BlockLightwoodSapling; @@ -95,6 +96,7 @@ import zmaster587.advancedRocketry.tile.cables.TileLiquidPipe; import zmaster587.advancedRocketry.tile.cables.TileWirelessTransciever; import zmaster587.advancedRocketry.tile.hatch.TileDataBus; +import zmaster587.advancedRocketry.tile.hatch.TileDataBusBig; import zmaster587.advancedRocketry.tile.hatch.TileInvHatch; import zmaster587.advancedRocketry.tile.hatch.TileSatelliteHatch; import zmaster587.advancedRocketry.tile.infrastructure.*; @@ -374,6 +376,7 @@ public void preInit(FMLPreInitializationEvent event) { GameRegistry.registerTileEntity(TileCrystallizer.class, "ARcrystallizer"); GameRegistry.registerTileEntity(TileCuttingMachine.class, "ARcuttingmachine"); GameRegistry.registerTileEntity(TileDataBus.class, "ARdataBus"); + GameRegistry.registerTileEntity(TileDataBusBig.class, "ARdataBusBig"); GameRegistry.registerTileEntity(TileSatelliteHatch.class, "ARsatelliteHatch"); GameRegistry.registerTileEntity(TileInvHatch.class, "ARinventoryHatch"); GameRegistry.registerTileEntity(TileGuidanceComputerAccessHatch.class, "ARguidanceComputerHatch"); @@ -427,6 +430,7 @@ public void preInit(FMLPreInitializationEvent event) { GameRegistry.registerTileEntity(TileCentrifuge.class, new ResourceLocation(Constants.modId, "ARCentrifuge")); GameRegistry.registerTileEntity(TilePrecisionLaserEtcher.class, new ResourceLocation(Constants.modId, "ARPrecisionLaserEtcher")); GameRegistry.registerTileEntity(TileSolarArray.class, new ResourceLocation(Constants.modId, "ARSolarArray")); + GameRegistry.registerTileEntity(TileOrbitalRegistry.class, new ResourceLocation(Constants.modId, "orbitalRegistry")); if (zmaster587.advancedRocketry.api.ARConfiguration.getCurrentConfig().enableGravityController) GameRegistry.registerTileEntity(TileAreaGravityController.class, "ARGravityMachine"); @@ -649,6 +653,7 @@ public void registerBlocks(RegistryEvent.Register evt) { AdvancedRocketryBlocks.blockPlanetAnalyser = new BlockMultiblockMachine(TileAstrobodyDataProcessor.class, GuiHandler.guiId.MODULARNOINV.ordinal()).setUnlocalizedName("planetanalyser").setCreativeTab(tabAdvRocketry).setHardness(3f); AdvancedRocketryBlocks.blockCentrifuge = new BlockMultiblockMachine(TileCentrifuge.class, GuiHandler.guiId.MODULAR.ordinal()).setCreativeTab(tabAdvRocketry).setHardness(3f).setUnlocalizedName("centrifuge"); AdvancedRocketryBlocks.blockSatelliteBuilder = new BlockMultiblockMachine(TileSatelliteBuilder.class, GuiHandler.guiId.MODULAR.ordinal()).setCreativeTab(tabAdvRocketry).setHardness(3f).setUnlocalizedName("satelliteBuilder"); + //Energy AdvancedRocketryBlocks.blockBlackHoleGenerator = new BlockMultiblockMachine(TileBlackHoleGenerator.class, GuiHandler.guiId.MODULAR.ordinal()).setUnlocalizedName("blackholegenerator").setCreativeTab(tabAdvRocketry).setHardness(3f); AdvancedRocketryBlocks.blockMicrowaveReciever = new BlockMultiblockMachine(TileMicrowaveReciever.class, GuiHandler.guiId.MODULAR.ordinal()).setCreativeTab(tabAdvRocketry).setHardness(3f).setUnlocalizedName("microwaveReciever"); @@ -667,6 +672,11 @@ public void registerBlocks(RegistryEvent.Register evt) { AdvancedRocketryBlocks.blockGravityMachine = new BlockMultiblockMachine(TileAreaGravityController.class, GuiHandler.guiId.MODULARNOINV.ordinal()).setUnlocalizedName("gravityMachine").setCreativeTab(tabAdvRocketry).setHardness(3f); if (ARConfiguration.getCurrentConfig().enableLaserDrill) AdvancedRocketryBlocks.blockSpaceLaser = new BlockOrbitalLaserDrill().setHardness(2f).setCreativeTab(tabAdvRocketry); + if (ARConfiguration.getCurrentConfig().enableOrbitalRegistry) + AdvancedRocketryBlocks.blockOrbitalRegistry = new BlockMultiblockMachine(TileOrbitalRegistry.class, GuiHandler.guiId.MODULARNOINV.ordinal()).setCreativeTab(tabAdvRocketry).setHardness(3f).setUnlocalizedName("orbitalRegistry"); + + + //Docking blocks AdvancedRocketryBlocks.blockLaunchpad = new BlockLinkedHorizontalTexture(Material.ROCK).setUnlocalizedName("pad").setCreativeTab(tabAdvRocketry).setHardness(2f).setResistance(10f); AdvancedRocketryBlocks.blockLandingPad = new BlockLandingPad(Material.ROCK).setUnlocalizedName("dockingPad").setHardness(3f).setCreativeTab(tabAdvRocketry); @@ -695,11 +705,14 @@ public void registerBlocks(RegistryEvent.Register evt) { AdvancedRocketryBlocks.blockDeployableRocketBuilder = new BlockTileWithMultitooltip(TileUnmannedVehicleAssembler.class, GuiHandler.guiId.MODULARNOINV.ordinal()).setUnlocalizedName("deployableRocketAssembler").setCreativeTab(tabAdvRocketry).setHardness(3f); //Infrastructure machines AdvancedRocketryBlocks.blockLoader = new BlockARHatch(Material.IRON).setUnlocalizedName("loader").setCreativeTab(tabAdvRocketry).setHardness(3f); + // Big Data Bus Hatch + AdvancedRocketryBlocks.blockDataBusBig = new BlockDataBusBig(Material.IRON).setUnlocalizedName("databusbig").setCreativeTab(tabAdvRocketry).setHardness(3f); AdvancedRocketryBlocks.blockFuelingStation = new BlockTileRedstoneEmitter(TileFuelingStation.class, GuiHandler.guiId.MODULAR.ordinal()).setUnlocalizedName("fuelStation").setCreativeTab(tabAdvRocketry).setHardness(3f); AdvancedRocketryBlocks.blockMonitoringStation = new BlockTileNeighborUpdate(TileRocketMonitoringStation.class, GuiHandler.guiId.MODULARNOINV.ordinal()).setCreativeTab(tabAdvRocketry).setHardness(3f).setUnlocalizedName("monitoringstation"); AdvancedRocketryBlocks.blockSatelliteControlCenter = new BlockTile(TileSatelliteTerminal.class, GuiHandler.guiId.MODULAR.ordinal()).setCreativeTab(tabAdvRocketry).setHardness(3f).setUnlocalizedName("satelliteMonitor"); AdvancedRocketryBlocks.blockTerraformingTerminal = new BlockTileTerraformer(TileTerraformingTerminal.class, GuiHandler.guiId.MODULAR.ordinal()).setCreativeTab(tabAdvRocketry).setHardness(3f).setUnlocalizedName("terraformingTerminal"); AdvancedRocketryBlocks.blockServiceStation = new BlockTile(TileRocketServiceStation.class, GuiHandler.guiId.MODULARNOINV.ordinal()).setCreativeTab(tabAdvRocketry).setHardness(3f).setUnlocalizedName("serviceStation"); + //Station machines AdvancedRocketryBlocks.blockWarpShipMonitor = new BlockWarpController(TileWarpController.class, GuiHandler.guiId.MODULARNOINV.ordinal()).setCreativeTab(tabAdvRocketry).setHardness(3f).setUnlocalizedName("stationmonitor"); @@ -823,6 +836,7 @@ public void registerBlocks(RegistryEvent.Register evt) { LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockPlanetAnalyser.setRegistryName("planetAnalyser")); LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockCentrifuge.setRegistryName("centrifuge")); LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockSatelliteBuilder.setRegistryName("satelliteBuilder")); + //Energy LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockBlackHoleGenerator.setRegistryName("blackholegenerator")); LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockMicrowaveReciever.setRegistryName("microwaveReciever")); @@ -840,6 +854,7 @@ public void registerBlocks(RegistryEvent.Register evt) { LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockGravityMachine.setRegistryName("gravityMachine")); if (zmaster587.advancedRocketry.api.ARConfiguration.getCurrentConfig().enableLaserDrill) LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockSpaceLaser.setRegistryName("spaceLaser")); + //Docking blocks LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockLaunchpad.setRegistryName("launchpad")); LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockLandingPad.setRegistryName("landingPad")); @@ -868,10 +883,14 @@ public void registerBlocks(RegistryEvent.Register evt) { LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockDeployableRocketBuilder.setRegistryName("deployableRocketBuilder")); //Infrastructure machines LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockLoader.setRegistryName("loader"), ItemBlockMeta.class, false); + LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockDataBusBig.setRegistryName("databusbig"), zmaster587.advancedRocketry.item.ItemBlockDataBusBig.class, true); LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockServiceStation.setRegistryName("serviceStation")); LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockFuelingStation.setRegistryName("fuelingStation")); LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockMonitoringStation.setRegistryName("monitoringStation")); LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockSatelliteControlCenter.setRegistryName("satelliteControlCenter")); + if (ARConfiguration.getCurrentConfig().enableOrbitalRegistry) + LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockOrbitalRegistry.setRegistryName("orbitalRegistry")); + LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockTerraformingTerminal.setRegistryName("terraformingTerminal")); //Station machines LibVulpesBlocks.registerBlock(AdvancedRocketryBlocks.blockWarpShipMonitor.setRegistryName("warpMonitor")); @@ -1039,6 +1058,7 @@ public void load(FMLInitializationEvent event) { List list = new LinkedList<>(); list.add(new BlockMeta(AdvancedRocketryBlocks.blockLoader, 0)); list.add(new BlockMeta(AdvancedRocketryBlocks.blockLoader, 8)); + list.add(new BlockMeta(AdvancedRocketryBlocks.blockDataBusBig, 0)); TileMultiBlock.addMapping('D', list); machineRecipes.createAutoGennedRecipes(modProducts); From 8cb9f323ea9acdcc2934a5431cbf5ceeaef910f2 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:06:43 +0100 Subject: [PATCH 321/424] Remove TODO comment in addFuelAmount method Removed TODO comment for adding fuel types in addFuelAmount method. --- src/main/java/zmaster587/advancedRocketry/api/StatsRocket.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/api/StatsRocket.java b/src/main/java/zmaster587/advancedRocketry/api/StatsRocket.java index eb292e2b0..83beafcd4 100644 --- a/src/main/java/zmaster587/advancedRocketry/api/StatsRocket.java +++ b/src/main/java/zmaster587/advancedRocketry/api/StatsRocket.java @@ -502,7 +502,6 @@ public void setFuelCapacity(@Nonnull FuelRegistry.FuelType type, int amt) { * @return amount of fuel added */ public int addFuelAmount(@Nonnull FuelRegistry.FuelType type, int amt) { - //TODO: finish other ones switch (type) { case WARP: int maxAddWarp = fuelCapacityWarp - fuelWarp; From 8537f269bbaaf12d17bb49a5064d7b314de6dbef Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:07:26 +0100 Subject: [PATCH 322/424] Add BlockDataBusBig class for data bus functionality --- .../block/multiblock/BlockDataBusBig.java | 106 ++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/block/multiblock/BlockDataBusBig.java diff --git a/src/main/java/zmaster587/advancedRocketry/block/multiblock/BlockDataBusBig.java b/src/main/java/zmaster587/advancedRocketry/block/multiblock/BlockDataBusBig.java new file mode 100644 index 000000000..2bf42f37a --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/block/multiblock/BlockDataBusBig.java @@ -0,0 +1,106 @@ +package zmaster587.advancedRocketry.block.multiblock; + +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.stats.StatList; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.NonNullList; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import zmaster587.advancedRocketry.api.DataStorage; +import zmaster587.advancedRocketry.tile.hatch.TileDataBusBig; + +public class BlockDataBusBig extends BlockARHatch { + + public BlockDataBusBig(Material material) { + super(material); + } + + @Override + public void getSubBlocks(CreativeTabs tab, NonNullList list) { + list.add(new ItemStack(this, 1, 0)); + } + + @Override + public boolean hasTileEntity(IBlockState state) { + return true; + } + + @Override + public TileEntity createTileEntity(World world, IBlockState state) { + return new TileDataBusBig(2); + } + + /** + * Builds the dropped ItemStack. + * IMPORTANT: + * - Only attach NBT if we actually have stored data. + * This allows empty blocks to stack normally. + */ + private ItemStack makeDataStack(IBlockAccess world, BlockPos pos) { + ItemStack stack = new ItemStack(this, 1, 0); + + TileEntity te = world.getTileEntity(pos); + if (te instanceof TileDataBusBig) { + TileDataBusBig bus = (TileDataBusBig) te; + + DataStorage storage = bus.getDataObject(); + if (storage != null && storage.getData() > 0) { + NBTTagCompound tag = new NBTTagCompound(); + storage.writeToNBT(tag); + stack.setTagCompound(tag); + } + } + + return stack; + } + + @Override + public void getDrops(NonNullList drops, IBlockAccess world, BlockPos pos, + IBlockState state, int fortune) { + drops.add(makeDataStack(world, pos)); + } + + @Override + public ItemStack getItem(World worldIn, BlockPos pos, IBlockState state) { + return makeDataStack(worldIn, pos); + } + + /** + * Robust TE harvest pattern for 1.12: + * - If willHarvest, delay removal so harvestBlock can run with TE intact. + */ + @Override + public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, + EntityPlayer player, boolean willHarvest) { + if (willHarvest) { + return true; // harvestBlock will handle drops, then we remove block there + } + return super.removedByPlayer(state, world, pos, player, false); + } + + /** + * Force our custom drop and then remove the block. + * This sidesteps parent hatch drop logic. + */ + @Override + public void harvestBlock(World worldIn, EntityPlayer player, BlockPos pos, + IBlockState state, TileEntity te, ItemStack tool) { + + player.addStat(StatList.getBlockStats(this)); + player.addExhaustion(0.005F); + + if (!worldIn.isRemote) { + spawnAsEntity(worldIn, pos, makeDataStack(worldIn, pos)); + } + + // Now actually remove the block + worldIn.setBlockToAir(pos); + } +} From 592778cb11f5f7c44c32d93b83c6610df9fb5b06 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:07:57 +0100 Subject: [PATCH 323/424] Update fluid tank tooltip localization --- .../advancedRocketry/item/ItemBlockFluidTank.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java b/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java index 2f05015fd..c3941398c 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemBlockFluidTank.java @@ -52,11 +52,12 @@ public void addInformation(@Nonnull ItemStack stack, @Nullable World world, List final int capMb = getCapMb(); final FluidStack fs = getFluid(stack); - final String fluidName = (fs != null && fs.getFluid() != null) ? fs.getLocalizedName() : "Empty"; + final String fluidName = (fs != null && fs.getFluid() != null) ? fs.getLocalizedName() : I18n.format("tooltip.advancedrocketry.fluidtank.empty");; final int amount = (fs != null) ? fs.amount : 0; - list.add("Fluid: " + fluidName); - list.add("Level: " + amount + "/" + capMb + " mB"); + list.add(I18n.format("tooltip.advancedrocketry.fluidtank.fluid") + fluidName); + list.add(I18n.format("tooltip.advancedrocketry.fluidtank.level") + amount + "/" + capMb + " mB"); + // --- SHIFT for more info --- if (GuiScreen.isShiftKeyDown()) { From a3b1eda625416715a361bb319a43e1087ae6e6b2 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:08:33 +0100 Subject: [PATCH 324/424] Update fluid name localization in ItemPressureTank --- .../item/components/ItemPressureTank.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java b/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java index 163ace625..84d8edfc9 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java +++ b/src/main/java/zmaster587/advancedRocketry/item/components/ItemPressureTank.java @@ -52,13 +52,13 @@ public void addInformation(@Nonnull ItemStack stack, @Nullable World world, final int capMb = Math.max(0, getCapacity(stack)); final net.minecraftforge.fluids.FluidStack fs = zmaster587.libVulpes.util.FluidUtils.getFluidForItem(stack); - final String fluidName = (fs != null && fs.getFluid() != null) ? fs.getLocalizedName() : "Empty"; + final String fluidName = (fs != null && fs.getFluid() != null) ? fs.getLocalizedName() : I18n.format("tooltip.advancedrocketry.fluidtank.empty"); final int amount = (fs != null) ? fs.amount : 0; // Match main tank style - list.add(TextFormatting.DARK_PURPLE + "Space Suit Component"); - list.add("Fluid: " + fluidName); - list.add("Level: " + amount + "/" + capMb + " mB"); + list.add(I18n.format("tooltip.advancedrocketry.itemdata.header")); + list.add(I18n.format("tooltip.advancedrocketry.fluidtank.fluid") + fluidName); + list.add(I18n.format("tooltip.advancedrocketry.fluidtank.level") + amount + "/" + capMb + " mB"); // SHIFT block if (GuiScreen.isShiftKeyDown()) { From a2bb01891bfb6113ddb737ff062b8a71c37c54a7 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:09:13 +0100 Subject: [PATCH 325/424] Update button labels and remove unused variables --- .../tile/infrastructure/TileRocketMonitoringStation.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java index 8630d1b6c..4583bf22d 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java @@ -370,7 +370,7 @@ public boolean linkRocket(EntityRocketBase rocket) { if (!world.isRemote) { final int dim = rocket.world.provider.getDimension(); final int eid = rocket.getEntityId(); - final double rx = rocket.posX, ry = rocket.posY, rz = rocket.posZ; + // final double rx = rocket.posX, ry = rocket.posY, rz = rocket.posZ; final zmaster587.advancedRocketry.api.fuel.FuelRegistry.FuelType ft = rocket.getRocketFuelType(); @@ -751,7 +751,7 @@ public List getModules(int ID, EntityPlayer player) { if (tabModule.getTab() == 0) { // === STATUS TAB === - modules.add(new ModuleButton(20, 40, 0, "Launch!", this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); + modules.add(new ModuleButton(20, 40, 0, LibVulpes.proxy.getLocalizedString("msg.monitoringStation.buttonLaunch"), this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); if (world.isRemote) { launchStatus = new ModuleText(88, 92, "", 0xFFFFFF22, true); // centered From ae07e8c740e036d529534fa0ff072acd09eb7850 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:10:47 +0100 Subject: [PATCH 326/424] Localize 'Research' text in TileAstrobodyDataProcessor --- .../tile/multiblock/TileAstrobodyDataProcessor.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileAstrobodyDataProcessor.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileAstrobodyDataProcessor.java index f80127fd1..8a7883e3b 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileAstrobodyDataProcessor.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileAstrobodyDataProcessor.java @@ -411,7 +411,8 @@ public List getModules(int ID, EntityPlayer player) { int xStart = 150; int yStart = 14; - modules.add(new ModuleText(15, 76, "Research", 0x404040)); + modules.add(new ModuleText(15, 76, LibVulpes.proxy.getLocalizedString("msg.abdp.research"), 0x404040)); + modules.add(new ModuleToggleSwitch(15, 86, 4, "", this, zmaster587.libVulpes.inventory.TextureResources.buttonToggleImage, LibVulpes.proxy.getLocalizedString("msg.abdp.compositionresearch"), 11, 26, researchingAtmosphere)); modules.add(new ModuleToggleSwitch(65, 86, 5, "", this, zmaster587.libVulpes.inventory.TextureResources.buttonToggleImage, LibVulpes.proxy.getLocalizedString("msg.abdp.distanceresearch"), 11, 26, researchingDistance)); From 9d68574f4ed39837c62f379c613e36022f229cae Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:11:40 +0100 Subject: [PATCH 327/424] Update weather controller mode descriptions --- .../advancedRocketry/item/ItemWeatherController.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemWeatherController.java b/src/main/java/zmaster587/advancedRocketry/item/ItemWeatherController.java index e29e11504..9e10b0079 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemWeatherController.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemWeatherController.java @@ -75,16 +75,16 @@ public void addInformation(@Nonnull ItemStack stack, World world, List l } else if (mapping.getDimensionId() == world.provider.getDimension()) { list.add(LibVulpes.proxy.getLocalizedString("msg.connected")); if (mapping.mode_id == 0) - list.add("Mode: Rain - Fills small basins in the terrain with water"); + list.add(LibVulpes.proxy.getLocalizedString("tooltip.advancedrocketry.weathercontrollerremote.mode.rain")); if (mapping.mode_id == 1) - list.add("Mode: Dry - Drys all water in a radius of 16"); + list.add(LibVulpes.proxy.getLocalizedString("tooltip.advancedrocketry.weathercontrollerremote.mode.dry")); if (mapping.mode_id == 2) - list.add("Mode: Flood - Floods area with a radius of 16 with water"); + list.add(LibVulpes.proxy.getLocalizedString("tooltip.advancedrocketry.weathercontrollerremote.mode.flood")); } else { list.add(LibVulpes.proxy.getLocalizedString("msg.notconnected")); } - // Still let the parent add its usual info (except "unprogrammed", which we handled above) + // Still let the parent add its usual info super.addInformation(stack, world, list, flag); } From e3fdd53c5ccb139f0b347cbc601a1a6f47ee8969 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:12:21 +0100 Subject: [PATCH 328/424] Update tooltip for station chip location display --- .../zmaster587/advancedRocketry/item/ItemStationChip.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemStationChip.java b/src/main/java/zmaster587/advancedRocketry/item/ItemStationChip.java index 0380cd43b..671c79531 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemStationChip.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemStationChip.java @@ -359,11 +359,11 @@ public void addInformation(@Nonnull ItemStack stack, World player, List LandingLocation loc = getTakeoffCoords(stack, spaceObject.getOrbitingPlanetId()); if (loc != null) { Vector3F vec = loc.location; - list.add("Name: " + loc.name); + list.add(LibVulpes.proxy.getLocalizedString("tooltip.advancedrocketry.stationchip.namelabel") + loc.name); list.add("X: " + vec.x); list.add("Z: " + vec.z); } else { - list.add("Name: N/A"); + list.add(LibVulpes.proxy.getLocalizedString("tooltip.advancedrocketry.stationchip.namelabel") + "N/A"); list.add("X: N/A"); list.add("Z: N/A"); } @@ -372,11 +372,11 @@ public void addInformation(@Nonnull ItemStack stack, World player, List LandingLocation loc = getTakeoffCoords(stack, player.provider.getDimension()); if (loc != null) { Vector3F vec = loc.location; - list.add("Name: " + loc.name); + list.add(LibVulpes.proxy.getLocalizedString("tooltip.advancedrocketry.stationchip.namelabel") + loc.name); list.add("X: " + vec.x); list.add("Z: " + vec.z); } else { - list.add("Name: N/A"); + list.add(LibVulpes.proxy.getLocalizedString("tooltip.advancedrocketry.stationchip.namelabel") + "N/A"); list.add("X: N/A"); list.add("Z: N/A"); } From a1e7d5a38ba6201d5c26c117fb4468522b481ddc Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:13:01 +0100 Subject: [PATCH 329/424] Implement IDataItem interface in ItemData class --- .../advancedRocketry/item/ItemData.java | 67 ++++++++++++------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemData.java b/src/main/java/zmaster587/advancedRocketry/item/ItemData.java index 4de0f0af9..010ea3d4e 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemData.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemData.java @@ -1,6 +1,5 @@ package zmaster587.advancedRocketry.item; -import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.resources.I18n; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.item.ItemStack; @@ -14,22 +13,26 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; - import java.util.List; -public class ItemData extends ItemIngredient { - - int maxData; +public class ItemData extends ItemIngredient implements IDataItem { public ItemData() { super(1); setMaxStackSize(1); } + // ---- OLD API (keep) ---- public int getMaxData(int damage) { return damage == 0 ? 1000 : 0; } + // ---- NEW API (IDataItem) ---- + @Override + public int getMaxData(@Nonnull ItemStack stack) { + return getMaxData(stack.getItemDamage()); + } + @Override public int getItemStackLimit(@Nonnull ItemStack stack) { return getData(stack) == 0 ? super.getItemStackLimit(stack) : 1; @@ -43,21 +46,29 @@ public DataStorage.DataType getDataType(@Nonnull ItemStack stack) { return getDataStorage(stack).getDataType(); } + @Override + @Nonnull public DataStorage getDataStorage(@Nonnull ItemStack item) { DataStorage data = new DataStorage(); if (!item.hasTagCompound()) { - data.setMaxData(getMaxData(item.getItemDamage())); + data.setMaxData(getMaxData(item)); NBTTagCompound nbt = new NBTTagCompound(); data.writeToNBT(nbt); - } else + // NOTE: original ItemData does NOT auto-attach tag here. + // Keep behavior to avoid subtle side effects. + } else { data.readFromNBT(item.getTagCompound()); + // make sure capacity is correct for this item + data.setMaxData(getMaxData(item)); + } return data; } - public int addData(@Nonnull ItemStack item, int amount, DataStorage.DataType dataType) { + @Override + public int addData(@Nonnull ItemStack item, int amount, @Nonnull DataStorage.DataType dataType) { DataStorage data = getDataStorage(item); int amt = data.addData(amount, dataType, true); @@ -69,7 +80,8 @@ public int addData(@Nonnull ItemStack item, int amount, DataStorage.DataType dat return amt; } - public int removeData(@Nonnull ItemStack item, int amount, DataStorage.DataType dataType) { + @Override + public int removeData(@Nonnull ItemStack item, int amount, @Nonnull DataStorage.DataType dataType) { DataStorage data = getDataStorage(item); int amt = data.removeData(amount, true); @@ -81,7 +93,8 @@ public int removeData(@Nonnull ItemStack item, int amount, DataStorage.DataType return amt; } - public void setData(@Nonnull ItemStack item, int amount, DataStorage.DataType dataType) { + @Override + public void setData(@Nonnull ItemStack item, int amount, @Nonnull DataStorage.DataType dataType) { DataStorage data = getDataStorage(item); data.setData(amount, dataType); @@ -93,29 +106,31 @@ public void setData(@Nonnull ItemStack item, int amount, DataStorage.DataType da @Override @SideOnly(Side.CLIENT) - public void addInformation(@Nonnull ItemStack stack, @Nullable World world, List list, ITooltipFlag flag) { + public void addInformation(@Nonnull ItemStack stack, @Nullable World world, + List list, ITooltipFlag flag) { super.addInformation(stack, world, list, flag); DataStorage data = getDataStorage(stack); - // Type: - list.add(TextFormatting.DARK_PURPLE + "Space Suit Component"); - String typeText = net.minecraft.client.resources.I18n.format(data.getDataType().toString()); - list.add(net.minecraft.util.text.TextFormatting.WHITE + "Type: " + typeText); + // Type: + list.add(I18n.format("tooltip.advancedrocketry.itemdata.header")); + String typeText = I18n.format(data.getDataType().toString()); + list.add(I18n.format("tooltip.advancedrocketry.itemdata.type") + typeText); + // Data: - list.add(net.minecraft.util.text.TextFormatting.WHITE + "Data stored: " - + net.minecraft.util.text.TextFormatting.GOLD + data.getData() - + net.minecraft.util.text.TextFormatting.WHITE + " / " - + net.minecraft.util.text.TextFormatting.GOLD + data.getMaxData()); + list.add(I18n.format("tooltip.advancedrocketry.itemdata.data") + + TextFormatting.GOLD + data.getData() + + TextFormatting.WHITE + " / " + + TextFormatting.GOLD + data.getMaxData()); - // Hold Shift for more info + // Hold Shift: if (net.minecraft.client.gui.GuiScreen.isShiftKeyDown()) { - list.add(net.minecraft.util.text.TextFormatting.GRAY + - net.minecraft.client.resources.I18n.format("tooltip.advancedrocketry.itemdataunit.shift.1")); - } else if (net.minecraft.client.resources.I18n.hasKey("tooltip.advancedrocketry.hold_shift")) { - list.add(net.minecraft.util.text.TextFormatting.DARK_GRAY.toString() + - net.minecraft.util.text.TextFormatting.ITALIC + - net.minecraft.client.resources.I18n.format("tooltip.advancedrocketry.hold_shift")); + list.add(TextFormatting.GRAY + + I18n.format("tooltip.advancedrocketry.itemdataunit.shift.1")); + } else if (I18n.hasKey("tooltip.advancedrocketry.hold_shift")) { + list.add(TextFormatting.DARK_GRAY.toString() + + TextFormatting.ITALIC + + I18n.format("tooltip.advancedrocketry.hold_shift")); } } } From aa940894e42127b24d9f1ce3056893bcda0cb5c6 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:16:04 +0100 Subject: [PATCH 330/424] Add IDataItem interface for data container items --- .../advancedRocketry/item/IDataItem.java | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/item/IDataItem.java diff --git a/src/main/java/zmaster587/advancedRocketry/item/IDataItem.java b/src/main/java/zmaster587/advancedRocketry/item/IDataItem.java new file mode 100644 index 000000000..9d6d66b60 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/item/IDataItem.java @@ -0,0 +1,70 @@ +package zmaster587.advancedRocketry.item; + +import net.minecraft.item.ItemStack; +import zmaster587.advancedRocketry.api.DataStorage; + +import javax.annotation.Nonnull; + +/** + * Common interface for any item that behaves like an ItemData-style data container. + * + * Goal: + * - Allow commands (/advancedrocketry filldata), GUI slots (SlotData), + * and machine logic (TileDataBus/Observatory/Terminal/etc) + * to accept multiple item implementations without hard-typing to ItemData. + * + * Contract: + * - Implementations should store their DataStorage in the root tag of the ItemStack + * in the same shape as DataStorage#writeToNBT / readFromNBT expects. + * - getDataStorage MUST return a DataStorage instance representing the stack state. + * - setData/addData/removeData MUST persist changes back into the stack NBT. + */ +public interface IDataItem { + + /** + * @return max capacity for this specific stack. + * Implementations may compute this from damage, NBT, config, etc. + */ + int getMaxData(@Nonnull ItemStack stack); + + /** + * Reads a DataStorage snapshot from the stack. + * Implementations should ensure returned storage has correct maxData applied. + */ + @Nonnull + DataStorage getDataStorage(@Nonnull ItemStack stack); + + /** + * Convenience read of current amount. + */ + default int getData(@Nonnull ItemStack stack) { + return getDataStorage(stack).getData(); + } + + /** + * Convenience read of current type. + */ + @Nonnull + default DataStorage.DataType getDataType(@Nonnull ItemStack stack) { + return getDataStorage(stack).getDataType(); + } + + /** + * Adds data of the given type to this stack. + * + * @return amount actually added + */ + int addData(@Nonnull ItemStack stack, int amount, @Nonnull DataStorage.DataType dataType); + + /** + * Removes data of the given type from this stack. + * + * @return amount actually removed + */ + int removeData(@Nonnull ItemStack stack, int amount, @Nonnull DataStorage.DataType dataType); + + /** + * Sets (overwrites) data amount + type on this stack. + */ + void setData(@Nonnull ItemStack stack, int amount, @Nonnull DataStorage.DataType dataType); +} From bc1d84f6f24db804c37d46763a791a449cc07278 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:16:37 +0100 Subject: [PATCH 331/424] Add ItemBlockDataBusBig class for data storage --- .../item/ItemBlockDataBusBig.java | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/item/ItemBlockDataBusBig.java diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemBlockDataBusBig.java b/src/main/java/zmaster587/advancedRocketry/item/ItemBlockDataBusBig.java new file mode 100644 index 000000000..44f0aac21 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemBlockDataBusBig.java @@ -0,0 +1,150 @@ +package zmaster587.advancedRocketry.item; + +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.resources.I18n; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import zmaster587.advancedRocketry.api.DataStorage; +import zmaster587.advancedRocketry.tile.hatch.TileDataBusBig; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.List; + +public class ItemBlockDataBusBig extends ItemBlock implements IDataItem { + + // Keep this local and explicit + private static final int BIG_MAX_DATA = 2000 * 4; + + public ItemBlockDataBusBig(Block block) { + super(block); + setHasSubtypes(false); + setMaxDamage(0); + } + + // ---- IDataItem ---- + + @Override + public int getMaxData(@Nonnull ItemStack stack) { + return BIG_MAX_DATA; + } + + @Override + @Nonnull + public DataStorage getDataStorage(@Nonnull ItemStack stack) { + DataStorage data = new DataStorage(); + + if (!stack.hasTagCompound()) { + data.setMaxData(getMaxData(stack)); + data.setData(0, DataStorage.DataType.UNDEFINED); + } else { + data.readFromNBT(stack.getTagCompound()); + data.setMaxData(getMaxData(stack)); + if (data.getData() > data.getMaxData()) { + data.setData(data.getMaxData(), data.getDataType()); + } + } + return data; + } + + @Override + public int addData(@Nonnull ItemStack stack, int amount, @Nonnull DataStorage.DataType dataType) { + DataStorage data = getDataStorage(stack); + + int added = data.addData(amount, dataType, true); + + NBTTagCompound nbt = new NBTTagCompound(); + data.writeToNBT(nbt); + stack.setTagCompound(nbt); + + return added; + } + + @Override + public int removeData(@Nonnull ItemStack stack, int amount, @Nonnull DataStorage.DataType dataType) { + DataStorage data = getDataStorage(stack); + + int removed = data.removeData(amount, true); + + NBTTagCompound nbt = new NBTTagCompound(); + data.writeToNBT(nbt); + stack.setTagCompound(nbt); + + return removed; + } + + @Override + public void setData(@Nonnull ItemStack stack, int amount, @Nonnull DataStorage.DataType dataType) { + DataStorage data = getDataStorage(stack); + + data.setData(amount, dataType); + + NBTTagCompound nbt = new NBTTagCompound(); + data.writeToNBT(nbt); + stack.setTagCompound(nbt); + } + + // ---- stacking rule (same behavior as ItemData) ---- + @Override + public int getItemStackLimit(@Nonnull ItemStack stack) { + return getData(stack) == 0 ? super.getItemStackLimit(stack) : 1; + } + + // ---- place NBT into TE ---- + @Override + public boolean placeBlockAt(ItemStack stack, EntityPlayer player, World world, BlockPos pos, + EnumFacing side, float hitX, float hitY, float hitZ, IBlockState newState) { + + boolean placed = super.placeBlockAt(stack, player, world, pos, side, hitX, hitY, hitZ, newState); + if (!placed || world.isRemote) return placed; + + if (!stack.hasTagCompound()) return placed; + + TileEntity te = world.getTileEntity(pos); + if (!(te instanceof TileDataBusBig)) return placed; + + TileDataBusBig bus = (TileDataBusBig) te; + + NBTTagCompound tag = stack.getTagCompound(); + if (tag != null) { + bus.getDataObject().readFromNBT(tag); + bus.markDirty(); + world.notifyBlockUpdate(pos, newState, newState, 3); + } + + return placed; + } + + // ---- tooltip parity with ItemData ---- + @Override + @SideOnly(Side.CLIENT) + public void addInformation(@Nonnull ItemStack stack, @Nullable World world, + List list, ITooltipFlag flag) { + + DataStorage data = getDataStorage(stack); + + // Header + list.add(I18n.format("tooltip.advancedrocketry.databusbig.header")); + + // Type + String typeText = I18n.format(data.getDataType().toString()); + list.add(I18n.format("tooltip.advancedrocketry.itemdata.type") + typeText); + + // Data + list.add(I18n.format("tooltip.advancedrocketry.itemdata.data") + + TextFormatting.GOLD + data.getData() + + TextFormatting.WHITE + " / " + + TextFormatting.GOLD + data.getMaxData()); + } +} From 5b49deb342353f6498409244a58c352ba92b2883 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:17:13 +0100 Subject: [PATCH 332/424] Refactor WorldCommand to use IDataItem interface --- .../advancedRocketry/command/WorldCommand.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/command/WorldCommand.java b/src/main/java/zmaster587/advancedRocketry/command/WorldCommand.java index 3ae264070..fc7fbe9c2 100644 --- a/src/main/java/zmaster587/advancedRocketry/command/WorldCommand.java +++ b/src/main/java/zmaster587/advancedRocketry/command/WorldCommand.java @@ -28,6 +28,7 @@ import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.advancedRocketry.dimension.DimensionProperties; import zmaster587.advancedRocketry.integration.CompatibilityMgr; +import zmaster587.advancedRocketry.item.IDataItem; import zmaster587.advancedRocketry.item.ItemData; import zmaster587.advancedRocketry.item.ItemMultiData; import zmaster587.advancedRocketry.item.ItemStationChip; @@ -176,15 +177,16 @@ private void commandFillData(ICommandSender sender, String[] cmdstring) { return; } - if (!stack.isEmpty() && stack.getItem() instanceof ItemData) { - ItemData item = (ItemData) stack.getItem(); - int dataAmount = item.getMaxData(stack.getItemDamage()); + if (!stack.isEmpty() && stack.getItem() instanceof IDataItem) { + IDataItem item = (IDataItem) stack.getItem(); + + int dataAmount = item.getMaxData(stack); DataType dataType; try { dataType = DataType.valueOf(cmdstring[1].toUpperCase(Locale.ENGLISH)); } catch (IllegalArgumentException e) { - sender.sendMessage(new TextComponentString("Did you mean: /advrocketry" + cmdstring[0] + " [datatype] [amountFill]")); + sender.sendMessage(new TextComponentString("Did you mean: /advrocketry " + cmdstring[0] + " [datatype] [amountFill]")); sender.sendMessage(new TextComponentString("Not a valid datatype")); StringBuilder value = new StringBuilder(); for (DataType data : DataType.values()) { @@ -192,21 +194,23 @@ private void commandFillData(ICommandSender sender, String[] cmdstring) { value.append(data.name().toLowerCase()).append(", "); } } - sender.sendMessage(new TextComponentString("Try " + value)); return; } - if (cmdstring.length >= 3) + + if (cmdstring.length >= 3) { try { dataAmount = Integer.parseInt(cmdstring[2]); } catch (NumberFormatException e) { - sender.sendMessage(new TextComponentString("Did you mean: /advrocketry" + cmdstring[0] + " [datatype] [amountFill]")); + sender.sendMessage(new TextComponentString("Did you mean: /advrocketry " + cmdstring[0] + " [datatype] [amountFill]")); sender.sendMessage(new TextComponentString("Not a valid number")); return; } + } item.setData(stack, dataAmount, dataType); sender.sendMessage(new TextComponentString("Data filled!")); + } else if (!stack.isEmpty() && stack.getItem() instanceof ItemMultiData) { ItemMultiData item = (ItemMultiData) stack.getItem(); int dataAmount = item.getMaxData(stack); From d2a06e338d2f27a3c0c27d6c1e68fc9bccfc860c Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:18:08 +0100 Subject: [PATCH 333/424] Refactor setData method for clarity and safety --- .../java/zmaster587/advancedRocketry/api/DataStorage.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/api/DataStorage.java b/src/main/java/zmaster587/advancedRocketry/api/DataStorage.java index c99849801..1693d93b1 100644 --- a/src/main/java/zmaster587/advancedRocketry/api/DataStorage.java +++ b/src/main/java/zmaster587/advancedRocketry/api/DataStorage.java @@ -21,12 +21,12 @@ public DataStorage(DataType data) { public boolean setData(int data, DataType dataType) { // If empty/typeless, allow adopting the provided type (unless locked) - if (this.dataType == DataStorage.DataType.UNDEFINED && !this.locked) { + if (!this.locked && this.dataType == DataType.UNDEFINED && dataType != DataType.UNDEFINED) { this.dataType = dataType; } - if (dataType == DataStorage.DataType.UNDEFINED || dataType == this.dataType) { - this.data = Math.min(data, maxData); + if (dataType == DataType.UNDEFINED || dataType == this.dataType) { + this.data = Math.max(0, Math.min(data, maxData)); // If we just became empty and are not locked, clear type if (!this.locked && this.data == 0) { From 76570b6dbea49f478f8fd0f0eb364f282d523626 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:19:07 +0100 Subject: [PATCH 334/424] Refactor TileDataBus to use IDataItem interface --- .../tile/hatch/TileDataBus.java | 67 +++++++++++++++---- 1 file changed, 54 insertions(+), 13 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/hatch/TileDataBus.java b/src/main/java/zmaster587/advancedRocketry/tile/hatch/TileDataBus.java index 41d989503..5980e6593 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/hatch/TileDataBus.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/hatch/TileDataBus.java @@ -9,6 +9,7 @@ import zmaster587.advancedRocketry.api.DataStorage; import zmaster587.advancedRocketry.api.DataStorage.DataType; import zmaster587.advancedRocketry.inventory.modules.ModuleAutoData; +import zmaster587.advancedRocketry.item.IDataItem; import zmaster587.advancedRocketry.item.ItemData; import zmaster587.advancedRocketry.util.IDataInventory; import zmaster587.libVulpes.inventory.modules.ModuleBase; @@ -22,17 +23,18 @@ public class TileDataBus extends TileInventoryHatch implements IDataInventory, INetworkMachine { - DataStorage data; + protected DataStorage data; + protected static final int BASE_MAX_DATA = 2000; public TileDataBus() { data = new DataStorage(DataStorage.DataType.UNDEFINED); - data.setMaxData(2000); + data.setMaxData(BASE_MAX_DATA); } public TileDataBus(int number) { super(number); data = new DataStorage(DataStorage.DataType.UNDEFINED); - data.setMaxData(2000); + data.setMaxData(BASE_MAX_DATA); inventory.setCanInsertSlot(0, true); inventory.setCanInsertSlot(1, false); @@ -45,14 +47,25 @@ public void loadData(int id) { ItemStack itemStack = inventory.getStackInSlot(0); - if (itemStack != ItemStack.EMPTY && itemStack.getItem() instanceof ItemData) { - ItemData itemData = (ItemData) itemStack.getItem(); - itemData.removeData(itemStack, this.data.addData(itemData.getData(itemStack), itemData.getDataType(itemStack), true), DataStorage.DataType.UNDEFINED); + if (!itemStack.isEmpty() && itemStack.getItem() instanceof IDataItem) { + IDataItem item = (IDataItem) itemStack.getItem(); + + DataStorage chip = item.getDataStorage(itemStack); + + int moved = this.data.addData( + chip.getData(), + chip.getDataType(), + true + ); + + // Remove exactly what was accepted + item.removeData(itemStack, moved, DataStorage.DataType.UNDEFINED); inventory.setInventorySlotContents(1, decrStackSize(0, 1)); } } + @Override public String getModularInventoryName() { return "tile.loader.0.name"; @@ -62,9 +75,19 @@ public String getModularInventoryName() { public void storeData(int id) { ItemStack itemStack = inventory.getStackInSlot(0); - if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemData && inventory.getStackInSlot(1) == ItemStack.EMPTY) { - ItemData itemData = (ItemData) itemStack.getItem(); - this.data.removeData(itemData.addData(itemStack, this.data.getData(), this.data.getDataType()), true); + if (!itemStack.isEmpty() + && itemStack.getItem() instanceof IDataItem + && inventory.getStackInSlot(1).isEmpty()) { + + IDataItem item = (IDataItem) itemStack.getItem(); + + int added = item.addData( + itemStack, + this.data.getData(), + this.data.getDataType() + ); + + this.data.removeData(added, true); inventory.setInventorySlotContents(1, decrStackSize(0, 1)); } @@ -126,16 +149,29 @@ public void readFromNBT(NBTTagCompound nbt) { @Override public void setInventorySlotContents(int slot, @Nonnull ItemStack stack) { inventory.setInventorySlotContents(slot, stack); + ItemStack itemStack = inventory.getStackInSlot(0); - if (itemStack != ItemStack.EMPTY && itemStack.getItem() instanceof ItemData && inventory.getStackInSlot(1) == ItemStack.EMPTY) { - ItemData itemData = (ItemData) itemStack.getItem(); - if (itemData.getData(itemStack) > 0 && data.getData() != data.getMaxData()) { + if (!itemStack.isEmpty() + && itemStack.getItem() instanceof IDataItem + && inventory.getStackInSlot(1).isEmpty()) { + + IDataItem item = (IDataItem) itemStack.getItem(); + DataStorage chip = item.getDataStorage(itemStack); + + int chipData = chip.getData(); + int chipMax = chip.getMaxData(); + + // Auto-load from chip -> bus + if (chipData > 0 && data.getData() < data.getMaxData()) { loadData(0); - } else if (data.getData() != 0 && 1000 > itemData.getData(itemStack)) { + + // Auto-store from bus -> chip + } else if (data.getData() > 0 && chipData < chipMax) { storeData(0); } } + inventory.markDirty(); markDirty(); this.handleUpdateTag(getUpdateTag()); @@ -144,6 +180,11 @@ public void setInventorySlotContents(int slot, @Nonnull ItemStack stack) { ((TileMultiBlock) this.getMasterBlock()).onInventoryUpdated(); } + @Override + public int getInventoryStackLimit() { + return 1; + } + @Override public boolean canExtractItem(int index, @Nonnull ItemStack stack, EnumFacing direction) { return index == 1; From 0f6039439461bbd995adaf93bdf847641f4e9768 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:19:52 +0100 Subject: [PATCH 335/424] Refactor SlotData to use IDataItem and limit stack size Updated item validation logic and added stack limits. --- .../inventory/modules/SlotData.java | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/inventory/modules/SlotData.java b/src/main/java/zmaster587/advancedRocketry/inventory/modules/SlotData.java index db218d096..59bf320de 100644 --- a/src/main/java/zmaster587/advancedRocketry/inventory/modules/SlotData.java +++ b/src/main/java/zmaster587/advancedRocketry/inventory/modules/SlotData.java @@ -3,7 +3,7 @@ import net.minecraft.inventory.IInventory; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; -import zmaster587.advancedRocketry.item.ItemData; +import zmaster587.advancedRocketry.item.IDataItem; import javax.annotation.Nonnull; @@ -17,9 +17,16 @@ public SlotData(IInventory p_i1824_1_, int p_i1824_2_, int p_i1824_3_, @Override public boolean isItemValid(@Nonnull ItemStack stack) { - if (stack.isEmpty() || stack.getItem() instanceof ItemData) - return super.isItemValid(stack); - return false; + return !stack.isEmpty() && stack.getItem() instanceof IDataItem; } + @Override + public int getSlotStackLimit() { + return 1; + } + + @Override + public int getItemStackLimit(@Nonnull ItemStack stack) { + return 1; + } } From 43563609de8286ede1665bfc9690b814c4ea6cb0 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:20:23 +0100 Subject: [PATCH 336/424] Update tooltip data display in ModuleAutoData --- .../advancedRocketry/inventory/modules/ModuleAutoData.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleAutoData.java b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleAutoData.java index a1752b9f6..d1969b9c2 100644 --- a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleAutoData.java +++ b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleAutoData.java @@ -104,8 +104,9 @@ public void renderForeground(int guiOffsetX, int guiOffsetY, int mouseX, int mou } List list = new LinkedList<>(); - list.add(totalData + " / " + totalMaxData + " Data"); - list.add("Type: " + I18n.format(data[0].getDataType().toString())); + list.add(totalData + " / " + totalMaxData + " " + I18n.format("data.label.data")); + list.add(I18n.format("data.label.type") + " " + I18n.format(data[0].getDataType().toString())); + this.drawTooltip(gui, list, mouseX, mouseY, zLevel, font); } From 893263cea131f703e1099f74bd901dbc9992592c Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:20:57 +0100 Subject: [PATCH 337/424] Update tooltip formatting in ModuleData.java --- .../advancedRocketry/inventory/modules/ModuleData.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleData.java b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleData.java index f6becbf65..a2bd48f74 100644 --- a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleData.java +++ b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleData.java @@ -132,8 +132,9 @@ public void renderForeground(int guiOffsetX, int guiOffsetY, int mouseX, int mou } List list = new LinkedList<>(); - list.add(totalData + " / " + totalMaxData + " Data"); - list.add("Type: " + I18n.format(data[0].getDataType().toString())); + list.add(totalData + " / " + totalMaxData + " " + I18n.format("data.label.data")); + list.add(I18n.format("data.label.type") + " " + I18n.format(data[0].getDataType().toString())); + this.drawTooltip(gui, list, mouseX, mouseY, zLevel, font); } From bf64f4466b0edd260497aeda23a8bfe133c322db Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:21:37 +0100 Subject: [PATCH 338/424] Update data label formatting in ItemMultiData --- .../java/zmaster587/advancedRocketry/item/ItemMultiData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemMultiData.java b/src/main/java/zmaster587/advancedRocketry/item/ItemMultiData.java index e9f48657b..2e2e4e145 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemMultiData.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemMultiData.java @@ -127,7 +127,7 @@ public void addInformation(@Nonnull ItemStack stack, World player, List for (DataStorage.DataType type : SUPPORTED_TYPES) { final int amt = data.getDataAmount(type); - list.add(amt + " / " + data.getMaxData() + " " + I18n.format(type.toString()) + " Data"); + list.add(amt + " / " + data.getMaxData() + " " + I18n.format(type.toString()) + " " + I18n.format("data.label.data")); } } } From 2861e4889216a18ec066a71d5fd3f9e12fc6aef8 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:22:17 +0100 Subject: [PATCH 339/424] Refactor item validation and data handling methods --- .../tile/satellite/TileSatelliteTerminal.java | 97 +++++++++++++++---- 1 file changed, 80 insertions(+), 17 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java index c930fc2c3..a76a5f428 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java @@ -17,7 +17,7 @@ import zmaster587.advancedRocketry.inventory.TextureResources; import zmaster587.advancedRocketry.inventory.modules.ModuleData; import zmaster587.advancedRocketry.inventory.modules.ModuleSatellite; -import zmaster587.advancedRocketry.item.ItemData; +import zmaster587.advancedRocketry.item.IDataItem; import zmaster587.advancedRocketry.item.ItemSatelliteIdentificationChip; import zmaster587.advancedRocketry.satellite.SatelliteData; import zmaster587.advancedRocketry.util.IDataInventory; @@ -159,7 +159,14 @@ public String getModularInventoryName() { } @Override - public boolean isItemValidForSlot(int slot, @Nonnull ItemStack stack) { return true; } + public boolean isItemValidForSlot(int slot, @Nonnull ItemStack stack) { + if (stack.isEmpty()) return true; + if (slot == 0) return stack.getItem() instanceof ItemSatelliteIdentificationChip; + if (slot == 1) return stack.getItem() instanceof IDataItem; + return false; + } + + @Override public boolean canPerformFunction() { @@ -196,12 +203,15 @@ public void readDataFromNetwork(ByteBuf in, byte packetId, NBTTagCompound nbt) { @Override public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompound nbt) { - if (id == 0) { - // store data to item (server handles it inside storeData) - storeData(0); + if (id == -1) { + storeData(1); + return; + } else if (id == -2) { + loadData(1); + return; } else if (id == 100) { - // "Connect" / perform action + // connect logic if (!world.isRemote) { SatelliteBase sat = getSatelliteFromSlot(0); @@ -211,6 +221,7 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompou int hereDim = DimensionManager.getEffectiveDimId(world, pos).getId(); inRange = PlanetaryTravelHelper.isTravelAnywhereInPlanetarySystem(satDim, hereDim); } + boolean hasLink = (sat instanceof SatelliteData) && inRange; boolean hasPower = getUniversalEnergyStored() >= getPowerPerOperation(); @@ -219,6 +230,7 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompou this.energy.extractEnergy(getPowerPerOperation(), false); } } + return; } else if (id == 101) { if (!world.isRemote) { @@ -234,13 +246,14 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompou } idchip.erase(stack); - // server mutates the inventory; client will get it via normal container sync setInventorySlotContents(0, stack); } } + return; } } + @Nullable private SatelliteBase resolveSatelliteFresh() { ItemStack s0 = getStackInSlot(0); @@ -328,21 +341,71 @@ public void readFromNBT(NBTTagCompound nbt) { } @Override - public void loadData(int id) { } + public int getInventoryStackLimit() { + return 1; + } @Override - public void storeData(int id) { - if (!world.isRemote) { - ItemStack stack = getStackInSlot(1); - if (!stack.isEmpty() && stack.getItem() instanceof ItemData && stack.getCount() == 1) { - ItemData dataItem = (ItemData) stack.getItem(); - data.removeData(dataItem.addData(stack, data.getData(), data.getDataType()), true); - } - } else { - PacketHandler.sendToServer(new PacketMachine(this, (byte) 0)); + public void loadData(int slotId) { + if (world == null || world.isRemote) { + // Client triggers server action + PacketHandler.sendToServer(new PacketMachine(this, (byte) -2)); + return; + } + + ItemStack stack = getStackInSlot(slotId); + if (stack.isEmpty() || !(stack.getItem() instanceof IDataItem)) return; + + IDataItem dataItem = (IDataItem) stack.getItem(); + DataStorage itemStore = dataItem.getDataStorage(stack); + + int available = itemStore.getData(); + if (available <= 0) return; + + DataType type = itemStore.getDataType(); + + // How much room does the terminal buffer have? + int room = data.getMaxData() - data.getData(); + if (room <= 0) return; + + int toMove = Math.min(available, room); + + // Add to terminal first (authoritative return value) + int added = data.addData(toMove, type, true); + + if (added > 0) { + // Remove only what actually got accepted + dataItem.removeData(stack, added, type); + setInventorySlotContents(slotId, stack); + markDirty(); } } + @Override + public void storeData(int slotId) { + if (world == null || world.isRemote) { + PacketHandler.sendToServer(new PacketMachine(this, (byte) -1)); + return; + } + + ItemStack stack = getStackInSlot(slotId); + if (stack.isEmpty() || !(stack.getItem() instanceof IDataItem)) return; + + if (data.getData() <= 0 || data.getDataType() == DataType.UNDEFINED) return; + + IDataItem dataItem = (IDataItem) stack.getItem(); + + int moved = dataItem.addData(stack, data.getData(), data.getDataType()); + + if (moved > 0) { + data.removeData(moved, true); + setInventorySlotContents(slotId, stack); + markDirty(); + } + } + + + @Override public int extractData(int maxAmount, DataType type, EnumFacing dir, boolean commit) { // 1) Type guard From f3303d6b220ab7b196cbe055c74a89ec9b2490f0 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:22:49 +0100 Subject: [PATCH 340/424] Add progress bar support to ModulePlanetSelector --- .../modules/ModulePlanetSelector.java | 127 ++++++++++++++++-- 1 file changed, 113 insertions(+), 14 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModulePlanetSelector.java b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModulePlanetSelector.java index 41380acbe..f453c8857 100644 --- a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModulePlanetSelector.java +++ b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModulePlanetSelector.java @@ -8,6 +8,7 @@ import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.resources.I18n; import net.minecraft.inventory.Container; import net.minecraft.inventory.IContainerListener; import net.minecraft.util.ResourceLocation; @@ -49,14 +50,48 @@ public class ModulePlanetSelector extends ModuleContainerPan implements IButtonI private PlanetRenderProperties currentlySelectedPlanet; private IPlanetDefiner planetDefiner; private int currentlySelectedPlanetID = -1; + + private IProgressBar progressSource; + + private static final IProgressBar NULL_PROGRESS = new IProgressBar() { + @Override public float getNormallizedProgress(int id) { return 0f; } + @Override public void setProgress(int id, int progress) {} + @Override public int getProgress(int id) { return 0; } + @Override public int getTotalProgress(int id) { return 1; } + @Override public void setTotalProgress(int id, int progress) {} + }; + + public ModulePlanetSelector(int planetId, ResourceLocation backdrop, ISelectionNotify tile, boolean star) { - this(planetId, backdrop, tile, null, star); + this(planetId, backdrop, tile, null, null, star); } public ModulePlanetSelector(int planetId, ResourceLocation backdrop, ISelectionNotify tile, IPlanetDefiner definer, boolean star) { + this(planetId, backdrop, tile, null, definer, star); + } + + // NEW overloads for Option A + public ModulePlanetSelector(int planetId, ResourceLocation backdrop, ISelectionNotify tile, + IProgressBar progress, boolean star) { + this(planetId, backdrop, tile, progress, null, star); + } + + public ModulePlanetSelector(int planetId, ResourceLocation backdrop, ISelectionNotify tile, + IProgressBar progress, IPlanetDefiner definer, boolean star) { super(0, 0, null, null, backdrop, 0, 0, 0, 0, size, size); + this.planetDefiner = definer; - hostTile = tile; + this.hostTile = tile; + + // choose progress provider safely + if (progress != null) { + this.progressSource = progress; + } else if (tile instanceof IProgressBar) { + this.progressSource = (IProgressBar) tile; + } else { + this.progressSource = NULL_PROGRESS; + } + int center = size / 2; zoom = 1.0; @@ -69,20 +104,36 @@ public ModulePlanetSelector(int planetId, ResourceLocation backdrop, ISelectionN selectedSystem = Constants.INVALID_PLANET; stellarView = false; - staticModuleList.add(new ModuleButton(0, 0, Constants.INVALID_PLANET, "<< Up", this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); - staticModuleList.add(new ModuleButton(0, 18, Constants.INVALID_PLANET + 1, "Select", this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); - staticModuleList.add(new ModuleButton(0, 36, Constants.INVALID_PLANET + 2, "PlanetList", this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); + staticModuleList.add(new ModuleButton(0, 0, Constants.INVALID_PLANET, + I18n.format("msg.advancedrocketry.planetselector.up"), + this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); + + staticModuleList.add(new ModuleButton(0, 18, Constants.INVALID_PLANET + 1, + I18n.format("msg.advancedrocketry.planetselector.select"), + this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); + + staticModuleList.add(new ModuleButton(0, 36, Constants.INVALID_PLANET + 2, + I18n.format("msg.advancedrocketry.planetselector.planet.list"), + this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); ModuleDualProgressBar progressBar; - staticModuleList.add(progressBar = new ModuleDualProgressBar(100, 0, 0, TextureResources.atmIndicator, (IProgressBar) tile, "%b -> %a Earth's atmospheric pressure")); + + staticModuleList.add(progressBar = new ModuleDualProgressBar(100, 0, 0, + TextureResources.atmIndicator, progressSource, + net.minecraft.util.text.translation.I18n.translateToLocal("msg.advancedrocketry.planetselector.atm.tooltip"))); progressBar.setTooltipValueMultiplier(.16f); - staticModuleList.add(progressBar = new ModuleDualProgressBar(200, 0, 2, TextureResources.massIndicator, (IProgressBar) tile, "%b -> %a Earth's mass")); + staticModuleList.add(progressBar = new ModuleDualProgressBar(200, 0, 2, + TextureResources.massIndicator, progressSource, + net.minecraft.util.text.translation.I18n.translateToLocal("msg.advancedrocketry.planetselector.mass.tooltip"))); progressBar.setTooltipValueMultiplier(.02f); - staticModuleList.add(progressBar = new ModuleDualProgressBar(300, 0, 1, TextureResources.distanceIndicator, (IProgressBar) tile, "%b -> %a Relative Distance units")); + staticModuleList.add(progressBar = new ModuleDualProgressBar(300, 0, 1, + TextureResources.distanceIndicator, progressSource, + net.minecraft.util.text.translation.I18n.translateToLocal("msg.advancedrocketry.planetselector.distance.tooltip"))); progressBar.setTooltipValueMultiplier(.16f); + //renderPlanetarySystem(properties, center, center, 3f); if (FMLCommonHandler.instance().getSide().isClient()) { @@ -160,15 +211,36 @@ private void renderGalaxyMap(IGalaxy galaxy, int posX, int posY, float distanceZ deltaX = (int) ((int) (star2.getStarSeparation() * MathHelper.cos(phase) * 0.5*distanceZoomMultiplier)); deltaY = (int) ((int) (star2.getStarSeparation() * MathHelper.sin(phase) * 0.5*distanceZoomMultiplier)); - planetList.add(button = new ModuleButton(offsetX + deltaX, offsetY + deltaY, star2.getId() + Constants.STAR_ID_OFFSET, "", this, new ResourceLocation[]{star2.isBlackHole() ? TextureResources.locationBlackHole_icon : TextureResources.locationSunNew}, String.format("Name: %s\nNumber of Planets: %d", star2.getName(), star.getNumPlanets()), displaySize, displaySize)); + planetList.add(button = new ModuleButton( + offsetX + deltaX, + offsetY + deltaY, + star2.getId() + Constants.STAR_ID_OFFSET, + "", + this, + new ResourceLocation[]{star2.isBlackHole() ? TextureResources.locationBlackHole_icon : TextureResources.locationSunNew}, + I18n.format("msg.advancedrocketry.planetselector.star.tooltip.name", star2.getName()) + + "\n" + + I18n.format("msg.advancedrocketry.planetselector.star.tooltip.number.of.planets", star.getNumPlanets()), + displaySize, + displaySize)); button.setSound("buttonBlipA"); button.setBGColor(star2.getColorRGB8()); phase += phaseInc; } } - planetList.add(button = new ModuleButton(offsetX, offsetY, star.getId() + Constants.STAR_ID_OFFSET, "", this, new ResourceLocation[]{star.isBlackHole() ? TextureResources.locationBlackHole_icon : TextureResources.locationSunNew}, String.format("Name: %s\nNumber of Planets: %d", star.getName(), star.getNumPlanets()), displaySize, displaySize)); - + planetList.add(button = new ModuleButton( + offsetX, offsetY, + star.getId() + Constants.STAR_ID_OFFSET, + "", + this, + new ResourceLocation[]{star.isBlackHole() ? TextureResources.locationBlackHole_icon : TextureResources.locationSunNew}, + I18n.format("msg.advancedrocketry.planetselector.star.tooltip.name", star.getName()) + + "\n" + + I18n.format("msg.advancedrocketry.planetselector.star.tooltip.number.of.planets", star.getNumPlanets()), + displaySize, displaySize)); + + button.setSound("buttonBlipA"); button.setBGColor(star.getColorRGB8()); @@ -200,7 +272,18 @@ private void renderStarSystem(StellarBody star, int posX, int posY, float distan deltaX = (int) (star2.getStarSeparation() * MathHelper.cos(phase) * 0.5); deltaY = (int) (star2.getStarSeparation() * MathHelper.sin(phase) * 0.5); - planetList.add(button = new ModuleButton(offsetX + deltaX, offsetY + deltaY, star2.getId() + Constants.STAR_ID_OFFSET, "", this, new ResourceLocation[]{star2.isBlackHole() ? TextureResources.locationBlackHole_icon : TextureResources.locationSunNew}, String.format("Name: %s\nNumber of Planets: %d", star2.getName(), star.getNumPlanets()), displaySize, displaySize)); + planetList.add(button = new ModuleButton( + offsetX + deltaX, offsetY + deltaY, + star2.getId() + Constants.STAR_ID_OFFSET, + "", + this, + new ResourceLocation[]{star2.isBlackHole() ? TextureResources.locationBlackHole_icon : TextureResources.locationSunNew}, + I18n.format("msg.advancedrocketry.planetselector.star.tooltip.name", star2.getName()) + + "\n" + + I18n.format("msg.advancedrocketry.planetselector.star.tooltip.number.of.planets", star.getNumPlanets()), + displaySize, displaySize + )); + button.setSound("buttonBlipA"); button.setBGColor(star2.getColorRGB8()); phase += phaseInc; @@ -210,7 +293,18 @@ private void renderStarSystem(StellarBody star, int posX, int posY, float distan offsetX = posX - displaySize / 2; offsetY = posY - displaySize / 2; - planetList.add(button = new ModuleButton(offsetX, offsetY, star.getId() + Constants.STAR_ID_OFFSET, "", this, new ResourceLocation[]{star.isBlackHole() ? TextureResources.locationBlackHole_icon : TextureResources.locationSunNew}, String.format("Name: %s\nNumber of Planets: %d", star.getName(), star.getNumPlanets()), displaySize, displaySize)); + planetList.add(button = new ModuleButton( + offsetX, offsetY, + star.getId() + Constants.STAR_ID_OFFSET, + "", + this, + new ResourceLocation[]{star.isBlackHole() ? TextureResources.locationBlackHole_icon : TextureResources.locationSunNew}, + I18n.format("msg.advancedrocketry.planetselector.star.tooltip.name", star.getName()) + + "\n" + + I18n.format("msg.advancedrocketry.planetselector.star.tooltip.number.of.planets", star.getNumPlanets()), + displaySize, displaySize + )); + button.setSound("buttonBlipA"); button.setBGColor(star.getColorRGB8()); renderPropertiesMap.put(star.getId() + Constants.STAR_ID_OFFSET, new PlanetRenderProperties(displaySize, offsetX, offsetY)); @@ -279,7 +373,12 @@ private void renderPlanets(DimensionProperties planet, int parentOffsetX, int pa ModuleButton button; - planetList.add(button = new ModuleButtonPlanet(offsetX, offsetY, planet.getId(), "", this, planet, planet.getName() + "\nMoons: " + planet.getChildPlanets().size(), displaySize, displaySize)); + planetList.add(button = new ModuleButtonPlanet( + offsetX, offsetY, planet.getId(), "", this, planet, + I18n.format("msg.advancedrocketry.planetselector.planet.tooltip.name", planet.getName()) + + "\n" + + I18n.format("msg.advancedrocketry.planetselector.planet.tooltip.moons.count", planet.getChildPlanets().size()), + displaySize, displaySize)); button.setSound("buttonBlipA"); renderPropertiesMap.put(planet.getId(), new PlanetRenderProperties(displaySize, offsetX, offsetY)); From 7f95ff2f9bd23ff8b92bf124063e9b7ac9add1b2 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:23:31 +0100 Subject: [PATCH 341/424] Refactor TileWarpController for better data handling --- .../tile/station/TileWarpController.java | 78 ++++++++++++++----- 1 file changed, 60 insertions(+), 18 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/station/TileWarpController.java b/src/main/java/zmaster587/advancedRocketry/tile/station/TileWarpController.java index 686d5f18b..69ad9b155 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/station/TileWarpController.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/station/TileWarpController.java @@ -26,6 +26,7 @@ import zmaster587.advancedRocketry.inventory.modules.ModuleData; import zmaster587.advancedRocketry.inventory.modules.ModulePlanetImage; import zmaster587.advancedRocketry.inventory.modules.ModulePlanetSelector; +import zmaster587.advancedRocketry.item.IDataItem; import zmaster587.advancedRocketry.item.ItemData; import zmaster587.advancedRocketry.item.ItemPlanetIdentificationChip; import zmaster587.advancedRocketry.network.PacketSpaceStationInfo; @@ -68,6 +69,9 @@ public class TileWarpController extends TileEntity implements ITickable, IModula private EmbeddedInventory inv; private ModuleProgress programmingProgress; private int progress; + private int lastSelectedSystem = Constants.INVALID_PLANET; + private long lastClientInfoUpdate = 0L; + public TileWarpController() { tabModule = new ModuleTab(4, 0, 0, this, 3, new String[]{LibVulpes.proxy.getLocalizedString("msg.warpmon.tab.warp"), LibVulpes.proxy.getLocalizedString("msg.warpmon.tab.data"), LibVulpes.proxy.getLocalizedString("msg.warpmon.tab.tracking")}, new ResourceLocation[][]{TextureResources.tabWarp, TextureResources.tabData, TextureResources.tabPlanetTracking}); @@ -196,8 +200,13 @@ public List getModules(int ID, EntityPlayer player) { ISpaceObject station = getSpaceObject(); boolean isOnStation = station != null; - if (world.isRemote) - setPlanetModuleInfo(); + if (world.isRemote) { + long now = System.currentTimeMillis(); + if (now - lastClientInfoUpdate > 200) { + setPlanetModuleInfo(); + lastClientInfoUpdate = now; + } + } //Source planet int baseX = 10; @@ -210,7 +219,7 @@ public List getModules(int ID, EntityPlayer player) { modules.add(srcPlanetImg); - ModuleText text = new ModuleText(baseX + 4, baseY + 4, "Orbiting:", 0xFFFFFF); + ModuleText text = new ModuleText(baseX + 4, baseY + 4, LibVulpes.proxy.getLocalizedString("msg.warpmon.orbit"), 0xFFFFFF); text.setAlwaysOnTop(true); modules.add(text); @@ -308,7 +317,14 @@ public List getModules(int ID, EntityPlayer player) { int starId = 0; if (station != null) starId = station.getProperties().getParentProperties().getStar().getId(); - container = new ModulePlanetSelector(starId, zmaster587.libVulpes.inventory.TextureResources.starryBG, this, this, true); + container = new ModulePlanetSelector( + starId, + zmaster587.libVulpes.inventory.TextureResources.starryBG, + this, + (IProgressBar) this, + (IPlanetDefiner) this, + true + ); container.setOffset(1000, 1000); container.setAllowStarSelection(true); modules.add(container); @@ -407,7 +423,7 @@ private void setPlanetModuleInfo() { @Override public String getModularInventoryName() { - return AdvancedRocketryBlocks.blockWarpShipMonitor.getLocalizedName(); + return ""; } @Override @@ -433,7 +449,7 @@ else if (buttonId == 1) { @Override public void writeDataToNetwork(ByteBuf out, byte id) { if (id == 1 || id == 3) - out.writeInt(container.getSelectedSystem()); + out.writeInt(lastSelectedSystem); else if (id == TAB_SWITCH) out.writeShort(tabModule.getTab()); else if (id >= 10 && id < 20) { @@ -551,24 +567,36 @@ public void onSelectionConfirmed(Object sender) { @Override public void onSelected(Object sender) { - selectSystem(container.getSelectedSystem()); + if (sender instanceof ModulePlanetSelector) { + int id = ((ModulePlanetSelector) sender).getSelectedSystem(); + lastSelectedSystem = id; + selectSystem(id); + } } + private void selectSystem(int id) { - if (getSpaceObject().getOrbitingPlanetId() == SpaceObjectManager.WARPDIMID || id == SpaceObjectManager.WARPDIMID) + // Cache the space object once to avoid repeated lookups + NPE risk + SpaceStationObject so = getSpaceObject(); + if (so == null) { dimCache = null; - else { - dimCache = DimensionManager.getInstance().getDimensionProperties(container.getSelectedSystem()); - - ISpaceObject station = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(this.getPos()); - if (station != null) { - station.setDestOrbitingBody(id); - } + return; + } + // If either side is the warp dimension, clear cache and don't compute stats + if (so.getOrbitingPlanetId() == SpaceObjectManager.WARPDIMID || id == SpaceObjectManager.WARPDIMID) { + dimCache = null; + return; } + dimCache = DimensionManager.getInstance().getDimensionProperties(id); + so.setDestOrbitingBody(id); } + @Override public void onSystemFocusChanged(Object sender) { + if (sender instanceof ModulePlanetSelector) { + lastSelectedSystem = ((ModulePlanetSelector) sender).getSelectedSystem(); + } PacketHandler.sendToServer(new PacketMachine(this, (byte) 1)); } @@ -805,7 +833,7 @@ public void loadData(int id) { } - if (!stack.isEmpty() && stack.getItem() instanceof ItemData) { + if (!stack.isEmpty() && stack.getItem() instanceof IDataItem) { ItemData item = (ItemData) stack.getItem(); if (item.getDataType(stack) == type) item.removeData(stack, this.addData(item.getData(stack), item.getDataType(stack), EnumFacing.UP, true), type); @@ -832,8 +860,8 @@ public void storeData(int id) { type = DataType.COMPOSITION; } - if (!stack.isEmpty() && stack.getItem() instanceof ItemData) { - ItemData item = (ItemData) stack.getItem(); + if (!stack.isEmpty() && stack.getItem() instanceof IDataItem) { + IDataItem item = (IDataItem) stack.getItem(); data.extractData(item.addData(stack, data.getDataAmount(type), type), type, EnumFacing.UP, true); } @@ -955,4 +983,18 @@ public boolean isStarKnown(StellarBody body) { return spaceStationObject.isStarKnown(body); return false; } + + @Override + public void onChunkUnload() { + super.onChunkUnload(); + station = null; + dimCache = null; + } + + @Override + public void invalidate() { + super.invalidate(); + station = null; + dimCache = null; + } } From f21060ac08679320eeb73b4e3a06168f1f28a850 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:24:23 +0100 Subject: [PATCH 342/424] Fix missing newline at end of TileWarpCore.java Add missing newline at the end of TileWarpCore.java From 5fbd983cd38ff8afdb335fbecdeb78848eef7de4 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:29:45 +0100 Subject: [PATCH 343/424] Add crafting recipe for databusbig --- .../advancedrocketry/recipes/databusbig.json | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/main/resources/assets/advancedrocketry/recipes/databusbig.json diff --git a/src/main/resources/assets/advancedrocketry/recipes/databusbig.json b/src/main/resources/assets/advancedrocketry/recipes/databusbig.json new file mode 100644 index 000000000..827a2f8f8 --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/recipes/databusbig.json @@ -0,0 +1,37 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": + [ + " a ", + "cmb", + " a " + ], + "key": + { + "c": + { + "item": "advancedrocketry:loader", + "data": 0 + }, + "m": + { + "item": "libvulpes:advstructuremachine" + }, + "a": + { + "item": "advancedrocketry:ic", + "data": 2 + }, + "b": + { + "item": "advancedrocketry:dataunit", + "data": 0 + } + }, + "result": + { + "item": "advancedrocketry:databusbig", + "data": 0, + "count": 1 + } +} From e0b2a5f01e927af359cf3537b2b9b03b2ff5507e Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:31:17 +0100 Subject: [PATCH 344/424] Add ModuleSideSelectorTooltipOverlay class --- .../ModuleSideSelectorTooltipOverlay.java | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleSideSelectorTooltipOverlay.java diff --git a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleSideSelectorTooltipOverlay.java b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleSideSelectorTooltipOverlay.java new file mode 100644 index 000000000..b7c1c1eb8 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleSideSelectorTooltipOverlay.java @@ -0,0 +1,83 @@ +package zmaster587.advancedRocketry.inventory.modules; + +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.resources.I18n; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import zmaster587.libVulpes.inventory.modules.ModuleBase; +import zmaster587.libVulpes.inventory.modules.ModuleBlockSideSelector; + +import java.util.ArrayList; +import java.util.List; + +@SideOnly(Side.CLIENT) +public class ModuleSideSelectorTooltipOverlay extends ModuleBase { + + private final ModuleBlockSideSelector selector; + private final String[] stateNames; + + // Match lib layout + side order + private final int[][] rects; + + // Keep allocations low: reuse list + private final List tooltip = new ArrayList<>(2); + + private static String dirName(int side) { + switch (side) { + case 0: return I18n.format("advancedrocketry.sideselector.direction.bottom"); + case 1: return I18n.format("advancedrocketry.sideselector.direction.top"); + case 2: return I18n.format("advancedrocketry.sideselector.direction.north"); + case 3: return I18n.format("advancedrocketry.sideselector.direction.south"); + case 4: return I18n.format("advancedrocketry.sideselector.direction.west"); + case 5: return I18n.format("advancedrocketry.sideselector.direction.east"); + default: return "?"; + } + } + + public ModuleSideSelectorTooltipOverlay(int offsetX, int offsetY, + ModuleBlockSideSelector selector, + String[] stateNames) { + super(offsetX, offsetY); + this.selector = selector; + this.stateNames = stateNames; + + // These positions match ModuleBlockSideSelector constructor + rects = new int[][]{ + {offsetX + 42, offsetY + 42, 16, 16}, // 0 bottom + {offsetX + 21, offsetY + 21, 16, 16}, // 1 top + {offsetX + 21, offsetY + 0, 16, 16}, // 2 north + {offsetX + 21, offsetY + 42, 16, 16}, // 3 south + {offsetX + 0, offsetY + 21, 16, 16}, // 4 west + {offsetX + 42, offsetY + 21, 16, 16} // 5 east + }; + } + + @Override + public void renderToolTip(int guiOffsetX, int guiOffsetY, + int mouseX, int mouseY, float zLevel, + GuiContainer gui, FontRenderer font) { + + for (int side = 0; side < 6; side++) { + int[] r = rects[side]; + + int rx = r[0]; + int ry = r[1]; + int rw = r[2]; + int rh = r[3]; + + if (mouseX >= rx && mouseX < rx + rw && mouseY >= ry && mouseY < ry + rh) { + int state = selector.getStateForSide(side); + String mode = (state >= 0 && state < stateNames.length) + ? stateNames[state] + : "Unknown"; + + tooltip.clear(); + tooltip.add(dirName(side) + ": " + mode); + + this.drawTooltip(gui, tooltip, mouseX, mouseY, zLevel, font); + return; + } + } + } +} From fb97e7d4c80f0d1fc93173217ca0212005504c43 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:33:17 +0100 Subject: [PATCH 345/424] added Orbital registry --- .../tile/TileOrbitalRegistry.java | 1484 +++++++++++++++++ 1 file changed, 1484 insertions(+) create mode 100644 src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java b/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java new file mode 100644 index 000000000..a904ff552 --- /dev/null +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java @@ -0,0 +1,1484 @@ +package zmaster587.advancedRocketry.tile; + +import io.netty.buffer.ByteBuf; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.EnumFacing; +import net.minecraftforge.common.util.Constants; +import net.minecraftforge.fml.relauncher.Side; +import zmaster587.advancedRocketry.api.SatelliteRegistry; +import zmaster587.advancedRocketry.api.satellite.SatelliteBase; +import zmaster587.advancedRocketry.api.satellite.SatelliteProperties; +import zmaster587.advancedRocketry.api.stations.ISpaceObject; +import zmaster587.advancedRocketry.dimension.DimensionManager; +import zmaster587.advancedRocketry.dimension.DimensionProperties; +import zmaster587.advancedRocketry.inventory.TextureResources; +import zmaster587.advancedRocketry.inventory.modules.ModuleContainerPanYOnlyWithScrollCache; +import zmaster587.advancedRocketry.item.ItemOreScanner; +import zmaster587.advancedRocketry.item.ItemSatelliteIdentificationChip; +import zmaster587.advancedRocketry.item.ItemStationChip; +import zmaster587.advancedRocketry.stations.SpaceObjectManager; +import zmaster587.advancedRocketry.stations.SpaceStationObject; +import zmaster587.advancedRocketry.util.StationLandingLocation; + +import zmaster587.libVulpes.client.util.ProgressBarImage; +import zmaster587.libVulpes.LibVulpes; +import zmaster587.libVulpes.gui.CommonResources; +import zmaster587.libVulpes.inventory.GuiHandler; +import zmaster587.libVulpes.inventory.modules.*; +import zmaster587.libVulpes.network.PacketHandler; +import zmaster587.libVulpes.network.PacketMachine; +import zmaster587.libVulpes.tile.multiblock.TileMultiPowerConsumer; +import zmaster587.libVulpes.util.EmbeddedInventory; +import zmaster587.libVulpes.util.IconResource; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.LinkedList; +import java.util.List; + + +/** + * Orbital Registry: satellites + stations + * + * Two tabs: + * 0 - Satellites + * 1 - Stations + * + * Both tabs: + * - Left window: scrollable list of objects (buttons) + * - Right window: detail view for the selected object + * - Slot 0: input chip (sat or station chip) + * - Slot 1: output written chip + * - "Scan" button to populate/refresh the list from server state + */ +public class TileOrbitalRegistry extends TileMultiPowerConsumer + implements IModularInventory, IButtonInventory, IGuiCallback, IInventory { + + // Simple 1x2 structure, same pattern as TileSatelliteBuilder + public static final Object[][][] structure = new Object[][][] { + { { 'c' } } + }; + + // Inventory slots + private static final int SLOT_CHIP_IN = 0; + private static final int SLOT_CHIP_OUT = 1; + + // Tabs + private static final int TAB_SATELLITES = 0; + private static final int TAB_STATIONS = 1; + + // Left list: only slightly wider + private static final int OBS_LIST_BASE_X = 5; + private static final int OBS_LIST_BASE_Y = 32; + private static final int OBS_LIST_SIZE_X = 120; + private static final int OBS_LIST_SIZE_Y = 46; + + // Keep a small gap, give the rest of the width to the detail pane + private static final int OBS_DETAIL_BASE_X = 135; + private static final int OBS_DETAIL_BASE_Y = 32; + private static final int OBS_DETAIL_SIZE_X = 110; + private static final int OBS_DETAIL_SIZE_Y = 46; + + // Chip IO area (same as Observatory asteroid tab) + private static final int OBS_CHIP_X = 5; + private static final int OBS_CHIP_Y = 120; + + // GUI button IDs (client-side) + private static final int GUI_BUTTON_WRITE = 0; + private static final int GUI_BUTTON_SCAN = 1; + + // GUI list offsets (client-side) + private static final short SAT_LIST_OFFSET = 100; + private static final short STATION_LIST_OFFSET = 200; + + // Network IDs (PacketMachine) + private static final byte NET_TAB_SWITCH = 10; + private static final byte NET_BUTTON_SELECT_SAT = 11; + private static final byte NET_BUTTON_WRITE_CHIP = 12; + private static final byte NET_BUTTON_SCAN = 13; + private static final byte NET_BUTTON_SELECT_STAT = 14; + + // Inventory + private final EmbeddedInventory inv; + + // Dimension whose satellites we show (usually effective dim of this tile) + private int satDimId = 0; + + // Selection / last pressed list button + private int lastSatButton = -1; + private long selectedSatId = -1L; + + private int lastStationButton = -1; + private int selectedStationId = -1; + + // Cached scan results (server-side authoritative, synced to client) + private final List satCache = new ArrayList<>(); + private final List stationCache = new ArrayList<>(); + + // Tab module (0 = satellites, 1 = stations) + private final ModuleTab tabModule; + + private static class SatEntry { + long id; + int dimId; + String registryKey; // satellite type / registry id / dataType + int powerGen; + int powerStorage; + long maxData; + } + + private static class StationEntry { + int id; + int dimId; + int orbitingBodyId; + boolean anchored; + boolean hasWarpCore; + int freePads; + } + + public TileOrbitalRegistry() { + this.inv = new EmbeddedInventory(2); + this.powerPerTick = 0; // mostly passive + this.completionTime = 0; + + this.tabModule = new ModuleTab( + 4, 0, 0, + this, + 2, + new String[] { + LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.tab.satellites"), + LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.tab.stations") + }, + new net.minecraft.util.ResourceLocation[][] { + TextureResources.tabData, + TextureResources.tabAsteroid + } + ); + } + + /* ------------------------------------------------------------------------ + * Multiblock basics + * --------------------------------------------------------------------- */ + + @Override + public Object[][][] getStructure() { + return structure; + } + + @Override + public boolean completeStructure(net.minecraft.block.state.IBlockState state) { + boolean result = super.completeStructure(state); + ((zmaster587.libVulpes.block.multiblock.BlockMultiblockMachine) + world.getBlockState(pos).getBlock()) + .setBlockState(world, world.getBlockState(pos), pos, result); + return result; + } + + @Override + public String getMachineName() { + return LibVulpes.proxy.getLocalizedString("tile.orbitalRegistry.name"); + } + + /* ------------------------------------------------------------------------ + * Helpers / scans + * --------------------------------------------------------------------- */ + + private int getEffectiveSatDim() { + if (world == null) { + return satDimId; + } + int eff = DimensionManager.getEffectiveDimId(world, pos).getId(); + if (satDimId == 0) { + satDimId = eff; + } + return satDimId; + } + + // Blacklist for "satellites" that should not appear in the orbital registry + private static final java.util.Set SAT_BLACKLIST = + java.util.Collections.unmodifiableSet( + new java.util.HashSet<>(java.util.Arrays.asList( + "asteroidMiner", + "gasMining" + )) + ); + + + /** + * Build satellite cache from DimensionProperties. + * Only called when Scan is pressed on the satellites tab. + */ + + private void rescanSatellites() { + satCache.clear(); + + int dimId = getEffectiveSatDim(); + DimensionProperties props = DimensionManager.getInstance().getDimensionProperties(dimId); + if (props == null) { + selectedSatId = -1L; + lastSatButton = -1; + return; + } + + java.util.Collection raw = props.getAllSatellites(); + if (raw == null) raw = java.util.Collections.emptyList(); + + List sats = new ArrayList<>(raw); + sats.sort(Comparator.comparingLong(SatelliteBase::getId)); + + for (SatelliteBase sat : sats) { + SatEntry entry = new SatEntry(); + entry.id = sat.getId(); + entry.dimId = sat.getDimensionId(); + + entry.registryKey = ""; + entry.powerGen = 0; + entry.powerStorage = 0; + entry.maxData = 0; + + try { + zmaster587.advancedRocketry.api.satellite.SatelliteProperties sProps = sat.getProperties(); + if (sProps != null) { + String type = sProps.getSatelliteType(); + if (type != null && !type.isEmpty()) { + entry.registryKey = type; + } + entry.powerGen = sProps.getPowerGeneration(); + entry.powerStorage = sProps.getPowerStorage(); + entry.maxData = sProps.getMaxDataStorage(); + } + } catch (Throwable ignored) {} + + // Fallback: derive registry key from the satellite class if properties didn't give one + if (entry.registryKey == null || entry.registryKey.isEmpty()) { + try { + String key = SatelliteRegistry.getKey(sat.getClass()); + if (key != null && !"poo".equals(key)) { // "poo" is the error sentinel in SatelliteRegistry + entry.registryKey = key; + } + } catch (Throwable ignored) {} + } + + // Absolute last-resort fallback so we always have "something" + if (entry.registryKey == null || entry.registryKey.isEmpty()) { + entry.registryKey = sat.getClass().getSimpleName().toLowerCase(); + } + + if (SAT_BLACKLIST.contains(entry.registryKey)) { + continue; + } + /* UNCOMMENT TO EXCLUDE MISSIONS FROM ORBITAL REGISTRY + BLACKLIST OVER SHOULD HOLD FOR NOW + if (sat instanceof zmaster587.advancedRocketry.api.IMission) { + continue; + } + */ + + satCache.add(entry); + } + + // Keep selection if possible + long prevSelected = selectedSatId; + selectedSatId = -1L; + lastSatButton = -1; + + if (prevSelected >= 0L) { + for (int i = 0; i < satCache.size(); i++) { + if (satCache.get(i).id == prevSelected) { + selectedSatId = prevSelected; + lastSatButton = SAT_LIST_OFFSET + i; + break; + } + } + } + } + + /** + * Build station cache from SpaceObjectManager. + * Only called when Scan is pressed on the stations tab. + * + * NOTE: This assumes SpaceObjectManager exposes a way to iterate space objects. + * If your API is different (e.g. getSpaceStations(), getSpaceObjects()), + * adjust the iteration inside this method. + */ + + private void rescanStations() { + stationCache.clear(); + + final SpaceObjectManager manager = SpaceObjectManager.getSpaceManager(); + if (manager == null) { + selectedStationId = -1; + lastStationButton = -1; + return; + } + + final Iterable objects = manager.getSpaceObjects(); + if (objects == null) { + selectedStationId = -1; + lastStationButton = -1; + return; + } + + for (ISpaceObject obj : objects) { + if (obj == null) continue; // ultra-defensive, cheap + + StationEntry entry = new StationEntry(); + entry.id = obj.getId(); + entry.orbitingBodyId = obj.getOrbitingPlanetId(); + entry.anchored = obj.isAnchored(); + + entry.dimId = -1; + entry.hasWarpCore = false; + entry.freePads = 0; + + if (entry.orbitingBodyId == zmaster587.advancedRocketry.api.Constants.INVALID_PLANET + || entry.orbitingBodyId == SpaceObjectManager.WARPDIMID) { + entry.dimId = -1; + } else { + entry.dimId = entry.orbitingBodyId; + } + + if (obj instanceof SpaceStationObject) { + SpaceStationObject station = (SpaceStationObject) obj; + entry.hasWarpCore = station.hasWarpCores; + + int free = 0; + for (StationLandingLocation pad : station.getLandingPads()) { + if (!pad.getOccupied()) { + free++; + } + } + entry.freePads = free; + } + + stationCache.add(entry); + } + + stationCache.sort(Comparator.comparingInt(e -> e.id)); + + int prevSelected = selectedStationId; + selectedStationId = -1; + lastStationButton = -1; + + if (prevSelected >= 0) { + for (int i = 0; i < stationCache.size(); i++) { + if (stationCache.get(i).id == prevSelected) { + selectedStationId = prevSelected; + lastStationButton = STATION_LIST_OFFSET + i; + break; + } + } + } + } + + + private void handleSatelliteSelectionFromButton(int buttonId) { + lastSatButton = buttonId; + int idx = lastSatButton - SAT_LIST_OFFSET; + + if (idx >= 0 && idx < satCache.size()) { + selectedSatId = satCache.get(idx).id; + } else { + selectedSatId = -1L; + } + } + + private void handleStationSelectionFromButton(int buttonId) { + lastStationButton = buttonId; + int idx = lastStationButton - STATION_LIST_OFFSET; + + if (idx >= 0 && idx < stationCache.size()) { + selectedStationId = stationCache.get(idx).id; + } else { + selectedStationId = -1; + } + } + + /** + * Returns a localized display name for a satellite based on its raw name. + * + * - Builds a lang key of the form: + * msg.orbitalregistry.sat.name. + * - If no translation exists (returned string == key), falls back to the raw name. + * - If name is null/empty, uses a generic "unnamed" key. + */ + + private String getLocalizedSatName(SatEntry sat) { + String baseKey = sat.registryKey; + if (baseKey == null || baseKey.isEmpty()) { + baseKey = "unknown"; + } + + // Lang key you will define in the lang file: + // msg.orbitalregistry.sat.name. + String langKey = "msg.orbitalregistry.sat.name." + baseKey; + String localized = LibVulpes.proxy.getLocalizedString(langKey); + + // If missing, LibVulpes usually returns the key itself → then we just show the registryKey as text. + if (localized == null || localized.isEmpty() || localized.equals(langKey)) { + return baseKey; + } + return localized; + } + + private static class WriteCheck { + final boolean ok; + final String tooltipKey; + + WriteCheck(boolean ok, String tooltipKey) { + this.ok = ok; + this.tooltipKey = tooltipKey; + } + + static WriteCheck fail(String key) { + return new WriteCheck(false, key); + } + + static WriteCheck ok(String key) { + return new WriteCheck(true, key); + } + } + + private WriteCheck checkWrite() { + int tab = tabModule.getTab(); + + ItemStack in = getStackInSlot(SLOT_CHIP_IN); + ItemStack out = getStackInSlot(SLOT_CHIP_OUT); + + // Output blocking reason is universal + if (!out.isEmpty()) { + return WriteCheck.fail("msg.orbitalregistry.writechip.hint.output"); + } + + // No input: avoid negative phrasing + if (in.isEmpty() || in.getCount() != 1) { + return WriteCheck.fail("msg.orbitalregistry.writechip.hint.insert"); + } + + // SATELLITES TAB + if (tab == TAB_SATELLITES) { + + // maybe: + // if (satCache.isEmpty()) { + // return WriteCheck.fail("msg.orbitalregistry.writechip.hint.scan"); + // } + + if (selectedSatId < 0L) { + return WriteCheck.fail("msg.orbitalregistry.writechip.hint.select"); + } + + SatelliteBase sat = DimensionManager.getInstance().getSatellite(selectedSatId); + if (sat == null) { + // Optional: could be hint.scan instead of select + return WriteCheck.fail("msg.orbitalregistry.writechip.hint.select"); + } + + boolean isIdChip = in.getItem() instanceof ItemSatelliteIdentificationChip; + boolean isOreScanner = in.getItem() instanceof ItemOreScanner; + + if (!isIdChip && !isOreScanner) { + return WriteCheck.fail("msg.orbitalregistry.writechip.hint.sat.or.idchip"); + } + + if (isOreScanner) { + if (!(sat instanceof zmaster587.advancedRocketry.satellite.SatelliteOreMapping)) { + return WriteCheck.fail("msg.orbitalregistry.writechip.hint.sat.orescanner.only"); + } + return WriteCheck.ok("msg.orbitalregistry.writechip.ok"); + } + + // ID-chip path + if (!sat.isAcceptableControllerItemStack(in)) { + return WriteCheck.fail("msg.orbitalregistry.writechip.hint.sat.badcontroller"); + } + + return WriteCheck.ok("msg.orbitalregistry.writechip.ok"); + } + + // STATIONS TAB + + // maybe: + // if (stationCache.isEmpty()) { + // return WriteCheck.fail("msg.orbitalregistry.writechip.hint.scan"); + // } + + if (!(in.getItem() instanceof ItemStationChip)) { + return WriteCheck.fail("msg.orbitalregistry.writechip.hint.sat.or.stationchip"); + } + + if (selectedStationId < 0) { + return WriteCheck.fail("msg.orbitalregistry.writechip.hint.select"); + } + + StationEntry selected = null; + for (StationEntry e : stationCache) { + if (e.id == selectedStationId) { + selected = e; + break; + } + } + + if (selected == null) { + return WriteCheck.fail("msg.orbitalregistry.writechip.hint.select"); + } + + if (selected.orbitingBodyId == zmaster587.advancedRocketry.api.Constants.INVALID_PLANET) { + return WriteCheck.fail("msg.orbitalregistry.writechip.hint.station.unlaunched"); + } + + return WriteCheck.ok("msg.orbitalregistry.writechip.ok"); + } + + + /* ------------------------------------------------------------------------ + * Chip writing + * --------------------------------------------------------------------- */ + + + private void writeSatelliteChipFromSelection() { + if (world == null || world.isRemote) return; + + SatelliteBase sat = DimensionManager.getInstance().getSatellite(selectedSatId); + if (sat == null) return; + + ItemStack source = decrStackSize(SLOT_CHIP_IN, 1); + if (source.isEmpty()) return; + + if (source.getItem() instanceof ItemOreScanner) { + ItemOreScanner scanner = (ItemOreScanner) source.getItem(); + + if (!(sat instanceof zmaster587.advancedRocketry.satellite.SatelliteOreMapping)) { + setInventorySlotContents(SLOT_CHIP_IN, source); + return; + } + + scanner.setSatelliteID(source, selectedSatId); + setInventorySlotContents(SLOT_CHIP_OUT, source); + + markDirty(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); + return; + } + + SatelliteProperties props = sat.getProperties(); + if (props == null) { + setInventorySlotContents(SLOT_CHIP_IN, source); + return; + } + + ItemStack programmed = sat.getControllerItemStack(source, props); + setInventorySlotContents(SLOT_CHIP_OUT, programmed); + + markDirty(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); + } + + private boolean canWriteChipForCurrentTab() { + return checkWrite().ok; + } + + private void writeChipForCurrentTab() { + if (!checkWrite().ok) return; + + if (tabModule.getTab() == TAB_SATELLITES) { + writeSatelliteChipFromSelection(); + } else { + writeStationChipFromSelection(); + } + } + + /** + * Writes a station chip for the selected space station. + */ + private void writeStationChipFromSelection() { + if (world == null || world.isRemote) return; + + ItemStack sourceChip = decrStackSize(SLOT_CHIP_IN, 1); + if (sourceChip.isEmpty() || !(sourceChip.getItem() instanceof ItemStationChip)) { + return; + } + + ItemStationChip chipItem = (ItemStationChip) sourceChip.getItem(); + chipItem.setUUID(sourceChip, selectedStationId); + + setInventorySlotContents(SLOT_CHIP_OUT, sourceChip); + + markDirty(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); + } + + /* ------------------------------------------------------------------------ + * Core tick / processing + * --------------------------------------------------------------------- */ + + @Override + protected void processComplete() { + } + + @Override + public boolean isRunning() { + return false; + } + + /* ------------------------------------------------------------------------ + * GUI modules + * --------------------------------------------------------------------- */ + + @Override + public List getModules(int ID, EntityPlayer player) { + List modules = new LinkedList<>(); + + // --- Extra right-hand backdrop: stretch main GUI full height with 3 slices --- + if (world != null && world.isRemote) { + + final int extX = 173; + final int guiTopY = 0; + final int guiBottomY = 168; + final int extWidth = 78; + + // TOP: the 86px slice that already lined up with the main GUI top + modules.add(new ModuleImage( + extX, guiTopY, + new IconResource( + 98, 0, + extWidth, 86, + CommonResources.genericBackground + ) + )); + + // MIDDLE: fill from y=86 down to y=168, + modules.add(new ModuleImage( + extX, guiTopY + 86, + new IconResource( + 98, 3, + extWidth, guiBottomY - 86, + CommonResources.genericBackground + ) + )); + + // BOTTOM: the 3px strip that already lined up with the main GUI bottom + modules.add(new ModuleImage( + extX, guiBottomY, + new IconResource( + 98, 168, + extWidth, 3, + CommonResources.genericBackground + ) + )); + } + + modules.add(tabModule); + //no powerbar + //modules.add(new ModulePower(18, 20, getBatteries())); + + final int tab = tabModule.getTab(); + + // ----- CHIP IO + BUTTONS (bottom, same as Observatory) ----- + // Same layout as TileObservatory asteroid tab: (5,120) / (45,120) / 25 / 100 + modules.add(new ModuleTexturedSlotArray( + OBS_CHIP_X, OBS_CHIP_Y, + this, + SLOT_CHIP_IN, SLOT_CHIP_IN + 1, + TextureResources.idChip)); + + modules.add(new ModuleOutputSlotArray( + OBS_CHIP_X + 40, OBS_CHIP_Y, + this, + SLOT_CHIP_OUT, SLOT_CHIP_OUT + 1)); + + // Progress bar behind the write button + modules.add(new ModuleProgress( + OBS_CHIP_X + 20, OBS_CHIP_Y, + 0, + new ProgressBarImage( + 217, 0, 17, 17, + 234, 0, + EnumFacing.DOWN, + TextureResources.progressBars + ), + this + )); + + ModuleButton writeBtn = new ModuleButton( + OBS_CHIP_X + 20, OBS_CHIP_Y, + GUI_BUTTON_WRITE, + "", + this, + zmaster587.libVulpes.inventory.TextureResources.buttonNull, + LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.writechip"), + 17, 17 + ); + WriteCheck wc = checkWrite(); + writeBtn.setToolTipText(LibVulpes.proxy.getLocalizedString(wc.tooltipKey)); + + + modules.add(writeBtn); + + ModuleButton scanBtn = new ModuleButton( + 110, OBS_CHIP_Y, + GUI_BUTTON_SCAN, + LibVulpes.proxy.getLocalizedString("msg.observetory.scan.button"), + this, + zmaster587.libVulpes.inventory.TextureResources.buttonBuild, + LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.scan.tooltip"), + 64, 18 + ); + modules.add(scanBtn); + + // ----- WINDOWS (left list + right detail) ----- + + final int listBaseX = OBS_LIST_BASE_X; + final int listBaseY = OBS_LIST_BASE_Y; + final int listSizeX = OBS_LIST_SIZE_X; + final int listSizeY = OBS_LIST_SIZE_Y; + + final int detailBaseX = OBS_DETAIL_BASE_X; + final int detailBaseY = OBS_DETAIL_BASE_Y; + final int detailSizeX = OBS_DETAIL_SIZE_X; + final int detailSizeY = OBS_DETAIL_SIZE_Y; + + if (world != null && world.isRemote) { + // Left window frame + modules.add(new ModuleScaledImage( + listBaseX - 3, listBaseY - 3, + 3, listBaseY + listSizeY + 6, + TextureResources.verticalBar)); + modules.add(new ModuleScaledImage( + listBaseX + listSizeX, listBaseY - 3, + -3, listBaseY + listSizeY + 6, + TextureResources.verticalBar)); + modules.add(new ModuleScaledImage( + listBaseX, listBaseY - 3, + listSizeX, 3, + TextureResources.horizontalBar)); + modules.add(new ModuleScaledImage( + listBaseX, 2 * listBaseY + listSizeY, + listSizeX, -3, + TextureResources.horizontalBar)); + + // Right window frame + modules.add(new ModuleScaledImage( + detailBaseX - 3, detailBaseY - 3, + 3, detailBaseY + detailSizeY + 6, + TextureResources.verticalBar)); + modules.add(new ModuleScaledImage( + detailBaseX + detailSizeX, detailBaseY - 3, + -3, detailBaseY + detailSizeY + 6, + TextureResources.verticalBar)); + modules.add(new ModuleScaledImage( + detailBaseX, detailBaseY - 3, + detailSizeX, 3, + TextureResources.horizontalBar)); + modules.add(new ModuleScaledImage( + detailBaseX, 2 * detailBaseY + detailSizeY, + detailSizeX, -3, + TextureResources.horizontalBar)); + } + + // Title positions + if (tab == TAB_SATELLITES) { + modules.add(new ModuleText( + 10, 18, + LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.satellites"), + 0x2d2d2d + )); + modules.add(new ModuleText( + OBS_DETAIL_BASE_X - 5, + 18, + LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.details"), + 0x2d2d2d + )); + + buildSatelliteListWindow(modules, listBaseX, listBaseY, listSizeX, listSizeY); + buildSatelliteDetailWindow(modules, detailBaseX + 3, detailBaseY + 3); + + } else { + modules.add(new ModuleText( + 10, 18, + LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.stations"), + 0x2d2d2d + )); + modules.add(new ModuleText( + OBS_DETAIL_BASE_X - 5, + 18, + LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.details"), + 0x2d2d2d + )); + + buildStationListWindow(modules, listBaseX, listBaseY, listSizeX, listSizeY); + buildStationDetailWindow(modules, detailBaseX + 3, detailBaseY + 3); + } + + return modules; + } + + private void buildSatelliteListWindow(List modules, + int baseX, int baseY, int sizeX, int sizeY) { + + List satButtons = new LinkedList<>(); + + for (int i = 0; i < satCache.size(); i++) { + SatEntry sat = satCache.get(i); + + int buttonId = SAT_LIST_OFFSET + i; + String displayName = getLocalizedSatName(sat); + String label = String.format("ID %d %s", sat.id, displayName); + + ModuleButton button = new ModuleButton( + 0, + i * 18, + buttonId, + label, + this, + TextureResources.buttonAsteroid, + OBS_LIST_SIZE_X, 18 + ); + + if (sat.id == selectedSatId) { + button.setColor(0xFFFF00); + } + + satButtons.add(button); + } + + if (!satButtons.isEmpty()) { + ModuleContainerPanYOnlyWithScrollCache panLeft = + new ModuleContainerPanYOnlyWithScrollCache( + baseX, baseY, + satButtons, new LinkedList<>(), + null, + sizeX - 2, sizeY, + 0, -48, + 0, 72 + ); + modules.add(panLeft); + } + } + + + private void buildSatelliteDetailWindow(List modules, int startX, int startY) { + int x = startX; + int y = startY; + + if (selectedSatId < 0L || satCache.isEmpty()) { + modules.add(new ModuleText( + x, y, + LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.nosel"), + 0xAA0000 + )); + return; + } + + SatEntry selected = null; + for (SatEntry e : satCache) { + if (e.id == selectedSatId) { + selected = e; + break; + } + } + + if (selected == null) { + modules.add(new ModuleText( + x, y, + LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.notfound"), + 0xAA0000 + )); + return; + } + + // ----- ID: ----- + String idLabel = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.id"); // "ID:" + String idLine = idLabel + " " + selected.id; + modules.add(new ModuleText(x, y, idLine, 0x2d2d2d)); + y += 10; + + // ----- Type: localized satellite name (from registryKey) ----- + String typeLabel = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.type"); // "Type:" + String typeLine = typeLabel + " " + getLocalizedSatName(selected); + modules.add(new ModuleText(x, y, typeLine, 0x2d2d2d)); + y += 10; + + // ----- Dim: ----- + String dimLabel = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.dimid"); // "Dim:" + String dimLine = dimLabel + " " + selected.dimId; + modules.add(new ModuleText(x, y, dimLine, 0x2d2d2d)); + y += 10; + + // ----- Orbiting: ----- + String orbitLabel = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.orbit"); // "Orbiting:" + + String orbitName; + DimensionProperties bodyProps = + DimensionManager.getInstance().getDimensionProperties(selected.dimId); + if (bodyProps != null) { + orbitName = bodyProps.getName(); + } else { + orbitName = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.dimid.none"); + } + + String orbitLine = orbitLabel + " " + orbitName; + modules.add(new ModuleText(x, y, orbitLine, 0x2d2d2d)); + y += 10; + + // ----- Power + data ----- + if (selected.powerGen != 0 || selected.powerStorage != 0 || selected.maxData != 0) { + String pwrGenLabel = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.sat.pwrgen"); + String pwrStoreLabel = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.sat.pwrstore"); + String maxDataLabel = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.sat.maxdata"); + + modules.add(new ModuleText(x, y, pwrGenLabel + " " + selected.powerGen, 0x2d2d2d)); + y += 10; + modules.add(new ModuleText(x, y, pwrStoreLabel + " " + selected.powerStorage, 0x2d2d2d)); + y += 10; + modules.add(new ModuleText(x, y, maxDataLabel + " " + selected.maxData, 0x2d2d2d)); + y += 10; + } +} + + + + private void buildStationListWindow(List modules, + int baseX, int baseY, int sizeX, int sizeY) { + + List stationButtons = new LinkedList<>(); + + for (int i = 0; i < stationCache.size(); i++) { + StationEntry st = stationCache.get(i); + + int buttonId = STATION_LIST_OFFSET + i; + + // Short type text (localized) + String typeShort = st.hasWarpCore + ? LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.type.starshiplist") + : LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.type.station"); + + // "ID" label from lang, then "ID " + String listPrefix = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.listentry"); + String label = listPrefix + " " + st.id + " " + typeShort; + + + ModuleButton button = new ModuleButton( + 0, + i * 18, + buttonId, + label, + this, + TextureResources.buttonAsteroid, + OBS_LIST_SIZE_X, 18 + ); + + if (st.id == selectedStationId) { + button.setColor(0xFFFF00); + } + + stationButtons.add(button); + } + + if (!stationButtons.isEmpty()) { + ModuleContainerPanYOnlyWithScrollCache panLeft = + new ModuleContainerPanYOnlyWithScrollCache( + baseX, baseY, + stationButtons, new LinkedList<>(), + null, + sizeX - 2, sizeY, + 0, -48, + 0, 72 + ); + modules.add(panLeft); + } + } + + + private void buildStationDetailWindow(List modules, int startX, int startY) { + int x = startX; + int y = startY; + + if (selectedStationId < 0 || stationCache.isEmpty()) { + modules.add(new ModuleText( + x, y, + LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.nosel"), + 0xAA0000 + )); + return; + } + + StationEntry selected = null; + for (StationEntry e : stationCache) { + if (e.id == selectedStationId) { + selected = e; + break; + } + } + + if (selected == null) { + modules.add(new ModuleText( + x, y, + LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.notfound"), + 0xAA0000 + )); + return; + } + + // ----- ID: ----- + String idLabel = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.id"); // e.g. "ID:" + String idLine = idLabel + " " + selected.id; + modules.add(new ModuleText(x, y, idLine, 0x2d2d2d)); + y += 10; + + // ----- Type: ----- + String typeLabel = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.type"); // e.g. "Type:" + String typeKey = selected.hasWarpCore + ? LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.type.starship") + : LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.type.station"); + String typeLine = typeLabel + " " + typeKey; + modules.add(new ModuleText(x, y, typeLine, 0x2d2d2d)); + y += 10; + + // ----- DimID: ----- + String dimText; + if (selected.orbitingBodyId == zmaster587.advancedRocketry.api.Constants.INVALID_PLANET + || selected.orbitingBodyId == SpaceObjectManager.WARPDIMID) { + // No real body below → None + dimText = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.dimid.none"); + } else { + dimText = Integer.toString(selected.dimId); + } + String dimLabel = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.dimid"); // e.g. "DimID:" + String dimLine = dimLabel + " " + dimText; + modules.add(new ModuleText(x, y, dimLine, 0x2d2d2d)); + y += 10; + + // ----- Orbiting: ----- + String orbitName; + String systemName; + + if (selected.orbitingBodyId == zmaster587.advancedRocketry.api.Constants.INVALID_PLANET + || selected.orbitingBodyId == SpaceObjectManager.WARPDIMID) { + // Treat as unlaunched / no system + orbitName = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.orbit.unlaunched"); + systemName = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.system.none"); // e.g. "None" + } else { + DimensionProperties bodyProps = + zmaster587.advancedRocketry.dimension.DimensionManager + .getInstance().getDimensionProperties(selected.orbitingBodyId); + + if (bodyProps != null) { + orbitName = bodyProps.getName(); + + // Try to get star/system name + if (bodyProps.getStar() != null && bodyProps.getStar().getName() != null) { + systemName = bodyProps.getStar().getName(); + } else { + systemName = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.system.unknown"); + } + } else { + // Fallback: raw ID, unknown system + orbitName = Integer.toString(selected.orbitingBodyId); + systemName = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.system.unknown"); + } + } + + String orbitLabel = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.orbit"); // "Orbiting:" + String orbitLine = orbitLabel + " " + orbitName; + modules.add(new ModuleText(x, y, orbitLine, 0x2d2d2d)); + y += 10; + + // ----- System: ----- (NEW) + String systemLabel = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.system"); // "System:" + String systemLine = systemLabel + " " + systemName; + modules.add(new ModuleText(x, y, systemLine, 0x2d2d2d)); + y += 10; + + + // ----- Free landingpads: <#freepads> ----- + String padsLabel = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.freepads"); // "Free landingpads:" + String padsLine = padsLabel + " " + selected.freePads; + modules.add(new ModuleText(x, y, padsLine, 0x2d2d2d)); + y += 10; + + // ----- Anchored: yes/no ----- + String anchoredLabel = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.anchored"); // "Anchored:" + String anchoredYes = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.anchored.yes"); + String anchoredNo = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.anchored.no"); + String anchoredVal = selected.anchored ? anchoredYes : anchoredNo; + String anchoredLine = anchoredLabel + " " + anchoredVal; + modules.add(new ModuleText(x, y, anchoredLine, 0x2d2d2d)); + y += 10; + } + + /* ------------------------------------------------------------------------ + * Button handling + * --------------------------------------------------------------------- */ + + @Override + public void onInventoryButtonPressed(int buttonId) { + // Client → server via PacketMachine + if (world != null && world.isRemote) { + if (buttonId == GUI_BUTTON_WRITE) { + PacketHandler.sendToServer(new PacketMachine(this, NET_BUTTON_WRITE_CHIP)); + + } else if (buttonId == GUI_BUTTON_SCAN) { + PacketHandler.sendToServer(new PacketMachine(this, NET_BUTTON_SCAN)); + + } else if (buttonId >= SAT_LIST_OFFSET && buttonId < STATION_LIST_OFFSET) { + // NEW: update client-side selection immediately + lastSatButton = buttonId; + handleSatelliteSelectionFromButton(buttonId); + + PacketHandler.sendToServer(new PacketMachine(this, NET_BUTTON_SELECT_SAT)); + + } else if (buttonId >= STATION_LIST_OFFSET) { + // NEW: update client-side selection immediately + lastStationButton = buttonId; + handleStationSelectionFromButton(buttonId); + + PacketHandler.sendToServer(new PacketMachine(this, NET_BUTTON_SELECT_STAT)); + } + return; + } + + // Server-side fallback (normally PacketMachine + useNetworkData) + if (buttonId == GUI_BUTTON_WRITE) { + writeChipForCurrentTab(); + } else if (buttonId == GUI_BUTTON_SCAN) { + if (tabModule.getTab() == TAB_SATELLITES) { + rescanSatellites(); + } else { + rescanStations(); + } + markDirty(); + } else if (buttonId >= SAT_LIST_OFFSET && buttonId < STATION_LIST_OFFSET) { + handleSatelliteSelectionFromButton(buttonId); + } else if (buttonId >= STATION_LIST_OFFSET) { + handleStationSelectionFromButton(buttonId); + } + } + + + @Override + public void onModuleUpdated(ModuleBase module) { + // Tab switched; tell server to update and reopen GUI + PacketHandler.sendToServer(new PacketMachine(this, NET_TAB_SWITCH)); + } + + /* ------------------------------------------------------------------------ + * INetworkMachine: custom packets + * --------------------------------------------------------------------- */ + + @Override + public void writeDataToNetwork(ByteBuf out, byte id) { + super.writeDataToNetwork(out, id); + + if (id == NET_TAB_SWITCH) { + out.writeShort(tabModule.getTab()); + } else if (id == NET_BUTTON_SELECT_SAT) { + out.writeShort(lastSatButton); + } else if (id == NET_BUTTON_SELECT_STAT) { + out.writeShort(lastStationButton); + } + } + + @Override + public void readDataFromNetwork(ByteBuf in, byte packetId, NBTTagCompound nbt) { + super.readDataFromNetwork(in, packetId, nbt); + + if (packetId == NET_TAB_SWITCH) { + nbt.setShort("tab", in.readShort()); + } else if (packetId == NET_BUTTON_SELECT_SAT) { + nbt.setShort("buttonSat", in.readShort()); + } else if (packetId == NET_BUTTON_SELECT_STAT) { + nbt.setShort("buttonStation", in.readShort()); + } + } + + @Override + public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompound nbt) { + super.useNetworkData(player, side, id, nbt); + + if (!world.isRemote) { + if (id == NET_TAB_SWITCH) { + tabModule.setTab(nbt.getShort("tab")); + player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), + getWorld(), pos.getX(), pos.getY(), pos.getZ()); + + } else if (id == NET_BUTTON_SELECT_SAT) { + int btn = nbt.getShort("buttonSat"); + handleSatelliteSelectionFromButton(btn); + markDirty(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); + player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), + getWorld(), pos.getX(), pos.getY(), pos.getZ()); + + } else if (id == NET_BUTTON_SELECT_STAT) { + int btn = nbt.getShort("buttonStation"); + handleStationSelectionFromButton(btn); + markDirty(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); + player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), + getWorld(), pos.getX(), pos.getY(), pos.getZ()); + + } else if (id == NET_BUTTON_WRITE_CHIP) { + writeChipForCurrentTab(); + player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), + getWorld(), pos.getX(), pos.getY(), pos.getZ()); + + } else if (id == NET_BUTTON_SCAN) { + if (tabModule.getTab() == TAB_SATELLITES) { + rescanSatellites(); + } else { + rescanStations(); + } + // List contents changed → reset scroll cache + ModuleContainerPanYOnlyWithScrollCache.clearScrollCache(); + + markDirty(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); + player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), + getWorld(), pos.getX(), pos.getY(), pos.getZ()); + } + } + } + + /* ------------------------------------------------------------------------ + * Persistent state (world save + client sync) + * --------------------------------------------------------------------- */ + + @Override + protected void writeNetworkData(NBTTagCompound nbt) { + super.writeNetworkData(nbt); + writeCommonNBT(nbt); + } + + @Override + protected void readNetworkData(NBTTagCompound nbt) { + super.readNetworkData(nbt); + readCommonNBT(nbt); + } + + @Override + public NBTTagCompound writeToNBT(NBTTagCompound nbt) { + super.writeToNBT(nbt); + inv.writeToNBT(nbt); + writeCommonNBT(nbt); + return nbt; + } + + @Override + public void readFromNBT(NBTTagCompound nbt) { + super.readFromNBT(nbt); + inv.readFromNBT(nbt); + readCommonNBT(nbt); + } + + private void writeCommonNBT(NBTTagCompound nbt) { + nbt.setInteger("satDimId", satDimId); + nbt.setInteger("lastSatButton", lastSatButton); + nbt.setLong("selectedSatId", selectedSatId); + nbt.setInteger("lastStationButton", lastStationButton); + nbt.setInteger("selectedStationId", selectedStationId); + + // Satellite cache + NBTTagList satList = new NBTTagList(); + for (SatEntry e : satCache) { + NBTTagCompound tag = new NBTTagCompound(); + tag.setLong("id", e.id); + tag.setInteger("dimId", e.dimId); + tag.setString("registryKey", e.registryKey == null ? "" : e.registryKey); + tag.setInteger("powerGen", e.powerGen); + tag.setInteger("powerStorage", e.powerStorage); + tag.setLong("maxData", e.maxData); + satList.appendTag(tag); + } + nbt.setTag("satCache", satList); + + + + // Station cache + NBTTagList stationList = new NBTTagList(); + for (StationEntry e : stationCache) { + NBTTagCompound tag = new NBTTagCompound(); + tag.setInteger("id", e.id); + tag.setInteger("dimId", e.dimId); + tag.setInteger("orbitingBodyId", e.orbitingBodyId); + tag.setBoolean("anchored", e.anchored); + tag.setBoolean("hasWarpCore", e.hasWarpCore); + tag.setInteger("freePads", e.freePads); + stationList.appendTag(tag); + } + nbt.setTag("stationCache", stationList); + + } + + private void readCommonNBT(NBTTagCompound nbt) { + satDimId = nbt.getInteger("satDimId"); + lastSatButton = nbt.getInteger("lastSatButton"); + selectedSatId = nbt.getLong("selectedSatId"); + lastStationButton = nbt.getInteger("lastStationButton"); + selectedStationId = nbt.getInteger("selectedStationId"); + + satCache.clear(); + if (nbt.hasKey("satCache")) { + NBTTagList satList = nbt.getTagList("satCache", Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < satList.tagCount(); i++) { + NBTTagCompound tag = satList.getCompoundTagAt(i); + SatEntry e = new SatEntry(); + e.id = tag.getLong("id"); + e.dimId = tag.getInteger("dimId"); + e.registryKey = tag.getString("registryKey"); + e.powerGen = tag.getInteger("powerGen"); + e.powerStorage= tag.getInteger("powerStorage"); + e.maxData = tag.getLong("maxData"); + satCache.add(e); + } + } + + + stationCache.clear(); + if (nbt.hasKey("stationCache")) { + NBTTagList stationList = nbt.getTagList("stationCache", Constants.NBT.TAG_COMPOUND); + for (int i = 0; i < stationList.tagCount(); i++) { + NBTTagCompound tag = stationList.getCompoundTagAt(i); + StationEntry e = new StationEntry(); + e.id = tag.getInteger("id"); + e.dimId = tag.getInteger("dimId"); // NEW + e.orbitingBodyId = tag.getInteger("orbitingBodyId"); + e.anchored = tag.getBoolean("anchored"); + e.hasWarpCore = tag.getBoolean("hasWarpCore"); // NEW + e.freePads = tag.getInteger("freePads"); // NEW + stationCache.add(e); + } + } + } + + /* ------------------------------------------------------------------------ + * Inventory plumbing (2 slots) + * --------------------------------------------------------------------- */ + + @Override + public int getSizeInventory() { + return inv.getSizeInventory(); + } + + @Override + @Nonnull + public ItemStack getStackInSlot(int slot) { + return inv.getStackInSlot(slot); + } + + @Override + @Nonnull + public ItemStack decrStackSize(int slot, int amount) { + return inv.decrStackSize(slot, amount); + } + + @Override + public void setInventorySlotContents(int slot, @Nonnull ItemStack stack) { + inv.setInventorySlotContents(slot, stack); + } + + @Override + public boolean hasCustomName() { + return inv.hasCustomName(); + } + + @Override + public int getInventoryStackLimit() { + return 1; + } + + @Override + public boolean isUsableByPlayer(@Nullable EntityPlayer player) { + return player != null && player.getDistanceSq(pos) < 4096; + } + + @Override + public void openInventory(EntityPlayer player) { + inv.openInventory(player); + } + + @Override + public void closeInventory(EntityPlayer player) { + inv.closeInventory(player); + } + + @Override + public boolean isItemValidForSlot(int slot, @Nonnull ItemStack stack) { + if (slot == SLOT_CHIP_IN) { + if (stack.getCount() != 1) return false; + Item item = stack.getItem(); + + return (item instanceof ItemSatelliteIdentificationChip) + || (item instanceof ItemStationChip) + || (item instanceof ItemOreScanner); + } + return false; + } + + + @Override + @Nonnull + public ItemStack removeStackFromSlot(int index) { + return inv.removeStackFromSlot(index); + } + + @Override + public int getField(int id) { + return inv.getField(id); + } + + @Override + public void setField(int id, int value) { + inv.setField(id, value); + } + + @Override + public int getFieldCount() { + return inv.getFieldCount(); + } + + @Override + public void clear() { + inv.clear(); + } + + @Override + public boolean isEmpty() { + return inv.isEmpty(); + } + + @Override + @Nullable + public String getName() { + return null; + } + + @Override + public void invalidate() { + super.invalidate(); + + // Optional but nice to keep state sane + satCache.clear(); + stationCache.clear(); + selectedSatId = -1; + selectedStationId = -1; + lastSatButton = -1; + lastStationButton = -1; + + // Critical: reset static scroll cache so containers don't reuse old offsets + ModuleContainerPanYOnlyWithScrollCache.clearScrollCache(); + } + + @Override + public void onChunkUnload() { + super.onChunkUnload(); + ModuleContainerPanYOnlyWithScrollCache.clearScrollCache(); + } + +} From a7da44fd99f7d8a6cca54b2faf9ed56e540e25a8 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 13 Dec 2025 12:34:13 +0100 Subject: [PATCH 346/424] Refactor update method and improve state handling --- .../satellite/TileTerraformingTerminal.java | 69 ++++++++++++++----- 1 file changed, 52 insertions(+), 17 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileTerraformingTerminal.java b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileTerraformingTerminal.java index 8a1a8eed1..d508a37e6 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileTerraformingTerminal.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileTerraformingTerminal.java @@ -127,30 +127,43 @@ public void setInventorySlotContents(int slot, @Nonnull ItemStack stack) { @Override public void update() { - super.update(); - boolean has_redstone = world.isBlockIndirectlyGettingPowered(getPos()) != 0; + + // Fast path: truly idle — no chip and never enabled + if (getStackInSlot(0).isEmpty() && !was_enabled_last_tick) { + return; + } + int powerrequired = 80; //120; + if (!world.isRemote) { + boolean has_redstone = world.isBlockIndirectlyGettingPowered(getPos()) != 0; + boolean has_valid = hasValidBiomeChanger(); - if ((world.getTotalWorldTime() + 6) % 21 == 0) - PacketHandler.sendToNearby(new PacketMachine(this, (byte) 22), world.provider.getDimension(), pos, 16); + // Only sync when there’s actually a biome changer present + if (has_valid && (world.getTotalWorldTime() + 6) % 21 == 0) { + PacketHandler.sendToNearby(new PacketMachine(this, (byte) 22), + world.provider.getDimension(), pos, 16); + } - if (hasValidBiomeChanger() && has_redstone) { + if (has_valid && has_redstone) { was_enabled_last_tick = true; - if(!world.getBlockState(pos).getValue(BlockTileTerraformer.STATE)){ - world.setBlockState(pos, world.getBlockState(pos).withProperty(BlockTileTerraformer.STATE, true), 3); + if (!world.getBlockState(pos).getValue(BlockTileTerraformer.STATE)) { + world.setBlockState(pos, + world.getBlockState(pos).withProperty(BlockTileTerraformer.STATE, true), 3); } Item biomeChanger = getStackInSlot(0).getItem(); if (biomeChanger instanceof ItemBiomeChanger) { - SatelliteBiomeChanger sat = (SatelliteBiomeChanger) ItemSatelliteIdentificationChip.getSatellite(getStackInSlot(0)); + SatelliteBiomeChanger sat = (SatelliteBiomeChanger) + ItemSatelliteIdentificationChip.getSatellite(getStackInSlot(0)); sat_power_per_tick = sat.getPowerPerTick(); randomblocks_per_tick = (float) sat_power_per_tick / powerrequired; } } else { was_enabled_last_tick = false; - if(world.getBlockState(pos).getValue(BlockTileTerraformer.STATE)){ - world.setBlockState(pos, world.getBlockState(pos).withProperty(BlockTileTerraformer.STATE, false), 3); + if (world.getBlockState(pos).getValue(BlockTileTerraformer.STATE)) { + world.setBlockState(pos, + world.getBlockState(pos).withProperty(BlockTileTerraformer.STATE, false), 3); } } } @@ -207,24 +220,46 @@ public void update() { public void updateInventoryInfo() { if (moduleText != null) { - if (hasValidBiomeChanger() && world.isBlockIndirectlyGettingPowered(getPos()) != 0) { BigDecimal bd = new BigDecimal(randomblocks_per_tick); bd = bd.setScale(2, RoundingMode.HALF_UP); - moduleText.setText("Terraforming planet...\n" + - "\nPower generation: " + sat_power_per_tick + - "\nBlocks per tick: " + bd); + String header = LibVulpes.proxy.getLocalizedString("msg.terraformingterminal.terraforming"); + String powerLabel = LibVulpes.proxy.getLocalizedString("msg.terraformingterminal.powergen"); + String blocksLabel = LibVulpes.proxy.getLocalizedString("msg.terraformingterminal.blockspertick"); + + moduleText.setText( + header + "\n" + + "\n" + powerLabel + " " + sat_power_per_tick + + "\n" + blocksLabel + " " + bd + ); } else if (hasValidBiomeChanger()) { - moduleText.setText("Provide redstone signal\nto start the process"); + + String redstoneLine1 = LibVulpes.proxy.getLocalizedString("msg.terraformingterminal.needredstone.line1"); + String redstoneLine2 = LibVulpes.proxy.getLocalizedString("msg.terraformingterminal.needredstone.line2"); + + moduleText.setText( + redstoneLine1 + "\n" + + redstoneLine2 + ); + } else { - moduleText.setText("\nPlace a Biome Changer Remote\nhere to make the Satellite\nterraform the entire planet"); - } + String insertLine1 = LibVulpes.proxy.getLocalizedString("msg.terraformingterminal.insertchip.line1"); + String insertLine2 = LibVulpes.proxy.getLocalizedString("msg.terraformingterminal.insertchip.line2"); + String insertLine3 = LibVulpes.proxy.getLocalizedString("msg.terraformingterminal.insertchip.line3"); + + moduleText.setText( + "\n" + insertLine1 + "\n" + + insertLine2 + "\n" + + insertLine3 + ); + } } } + public boolean hasValidBiomeChanger() { ItemStack biomeChanger = getStackInSlot(0); SatelliteBase satellite; From 5b11fe00802795bc2e953cf611ccd98cbbc34793 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:44:27 +0100 Subject: [PATCH 347/424] Add blockstates for databusbig model --- .../blockstates/databusbig.json | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/main/resources/assets/advancedrocketry/blockstates/databusbig.json diff --git a/src/main/resources/assets/advancedrocketry/blockstates/databusbig.json b/src/main/resources/assets/advancedrocketry/blockstates/databusbig.json new file mode 100644 index 000000000..0328cba2f --- /dev/null +++ b/src/main/resources/assets/advancedrocketry/blockstates/databusbig.json @@ -0,0 +1,23 @@ +{ + "variants": { + "varient=0": { "model": "advancedrocketry:databusbig" }, + "varient=1": { "model": "advancedrocketry:databusbig" }, + "varient=2": { "model": "advancedrocketry:databusbig" }, + "varient=3": { "model": "advancedrocketry:databusbig" }, + "varient=4": { "model": "advancedrocketry:databusbig" }, + "varient=5": { "model": "advancedrocketry:databusbig" }, + "varient=6": { "model": "advancedrocketry:databusbig" }, + "varient=7": { "model": "advancedrocketry:databusbig" }, + + "varient=8": { "model": "advancedrocketry:databusbig" }, + "varient=9": { "model": "advancedrocketry:databusbig" }, + "varient=10": { "model": "advancedrocketry:databusbig" }, + "varient=11": { "model": "advancedrocketry:databusbig" }, + "varient=12": { "model": "advancedrocketry:databusbig" }, + "varient=13": { "model": "advancedrocketry:databusbig" }, + "varient=14": { "model": "advancedrocketry:databusbig" }, + "varient=15": { "model": "advancedrocketry:databusbig" }, + + "inventory": { "model": "advancedrocketry:databusbig" } + } +} From 809cd3cf1a7d7340c1a4e45d0cbce502a248bd14 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:44:52 +0100 Subject: [PATCH 348/424] Refactor VoidDrill class for better performance --- .../orbitallaserdrill/VoidDrill.java | 198 +++++++++++------- 1 file changed, 128 insertions(+), 70 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/VoidDrill.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/VoidDrill.java index 89a2ae7f8..510ef554d 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/VoidDrill.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/VoidDrill.java @@ -21,76 +21,90 @@ */ class VoidDrill extends AbstractDrill { - private final Random random; - private List ores; - private boolean planetOresInitialized; + private final Random random = new Random(); + private final List ores = new ArrayList<>(); + private boolean voidCobble; // performance optimization: if true, cobble is not even generated + private int opCounter = 0; // counts operations when voidCobble is true + private static final ItemStack[] EMPTY = new ItemStack[0]; VoidDrill() { - this.random = new Random(); - this.planetOresInitialized = false; loadGlobalOres(); } + void setVoidCobble(boolean voidCobble) { + this.voidCobble = voidCobble; + } + private void loadGlobalOres() { - //isEmpty check because is called in post init to register for holo projector - if (ores == null && !ARConfiguration.getCurrentConfig().standardLaserDrillOres.isEmpty()) { - ores = new ArrayList<>(); + ores.clear(); - for (int i = 0; i < ARConfiguration.getCurrentConfig().standardLaserDrillOres.size(); i++) { - String oreDictName = ARConfiguration.getCurrentConfig().standardLaserDrillOres.get(i); + // isEmpty check because is called in post init to register for holo projector + List configOres = ARConfiguration.getCurrentConfig().standardLaserDrillOres; + if (configOres == null || configOres.isEmpty()) { + return; // we'll handle empty list gracefully in performOperation + } - String[] args = oreDictName.split(":"); + for (String oreDictName : configOres) { + if (oreDictName == null || oreDictName.isEmpty()) { + continue; + } - List globalOres = OreDictionary.getOres(args[0]); + String[] args = oreDictName.split(":"); - if (globalOres != null && !globalOres.isEmpty()) { - int amt = 1; - if (args.length > 1) { - try { - amt = Integer.parseInt(args[1]); - } catch (NumberFormatException ignored) { - } - } - ores.add(new ItemStack(globalOres.get(0).getItem(), amt, globalOres.get(0).getItemDamage())); - } else { - String[] splitStr = oreDictName.split(":"); - String name; + // First try ore dictionary entry (e.g. "oreIron:2") + List globalOres = OreDictionary.getOres(args[0]); + if (globalOres != null && !globalOres.isEmpty()) { + int amt = 1; + if (args.length > 1) { try { - name = splitStr[0] + ":" + splitStr[1]; - } catch (IndexOutOfBoundsException e) { - AdvancedRocketry.logger.warn("Unexpected ore name: \"" + oreDictName + "\" during laser drill harvesting"); - continue; + amt = Integer.parseInt(args[1]); + } catch (NumberFormatException ignored) { } + } + ItemStack base = globalOres.get(0); + ores.add(new ItemStack(base.getItem(), amt, base.getItemDamage())); + continue; + } - int meta = 0; - int size = 1; - //format: "name meta size" - if (splitStr.length > 2) { - try { - meta = Integer.parseInt(splitStr[2]); - } catch (NumberFormatException ignored) { - } - } - if (splitStr.length > 3) { - try { - size = Integer.parseInt(splitStr[3]); - } catch (NumberFormatException ignored) { - } - } + // Fallback: "modid:blockname[:meta[:size]]" + String[] splitStr = oreDictName.split(":"); + String name; + try { + name = splitStr[0] + ":" + splitStr[1]; + } catch (IndexOutOfBoundsException e) { + AdvancedRocketry.logger.warn("Unexpected ore name: \"{}\" during laser drill harvesting", oreDictName); + continue; + } - ItemStack stack = ItemStack.EMPTY; - Block block = Block.getBlockFromName(name); - if (block == null) { - Item item = Item.getByNameOrId(name); - if (item != null) - stack = new ItemStack(item, size, meta); - } else - stack = new ItemStack(block, size, meta); - - if (!stack.isEmpty()) - ores.add(stack); + int meta = 0; + int size = 1; + if (splitStr.length > 2) { + try { + meta = Integer.parseInt(splitStr[2]); + } catch (NumberFormatException ignored) { + } + } + if (splitStr.length > 3) { + try { + size = Integer.parseInt(splitStr[3]); + } catch (NumberFormatException ignored) { } } + + ItemStack stack = ItemStack.EMPTY; + Block block = Block.getBlockFromName(name); + if (block == null) { + Item item = Item.getByNameOrId(name); + if (item != null) { + stack = new ItemStack(item, size, meta); + } + } else { + stack = new ItemStack(block, size, meta); + } + + if (!stack.isEmpty()) { + ores.add(stack); + } } } @@ -99,41 +113,85 @@ private void loadGlobalOres() { * * @return The ItemStacks produced by this tick of drilling */ + @Override ItemStack[] performOperation() { - ArrayList items = new ArrayList<>(); - if (random.nextInt(10) == 0) { - ItemStack item = ores.get(random.nextInt(ores.size())); - ItemStack newStack = item.copy(); - items.add(newStack); - } else - items.add(new ItemStack(Blocks.COBBLESTONE, 1)); - ItemStack[] stacks = new ItemStack[items.size()]; + // --- VOID-COBBLE MODE: only ores, every 10th operation --- + if (voidCobble) { + if (ores.isEmpty()) { + // No configured ores -> nothing to give + return EMPTY; + } - stacks = items.toArray(stacks); + opCounter++; + // 9 out of 10 operations: no items at all + if (opCounter % 10 != 0) { + return EMPTY; + } + + // 10th operation: roll one ore stack + ItemStack[] result = new ItemStack[1]; + ItemStack template = ores.get(random.nextInt(ores.size())); + result[0] = template.copy(); + return result; + } + + // --- NORMAL MODE: 10% ore, 90% cobble (old behavior) --- + + // 10% ore + boolean produceOre = !ores.isEmpty() && random.nextInt(10) == 0; - return stacks; + if (produceOre) { + ItemStack[] result = new ItemStack[1]; + ItemStack template = ores.get(random.nextInt(ores.size())); + result[0] = template.copy(); + return result; + } + + // Cobble case + ItemStack[] result = new ItemStack[1]; + result[0] = new ItemStack(Blocks.COBBLESTONE, 1); + return result; } + + + @Override boolean activate(World world, int x, int z) { - // Ideally, this should be done in the constructor, but the world provider is null there for reasons unknown, so this gets delayed until first activation - this.ores = null; - this.planetOresInitialized = false; + if (world == null) { + return false; + } + + // Rebuild base list from config loadGlobalOres(); - DimensionProperties dimProperties = DimensionManager.getInstance().getDimensionProperties(world.provider.getDimension()); - ores.addAll(dimProperties.laserDrillOres.stream().filter(s -> !ores.contains(s)).collect(Collectors.toSet())); - this.planetOresInitialized = true; + opCounter = 0; // reset when drill is (re)started + + DimensionProperties dimProperties = + DimensionManager.getInstance().getDimensionProperties(world.provider.getDimension()); + + if (dimProperties != null && dimProperties.laserDrillOres != null) { + for (ItemStack s : dimProperties.laserDrillOres) { + if (s != null && !ores.contains(s)) { + ores.add(s); + } + } + } return true; } + + @Override void deactivate() { + // No state required } + @Override boolean isFinished() { return false; } + @Override boolean needsRestart() { return false; } From f277e0e7d446ea10b75ce4c4fadd54a867250013 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:46:02 +0100 Subject: [PATCH 349/424] Enhance performance and button setup in TileOrbitalLaserDrill Added performance tweaks and improved button initialization for the orbital laser drill. when using drillplanet=false --- .../TileOrbitalLaserDrill.java | 277 +++++++++++++----- 1 file changed, 204 insertions(+), 73 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/TileOrbitalLaserDrill.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/TileOrbitalLaserDrill.java index 9e3ea86de..1191731a6 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/TileOrbitalLaserDrill.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/orbitallaserdrill/TileOrbitalLaserDrill.java @@ -92,8 +92,14 @@ public class TileOrbitalLaserDrill extends TileMultiPowerConsumer implements IGu private boolean terraformingstatus; boolean client_first_loop = true; // for render bug on client //private Ticket ticket; // this is useless anyway because it would not load the energy supply system and the laser would run out of energy - + + // Performance tweaks + private int lastTfDim = Integer.MIN_VALUE; + private boolean voidCobble; + private ModuleButton voidCobbleBtn; int last_orbit_dim; + private final boolean voidMiningMode; + TerraformingHelper t; WorldServer orbitWorld; @@ -101,6 +107,8 @@ public class TileOrbitalLaserDrill extends TileMultiPowerConsumer implements IGu public TileOrbitalLaserDrill() { super(); + this.voidMiningMode = !ARConfiguration.getCurrentConfig().laserDrillPlanet; + terraformingstatus = false; client_first_loop = true; @@ -109,13 +117,33 @@ public TileOrbitalLaserDrill() { yCenter = 0; numSteps = 0; prevDir = null; - resetBtn = new ModuleButton(40, 20, 2, LibVulpes.proxy.getLocalizedString("msg.spacelaser.reset"), this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild, 34, 20); + + resetBtn = new ModuleButton( + 40, 20, 2, + LibVulpes.proxy.getLocalizedString("msg.spacelaser.reset"), + this, + zmaster587.libVulpes.inventory.TextureResources.buttonBuild, + 34, 20 + ); + + // Only meaningful in void-mining mode (from config) + voidCobbleBtn = new ModuleButton( + 50, 60, + 3, // buttonId + LibVulpes.proxy.getLocalizedString("msg.spacelaser.voidcobble"), + this, + zmaster587.libVulpes.inventory.TextureResources.buttonBuild, + 85, 20 + ); + positionText = new ModuleText(83, 63, "empty... shit!", 0x0b0b0b); updateText = new ModuleText(83, 63, "also empty...", 0x0b0b0b); xtext = new ModuleText(83, 33, "X:", 0x0b0b0b); ztext = new ModuleText(83, 43, "Z:", 0x0b0b0b); - no_targets_text = new ModuleText(21, 43, "", 0x0b0b0b); - no_targets_text.setText("No target found!\nGo down and survey the area!"); + String ntLine1 = LibVulpes.proxy.getLocalizedString("msg.spacelaser.notarget1"); + String ntLine2 = LibVulpes.proxy.getLocalizedString("msg.spacelaser.notarget2"); + String ntText = ntLine1 + "\n" + ntLine2; + no_targets_text = new ModuleText(21, 43, ntText, 0x0b0b0b); locationX = new ModuleNumericTextbox(this, 93, 31, 50, 10, 16); locationZ = new ModuleNumericTextbox(this, 93, 41, 50, 10, 16); tickSinceLastOperation = 0; @@ -127,6 +155,7 @@ public TileOrbitalLaserDrill() { this.miningDrill = new MiningDrill(); else this.miningDrill = new VoidDrill(); + this.terraformingDrill = new terraformingdrill(); this.drill = miningDrill; @@ -134,8 +163,13 @@ public TileOrbitalLaserDrill() { finished = false; isJammed = false; mode = MODE.SINGLE; + + // If we ever need to set initial voidCobble from config, do it here + updateVoidCobbleButtonVisuals(); } + + @Override public Object[][][] getStructure() { return structure; @@ -172,7 +206,8 @@ public void writeDataToNetwork(ByteBuf out, byte id) { if (id == 15) { out.writeInt(this.laserX); out.writeInt(this.laserZ); - }else if (id == 11){ + } + else if (id == 11){ out.writeInt(mode.ordinal()); out.writeInt(this.xCenter); out.writeInt(this.yCenter); @@ -180,6 +215,7 @@ public void writeDataToNetwork(ByteBuf out, byte id) { out.writeInt(this.laserZ); out.writeBoolean(this.isRunning); out.writeBoolean(terraformingstatus); + out.writeBoolean(voidCobble); } else if (id == 12) { out.writeBoolean(isRunning); @@ -209,6 +245,7 @@ else if (id == 11){ nbt.setInteger("currentZ", in.readInt()); nbt.setBoolean("isRunning", in.readBoolean()); nbt.setBoolean("terraformingstatus", in.readBoolean()); + nbt.setBoolean("voidCobble", in.readBoolean()); } else if (id == 12) { nbt.setBoolean("isRunning", in.readBoolean()); @@ -233,76 +270,93 @@ public void client_update_tf_info(){ @Override public void useNetworkData(EntityPlayer player, Side side, byte id, - NBTTagCompound nbt) { + NBTTagCompound nbt) { super.useNetworkData(player, side, id, nbt); + if (id == 15) { laserZ = nbt.getInteger("currentZ"); laserX = nbt.getInteger("currentX"); - positionText.setText("position:\n"+this.laserX+" : "+this.laserZ); - }else if (id == 11){ + positionText.setText("position:\n" + this.laserX + " : " + this.laserZ); + } else if (id == 11) { resetSpiral(); this.isRunning = nbt.getBoolean("isRunning"); mode = MODE.values()[nbt.getInteger("mode")]; + if (voidMiningMode && mode != MODE.SINGLE) { + mode = MODE.SINGLE; + } xCenter = nbt.getInteger("newX"); yCenter = nbt.getInteger("newZ"); laserZ = nbt.getInteger("currentZ"); laserX = nbt.getInteger("currentX"); - positionText.setText("position:\n"+this.laserX+" : "+this.laserZ); + positionText.setText("position:\n" + this.laserX + " : " + this.laserZ); updateText.setText(this.getMode().toString()); locationX.setText(String.valueOf(this.xCenter)); locationZ.setText(String.valueOf(this.yCenter)); - //System.out.println("reset client:"+xCenter+":"+yCenter+":"+mode); resetBtn.setColor(0xf0f0f0); check_is_terraforming_update_gui(); this.terraformingstatus = nbt.getBoolean("terraformingstatus"); + this.voidCobble = nbt.getBoolean("voidCobble"); client_update_tf_info(); - //System.out.println("is running: "+ isRunning); - } - else if (id == 12) { + if (voidCobbleBtn != null) { + updateVoidCobbleButtonVisuals(); + } + + } else if (id == 12) { this.isRunning = nbt.getBoolean("isRunning"); - } - else if (id == 16){ + } else if (id == 16) { this.terraformingstatus = nbt.getBoolean("terraformingstatus"); client_update_tf_info(); + } else if (id == 14) { + resetSpiral(); + mode = MODE.values()[nbt.getInteger("mode")]; + xCenter = nbt.getInteger("newX"); + yCenter = nbt.getInteger("newZ"); + laserZ = yCenter; + laserX = xCenter; - } - else if (id == 14){ - resetSpiral(); - mode = MODE.values()[nbt.getInteger("mode")]; - xCenter = nbt.getInteger("newX"); - yCenter = nbt.getInteger("newZ"); - laserZ = yCenter; - laserX = xCenter; - //System.out.println("reset:"+xCenter+":"+yCenter+":"+mode); - // do all the reset stuff if (drill != null) { drill.deactivate(); } finished = false; setRunning(false); - if (mode == MODE.T_FORM){ + if (mode == MODE.T_FORM) { this.drill = this.terraformingDrill; - }else { + } else { this.drill = this.miningDrill; } - checkjam(); - checkCanRun(); - //update clients on new data - PacketHandler.sendToNearby(new PacketMachine(this, (byte) 11), this.world.provider.getDimension(), pos, 2048); - } - else if (id == 13) - //update clients on new data - PacketHandler.sendToNearby(new PacketMachine(this, (byte) 11), this.world.provider.getDimension(), pos, 2048); + checkjam(); + checkCanRun(); + PacketHandler.sendToNearby(new PacketMachine(this, (byte) 11), + this.world.provider.getDimension(), pos, 2048); + + } else if (id == 13) { + PacketHandler.sendToNearby(new PacketMachine(this, (byte) 11), + this.world.provider.getDimension(), pos, 2048); + + } else if (id == 17) { + // **IMPORTANT**: only act on server + if (!world.isRemote) { + this.voidCobble = !this.voidCobble; + if (miningDrill instanceof VoidDrill) { + ((VoidDrill) miningDrill).setVoidCobble(voidCobble); + } + // push new state to clients + PacketHandler.sendToNearby(new PacketMachine(this, (byte) 11), + this.world.provider.getDimension(), pos, 2048); + markDirty(); + } + } markDirty(); } + public void transferItems(IInventory inventorySource, IItemHandler inventoryTarget) { for (int i = 0; i < inventorySource.getSizeInventory(); i++) { ItemStack stack = inventorySource.getStackInSlot(i).copy(); @@ -430,7 +484,7 @@ public void update() { tickSinceLastOperation++; - if (mode != MODE.T_FORM) { + if (mode != MODE.T_FORM && isJammed) { checkjam(); } checkCanRun(); @@ -513,7 +567,10 @@ public void onDestroy() { if (this.drill != null) { this.drill.deactivate(); } - //ForgeChunkManager.releaseTicket(ticket); + orbitWorld = null; + t = null; + last_orbit_dim = 0; + lastTfDim = Integer.MIN_VALUE; } @Override @@ -522,6 +579,10 @@ public void onChunkUnload() { this.drill.deactivate(); } isRunning = false; + orbitWorld = null; + t = null; + last_orbit_dim = 0; + lastTfDim = Integer.MIN_VALUE; } @Override @@ -541,7 +602,7 @@ public NBTTagCompound writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); - + nbt.setBoolean("voidCobble", voidCobble); nbt.setInteger("laserX", laserX); nbt.setInteger("laserZ", laserZ); nbt.setByte("mode", (byte) mode.ordinal()); @@ -566,6 +627,10 @@ public void readFromNBT(NBTTagCompound nbt) { laserX = nbt.getInteger("laserX"); laserZ = nbt.getInteger("laserZ"); mode = MODE.values()[nbt.getByte("mode")]; + // If config says we are in void-mining mode, force SINGLE + if (voidMiningMode && mode != MODE.SINGLE) { + mode = MODE.SINGLE; + } this.isJammed = nbt.getBoolean("jammed"); xCenter = nbt.getInteger("CenterX"); @@ -582,18 +647,19 @@ public void readFromNBT(NBTTagCompound nbt) { }else { this.drill = this.miningDrill; } - } - + voidCobble = nbt.getBoolean("voidCobble"); + if (miningDrill instanceof VoidDrill) { + ((VoidDrill) miningDrill).setVoidCobble(voidCobble); + } + } + /** * Take items from internal inventory */ public void checkjam() { - - + // Only called when isJammed == true if (this.one_hatch_empty()) { this.isJammed = false; - }else{ - this.isJammed = true; } } @@ -626,7 +692,20 @@ private boolean unableToRun() { public void checkCanRun() { - if (world.isRemote) return; // client has no business here + if (world.isRemote) return; + + // Read redstone once and reuse it + final int redstonePower = world.isBlockIndirectlyGettingPowered(getPos()); + + // Fast path for void-mining: if there is no redstone, don't even bother + // with space station / dimension logic. + if (voidMiningMode && redstonePower == 0) { + if (isRunning) { + drill.deactivate(); + setRunning(false); + } + return; + } ISpaceObject spaceObject = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(this.pos); if(spaceObject == null){ @@ -638,54 +717,53 @@ public void checkCanRun() { } int orbitDimId = spaceObject.getOrbitingPlanetId(); - if (orbitDimId != last_orbit_dim ||orbitWorld== null || t == null){ + // Ensure orbitWorld exists when you might activate a drill + if (orbitDimId != last_orbit_dim || orbitWorld == null) { last_orbit_dim = orbitDimId; + if (!DimensionManager.isDimensionRegistered(orbitDimId)) { - if (isRunning) { - drill.deactivate(); - setRunning(false); - } + if (isRunning) { drill.deactivate(); setRunning(false); } return; } - orbitWorld = DimensionManager.getWorld(orbitDimId); + orbitWorld = DimensionManager.getWorld(orbitDimId); if (orbitWorld == null) { DimensionManager.initDimension(orbitDimId); orbitWorld = DimensionManager.getWorld(orbitDimId); if (orbitWorld == null) { - if (isRunning) { - drill.deactivate(); - setRunning(false); - } + if (isRunning) { drill.deactivate(); setRunning(false); } return; } } - t = terraformingDrill.get_my_helper(orbitWorld); } + if (mode == MODE.T_FORM) { + if (t == null || lastTfDim != orbitDimId) { + t = terraformingDrill.get_my_helper(orbitWorld); + lastTfDim = orbitDimId; + } - - if (!t.has_blocks_in_tf_queue()) { - if (terraformingstatus) { - terraformingstatus = false; + boolean hasQueue = t != null && t.has_blocks_in_tf_queue(); + if (terraformingstatus != hasQueue) { + terraformingstatus = hasQueue; PacketHandler.sendToAll(new PacketMachine(this, (byte) 16)); - } } else { - if (!terraformingstatus) { - terraformingstatus = true; + if (terraformingstatus) { + terraformingstatus = false; PacketHandler.sendToAll(new PacketMachine(this, (byte) 16)); } } + //Laser redstone power, not be jammed, and be in orbit and energy to function - if ((mode == MODE.T_FORM && (t==null ||!t.has_blocks_in_tf_queue())) || this.finished || (this.isJammed && mode != MODE.T_FORM) || world.isBlockIndirectlyGettingPowered(getPos()) == 0 || unableToRun()) { + if ((mode == MODE.T_FORM && (t==null ||!t.has_blocks_in_tf_queue())) || this.finished || (this.isJammed && mode != MODE.T_FORM) || redstonePower == 0 || unableToRun()) { if (isRunning) { drill.deactivate(); setRunning(false); } - } else if (world.isBlockIndirectlyGettingPowered(getPos()) > 0) { + } else if (redstonePower > 0) { if (orbitDimId == SpaceObjectManager.WARPDIMID) @@ -769,39 +847,76 @@ public void onModuleUpdated(ModuleBase module) { } + private void updateVoidCobbleButtonVisuals() { + if (voidCobbleBtn == null) return; + + String key = voidCobble + ? "msg.spacelaser.voidcobble.on" + : "msg.spacelaser.voidcobble.off"; + + voidCobbleBtn.setText(LibVulpes.proxy.getLocalizedString(key)); + voidCobbleBtn.setColor(voidCobble ? 0x90ff90 : 0xf0f0f0); + } + + + + @Override public List getModules(int id, EntityPlayer player) { List modules = new LinkedList<>(); + // --- VOID-MINING SIMPLIFIED GUI --- + if (voidMiningMode) { + if (world.isRemote) { + // Ask server for current state (mode, running, voidCobble, etc.) + PacketHandler.sendToServer(new PacketMachine(this, (byte) 13)); + + // Lore text: two lines, joined with '\n' in Java + String line1 = LibVulpes.proxy.getLocalizedString("msg.spacelaser.voidmining.line1"); + String line2 = LibVulpes.proxy.getLocalizedString("msg.spacelaser.voidmining.line2"); + String lore = line1 + "\n" + line2; + + modules.add(new ModuleText(35, 30, lore, 0x0b0b0b)); + + // Void cobble toggle button + updateVoidCobbleButtonVisuals(); + modules.add(voidCobbleBtn); + } + + // Power bar is still useful + modules.add(new ModulePower(11, 25, batteries)); + return modules; + } + + // --- ORIGINAL PLANET-MINING GUI --- if (world.isRemote) { //request update on information PacketHandler.sendToServer(new PacketMachine(this, (byte) 13)); modules.add(updateText = new ModuleText(110, 20, this.getMode().toString(), 0x0b0b0b, true)); - modules.add(locationX); modules.add(locationZ); - modules.add(xtext); modules.add(ztext); modules.add(no_targets_text); - modules.add(positionText); - - //modules.add(new ModuleImage(8, 16, TextureResources.laserGuiBG)); + // modules.add(new ModuleImage(8, 16, TextureResources.laserGuiBG)); } - modules.add(new ModuleButton(83, 20, 0, "", this, zmaster587.libVulpes.inventory.TextureResources.buttonLeft, 5, 8)); - modules.add(new ModuleButton(137, 20, 1, "", this, zmaster587.libVulpes.inventory.TextureResources.buttonRight, 5, 8)); + modules.add(new ModuleButton(83, 20, 0, "", this, + zmaster587.libVulpes.inventory.TextureResources.buttonLeft, 5, 8)); + modules.add(new ModuleButton(137, 20, 1, "", this, + zmaster587.libVulpes.inventory.TextureResources.buttonRight, 5, 8)); modules.add(resetBtn); modules.add(new ModulePower(11, 25, batteries)); return modules; } + @Override public String getModularInventoryName() { return "tile.spaceLaser.name"; @@ -845,10 +960,26 @@ public void onInventoryButtonPressed(int buttonId) { } else if (buttonId == 2) { PacketHandler.sendToServer(new PacketMachine(this, (byte) 14)); return; + } else if (buttonId == 3) { + // Ask server to toggle voidCobble (no payload needed) + PacketHandler.sendToServer(new PacketMachine(this, (byte) 17)); + return; } else return; } + @Override + public void invalidate() { + super.invalidate(); + + if (!world.isRemote) { + if (drill != null) { + drill.deactivate(); + } + isRunning = false; + } + } + @Override @SideOnly(Side.CLIENT) public double getMaxRenderDistanceSquared() { @@ -861,4 +992,4 @@ public enum MODE { SPIRAL, T_FORM } -} \ No newline at end of file +} From 5ac7c219c16c5b97c0bb1f10df92d3418009a546 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:46:51 +0100 Subject: [PATCH 350/424] Add configuration for nuclear rockets and orbital registry --- .../advancedRocketry/api/ARConfiguration.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/api/ARConfiguration.java b/src/main/java/zmaster587/advancedRocketry/api/ARConfiguration.java index 9051d7528..33122417a 100644 --- a/src/main/java/zmaster587/advancedRocketry/api/ARConfiguration.java +++ b/src/main/java/zmaster587/advancedRocketry/api/ARConfiguration.java @@ -87,6 +87,8 @@ public class ARConfiguration { public boolean rocketRequireFuel = true; @ConfigProperty public boolean canBeFueledByHand = true; + @ConfigProperty(needsSync = true) + public boolean nuclearRocketsRespectArtifactGating = true; @ConfigProperty public boolean enableNausea = true; @ConfigProperty @@ -153,6 +155,8 @@ public class ARConfiguration { @ConfigProperty public boolean enableLaserDrill; @ConfigProperty + public boolean enableOrbitalRegistry; + @ConfigProperty public int spaceSuitOxygenTime; @ConfigProperty public float suitTankCapacity; @@ -378,7 +382,7 @@ public static void loadPreInit() { arConfig.crystalliserMaximumGravity = (float) config.get(Configuration.CATEGORY_GENERAL, "crystalliserMaximumGravity", 0f, "Maximum gravity the crystalliser will function at. Use 0.0 to disable!").getDouble(); arConfig.enableLaserDrill = config.get(Configuration.CATEGORY_GENERAL, "EnableLaserDrill", true, "Enables the laser drill machine").getBoolean(); arConfig.spaceLaserPowerMult = (float) config.get(Configuration.CATEGORY_GENERAL, "LaserDrillPowerMultiplier", 1d, "Power multiplier for the laser drill machine").getDouble(); - arConfig.laserDrillPlanet = config.get(Configuration.CATEGORY_GENERAL, "laserDrillPlanet", false, "If true the orbital laser will actually mine blocks on the planet below").getBoolean(); + arConfig.laserDrillPlanet = config.get(Configuration.CATEGORY_GENERAL, "laserDrillPlanet", false, "If true the orbital laser will actually mine blocks on the planet below, (false makes it a VoidMiner with improved performance especially when using Void Cobble: ON in the GUI)").getBoolean(); String[] str = config.getStringList("spaceLaserDimIdBlackList", Configuration.CATEGORY_GENERAL, new String[]{}, "Laser drill will not mine these dimension"); arConfig.enableTerraforming = config.get(Configuration.CATEGORY_GENERAL, "EnableTerraforming", true, "Enables terraforming items and blocks").getBoolean(); arConfig.terraformSpeed = config.get(Configuration.CATEGORY_GENERAL, "terraformMult", 1f, "Multplier for atmosphere change speed").getDouble(); @@ -388,6 +392,9 @@ public static void loadPreInit() { arConfig.allowTerraformNonAR = config.get(Configuration.CATEGORY_GENERAL, "allowTerraformingNonARWorlds", false, "If true dimensions not added by AR can be terraformed, including the overworld").getBoolean(); arConfig.enableGravityController = config.get(Configuration.CATEGORY_GENERAL, "enableGravityMachine", true, "If false the gravity controller cannot be built or used").getBoolean(); arConfig.allowNonArBiomesInTerraforming = config.get(Configuration.CATEGORY_GENERAL, "allowNonArBiomesInTerraforming", false, "non-ar biomes from mods with custom world gen can not be decorated in terraforming. If you want fully decorated terraforming with only default biomes, set this to false").getBoolean(); + arConfig.enableOrbitalRegistry = config.get(Configuration.CATEGORY_GENERAL,"EnableOrbitalRegistry",true, "Enables the orbital registry machine").getBoolean(); + + //Oxygen arConfig.enableOxygen = config.get(OXYGEN, "EnableAtmosphericEffects", true, "If true, allows players being hurt due to lack of oxygen and allows effects from non-standard atmosphere types").getBoolean(); @@ -463,6 +470,7 @@ public static void loadPreInit() { //Rockets arConfig.rocketRequireFuel = config.get(ROCKET, "rocketsRequireFuel", true, "Set to false if rockets should not require fuel to fly").getBoolean(); arConfig.canBeFueledByHand = config.get(ROCKET, "canBeFueledByHand", true, "Set to false if rockets should not be able to be fueled by and and will require a fueling station").getBoolean(); + arConfig.nuclearRocketsRespectArtifactGating = config.get(ROCKET, "nuclearRocketsRespectArtifactGating", true, "Nuclear rocket should respect artifact gating for planets").getBoolean(); liquidMonopropellant = config.get(ROCKET, "rocketFuels", new String[]{"rocketfuel;10"}, "List of fluid names for fluids that can be used as rocket monopropellants").getStringList(); liquidBipropellantFuel = config.get(ROCKET, "rocketBipropellants", new String[]{"hydrogen;10"}, "List of fluid names for fluids that can be used as rocket bipropellant fuels").getStringList(); liquidBipropellantOxidizer = config.get(ROCKET, "rocketOxidizers", new String[]{"oxygen;10"}, "List of fluid names for fluids that can be used as rocket bipropellant oxidizers").getStringList(); From 305dc76d8645f1a2f16818ec8ba9df7fadf9451b Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:47:33 +0100 Subject: [PATCH 351/424] Add tooltips for structure machines and items --- .../client/TooltipInjector.java | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/client/TooltipInjector.java b/src/main/java/zmaster587/advancedRocketry/client/TooltipInjector.java index 3ee9cf119..68254fda8 100644 --- a/src/main/java/zmaster587/advancedRocketry/client/TooltipInjector.java +++ b/src/main/java/zmaster587/advancedRocketry/client/TooltipInjector.java @@ -62,6 +62,14 @@ private TooltipInjector() {} KEY_BY_ID.put("advancedrocketry:structuretower", "tooltip.advancedrocketry.structuretower"); KEY_BY_SUFFIX.put("structuretower", "tooltip.advancedrocketry.structuretower"); + // ---- Structure Machine ---- + KEY_BY_ID.put("libvulpes:structuremachine", "tooltip.libvulpes.structuremachine"); + KEY_BY_SUFFIX.put("structuremachine", "tooltip.libvulpes.structuremachine"); + + // ---- Structure Tower ---- + KEY_BY_ID.put("libvulpes:advstructuremachine", "tooltip.libvulpes.advstructuremachine"); + KEY_BY_SUFFIX.put("advstructuremachine", "tooltip.libvulpes.advstructuremachine"); + // --- ItemUpgrade (meta-based) 6 Space Suit Components--- KEY_RESOLVER_BY_ID.put("advancedrocketry:itemupgrade", s -> "tooltip.advancedrocketry.itemupgrade." + s.getItemDamage()); @@ -207,6 +215,11 @@ private TooltipInjector() {} KEY_BY_ID.put("advancedrocketry:solararraypanel", "tooltip.advancedrocketry.solararraypanel"); KEY_BY_SUFFIX.put("solararraypanel", "tooltip.advancedrocketry.solararraypanel"); + // Advanced Data Bus + KEY_BY_ID.put("advancedrocketry:databusbig", "tooltip.advancedrocketry.databusbig"); + KEY_BY_SUFFIX.put("databusbig", "tooltip.advancedrocketry.databusbig"); + + // ---- BlockARHatch (registered as advancedrocketry:loader), meta 0..6 ---- KEY_RESOLVER_BY_ID.put("advancedrocketry:loader", s -> { final int v = s.getMetadata() & 7; // strip redstone/state bit @@ -259,6 +272,9 @@ private TooltipInjector() {} KEY_BY_ID.put("advancedrocketry:centrifuge", "tooltip.advancedrocketry.centrifuge"); KEY_BY_SUFFIX.put("centrifuge", "tooltip.advancedrocketry.centrifuge"); + KEY_BY_ID.put("advancedrocketry:orbitalregistry", "tooltip.advancedrocketry.orbitalregistry"); + KEY_BY_SUFFIX.put("orbitalRegistry", "tooltip.advancedrocketry.orbitalregistry"); + // ---- Aux / Huge ---- KEY_BY_ID.put("advancedrocketry:warpcore", "tooltip.advancedrocketry.warpcore"); KEY_BY_SUFFIX.put("warpCore", "tooltip.advancedrocketry.warpcore"); @@ -344,7 +360,6 @@ private TooltipInjector() {} // itemLens KEY_BY_ID.put("advancedrocketry:lens", "tooltip.advancedrocketry.itemlens"); - KEY_BY_SUFFIX.put("lens", "tooltip.advancedrocketry.itemlens"); // Integrated Circuit (IC) KEY_BY_ID.put("advancedrocketry:ic", "tooltip.advancedrocketry.circuitic"); @@ -370,11 +385,18 @@ private TooltipInjector() {} KEY_BY_SUFFIX.put("stationbuilder", "tooltip.advancedrocketry.stationassembler"); KEY_BY_SUFFIX.put("stationAssembler", "tooltip.advancedrocketry.stationassembler"); - // Deployable Rocket Assembler (unmanned vehicle) + // Station Deployable Rocket Assembler (Unmanned Vehicle) KEY_BY_ID.put("advancedrocketry:deployablerocketbuilder", "tooltip.advancedrocketry.deployablerocketassembler"); KEY_BY_SUFFIX.put("deployablerocketbuilder", "tooltip.advancedrocketry.deployablerocketassembler"); KEY_BY_SUFFIX.put("deployableRocketAssembler", "tooltip.advancedrocketry.deployablerocketassembler"); + // ---- LibVulpes blocks ---- + KEY_BY_ID.put("libvulpes:coalgenerator", "tooltip.advancedrocketry.libvulpes.coalgenerator"); + KEY_BY_ID.put("libvulpes:hatch", "tooltip.advancedrocketry.libvulpes.hatch"); + KEY_BY_ID.put("libvulpes:forgepowerinput", "tooltip.advancedrocketry.libvulpes.forgepowerinput"); + KEY_BY_ID.put("libvulpes:forgepoweroutput", "tooltip.advancedrocketry.libvulpes.forgepoweroutput"); + KEY_BY_ID.put("libvulpes:creativepowerbattery", "tooltip.advancedrocketry.libvulpes.creativepowerbattery"); + // ---- Fuel Tanks ---- // Monopropellant Fuel Tank KEY_BY_ID.put("advancedrocketry:fueltank", "tooltip.advancedrocketry.fueltank"); From 1266524f486f88c0866d5fd39576b965bef3c7fb Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:48:08 +0100 Subject: [PATCH 352/424] Refactor TileRocketLoader to improve item handling --- .../tile/infrastructure/TileRocketLoader.java | 238 +++++++++++------- 1 file changed, 152 insertions(+), 86 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketLoader.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketLoader.java index 689f7bbbd..c9000473d 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketLoader.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketLoader.java @@ -3,7 +3,6 @@ import io.netty.buffer.ByteBuf; import net.minecraft.client.Minecraft; import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.NetworkManager; @@ -14,16 +13,21 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; +import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.wrapper.InvWrapper; import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; import zmaster587.advancedRocketry.api.EntityRocketBase; import zmaster587.advancedRocketry.api.IInfrastructure; import zmaster587.advancedRocketry.api.IMission; import zmaster587.advancedRocketry.block.multiblock.BlockARHatch; import zmaster587.advancedRocketry.entity.EntityRocket; +import zmaster587.advancedRocketry.inventory.modules.ModuleSideSelectorTooltipOverlay; import zmaster587.advancedRocketry.tile.TileGuidanceComputer; +import zmaster587.advancedRocketry.tile.hatch.TileSatelliteHatch; import zmaster587.advancedRocketry.tile.TileRocketAssemblingMachine; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.inventory.modules.*; @@ -39,6 +43,7 @@ public class TileRocketLoader extends TileInventoryHatch implements IInfrastructure, ITickable, IButtonInventory, INetworkMachine, IGuiCallback { + private String[] sideStateNames; private final static int ALLOW_REDSTONEOUT = 2; EntityRocket rocket; ModuleRedstoneOutputButton redstoneControl; @@ -47,13 +52,21 @@ public class TileRocketLoader extends TileInventoryHatch implements IInfrastruct RedstoneState inputstate; ModuleBlockSideSelector sideSelectorModule; + protected static final int TRANSFER_INTERVAL_TICKS = 20; + protected static final int MAX_TRANSFER_PER_OPERATION = 64; + protected int transferCooldown = 0; + + // Own wrapper around the EmbeddedInventory from TileInventoryHatch. + // We DO NOT use the broken capability from LibVulpes for ourselves. + protected final IItemHandler ownItemHandler = new InvWrapper(this.inventory); + public TileRocketLoader() { redstoneControl = new ModuleRedstoneOutputButton(174, 4, 0, "", this, LibVulpes.proxy.getLocalizedString("msg.rocketLoader.loadingState")); state = RedstoneState.ON; inputRedstoneControl = new ModuleRedstoneOutputButton(174, 32, 1, "", this, LibVulpes.proxy.getLocalizedString("msg.rocketLoader.allowLoading")); inputstate = RedstoneState.OFF; inputRedstoneControl.setRedstoneState(inputstate); - sideSelectorModule = new ModuleBlockSideSelector(90, 15, this, LibVulpes.proxy.getLocalizedString("msg.rocketLoader.none"), LibVulpes.proxy.getLocalizedString("msg.rocketLoader.allowredstoneoutput"), LibVulpes.proxy.getLocalizedString("msg.rocketLoader.allowredstoneinput")); + initSideSelector(); } public TileRocketLoader(int size) { @@ -71,8 +84,51 @@ public TileRocketLoader(int size) { inputRedstoneControl = new ModuleRedstoneOutputButton(174, 32, 1, "", this, LibVulpes.proxy.getLocalizedString("msg.rocketLoader.allowLoading")); inputstate = RedstoneState.OFF; inputRedstoneControl.setRedstoneState(inputstate); - sideSelectorModule = new ModuleBlockSideSelector(90, 15, this, LibVulpes.proxy.getLocalizedString("msg.rocketLoader.none"), LibVulpes.proxy.getLocalizedString("msg.rocketLoader.allowredstoneoutput"), LibVulpes.proxy.getLocalizedString("msg.rocketLoader.allowredstoneinput")); + initSideSelector(); + } + + // Used for rocket / other tiles – they SHOULD implement IItemHandler correctly. + protected IItemHandler getItemHandler(TileEntity tile) { + if (tile == null || tile.isInvalid()) + return null; + + // Prefer null side + if (tile.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null)) { + Object cap = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null); + if (cap instanceof IItemHandler) { + return (IItemHandler) cap; + } + } + + // Fallback: try all sides + for (EnumFacing side : EnumFacing.values()) { + if (tile.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side)) { + Object cap = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side); + if (cap instanceof IItemHandler) { + return (IItemHandler) cap; + } + } + } + + return null; + } + + + // For THIS tile only: never go through LibVulpes’ capability (it returns EmbeddedInventory). + protected IItemHandler getOwnItemHandler() { + return ownItemHandler; + } + + + private void initSideSelector() { + sideStateNames = new String[] { + LibVulpes.proxy.getLocalizedString("msg.rocketLoader.none"), + LibVulpes.proxy.getLocalizedString("msg.rocketLoader.allowredstoneoutput"), + LibVulpes.proxy.getLocalizedString("msg.rocketLoader.allowredstoneinput") + }; + + sideSelectorModule = new ModuleBlockSideSelector(90, 15, this, sideStateNames); } @Override @@ -98,6 +154,10 @@ public List getModules(int ID, EntityPlayer player) { list.add(redstoneControl); list.add(inputRedstoneControl); list.add(sideSelectorModule); + if (FMLCommonHandler.instance().getSide().isClient()) { + list.add(new ModuleSideSelectorTooltipOverlay(90, 15, sideSelectorModule, sideStateNames)); + } + return list; } @@ -111,94 +171,100 @@ protected boolean getStrongPowerForSides(World world, BlockPos pos) { @Override public void update() { - //Move a stack of items - if (!world.isRemote && rocket != null) { - - boolean isAllowedToOperate = (inputstate == RedstoneState.OFF || isStateActive(inputstate, getStrongPowerForSides(world, getPos()))); - - List tiles = rocket.storage.getInventoryTiles(); - boolean foundStack = false; - boolean rocketContainsItems = false; - out: - //Function returns if something can be moved - for (TileEntity tile : tiles) { - if (tile.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, EnumFacing.UP)) { - if(tile instanceof TileGuidanceComputer) continue; - - IItemHandler inv = tile.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, EnumFacing.UP); - - for (int i = 0; i < inv.getSlots(); i++) { - if (inv.getStackInSlot(i).isEmpty()) - rocketContainsItems = true; - - //Loop though this inventory's slots and find a suitible one - for (int j = 0; j < getSizeInventory(); j++) { - if ((inv.getStackInSlot(i).isEmpty()) && !inventory.getStackInSlot(j).isEmpty()) { - if (isAllowedToOperate) { - inv.insertItem(i, inventory.getStackInSlot(j), false); - inventory.setInventorySlotContents(j, ItemStack.EMPTY); - } - rocketContainsItems = true; - break out; - } else if (!getStackInSlot(j).isEmpty() && inv.getStackInSlot(i).getItem() == getStackInSlot(j).getItem() && - ItemStack.areItemStackTagsEqual(inv.getStackInSlot(i), getStackInSlot(j)) && inv.getStackInSlot(i).getMaxStackSize() != inv.getStackInSlot(i).getCount()) { - if (isAllowedToOperate) { - ItemStack stack2 = inventory.decrStackSize(j, inv.getStackInSlot(i).getMaxStackSize() - inv.getStackInSlot(i).getCount()); - inv.getStackInSlot(i).setCount(inv.getStackInSlot(i).getCount() + stack2.getCount()); - } - rocketContainsItems = true; - - if (inventory.getStackInSlot(j).isEmpty()) - break out; - - foundStack = true; - } - } - if (foundStack) - break out; - } - } else { - if (tile instanceof IInventory && !(tile instanceof TileGuidanceComputer)) { - IInventory inv = ((IInventory) tile); - - for (int i = 0; i < inv.getSizeInventory(); i++) { - if (inv.getStackInSlot(i).isEmpty()) - rocketContainsItems = true; - - //Loop though this inventory's slots and find a suitible one - for (int j = 0; j < getSizeInventory(); j++) { - if ((inv.getStackInSlot(i).isEmpty()) && !inventory.getStackInSlot(j).isEmpty()) { - if (isAllowedToOperate) { - inv.setInventorySlotContents(i, inventory.getStackInSlot(j)); - inventory.setInventorySlotContents(j, ItemStack.EMPTY); - } - rocketContainsItems = true; - break out; - } else if (!getStackInSlot(j).isEmpty() && inv.isItemValidForSlot(i, getStackInSlot(j)) && inv.getStackInSlot(i).getItem() == getStackInSlot(j).getItem() && - ItemStack.areItemStackTagsEqual(inv.getStackInSlot(i), getStackInSlot(j)) && inv.getStackInSlot(i).getMaxStackSize() != inv.getStackInSlot(i).getCount()) { - if (isAllowedToOperate) { - ItemStack stack2 = inventory.decrStackSize(j, inv.getStackInSlot(i).getMaxStackSize() - inv.getStackInSlot(i).getCount()); - inv.getStackInSlot(i).setCount(inv.getStackInSlot(i).getCount() + stack2.getCount()); - } - rocketContainsItems = true; - - if (inventory.getStackInSlot(j).isEmpty()) - break out; - - foundStack = true; - } - } - if (foundStack) - break out; - } - } + if (world.isRemote || rocket == null) + return; + + // Throttle: only try to move items every TRANSFER_INTERVAL_TICKS + if (transferCooldown > 0) { + transferCooldown--; + return; + } + + boolean isAllowedToOperate = (inputstate == RedstoneState.OFF || + isStateActive(inputstate, getStrongPowerForSides(world, getPos()))); + + IItemHandler ownHandler = getOwnItemHandler(); + if (ownHandler == null || ownHandler.getSlots() == 0) { + // Nothing to move / no handler -> treat as not doing anything + setRedstoneState(false); + return; + } + + List tiles = rocket.storage.getInventoryTiles(); + boolean rocketHasCapacity = false; // true if any slot can still take items + + outer: + for (TileEntity tile : tiles) { + if (tile instanceof TileGuidanceComputer || tile instanceof TileSatelliteHatch) + continue; + + IItemHandler rocketHandler = getItemHandler(tile); + if (rocketHandler == null || rocketHandler.getSlots() == 0) + continue; + + int rocketSlots = rocketHandler.getSlots(); + int ownSlots = ownHandler.getSlots(); + + // Capacity detection for redstone: matches original semantics (any empty slot) + for (int rocketSlot = 0; rocketSlot < rocketSlots; rocketSlot++) { + ItemStack rocketStack = rocketHandler.getStackInSlot(rocketSlot); + if (rocketStack.isEmpty()) { + rocketHasCapacity = true; + break; } } - //Update redstone state - setRedstoneState(!rocketContainsItems); + // If we are not allowed to operate, we only care about capacity for redstone + if (!isAllowedToOperate) + continue; + + // Actual transfer: handler-wide insert using ItemHandlerHelper + for (int ownSlot = 0; ownSlot < ownSlots; ownSlot++) { + ItemStack sourceStack = ownHandler.getStackInSlot(ownSlot); + if (sourceStack.isEmpty()) + continue; + + // Limit per-operation transfer, but DO NOT assume anything about slot max size + int maxToMove = Math.min(MAX_TRANSFER_PER_OPERATION, sourceStack.getCount()); + if (maxToMove <= 0) + continue; + + // Simulate extraction from our inventory + ItemStack simulatedExtract = ownHandler.extractItem(ownSlot, maxToMove, true); + if (simulatedExtract.isEmpty()) + continue; + + // Simulate insertion into the rocket inventory as a whole + ItemStack simulatedRemainder = ItemHandlerHelper.insertItem(rocketHandler, simulatedExtract, true); + int accepted = simulatedExtract.getCount() - simulatedRemainder.getCount(); + if (accepted <= 0) + continue; + + // Actually extract exactly what the rocket said it will accept + ItemStack actuallyExtracted = ownHandler.extractItem(ownSlot, accepted, false); + if (actuallyExtracted.isEmpty()) + continue; + + // Actually insert into rocket + ItemStack remainder = ItemHandlerHelper.insertItem(rocketHandler, actuallyExtracted, false); + + // Normally remainder should be empty because we respected 'accepted'. + // Absolute last-resort fallback for misbehaving handlers: try to put remainder back. + if (!remainder.isEmpty()) { + ItemHandlerHelper.insertItem(ownHandler, remainder, false); + // If this still leaves items, they'll effectively vanish, but only + // in the case of a broken mod that lied during simulation. + } + transferCooldown = TRANSFER_INTERVAL_TICKS; + markDirty(); + tile.markDirty(); + break outer; // only one transfer per operation + } } + + // Redstone: ON when rocketHasCapacity == false (i.e. no empty slot -> "full" rocket) + setRedstoneState(!rocketHasCapacity); } @Override From ad0a2a39cb943c23174f9e204e09252b30812456 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:49:13 +0100 Subject: [PATCH 353/424] Refactor TileRocketFluidUnloader to TileRocketUnloader --- .../TileRocketFluidUnloader.java | 150 ++++++++++++------ 1 file changed, 103 insertions(+), 47 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidUnloader.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidUnloader.java index 60529a665..1a72c8959 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidUnloader.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidUnloader.java @@ -1,79 +1,135 @@ package zmaster587.advancedRocketry.tile.infrastructure; -import micdoodle8.mods.galacticraft.core.network.PacketEntityUpdate; + +import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ITickable; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.CapabilityFluidHandler; -import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; import zmaster587.advancedRocketry.api.IInfrastructure; -import zmaster587.advancedRocketry.entity.EntityRocket; +import zmaster587.advancedRocketry.tile.TileGuidanceComputer; +import zmaster587.advancedRocketry.tile.hatch.TileSatelliteHatch; import zmaster587.libVulpes.inventory.modules.IButtonInventory; -import zmaster587.libVulpes.network.PacketEntity; -import zmaster587.libVulpes.network.PacketHandler; import zmaster587.libVulpes.util.INetworkMachine; import zmaster587.libVulpes.util.ZUtils.RedstoneState; import java.util.List; -public class TileRocketFluidUnloader extends TileRocketFluidLoader implements IInfrastructure, ITickable, IButtonInventory, INetworkMachine { +public class TileRocketUnloader extends TileRocketLoader implements IInfrastructure, ITickable, IButtonInventory, INetworkMachine { + - public TileRocketFluidUnloader() { + public TileRocketUnloader() { super(); - this.setOutputOnly(true); } - public TileRocketFluidUnloader(int size) { + public TileRocketUnloader(int size) { super(size); + inventory.setCanInsertSlot(0, false); + inventory.setCanInsertSlot(1, false); + inventory.setCanInsertSlot(2, false); + inventory.setCanInsertSlot(3, false); + inventory.setCanExtractSlot(0, true); + inventory.setCanExtractSlot(1, true); + inventory.setCanExtractSlot(2, true); + inventory.setCanExtractSlot(3, true); } @Override public String getModularInventoryName() { - return "tile.loader.4.name"; + return "tile.loader.2.name"; } @Override public void update() { - //Move fluids - if (!world.isRemote && rocket != null) { - - boolean isAllowToOperate = (inputstate == RedstoneState.OFF || isStateActive(inputstate, getStrongPowerForSides(world, getPos()))); - - List tiles = rocket.storage.getFluidTiles(); - boolean rocketFluidFull = false; - - boolean doupdate = false; - //Function returns if something can be moved - for (TileEntity tile : tiles) { - IFluidHandler handler = tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); - - //See if we have anything to fill because redstone output - FluidStack rocketFluid = handler.drain(1, false); - if (handler.fill(rocketFluid, false) > 0) - rocketFluidFull = true; - - if (isAllowToOperate) { - boolean shouldOperate; - if (getFluidTank().getFluid() != null) - shouldOperate = getFluidTank().fill(handler.drain(new FluidStack(getFluidTank().getFluid(), getFluidTank().getCapacity() - getFluidTank().getFluidAmount()), false), false) > 0; - else - shouldOperate = getFluidTank().fill(handler.drain(getFluidTank().getCapacity(), false), false) > 0; - - if (shouldOperate) { - doupdate = true; - getFluidTank().fill(handler.drain(Math.max(50, getFluidTank().getCapacity() - getFluidTank().getFluidAmount()), true), true); - } + if (world.isRemote || rocket == null) + return; + + // Throttle: only try to move items every TRANSFER_INTERVAL_TICKS + if (transferCooldown > 0) { + transferCooldown--; + return; + } + + boolean isAllowedToOperate = (inputstate == RedstoneState.OFF || + isStateActive(inputstate, getStrongPowerForSides(world, getPos()))); + + IItemHandler ownHandler = getOwnItemHandler(); + if (ownHandler == null || ownHandler.getSlots() == 0) { + // No destination handler: consider rocket not empty (no "done unloading" signal) + setRedstoneState(false); + return; + } + + List tiles = rocket.storage.getInventoryTiles(); + boolean rocketIsEmpty = true; + + outer: + for (TileEntity tile : tiles) { + if (tile instanceof TileGuidanceComputer || tile instanceof TileSatelliteHatch) + continue; + + IItemHandler rocketHandler = getItemHandler(tile); + if (rocketHandler == null || rocketHandler.getSlots() == 0) + continue; + + int rocketSlots = rocketHandler.getSlots(); + + for (int rocketSlot = 0; rocketSlot < rocketSlots; rocketSlot++) { + ItemStack rocketStack = rocketHandler.getStackInSlot(rocketSlot); + + if (!rocketStack.isEmpty()) { + rocketIsEmpty = false; } - } - if (doupdate) { - PacketHandler.sendToNearby(new PacketEntity(rocket, (byte) 9987), world.provider.getDimension(), getPos(), 128); - } - //Update redstone state - setRedstoneState(!rocketFluidFull); + if (rocketStack.isEmpty()) + continue; + + // If we are not allowed to operate, we only care about rocketIsEmpty for redstone + if (!isAllowedToOperate) { + continue; + } + // Limit per-operation transfer, but DO NOT assume anything about slot max size + int maxToMove = Math.min(MAX_TRANSFER_PER_OPERATION, rocketStack.getCount()); + if (maxToMove <= 0) + continue; + + // Simulate extraction from rocket + ItemStack simulatedExtract = rocketHandler.extractItem(rocketSlot, maxToMove, true); + if (simulatedExtract.isEmpty()) + continue; + + // Simulate insertion into our own inventory + ItemStack simulatedRemainder = ItemHandlerHelper.insertItem(ownHandler, simulatedExtract, true); + int accepted = simulatedExtract.getCount() - simulatedRemainder.getCount(); + if (accepted <= 0) + continue; + + // Actually extract exactly what will fit + ItemStack actuallyExtracted = rocketHandler.extractItem(rocketSlot, accepted, false); + if (actuallyExtracted.isEmpty()) + continue; + + // Actually insert into our inventory + ItemStack remainder = ItemHandlerHelper.insertItem(ownHandler, actuallyExtracted, false); + + // Last-resort fallback for misbehaving mods: try to put remainder back + if (!remainder.isEmpty()) { + ItemHandlerHelper.insertItem(rocketHandler, remainder, false); + // Same note: if that still leaves items, they're from a broken handler. + } + + transferCooldown = TRANSFER_INTERVAL_TICKS; + markDirty(); + tile.markDirty(); + break outer; // only one transfer per operation + } } + + // Redstone: ON when rocketIsEmpty (unloading done) + setRedstoneState(rocketIsEmpty); } + } From 68bb8aedcd3be3f916cd7094dff966b6e2ec0525 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:49:44 +0100 Subject: [PATCH 354/424] Refactor TileRocketUnloader to TileRocketFluidUnloader --- .../TileRocketFluidUnloader.java | 150 ++++++------------ 1 file changed, 47 insertions(+), 103 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidUnloader.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidUnloader.java index 1a72c8959..60529a665 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidUnloader.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidUnloader.java @@ -1,135 +1,79 @@ package zmaster587.advancedRocketry.tile.infrastructure; - -import net.minecraft.item.ItemStack; +import micdoodle8.mods.galacticraft.core.network.PacketEntityUpdate; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ITickable; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.capability.CapabilityFluidHandler; +import net.minecraftforge.fluids.capability.IFluidHandler; import zmaster587.advancedRocketry.api.IInfrastructure; -import zmaster587.advancedRocketry.tile.TileGuidanceComputer; -import zmaster587.advancedRocketry.tile.hatch.TileSatelliteHatch; +import zmaster587.advancedRocketry.entity.EntityRocket; import zmaster587.libVulpes.inventory.modules.IButtonInventory; +import zmaster587.libVulpes.network.PacketEntity; +import zmaster587.libVulpes.network.PacketHandler; import zmaster587.libVulpes.util.INetworkMachine; import zmaster587.libVulpes.util.ZUtils.RedstoneState; import java.util.List; -public class TileRocketUnloader extends TileRocketLoader implements IInfrastructure, ITickable, IButtonInventory, INetworkMachine { - +public class TileRocketFluidUnloader extends TileRocketFluidLoader implements IInfrastructure, ITickable, IButtonInventory, INetworkMachine { - public TileRocketUnloader() { + public TileRocketFluidUnloader() { super(); + this.setOutputOnly(true); } - public TileRocketUnloader(int size) { + public TileRocketFluidUnloader(int size) { super(size); - inventory.setCanInsertSlot(0, false); - inventory.setCanInsertSlot(1, false); - inventory.setCanInsertSlot(2, false); - inventory.setCanInsertSlot(3, false); - inventory.setCanExtractSlot(0, true); - inventory.setCanExtractSlot(1, true); - inventory.setCanExtractSlot(2, true); - inventory.setCanExtractSlot(3, true); } @Override public String getModularInventoryName() { - return "tile.loader.2.name"; + return "tile.loader.4.name"; } @Override public void update() { - if (world.isRemote || rocket == null) - return; - - // Throttle: only try to move items every TRANSFER_INTERVAL_TICKS - if (transferCooldown > 0) { - transferCooldown--; - return; - } - - boolean isAllowedToOperate = (inputstate == RedstoneState.OFF || - isStateActive(inputstate, getStrongPowerForSides(world, getPos()))); - - IItemHandler ownHandler = getOwnItemHandler(); - if (ownHandler == null || ownHandler.getSlots() == 0) { - // No destination handler: consider rocket not empty (no "done unloading" signal) - setRedstoneState(false); - return; - } - - List tiles = rocket.storage.getInventoryTiles(); - boolean rocketIsEmpty = true; - - outer: - for (TileEntity tile : tiles) { - if (tile instanceof TileGuidanceComputer || tile instanceof TileSatelliteHatch) - continue; - - IItemHandler rocketHandler = getItemHandler(tile); - if (rocketHandler == null || rocketHandler.getSlots() == 0) - continue; - - int rocketSlots = rocketHandler.getSlots(); - - for (int rocketSlot = 0; rocketSlot < rocketSlots; rocketSlot++) { - ItemStack rocketStack = rocketHandler.getStackInSlot(rocketSlot); - - if (!rocketStack.isEmpty()) { - rocketIsEmpty = false; - } - - if (rocketStack.isEmpty()) - continue; - - // If we are not allowed to operate, we only care about rocketIsEmpty for redstone - if (!isAllowedToOperate) { - continue; + //Move fluids + if (!world.isRemote && rocket != null) { + + boolean isAllowToOperate = (inputstate == RedstoneState.OFF || isStateActive(inputstate, getStrongPowerForSides(world, getPos()))); + + List tiles = rocket.storage.getFluidTiles(); + boolean rocketFluidFull = false; + + boolean doupdate = false; + //Function returns if something can be moved + for (TileEntity tile : tiles) { + IFluidHandler handler = tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); + + //See if we have anything to fill because redstone output + FluidStack rocketFluid = handler.drain(1, false); + if (handler.fill(rocketFluid, false) > 0) + rocketFluidFull = true; + + if (isAllowToOperate) { + boolean shouldOperate; + if (getFluidTank().getFluid() != null) + shouldOperate = getFluidTank().fill(handler.drain(new FluidStack(getFluidTank().getFluid(), getFluidTank().getCapacity() - getFluidTank().getFluidAmount()), false), false) > 0; + else + shouldOperate = getFluidTank().fill(handler.drain(getFluidTank().getCapacity(), false), false) > 0; + + if (shouldOperate) { + doupdate = true; + getFluidTank().fill(handler.drain(Math.max(50, getFluidTank().getCapacity() - getFluidTank().getFluidAmount()), true), true); + } } + } + if (doupdate) { + PacketHandler.sendToNearby(new PacketEntity(rocket, (byte) 9987), world.provider.getDimension(), getPos(), 128); + } - // Limit per-operation transfer, but DO NOT assume anything about slot max size - int maxToMove = Math.min(MAX_TRANSFER_PER_OPERATION, rocketStack.getCount()); - if (maxToMove <= 0) - continue; - - // Simulate extraction from rocket - ItemStack simulatedExtract = rocketHandler.extractItem(rocketSlot, maxToMove, true); - if (simulatedExtract.isEmpty()) - continue; - - // Simulate insertion into our own inventory - ItemStack simulatedRemainder = ItemHandlerHelper.insertItem(ownHandler, simulatedExtract, true); - int accepted = simulatedExtract.getCount() - simulatedRemainder.getCount(); - if (accepted <= 0) - continue; - - // Actually extract exactly what will fit - ItemStack actuallyExtracted = rocketHandler.extractItem(rocketSlot, accepted, false); - if (actuallyExtracted.isEmpty()) - continue; - - // Actually insert into our inventory - ItemStack remainder = ItemHandlerHelper.insertItem(ownHandler, actuallyExtracted, false); - - // Last-resort fallback for misbehaving mods: try to put remainder back - if (!remainder.isEmpty()) { - ItemHandlerHelper.insertItem(rocketHandler, remainder, false); - // Same note: if that still leaves items, they're from a broken handler. - } + //Update redstone state + setRedstoneState(!rocketFluidFull); - transferCooldown = TRANSFER_INTERVAL_TICKS; - markDirty(); - tile.markDirty(); - break outer; // only one transfer per operation - } } - - // Redstone: ON when rocketIsEmpty (unloading done) - setRedstoneState(rocketIsEmpty); } - } From a460b76c84d2663293027fbe5a3936cda7f47620 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:50:04 +0100 Subject: [PATCH 355/424] Refactor TileRocketUnloader for item transfer logic --- .../infrastructure/TileRocketUnloader.java | 135 ++++++++++++------ 1 file changed, 89 insertions(+), 46 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketUnloader.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketUnloader.java index 9fe29982a..1a72c8959 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketUnloader.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketUnloader.java @@ -1,21 +1,22 @@ package zmaster587.advancedRocketry.tile.infrastructure; -import net.minecraft.inventory.IInventory; + import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ITickable; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; import zmaster587.advancedRocketry.api.IInfrastructure; import zmaster587.advancedRocketry.tile.TileGuidanceComputer; +import zmaster587.advancedRocketry.tile.hatch.TileSatelliteHatch; import zmaster587.libVulpes.inventory.modules.IButtonInventory; -import zmaster587.libVulpes.inventory.modules.ModuleRedstoneOutputButton; import zmaster587.libVulpes.util.INetworkMachine; import zmaster587.libVulpes.util.ZUtils.RedstoneState; import java.util.List; public class TileRocketUnloader extends TileRocketLoader implements IInfrastructure, ITickable, IButtonInventory, INetworkMachine { - ModuleRedstoneOutputButton redstoneControl; - RedstoneState state; + public TileRocketUnloader() { super(); @@ -41,52 +42,94 @@ public String getModularInventoryName() { @Override public void update() { + if (world.isRemote || rocket == null) + return; + + // Throttle: only try to move items every TRANSFER_INTERVAL_TICKS + if (transferCooldown > 0) { + transferCooldown--; + return; + } + + boolean isAllowedToOperate = (inputstate == RedstoneState.OFF || + isStateActive(inputstate, getStrongPowerForSides(world, getPos()))); + + IItemHandler ownHandler = getOwnItemHandler(); + if (ownHandler == null || ownHandler.getSlots() == 0) { + // No destination handler: consider rocket not empty (no "done unloading" signal) + setRedstoneState(false); + return; + } - //Move a stack of items - if (!world.isRemote && rocket != null) { - boolean isAllowedToOperate = (inputstate == RedstoneState.OFF || isStateActive(inputstate, getStrongPowerForSides(world, getPos()))); - - List tiles = rocket.storage.getInventoryTiles(); - boolean foundStack = false; - boolean rocketContainsNoItems = true; - out: - //Function returns if something can be moved - for (TileEntity tile : tiles) { - if (tile instanceof IInventory && !(tile instanceof TileGuidanceComputer)) { - IInventory inv = ((IInventory) tile); - for (int i = 0; i < inv.getSizeInventory(); i++) { - if (!inv.getStackInSlot(i).isEmpty()) { - rocketContainsNoItems = false; - //Loop though this inventory's slots and find a suitible one - for (int j = 0; j < getSizeInventory(); j++) { - if (getStackInSlot(j).isEmpty()) { - if (isAllowedToOperate) { - inventory.setInventorySlotContents(j, inv.getStackInSlot(i)); - inv.setInventorySlotContents(i, ItemStack.EMPTY); - } - break out; - } else if (!inv.getStackInSlot(i).isEmpty() && isItemValidForSlot(j, inv.getStackInSlot(i))) { - if (isAllowedToOperate) { - ItemStack stack2 = inv.decrStackSize(i, getStackInSlot(j).getMaxStackSize() - getStackInSlot(j).getCount()); - getStackInSlot(j).setCount(getStackInSlot(j).getCount() + stack2.getCount()); - } - if (inv.getStackInSlot(i).isEmpty()) - break out; - foundStack = true; - } - } - } - - if (foundStack) - break out; - } + List tiles = rocket.storage.getInventoryTiles(); + boolean rocketIsEmpty = true; + + outer: + for (TileEntity tile : tiles) { + if (tile instanceof TileGuidanceComputer || tile instanceof TileSatelliteHatch) + continue; + + IItemHandler rocketHandler = getItemHandler(tile); + if (rocketHandler == null || rocketHandler.getSlots() == 0) + continue; + + int rocketSlots = rocketHandler.getSlots(); + + for (int rocketSlot = 0; rocketSlot < rocketSlots; rocketSlot++) { + ItemStack rocketStack = rocketHandler.getStackInSlot(rocketSlot); + + if (!rocketStack.isEmpty()) { + rocketIsEmpty = false; } - } - //Update redstone state - setRedstoneState(rocketContainsNoItems); + if (rocketStack.isEmpty()) + continue; + // If we are not allowed to operate, we only care about rocketIsEmpty for redstone + if (!isAllowedToOperate) { + continue; + } + + // Limit per-operation transfer, but DO NOT assume anything about slot max size + int maxToMove = Math.min(MAX_TRANSFER_PER_OPERATION, rocketStack.getCount()); + if (maxToMove <= 0) + continue; + + // Simulate extraction from rocket + ItemStack simulatedExtract = rocketHandler.extractItem(rocketSlot, maxToMove, true); + if (simulatedExtract.isEmpty()) + continue; + + // Simulate insertion into our own inventory + ItemStack simulatedRemainder = ItemHandlerHelper.insertItem(ownHandler, simulatedExtract, true); + int accepted = simulatedExtract.getCount() - simulatedRemainder.getCount(); + if (accepted <= 0) + continue; + + // Actually extract exactly what will fit + ItemStack actuallyExtracted = rocketHandler.extractItem(rocketSlot, accepted, false); + if (actuallyExtracted.isEmpty()) + continue; + + // Actually insert into our inventory + ItemStack remainder = ItemHandlerHelper.insertItem(ownHandler, actuallyExtracted, false); + + // Last-resort fallback for misbehaving mods: try to put remainder back + if (!remainder.isEmpty()) { + ItemHandlerHelper.insertItem(rocketHandler, remainder, false); + // Same note: if that still leaves items, they're from a broken handler. + } + + transferCooldown = TRANSFER_INTERVAL_TICKS; + markDirty(); + tile.markDirty(); + break outer; // only one transfer per operation + } } + + // Redstone: ON when rocketIsEmpty (unloading done) + setRedstoneState(rocketIsEmpty); } -} + +} From 48f906009190114639a22eba953c177c44cbe52d Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:53:39 +0100 Subject: [PATCH 356/424] Implement data bus snapshot and restore functionality Added methods to snapshot and restore data buses during teardown. --- .../tile/multiblock/TileObservatory.java | 218 +++++++++++++++--- 1 file changed, 188 insertions(+), 30 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java index 7a06f4df2..733ebee33 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java @@ -21,6 +21,7 @@ import zmaster587.advancedRocketry.inventory.TextureResources; import zmaster587.advancedRocketry.inventory.modules.ModuleData; import zmaster587.advancedRocketry.inventory.modules.ModuleContainerPanYOnlyWithScrollCache; +import zmaster587.advancedRocketry.item.IDataItem; import zmaster587.advancedRocketry.item.ItemAsteroidChip; import zmaster587.advancedRocketry.item.ItemData; import zmaster587.advancedRocketry.tile.hatch.TileDataBus; @@ -38,6 +39,7 @@ import zmaster587.libVulpes.network.PacketMachine; import zmaster587.libVulpes.tile.multiblock.TileMultiBlock; import zmaster587.libVulpes.tile.multiblock.TileMultiPowerConsumer; +import zmaster587.libVulpes.tile.multiblock.TilePlaceholder; import zmaster587.libVulpes.util.EmbeddedInventory; import javax.annotation.Nonnull; @@ -46,6 +48,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Random; +import java.util.Map; public class TileObservatory extends TileMultiPowerConsumer implements IModularInventory, IDataInventory, IGuiCallback { @@ -53,6 +56,7 @@ public class TileObservatory extends TileMultiPowerConsumer implements IModularI private java.util.HashSet printedButtonsThisSeed = new java.util.HashSet<>(); private long printedSetSeed = -1; // track which seed the set belongs to + private final java.util.Map savedDataBusNbt = new java.util.HashMap<>(); final static int openTime = 100; final static int observationTime = 1000; private static final Block[] lens = {AdvancedRocketryBlocks.blockLens, Blocks.GLASS}; @@ -118,23 +122,107 @@ public float getOpenProgress() { return openProgress / (float) openTime; } + private void snapshotDataBusesBeforeTeardown() { + savedDataBusNbt.clear(); + + final Object[][][] struct = getStructure(); + if (struct == null || world == null) return; + + final zmaster587.libVulpes.util.Vector3F off = getControllerOffset(struct); + final EnumFacing front = getFrontDirection(world.getBlockState(pos)); + + for (int y = 0; y < struct.length; y++) { + for (int z = 0; z < struct[0].length; z++) { + for (int x = 0; x < struct[0][0].length; x++) { + if (struct[y][z][x] == null) continue; + + int gx = pos.getX() + (x - off.x) * front.getFrontOffsetZ() + - (z - off.z) * front.getFrontOffsetX(); + int gy = pos.getY() - y + off.y; + int gz = pos.getZ() - (x - off.x) * front.getFrontOffsetX() + - (z - off.z) * front.getFrontOffsetZ(); + BlockPos bp = new BlockPos(gx, gy, gz); + + TileEntity te = world.getTileEntity(bp); + if (te instanceof zmaster587.libVulpes.tile.multiblock.TilePlaceholder) { + te = ((zmaster587.libVulpes.tile.multiblock.TilePlaceholder) te).getReplacedTileEntity(); + } + + if (te instanceof zmaster587.advancedRocketry.tile.hatch.TileDataBus) { + NBTTagCompound tag = new NBTTagCompound(); + te.writeToNBT(tag); + savedDataBusNbt.put(bp.toLong(), tag); + } + } + } + } + } + + private void restoreDataBusesAfterTeardown() { + if (world == null || savedDataBusNbt.isEmpty()) return; + + try { + for (Map.Entry e : savedDataBusNbt.entrySet()) { + BlockPos bp = BlockPos.fromLong(e.getKey()); + TileEntity te = world.getTileEntity(bp); + + if (te instanceof TilePlaceholder) { + te = ((TilePlaceholder) te).getReplacedTileEntity(); + } + + if (te instanceof TileDataBus) { + TileDataBus bus = (TileDataBus) te; + bus.readFromNBT(e.getValue()); + bus.lockData(null); + bus.markDirty(); + world.notifyBlockUpdate(bp, world.getBlockState(bp), world.getBlockState(bp), 3); + } + } + } finally { + savedDataBusNbt.clear(); + } + } + + @Override protected void integrateTile(TileEntity tile) { super.integrateTile(tile); if (tile instanceof TileDataBus) { - dataCables.add((TileDataBus) tile); - ((TileDataBus) tile).lockData(((TileDataBus) tile).getDataObject().getDataType()); + TileDataBus bus = (TileDataBus) tile; + dataCables.add(bus); + + DataType type = bus.getDataObject().getDataType(); + + // If bus already has a meaningful type, preserve it. + if (type != null && type != DataType.UNDEFINED) { + bus.lockData(type); + } else { + // Default untyped buses to DISTANCE + bus.lockData(DataType.DISTANCE); + } } } + @Override - public void deconstructMultiBlock(World world, BlockPos destroyedPos, - boolean blockBroken, IBlockState state) { - super.deconstructMultiBlock(world, destroyedPos, blockBroken, state); + public void deconstructMultiBlock(World worldIn, BlockPos destroyedPos, + boolean blockBroken, IBlockState state) { + + if (!worldIn.isRemote) { + snapshotDataBusesBeforeTeardown(); + } + + super.deconstructMultiBlock(worldIn, destroyedPos, blockBroken, state); + + if (!worldIn.isRemote) { + restoreDataBusesAfterTeardown(); + } + viewDistance = 0; } + @Override protected void replaceStandardBlock(BlockPos newPos, IBlockState state, TileEntity tile) { @@ -383,7 +471,13 @@ public List getModules(int ID, EntityPlayer player) { float time = asteroidSmol.timeMultiplier; - buttonList.add(new ModuleText(0, 24 * (1 + (g / 2)), String.format("%s\n%.2fx", "Time:", time), 0x2f2f2f)); + String timeLabel = LibVulpes.proxy.getLocalizedString("msg.observetory.text.time"); + buttonList.add(new ModuleText( + 0, + 24 * (1 + (g / 2)), + String.format("%s\n%.2fx", timeLabel, time), + 0x2f2f2f + )); } @@ -548,15 +642,15 @@ public void onInventoryButtonPressed(int buttonId) { PacketHandler.sendToServer(new PacketMachine(this, BUTTON_PRESS)); } if (buttonId == 2) { - - //for(TileDataBus bus : getDataBus()) { + PacketHandler.sendToServer(new PacketMachine(this, SEED_CHANGE)); + /*/for(TileDataBus bus : getDataBus()) { if (extractData(dataConsumedPerRefresh, DataType.DISTANCE, EnumFacing.UP, false) == dataConsumedPerRefresh) { lastSeed = world.getTotalWorldTime() / 100; lastButton = -1; lastType = ""; PacketHandler.sendToServer(new PacketMachine(this, SEED_CHANGE)); } - //} + /}*/ } } @@ -720,10 +814,28 @@ public void closeInventory(EntityPlayer player) { } @Override - public boolean isItemValidForSlot(int p_94041_1_, @Nonnull ItemStack p_94041_2_) { - return inv.isItemValidForSlot(p_94041_1_, p_94041_2_); + public boolean isItemValidForSlot(int slot, @Nonnull ItemStack stack) { + if (stack.isEmpty()) return false; + + // data chip slots + if (slot == 0 || slot == 3 || slot == 4) { + return stack.getItem() instanceof IDataItem; + } + + // asteroid chip input slot (if that's your intended one) + if (slot == 1) { + return stack.getItem() instanceof ItemAsteroidChip; + } + + // output slot(s) + if (slot == 2) { + return false; + } + + return true; } + @Override public int extractData(int maxAmount, DataType type, EnumFacing dir, boolean commit) { int amt = 0; @@ -742,20 +854,49 @@ public int addData(int maxAmount, DataType type, EnumFacing dir, boolean commit) @Override public void loadData(int id) { - int chipSlot = !inv.getStackInSlot(0).isEmpty() ? 0 : !inv.getStackInSlot(3).isEmpty() ? 3 : 4; - ItemStack dataChip = !inv.getStackInSlot(0).isEmpty() ? inv.getStackInSlot(0) : !inv.getStackInSlot(3).isEmpty() ? inv.getStackInSlot(3) : inv.getStackInSlot(4); + int chipSlot = !inv.getStackInSlot(0).isEmpty() ? 0 + : !inv.getStackInSlot(3).isEmpty() ? 3 + : 4; - if (dataChip != ItemStack.EMPTY && dataChip.getItem() instanceof ItemData && dataChip.getCount() == 1) { + ItemStack dataChip = !inv.getStackInSlot(0).isEmpty() ? inv.getStackInSlot(0) + : !inv.getStackInSlot(3).isEmpty() ? inv.getStackInSlot(3) + : inv.getStackInSlot(4); - ItemData dataItem = (ItemData) dataChip.getItem(); - DataStorage data = dataItem.getDataStorage(dataChip); + if (!dataChip.isEmpty() && dataChip.getItem() instanceof IDataItem && dataChip.getCount() == 1) { - for (TileDataBus tile : dataCables) { - if (doesSlotIndexMatchDataType(data.getDataType(), chipSlot)) - dataItem.removeData(dataChip, tile.addData(Math.min(tile.getDataObject().getMaxData() - tile.getData(), data.getData()), data.getDataType(), EnumFacing.UP, true), DataStorage.DataType.UNDEFINED); - } + IDataItem dataItem = (IDataItem) dataChip.getItem(); + DataStorage chipData = dataItem.getDataStorage(dataChip); + DataType chipType = chipData.getDataType(); + + if (doesSlotIndexMatchDataType(chipType, chipSlot)) { + + for (TileDataBus tile : dataCables) { - //dataItem.setData(dataChip, data.getData(), data.getData() != 0 ? data.getDataType() : DataType.UNDEFINED); + // Only push into buses that match the chip's type by design + if (tile.getDataObject().getDataType() != chipType && + tile.getDataObject().getDataType() != DataType.UNDEFINED) { + continue; + } + + int remaining = chipData.getData(); + if (remaining <= 0) break; + + int space = tile.getDataObject().getMaxData() - tile.getData(); + if (space <= 0) continue; + + int toMove = Math.min(space, remaining); + + int accepted = tile.addData(toMove, chipType, EnumFacing.UP, true); + if (accepted > 0) { + // IMPORTANT: decrement the LOCAL chipData so the next bus + // doesn't see the original amount + chipData.removeData(accepted, true); + } + } + + // Write the final state back to the item once + dataItem.setData(dataChip, chipData.getData(), chipData.getDataType()); + } } if (world.isRemote) { @@ -763,23 +904,37 @@ public void loadData(int id) { } } + @Override public void storeData(int id) { - int chipSlot = !inv.getStackInSlot(0).isEmpty() ? 0 : !inv.getStackInSlot(3).isEmpty() ? 3 : 4; - ItemStack dataChip = !inv.getStackInSlot(0).isEmpty() ? inv.getStackInSlot(0) : !inv.getStackInSlot(3).isEmpty() ? inv.getStackInSlot(3) : inv.getStackInSlot(4); + int chipSlot = !inv.getStackInSlot(0).isEmpty() ? 0 + : !inv.getStackInSlot(3).isEmpty() ? 3 + : 4; - if (dataChip != ItemStack.EMPTY && dataChip.getItem() instanceof ItemData && dataChip.getCount() == 1) { + ItemStack dataChip = !inv.getStackInSlot(0).isEmpty() ? inv.getStackInSlot(0) + : !inv.getStackInSlot(3).isEmpty() ? inv.getStackInSlot(3) + : inv.getStackInSlot(4); - ItemData dataItem = (ItemData) dataChip.getItem(); - DataStorage data = dataItem.getDataStorage(dataChip); + if (!dataChip.isEmpty() && dataChip.getItem() instanceof IDataItem && dataChip.getCount() == 1) { + + IDataItem dataItem = (IDataItem) dataChip.getItem(); + DataStorage chipData = dataItem.getDataStorage(dataChip); for (TileDataBus tile : dataCables) { - DataStorage.DataType dataType = tile.getDataObject().getDataType(); - if (doesSlotIndexMatchDataType(dataType, chipSlot)) - data.addData(tile.extractData(data.getMaxData() - data.getData(), data.getDataType(), EnumFacing.UP, true), dataType, true); + DataType busType = tile.getDataObject().getDataType(); + + if (!doesSlotIndexMatchDataType(busType, chipSlot)) continue; + + int remainingCap = chipData.getMaxData() - chipData.getData(); + if (remainingCap <= 0) break; + + int pulled = tile.extractData(remainingCap, chipData.getDataType(), EnumFacing.UP, true); + if (pulled > 0) { + chipData.addData(pulled, busType, true); + } } - dataItem.setData(dataChip, data.getData(), data.getDataType()); + dataItem.setData(dataChip, chipData.getData(), chipData.getDataType()); } if (world.isRemote) { @@ -787,6 +942,7 @@ public void storeData(int id) { } } + @Override @Nullable public String getName() { @@ -830,6 +986,7 @@ public void invalidate() { lastButton = -1; lastType = ""; ModuleContainerPanYOnlyWithScrollCache.clearScrollCache(); // static GUI cache + savedDataBusNbt.clear(); } @Override @@ -837,6 +994,7 @@ public void onChunkUnload() { super.onChunkUnload(); dataCables.clear(); ModuleContainerPanYOnlyWithScrollCache.clearScrollCache(); + savedDataBusNbt.clear(); } @Override From cf932dfac73def46e50cda107261268175ca36b8 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:54:32 +0100 Subject: [PATCH 357/424] Replace static button label with localized string --- .../tile/satellite/TileSatelliteBuilder.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteBuilder.java b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteBuilder.java index 3d8847b2c..476bb483a 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteBuilder.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteBuilder.java @@ -198,7 +198,8 @@ public List getModules(int ID, EntityPlayer player) { modules.add(new ModuleTexturedSlotArray(58, 16, this, chipSlot, chipSlot + 1, TextureResources.idChip)); // Id chip modules.add(new ModuleTexturedSlotArray(82, 16, this, chipCopySlot, chipCopySlot + 1, TextureResources.idChip)); // Id chip modules.add(new ModuleProgress(75, 36, 0, new ProgressBarImage(217, 0, 17, 17, 234, 0, EnumFacing.DOWN, TextureResources.progressBars), this)); - modules.add(new ModuleButton(40, 56, 0, "Build", this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); + String buildLabel = LibVulpes.proxy.getLocalizedString("msg.rocketbuilder.build"); + modules.add(new ModuleButton(40, 56, 0, buildLabel, this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); modules.add(new ModuleButton(173, 3, 1, "", this, TextureResources.buttonCopy, LibVulpes.proxy.getLocalizedString("msg.satbuilder.writesecondchip"), 24, 24)); return modules; @@ -381,4 +382,4 @@ public void clear() { public boolean isEmpty() { return inventory.isEmpty(); } -} \ No newline at end of file +} From ecc0d3828d46ad660b4524ba7ae9ef381dd034fc Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:55:13 +0100 Subject: [PATCH 358/424] Enhance planet selector and cache management Added planet selector functionality and improved caching for dimension properties. --- .../advancedRocketry/entity/EntityRocket.java | 250 ++++++++++++++++-- 1 file changed, 230 insertions(+), 20 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java b/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java index 4945bc0b7..740c377ee 100644 --- a/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java +++ b/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java @@ -43,6 +43,7 @@ import net.minecraftforge.fluids.FluidUtil; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import net.minecraftforge.oredict.OreDictionary; import zmaster587.advancedRocketry.AdvancedRocketry; import zmaster587.advancedRocketry.advancements.ARAdvancements; import zmaster587.advancedRocketry.api.*; @@ -146,9 +147,12 @@ public class EntityRocket extends EntityRocketBase implements INetworkEntity, IM private int autoDescendTimer; // Is this value even used? //0 to 100, 100 is fully rotated and ready to go, 0 is normal mode private int rcs_mode_counter = 0; - //Used to most of the logic, determining if in RCS mode or not + // Used to most of the logic, determining if in RCS mode or not private boolean rcs_mode = false; + // Mirror PlanetSelector Progressbars + private DimensionProperties dimCache; + // Preload ticket for destination chunks on launch event should be enough time to get a warm dimension private Ticket destPreloadTicket = null; private int destPreloadDim = Integer.MIN_VALUE; @@ -197,6 +201,79 @@ public EntityRocket(World world, StorageChunk storage, StatsRocket stats, double landingPadDisplayText.setColor(0x00ff00); } + // PlanetSelector fixing methods + private void selectSystem(int id) { + if (id == Constants.INVALID_PLANET) { + dimCache = null; + } else { + dimCache = DimensionManager.getInstance().getDimensionProperties(id); + } + planetSelectorProgress.setProps(dimCache); + } + + + @Override + public void onSelected(Object sender) { + if (sender instanceof ModulePlanetSelector) { + int id = ((ModulePlanetSelector) sender).getSelectedSystem(); + selectSystem(id); + } + } + @Override + public void onSystemFocusChanged(Object sender) { + if (sender instanceof ModulePlanetSelector) { + int id = ((ModulePlanetSelector) sender).getSelectedSystem(); + selectSystem(id); + } + } + + private void clearPlanetSelectorCache() { + dimCache = null; + planetSelectorProgress.setProps(null); + + // Optional but nice: drop GUI references so nothing keeps stale state + container = null; + } + + private final PlanetSelectorProgressAdapter planetSelectorProgress = new PlanetSelectorProgressAdapter(); + + private static final class PlanetSelectorProgressAdapter implements IProgressBar { + private DimensionProperties props; + + void setProps(DimensionProperties props) { + this.props = props; + } + + @Override + public float getNormallizedProgress(int id) { + int total = getTotalProgress(id); + if (total <= 0) return 0f; + return MathHelper.clamp(getProgress(id) / (float) total, 0f, 1f); + } + + @Override public void setProgress(int id, int progress) {} + @Override public void setTotalProgress(int id, int progress) {} + + @Override + public int getProgress(int id) { + if (props == null) return 0; + // Placeholder style consistent with TilePlanetSelector + if (id == 0 || id == 1 || id == 2) return 25; + return 0; + } + + @Override + public int getTotalProgress(int id) { + if (props == null) return 50; + + if (id == 0) return Math.max(1, props.getAtmosphereDensity() / 16); + if (id == 1) return Math.max(1, props.orbitalDist / 16); + if (id == 2) return Math.max(1, (int)(props.gravitationalMultiplier * 50)); + return 1; + } + } + + /** * @param blockState the blockstate to damage * @return the blockstate that the input blockstate turns into @@ -426,6 +503,86 @@ else if (!isInFlight()) return super.getTextOverlay(); } + // Artifact gating + private boolean isPlanetGated(DimensionProperties props) { + if (props == null) return false; + List req = props.getRequiredArtifacts(); + return req != null && !req.isEmpty(); + } + + @Nullable + private EntityPlayer getPilot() { + for (Entity e : getPassengers()) { + if (e instanceof EntityPlayer) return (EntityPlayer) e; + } + return null; + } + + private boolean pilotHasGateArtifacts(EntityPlayer pilot, DimensionProperties destProps) { + if (destProps == null) return false; + + List required = destProps.getRequiredArtifacts(); + if (required == null || required.isEmpty()) return true; + + for (ItemStack req : required) { + if (!hasRequiredStack(pilot, req)) return false; + } + return true; + } + + private boolean hasRequiredStack(EntityPlayer pilot, ItemStack req) { + if (req.isEmpty()) return true; + + // main inventory + for (ItemStack have : pilot.inventory.mainInventory) { + if (matchesRequirement(have, req)) return true; + } + // armor + for (ItemStack have : pilot.inventory.armorInventory) { + if (matchesRequirement(have, req)) return true; + } + // offhand + for (ItemStack have : pilot.inventory.offHandInventory) { + if (matchesRequirement(have, req)) return true; + } + + return false; + } + + private boolean matchesRequirement(ItemStack have, ItemStack req) { + return !have.isEmpty() + && have.getItem() == req.getItem() + && (req.getItemDamage() == OreDictionary.WILDCARD_VALUE + || have.getItemDamage() == req.getItemDamage()) + && have.getCount() >= req.getCount(); + } + + @Nullable + private ItemStack getFirstMissingGateArtifact(@Nullable EntityPlayer pilot, @Nullable DimensionProperties destProps) { + if (pilot == null || destProps == null) return null; + + List required = destProps.getRequiredArtifacts(); + if (required == null || required.isEmpty()) return null; + + for (ItemStack req : required) { + if (!hasRequiredStack(pilot, req)) { + return req; + } + } + return null; + } + + private String getGateArtifactError(@Nullable EntityPlayer pilot, @Nullable DimensionProperties destProps) { + String base = LibVulpes.proxy.getLocalizedString("error.rocket.gatedArtifactMissing"); + + ItemStack missing = getFirstMissingGateArtifact(pilot, destProps); + if (missing == null || missing.isEmpty()) return base; + + // Keep it simple: show the in-game display name + return base + ": " + missing.getCount() + "x " + missing.getDisplayName(); + } + + private void setError(String error) { this.errorStr = error; this.lastErrorTime = this.world.getTotalWorldTime(); @@ -1964,10 +2121,43 @@ public void launch() { thisDimId = spaceObject.getProperties().getParentProperties().getId(); } - //Check to see if it's possible to reach - if (finalDest != Constants.INVALID_PLANET && (!stats.isNuclear() || DimensionManager.getInstance().getDimensionProperties(finalDest).getStarId() != DimensionManager.getInstance().getDimensionProperties(thisDimId).getStarId()) && !PlanetaryTravelHelper.isTravelAnywhereInPlanetarySystem(finalDest, thisDimId)) { - setError(LibVulpes.proxy.getLocalizedString("error.rocket.notSameSystem")); - return; + //Check to see if it's possible to reach (split failure modes) + if (finalDest != Constants.INVALID_PLANET) { + + DimensionProperties destProps = DimensionManager.getInstance().getDimensionProperties(finalDest); + DimensionProperties srcProps = DimensionManager.getInstance().getDimensionProperties(thisDimId); + + boolean isNuclear = stats.isNuclear(); + boolean sameStar = destProps.getStarId() == srcProps.getStarId(); + boolean outsidePlanetarySystem = !PlanetaryTravelHelper.isTravelAnywhereInPlanetarySystem(finalDest, thisDimId); + + // Only skip gating for nuclear rockets when config says so + boolean enforceGating = true; + if (isNuclear) { + enforceGating = ARConfiguration.getCurrentConfig().nuclearRocketsRespectArtifactGating; + } + + // Artifact gating: only when arriving from outside the planetary system + if (enforceGating && isPlanetGated(destProps) && outsidePlanetarySystem) { + EntityPlayer pilot = getPilot(); + if (pilot == null || !pilotHasGateArtifacts(pilot, destProps)) { + setError(getGateArtifactError(pilot, destProps)); + return; + } + } + + + // Nuclear cannot cross stars + if (isNuclear && !sameStar) { + setError(LibVulpes.proxy.getLocalizedString("error.rocket.outsideStarSystem")); + return; + } + + // Non-nuclear cannot go outside planetary system + if (!isNuclear && outsidePlanetarySystem) { + setError(LibVulpes.proxy.getLocalizedString("error.rocket.outsidePlanetarySystem")); + return; + } } } @@ -2063,6 +2253,7 @@ private void damageGroundBelowRocket(World world, int x, int y, int z, int radiu */ @Override public void deconstructRocket() { + clearPlanetSelectorCache(); super.deconstructRocket(); for (IInfrastructure infrastructure : connectedInfrastructure) { @@ -2077,6 +2268,7 @@ public void deconstructRocket() { @Override public void setDead() { + clearPlanetSelectorCache(); super.setDead(); releaseDestinationPreload(); @@ -2101,6 +2293,8 @@ public void setOverriddenCoords(int dimId, float x, float y, float z) { @Override public Entity changeDimension(int newDimId) { + clearPlanetSelectorCache(); + return changeDimension(newDimId, this.posX, getEntryHeight(newDimId), this.posZ); } @@ -2148,6 +2342,7 @@ public void copyDataFromOld(Entity entityIn) { nbttagcompound.removeTag("Passengers"); this.readFromNBT(nbttagcompound); this.timeUntilPortal = entityIn.timeUntilPortal; + clearPlanetSelectorCache(); } protected void readNetworkableNBT(NBTTagCompound nbt) { @@ -2316,9 +2511,13 @@ public void writeDataToNetwork(ByteBuf out, byte id) { if (id == PacketType.RECIEVENBT.ordinal()) { storage.writeToNetwork(out); } else if (id == PacketType.SENDPLANETDATA.ordinal()) { - if (world.isRemote) - out.writeInt(container.getSelectedSystem()); - else { + if (world.isRemote) { + int sel = Constants.INVALID_PLANET; + if (container != null) { + sel = container.getSelectedSystem(); + } + out.writeInt(sel); + } else { if (storage.getGuidanceComputer() != null) { ItemStack stack = storage.getGuidanceComputer().getStackInSlot(0); if (!stack.isEmpty() && stack.getItem() == AdvancedRocketryItems.itemPlanetIdChip) { @@ -2465,7 +2664,8 @@ private void setDestLandingPad(int padIndex) { } StationLandingLocation location = storage.getGuidanceComputer().getLandingLocation(uuid); - landingPadDisplayText.setText(location != null ? location.toString() : "None Selected"); + String noneLabel = LibVulpes.proxy.getLocalizedString("msg.entity.rocket.none"); + landingPadDisplayText.setText(location != null ? location.toString() : noneLabel); } } @@ -2614,9 +2814,23 @@ public List getModules(int ID, EntityPlayer player) { while (properties.getParentProperties() != null) properties = properties.getParentProperties(); if (stats.isNuclear()) - container = new ModulePlanetSelector(properties.getStarId(), zmaster587.libVulpes.inventory.TextureResources.starryBG, this, this, true); + container = new ModulePlanetSelector( + properties.getStarId(), + zmaster587.libVulpes.inventory.TextureResources.starryBG, + this, // selection notify + planetSelectorProgress, // progress source + this, // planet definer + true + ); else - container = new ModulePlanetSelector(properties.getId(), zmaster587.libVulpes.inventory.TextureResources.starryBG, this, false); + container = new ModulePlanetSelector( + properties.getId(), + zmaster587.libVulpes.inventory.TextureResources.starryBG, + this, // selection notify + planetSelectorProgress, // progress source + false + ); + container.setOffset(1000, 1000); modules.add(container); } @@ -2626,7 +2840,7 @@ public List getModules(int ID, EntityPlayer player) { @Override public String getModularInventoryName() { - return "Rocket"; + return ""; } @Override @@ -2691,6 +2905,7 @@ public int getTotalProgress(int id) { return 1; } + @Override public void setTotalProgress(int id, int progress) { } @@ -2732,21 +2947,13 @@ public StatsRocket getRocketStats() { return stats; } - @Override - public void onSelected(Object sender) { - - } @Override public void onSelectionConfirmed(Object sender) { PacketHandler.sendToServer(new PacketEntity(this, (byte) PacketType.SENDPLANETDATA.ordinal())); } - @Override - public void onSystemFocusChanged(Object sender) { - // TODO Auto-generated method stub - } public LinkedList getConnectedInfrastructure() { return connectedInfrastructure; @@ -2762,6 +2969,9 @@ public boolean isStarKnown(StellarBody body) { return true; } + + + public enum PacketType { RECIEVENBT, SENDINTERACT, From d2167fc6f8c381dd7357c5c7d0bb4a745ceb354f Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:55:51 +0100 Subject: [PATCH 359/424] Change name retrieval to use localization --- .../advancedRocketry/satellite/SatelliteOptical.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteOptical.java b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteOptical.java index 1142b2ce3..256599630 100644 --- a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteOptical.java +++ b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteOptical.java @@ -2,6 +2,7 @@ import zmaster587.advancedRocketry.api.DataStorage; import zmaster587.advancedRocketry.api.DataStorage.DataType; +import zmaster587.libVulpes.LibVulpes; public class SatelliteOptical extends SatelliteData { @@ -13,7 +14,7 @@ public SatelliteOptical() { @Override public String getName() { - return "Optical Telescope"; + return LibVulpes.proxy.getLocalizedString("item.satellite.opticaltelescope"); } @Override From 6513be1b9a4aa648d11efc190f466a6dd45d76e4 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:56:17 +0100 Subject: [PATCH 360/424] Update getName method to use localization --- .../advancedRocketry/satellite/SatelliteOreMapping.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteOreMapping.java b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteOreMapping.java index f536587b9..a0e5c3347 100644 --- a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteOreMapping.java +++ b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteOreMapping.java @@ -13,6 +13,7 @@ import zmaster587.advancedRocketry.api.satellite.SatelliteBase; import zmaster587.advancedRocketry.api.satellite.SatelliteProperties; import zmaster587.advancedRocketry.item.ItemOreScanner; +import zmaster587.libVulpes.LibVulpes; import javax.annotation.Nonnull; import java.util.ArrayList; @@ -209,7 +210,7 @@ public double failureChance() { @Override public String getName() { - return "Ore Mapper"; + return LibVulpes.proxy.getLocalizedString("item.satellite.oremapper"); } From c6695c01699c02965a641d1a23261bef819acd37 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:56:45 +0100 Subject: [PATCH 361/424] Change satellite name to localized string --- .../advancedRocketry/satellite/SatelliteMicrowaveEnergy.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteMicrowaveEnergy.java b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteMicrowaveEnergy.java index ecea02320..e7065c46b 100644 --- a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteMicrowaveEnergy.java +++ b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteMicrowaveEnergy.java @@ -34,7 +34,7 @@ public String getInfo(World world) { @Override public String getName() { - return "Microwave Energy Satellite"; + return LibVulpes.proxy.getLocalizedString("item.satellite.solar"); } @Override From 8ae838ea7018b24a06d7a5b2bac2b5649b2a5645 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:57:09 +0100 Subject: [PATCH 362/424] Change satellite name to localized string --- .../advancedRocketry/satellite/SatelliteComposition.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteComposition.java b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteComposition.java index d5d844b50..df59cc861 100644 --- a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteComposition.java +++ b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteComposition.java @@ -1,6 +1,7 @@ package zmaster587.advancedRocketry.satellite; import zmaster587.advancedRocketry.api.DataStorage; +import zmaster587.libVulpes.LibVulpes; public class SatelliteComposition extends SatelliteData { @@ -12,7 +13,7 @@ public SatelliteComposition() { @Override public String getName() { - return "Composition Scanner"; + return LibVulpes.proxy.getLocalizedString("item.satellite.composition"); } @Override From 5570642d83b8541535fff5bd4fb7f378a7923701 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:57:34 +0100 Subject: [PATCH 363/424] Use localized string for Mass Scanner name --- .../advancedRocketry/satellite/SatelliteMassScanner.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteMassScanner.java b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteMassScanner.java index e5b5f8b05..17e2d0edd 100644 --- a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteMassScanner.java +++ b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteMassScanner.java @@ -1,6 +1,7 @@ package zmaster587.advancedRocketry.satellite; import zmaster587.advancedRocketry.api.DataStorage; +import zmaster587.libVulpes.LibVulpes; public class SatelliteMassScanner extends SatelliteData { @@ -12,7 +13,7 @@ public SatelliteMassScanner() { @Override public String getName() { - return "Mass Scanner"; + return LibVulpes.proxy.getLocalizedString("item.satellite.massscanner"); } @Override From 373d6e496fbc38a894e1232ea107fc1b7077f919 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:58:10 +0100 Subject: [PATCH 364/424] Update getName method to use localization --- .../advancedRocketry/satellite/SatelliteBiomeChanger.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteBiomeChanger.java b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteBiomeChanger.java index 67639e104..c87a1c586 100644 --- a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteBiomeChanger.java +++ b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteBiomeChanger.java @@ -13,6 +13,7 @@ import zmaster587.advancedRocketry.api.satellite.SatelliteProperties; import zmaster587.advancedRocketry.item.ItemBiomeChanger; import zmaster587.advancedRocketry.util.BiomeHandler; +import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.api.IUniversalEnergy; import zmaster587.libVulpes.util.HashedBlockPosition; @@ -64,7 +65,7 @@ public String getInfo(World world) { @Override public String getName() { - return "Biome Changer"; + return LibVulpes.proxy.getLocalizedString("item.satellite.biomechanger"); } @Override From da0102aab803fd49d6be5d218605a1a79bd17eaa Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:58:35 +0100 Subject: [PATCH 365/424] Change satellite name to localized string --- .../advancedRocketry/satellite/SatelliteWeatherController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteWeatherController.java b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteWeatherController.java index d2d3676cf..b9b8b8844 100644 --- a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteWeatherController.java +++ b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteWeatherController.java @@ -27,6 +27,7 @@ import zmaster587.advancedRocketry.network.PacketAirParticle; import zmaster587.advancedRocketry.network.PacketFluidParticle; import zmaster587.advancedRocketry.util.BiomeHandler; +import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.api.IUniversalEnergy; import zmaster587.libVulpes.network.PacketHandler; import zmaster587.libVulpes.util.HashedBlockPosition; @@ -72,7 +73,7 @@ public String getInfo(World world) { @Override public String getName() { - return "Weather Satellite"; + return LibVulpes.proxy.getLocalizedString("item.satellite.weather"); } @Override From 41e6d8efd3ba89183eedffd3f4f75c0b548c76c6 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:59:06 +0100 Subject: [PATCH 366/424] Refactor message construction for satellite terminal --- .../inventory/modules/ModuleSatelliteTerminal.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleSatelliteTerminal.java b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleSatelliteTerminal.java index c9ce27b44..3a11af468 100644 --- a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleSatelliteTerminal.java +++ b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleSatelliteTerminal.java @@ -211,8 +211,13 @@ private void rebuildClientText() { } else if (status == 2) { msg = LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.toofar"); } else { - msg = LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.info") - + "\nPower gen.: " + ppt + "\nData: " + data + "/" + max; + String info = LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.info"); + String power = LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.power"); + String dataLbl = LibVulpes.proxy.getLocalizedString("msg.satctrlcenter.data"); + + msg = info + + "\n" + power + " " + ppt + + "\n" + dataLbl + " " + data + "/" + max; } if (satName != null && !satName.isEmpty()) { From be5854b472e90aaa74b49b74d8fd0d1a4f8c15f2 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 17:59:35 +0100 Subject: [PATCH 367/424] Refactor atmosphere detection and button creation --- .../atmosphere/TileAtmosphereDetector.java | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileAtmosphereDetector.java b/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileAtmosphereDetector.java index a18de9642..5a01063bf 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileAtmosphereDetector.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/atmosphere/TileAtmosphereDetector.java @@ -27,6 +27,7 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Locale; public class TileAtmosphereDetector extends TileEntity implements ITickable, IModularInventory, IButtonInventory, INetworkMachine { @@ -66,25 +67,52 @@ public boolean shouldRefresh(World world, BlockPos pos, return (oldState.getBlock() != newSate.getBlock()); } + @Override public List getModules(int id, EntityPlayer player) { List modules = new LinkedList<>(); List btns = new LinkedList<>(); - Iterator atmIter = AtmosphereRegister.getInstance().getAtmosphereList().iterator(); + Iterator atmIter = AtmosphereRegister.getInstance() + .getAtmosphereList().iterator(); int i = 0; while (atmIter.hasNext()) { IAtmosphere atm = atmIter.next(); - btns.add(new ModuleButton(60, 4 + i * 24, i, LibVulpes.proxy.getLocalizedString(atm.getUnlocalizedName()), this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); + + // Build a translation key from the internal ID + String key = "msg.atmosphere." + atm.getUnlocalizedName().toLowerCase(Locale.ROOT); + + // Ask for the localized string + String label = LibVulpes.proxy.getLocalizedString(key); + + // If no translation exists, LibVulpes will return the key; + // fall back to the raw ID so nothing breaks. + if (label.equals(key)) { + label = atm.getUnlocalizedName(); + } + + btns.add(new ModuleButton( + 60, + 4 + i * 24, + i, + label, + this, + zmaster587.libVulpes.inventory.TextureResources.buttonBuild + )); i++; } - ModuleContainerPan panningContainer = new ModuleContainerPan(5, 20, btns, new LinkedList<>(), zmaster587.libVulpes.inventory.TextureResources.starryBG, 160, 100, 0, 500); + ModuleContainerPan panningContainer = new ModuleContainerPan( + 5, 20, btns, new LinkedList<>(), + zmaster587.libVulpes.inventory.TextureResources.starryBG, + 160, 100, 0, 500 + ); modules.add(panningContainer); return modules; } + @Override public String getModularInventoryName() { return AdvancedRocketryBlocks.blockOxygenDetection.getLocalizedName(); From 6dcaec409174b55c2f1394a43d9effa752b0362f Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 18:00:23 +0100 Subject: [PATCH 368/424] Implement minimum brightness in stellar brightness calculation Added a minimum brightness constant and updated the getStellarBrightness method to ensure it never returns zero, NaN, or Infinity. --- .../util/AstronomicalBodyHelper.java | 28 +++++++++++++++---- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/util/AstronomicalBodyHelper.java b/src/main/java/zmaster587/advancedRocketry/util/AstronomicalBodyHelper.java index c015b0ad5..85c167559 100644 --- a/src/main/java/zmaster587/advancedRocketry/util/AstronomicalBodyHelper.java +++ b/src/main/java/zmaster587/advancedRocketry/util/AstronomicalBodyHelper.java @@ -114,7 +114,12 @@ public static int getAverageTemperature(StellarBody star, int orbitalDistance, i * @param orbitalDistance the distance from the star * @return the insolation of the planet relative to Earth insolation */ + private static final double MIN_BRIGHTNESS = 1.0e-9d; + public static double getStellarBrightness(StellarBody star, int orbitalDistance) { + if (star == null || orbitalDistance <= 0) { + return MIN_BRIGHTNESS; + } //Normal stars are 1.0 times this value, black holes with accretion discs emit less and so modify it float lightMultiplier = 1.0f; //Make all values ratios of Earth normal to get ratio compared to Earth @@ -122,17 +127,30 @@ public static double getStellarBrightness(StellarBody star, int orbitalDistance) float planetaryOrbitalRadius = orbitalDistance / 100f; //Check to see if the star is a black hole boolean blackHole = star.isBlackHole(); - for (StellarBody star2 : star.getSubStars()) - if (!star2.isBlackHole()) { - blackHole = false; - break; + Iterable subs = star.getSubStars(); + if (subs != null) { + for (StellarBody star2 : subs) { + if (star2 != null && !star2.isBlackHole()) { + blackHole = false; + break; + } } + } //There's no real easy way to get the light emitted by an accretion disc, so this substitutes if (blackHole) lightMultiplier *= 0.25; //Returns ratio compared to a planet at 1 AU for Sol, because the other values in AR are normalized, //and this works fairly well for hooking into with other mod's solar panels & such - return (lightMultiplier * ((Math.pow(star.getSize(), 2) * Math.pow(normalizedStarTemperature, 4)) / Math.pow(planetaryOrbitalRadius, 2))); + double brightness = + lightMultiplier * + ((Math.pow(star.getSize(), 2) * Math.pow(normalizedStarTemperature, 4)) / + Math.pow(planetaryOrbitalRadius, 2)); + + // Guarantee: never return 0, NaN, or Infinity + if (!Double.isFinite(brightness) || brightness < MIN_BRIGHTNESS) { + return MIN_BRIGHTNESS; + } + return brightness; } /** From e6d74f7bc1fc58a9c878c3902260d42808c4a407 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 18:00:52 +0100 Subject: [PATCH 369/424] Refactor language file for clarity and consistency Updated various item and tile names, improved error messages, and added new tooltips for better clarity. --- .../assets/advancedrocketry/lang/en_US.lang | 225 ++++++++++++++++-- 1 file changed, 201 insertions(+), 24 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index c6b05361b..76d1d241d 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -32,7 +32,8 @@ tile.Crystallizer.name=Crystallizer tile.blastBrick.name=HeatProof Brick tile.blastFurnaceController.name=HeatProof Furnace Controller tile.fuelStation.name=Fueling station -tile.loader.0.name=Data Bus +tile.databusbig.name=Advanced Databus +tile.loader.0.name=Databus tile.loader.1.name=Satellite Bay tile.loader.2.name=Rocket Unloader tile.loader.3.name=Rocket Loader @@ -139,6 +140,7 @@ tile.landingfloat.name=Landing Float tile.solararray.name=Solar Array Controller tile.solararraypanel.name=Solar Array Panel tile.serviceStation.name=Service Station +tile.orbitalRegistry.name=Orbital Registry item.lens.0.name=Basic Lens item.wafer.0.name=Silicon Wafer @@ -170,7 +172,7 @@ item.miscpart.0.name=User Interface item.miscpart.1.name=Carbon Brick item.station.name=Space Station Container item.stationChip.name=Space Station Id Chip -item.stationchip.openmenu=Crouch right-click to open configuration menu +item.stationchip.openmenu=Sneak right-click to open configuration menu item.spaceHelmet.name=Space Suit Helmet item.spaceChest.name=Space Suit Chest-Piece item.spaceLeggings.name=Space Suit Leggings @@ -192,6 +194,13 @@ item.basicLaserGun.name=Basic Laser Gun item.beaconFinder.name=Beacon Finder item.thermite.name=Thermite item.hovercraft.name=Hovercraft +item.satellite.opticaltelescope=Optical Telescope +item.satellite.composition=Composition Scanner +item.satellite.massscanner=Mass Scanner +item.satellite.solar=Solar +item.satellite.oremapper=Ore Mapper +item.satellite.biomechanger=Biome Changer +item.satellite.weather=Weather Satellite item.jetPack.name=Suit Jetpack @@ -210,13 +219,16 @@ material.TitaniumIridium.name=Titanium Iridium Alloy enchantment.spaceBreathing=Airtight Seal -data.undefined.name=Some Random Data +data.undefined.name=Undefined data.distance.name=Distance data.humidity.name=Humidity data.temperature.name=Temperature data.composition.name=Composition data.atmospheredensity.name=Atmosphere Density data.mass.name=Mass +data.label.type=Type: +data.label.data=Data + fluid.oxygen=Oxygen fluid.hydrogen=Hydrogen @@ -229,11 +241,13 @@ mission.gascollection.name=Gas Collection error.rocket.notEnoughMissionFuel=Not enough fuel! error.rocket.tooHeavy=Rocket is too heavy to launch (insufficient thrust). -error.rocket.cannotGetThere=Selected destination cannot be reached from here. +error.rocket.cannotGetThere=Selected destination cannot be reached. (Are you trying to land on a Gas Giant?) error.rocket.destinationNotExist=Selected space station does not exist. -error.rocket.notSameSystem=Interstellar travel requires a nuclear rocket and a valid route. error.rocket.partsWornOut=Critical parts are worn out — launch aborted. error.rocket.aborted=Launch aborted. +error.rocket.gatedArtifactMissing=Missing Artifact. (Player Inventory) +error.rocket.outsideStarSystem=Interstellar travel requires a Starship. +error.rocket.outsidePlanetarySystem=Planetary travel requires a Nuclear Rocket. advancement.holographic=Holographic advancement.holographic.desc=Craft a Holo-Projector @@ -291,8 +305,26 @@ msg.observetory.text.composition=Composition msg.observetory.text.processdiscovery=Process discovery msg.observetory.text.observabledistance=Observable distance: msg.observetory.text.missionTime=Mission Time: +msg.observetory.text.time=Time: msg.observetory.req.open=Observatory must be open (night, clear sky, sky access) or be in space! msg.observetory.print.already=You already have a chip for this asteroid! + +# Atmosphere detector GUI labels +msg.atmosphere.air=Normal Air +msg.atmosphere.pressurizedair=Pressurized Air +msg.atmosphere.lowo2=Low Oxygen +msg.atmosphere.vacuum=Vacuum +msg.atmosphere.highpressure=High Pressure +msg.atmosphere.superhighpressure=Super High Pressure +msg.atmosphere.veryhot=Very Hot +msg.atmosphere.superheated=Superheated +msg.atmosphere.noo2=No Oxygen (No O₂) +msg.atmosphere.highpressurenoo2=High Pressure (No O₂) +msg.atmosphere.superhighpressurenoo2=Super High Pressure (No O₂) +msg.atmosphere.veryhotnoo2=Very Hot (No O₂) +msg.atmosphere.superheatednooxygen=Superheated (No O₂) + + msg.tooltip.data=Data msg.tooltip.asteroidselection=Asteroid Selection msg.label.name=Name @@ -355,12 +387,19 @@ msg.fluidLoader.none=None msg.fluidLoader.link=You program the linker with the fluid loader at: msg.rocketLoader.loadingState=Loading State: msg.rocketLoader.allowLoading=Allow Loading: -msg.rocketLoader.allowredstoneinput=Allow redstone input -msg.rocketLoader.allowredstoneoutput=Allow redstone output -msg.rocketLoader.none=None +msg.rocketLoader.none=Disabled (Green) +msg.rocketLoader.allowredstoneoutput=Redstone Output (Blue) +msg.rocketLoader.allowredstoneinput=Redstone Input (Red) msg.rocketLoader.link=You program the linker with the rocket loader at: +advancedrocketry.sideselector.direction.bottom=Bottom +advancedrocketry.sideselector.direction.top=Top +advancedrocketry.sideselector.direction.north=North +advancedrocketry.sideselector.direction.south=South +advancedrocketry.sideselector.direction.west=West +advancedrocketry.sideselector.direction.east=East msg.microwaverec.notgenerating=Generating 0 RF/t msg.microwaverec.generating=Generating +msg.abdp.research=Research msg.abdp.compositionresearch=Composition Research msg.abdp.distanceresearch=Distance Research msg.abdp.massresearch=Mass Research @@ -372,6 +411,14 @@ msg.terraformer.outofgas=Aborted: Ran out of gasses msg.terraformer.notrunning=Not running msg.terraformer.status=Status msg.terraformer.pressure=Pressure +msg.terraformingterminal.terraforming=Terraforming planet... +msg.terraformingterminal.powergen=Power generation: +msg.terraformingterminal.blockspertick=Blocks per tick: +msg.terraformingterminal.needredstone.line1=Provide redstone signal +msg.terraformingterminal.needredstone.line2=to start the process +msg.terraformingterminal.insertchip.line1=Place a Biome Changer Remote +msg.terraformingterminal.insertchip.line2=here to make the Satellite +msg.terraformingterminal.insertchip.line3=terraform the entire planet msg.biomescanner.gas=nyehhh, Gassy, ain't it? msg.biomescanner.star=If only my sensors had sunshades msg.gravitycontroller.radius=Radius: @@ -383,11 +430,20 @@ msg.gravitycontroller.targetdir.1=Target-> msg.gravitycontroller.targetdir.2=Direction msg.railgun.transfermin=Min Transfer Size msg.spacelaser.reset=Reset +msg.spacelaser.notarget1=No target found! +msg.spacelaser.notarget2=Go down and survey the area! +msg.spacelaser.voidmining.line1=Mining the internals +msg.spacelaser.voidmining.line2=of the planet below +msg.spacelaser.voidcobble=Void Cobble +msg.spacelaser.voidcobble.on=Void Cobble: ON +msg.spacelaser.voidcobble.off=Void Cobble: OFF msg.satctrlcenter.toofar=Too Far msg.satctrlcenter.nolink=No Link... msg.satctrlcenter.info=Info: msg.satctrlcenter.destroysat=Destroy Satellite msg.satctrlcenter.connect=Download +msg.satctrlcenter.data=Data: +msg.satctrlcenter.power=Power gen.: msg.satctrlcenter.autodl_hint=Automatic with Wireless Tranciever (Extract) msg.satbuilder.writesecondchip=Write to Secondary Chip msg.dockingport.target=Target Id @@ -415,6 +471,7 @@ msg.warpmon.warp=Warp! msg.warpmon.fuelcost=Fuel Cost: msg.warpmon.fuel=Fuel: msg.warpmon.dest=Dest: +msg.warpmon.orbit=Orbiting: msg.warpmon.na=N/A msg.warpmon.search=Search for planet msg.warpmon.chip=Program from chip @@ -515,12 +572,26 @@ msg.entity.rocket.seldst=Select Dst msg.entity.rocket.clear=Clear msg.entity.rocket.rcs=RCS Mode msg.entity.rocket.none=None Selected +msg.entity.rocket.openGuiHint=Press %s to open Rocket GUI msg.wirelessTransciever.extract=extract msg.wirelessTransciever.insert=insert msg.wirelessTransciever.type=Type: %s msg.wirelessTransciever.network=Network: msg.wirelessTransciever.network.unlinked=Unlinked +msg.advancedrocketry.planetselector.up=<< Up +msg.advancedrocketry.planetselector.select=Select +msg.advancedrocketry.planetselector.planet.list=Planet List +msg.advancedrocketry.planetselector.atm.tooltip=%b -> %a Earth's atmospheric pressure +msg.advancedrocketry.planetselector.mass.tooltip=%b -> %a Earth's mass +msg.advancedrocketry.planetselector.distance.tooltip=%b -> %a Relative Distance units +msg.advancedrocketry.planetselector.star.tooltip.name=Name: %s +msg.advancedrocketry.planetselector.star.tooltip.number.of.planets=Number of Planets: %d +msg.advancedrocketry.planetselector.planet.tooltip.name=%s +msg.advancedrocketry.planetselector.planet.tooltip.moons.count=Moons: %d + + + msg.powerunit.rfpertick=RF/t msg.linker.error.firstMachine=This must be the first machine to link! msg.linker.program=Coordinates programmed into Linker @@ -545,11 +616,72 @@ msg.chat.nostation1=You wake up on the space station with a lingering feeling th msg.chat.nostation2=Maybe you should think before overstepping clearly logical and absolute boundaries again then deciding it was a good idea and not your fault if things go wrong msg.chat.nostation3=You must be on a space station to be in this dimension, and none have been created! +msg.orbitalregistry.tab.satellites=Satellites: +msg.orbitalregistry.tab.stations=Space Stations: +msg.orbitalregistry.text.details=Details: +msg.orbitalregistry.text.satellites=Satellites +msg.orbitalregistry.text.stations=Space Stations +msg.orbitalregistry.text.nosel=Select an object +msg.orbitalregistry.text.notfound=Not found +msg.orbitalregistry.scan.tooltip=Update this list +msg.orbitalregistry.writechip.ok=Click to program chip! +msg.orbitalregistry.writechip.no=Cannot program this +msg.orbitalregistry.writechip=Program chip + + +# List entry +msg.orbitalregistry.text.listentry=ID + +# StationDetails +msg.orbitalregistry.text.type.starshiplist=§6Starship +msg.orbitalregistry.text.type.starship=Starship +msg.orbitalregistry.text.type.station=Station +msg.orbitalregistry.text.id=ID: +msg.orbitalregistry.text.type=Type: +msg.orbitalregistry.text.dimid=Dim: +msg.orbitalregistry.text.dimid.none=None +msg.orbitalregistry.text.orbit=Orbiting: +msg.orbitalregistry.text.orbit.unlaunched=Not in orbit! +msg.orbitalregistry.text.freepads=Free landingpads: +msg.orbitalregistry.text.anchored=Anchored: +msg.orbitalregistry.text.anchored.yes=Yes +msg.orbitalregistry.text.anchored.no=No +msg.orbitalregistry.text.system=System: +msg.orbitalregistry.text.system.none=None +msg.orbitalregistry.text.system.unknown=Unknown +# SatelliteDetails power fields +msg.orbitalregistry.text.sat.pwrgen=Pwr Gen: +msg.orbitalregistry.text.sat.pwrstore=Pwr Store: +msg.orbitalregistry.text.sat.maxdata=Max Data: + +# Orbital Registry – satellite type names +msg.orbitalregistry.sat.name.optical=Telescope +msg.orbitalregistry.sat.name.density=Density +msg.orbitalregistry.sat.name.composition=Composition +msg.orbitalregistry.sat.name.mass=Mass +msg.orbitalregistry.sat.name.solarEnergy=Solar +msg.orbitalregistry.sat.name.oreScanner=Ore Scanner +msg.orbitalregistry.sat.name.biomeChanger=Biome Changer +msg.orbitalregistry.sat.name.weatherController=Weather + +msg.orbitalregistry.writechip.hint.insert=Insert a chip to write +msg.orbitalregistry.writechip.hint.select=Select an entry from the list +msg.orbitalregistry.writechip.hint.output=Clear the output slot first +msg.orbitalregistry.writechip.hint.sat.or.stationchip=Insert a Station Chip +msg.orbitalregistry.writechip.hint.sat.or.idchip=Insert a Satellite ID Chip or Controller +msg.orbitalregistry.writechip.hint.sat.badcontroller=This satellite does not accept this chip, use correct controller instead! +msg.orbitalregistry.writechip.hint.sat.orescanner.only=Ore Scanner can only link to Ore Mapping satellites +msg.orbitalregistry.writechip.hint.station.unlaunched=This station is not in orbit yet + + + commands.weather.always_not_clear=This planet is always not clear... commands.weather.cannot_rain=Cannot start a rain here commands.weather.cannot_thunder=Cannot start a thunder here # Jeistuff +jei.machinerecipe.power=Power: +jei.machinerecipe.time=Time: jei.sb.satellitepreview=Ready for orbit! jei.sb.copy.source=Source jei.sb.copy.output=New Copy @@ -588,7 +720,7 @@ tooltip.advancedrocketry.nuclearfueltank.alt.1=§fRequires §bNuclear Core§f an # Monopropellant Engine tooltip.advancedrocketry.monopropmotor=§cPart of Rocket -tooltip.advancedrocketry.monopropmotor.shift.1=Uses §bMonopropellant Fuel§7 +tooltip.advancedrocketry.monopropmotor.shift.1=§fUses §bMonopropellant Fuel tooltip.advancedrocketry.monopropmotor.alt.1=Check Fueling Station JEI-page # Nuclear Core @@ -600,25 +732,25 @@ tooltip.advancedrocketry.nuclearcore.alt.2=for Unmanned Vehicles (Gas Mission ro # Nuclear rocketengine tooltip.advancedrocketry.nuclearmotor=§cPart of Rocket §6Allows planetary travel! -tooltip.advancedrocketry.nuclearmotor.shift.1=Uses §bWorking fluid§7 +tooltip.advancedrocketry.nuclearmotor.shift.1=§fUses §bWorking fluid tooltip.advancedrocketry.nuclearmotor.shift.2=Needs Nuclear Core directly above. tooltip.advancedrocketry.nuclearmotor.alt.1=Check Fueling Station JEI-page # Bipropellant Engine tooltip.advancedrocketry.bipropmotor=§cPart of Rocket -tooltip.advancedrocketry.bipropmotor.shift.1=Uses §bBipropellant Fuel§7 and §bOxidizer§7 +tooltip.advancedrocketry.bipropmotor.shift.1=§fUses §bBipropellant Fuel§f and §bOxidizer tooltip.advancedrocketry.bipropmotor.alt.1=Check Fueling Station JEI-page # Drill tooltip.advancedrocketry.drill=§cPart of Rocket -tooltip.advancedrocketry.drill.shift.1=Lowers duration of §6Mining Missions§7 +tooltip.advancedrocketry.drill.shift.1=Lowers duration of §6Mining Missions tooltip.advancedrocketry.drill.shift.2=§bEffect stacks tooltip.advancedrocketry.drill.alt.1=This rocket is built with Rocket Assembling Machine tooltip.advancedrocketry.drill.alt.2=Requires a programmed Asteroid Chip # Gas Intake tooltip.advancedrocketry.intake=§cPart of Rocket -tooltip.advancedrocketry.intake.shift.1=Lowers duration of §6Gas Missions§7 +tooltip.advancedrocketry.intake.shift.1=Lowers duration of §6Gas Missions tooltip.advancedrocketry.intake.shift.2=§bEffect stacks tooltip.advancedrocketry.intake.alt.1=This rocket is built with Unmanned Vehicle Assembler tooltip.advancedrocketry.intake.alt.2=Launched from Space Station orbiting a Gas giant @@ -688,13 +820,26 @@ tooltip.advancedrocketry.satellitebuilder.shift.2=§bMust be on top of a Power P tooltip.advancedrocketry.satellitebuilder.alt.1=Insert chassis, Chip/Remote tooltip.advancedrocketry.satellitebuilder.alt.2=core component + other components +# Orbital Registry +tooltip.advancedrocketry.orbitalregistry=Tracks man-made objects in space +tooltip.advancedrocketry.orbitalregistry.shift.1=§fPrints new Chips! +tooltip.advancedrocketry.orbitalregistry.shift.2= +tooltip.advancedrocketry.orbitalregistry.alt.1=§fTo destroy a Satellite use chip in §4Satellite Terminal +tooltip.advancedrocketry.orbitalregistry.alt.2= + ### Infrastructure ## BlockARHatch +# TileDataBusBig +tooltip.advancedrocketry.databusbig.header=§cBus and Unit +tooltip.advancedrocketry.databusbig.shift.1=§bCan only hold one type of Data +tooltip.advancedrocketry.databusbig.alt.1=§bKeeps data when broken, works as item and block + # TileDataBus tooltip.advancedrocketry.hatch.databus=Capacity: §62000 §7Data tooltip.advancedrocketry.hatch.databus.shift.1=§bCan only hold one type of Data +tooltip.advancedrocketry.hatch.databus.alt.1=§fClears Data when broken # TileSatelliteHatch tooltip.advancedrocketry.hatch.satellite=§cPart of Rocket @@ -745,11 +890,13 @@ tooltip.advancedrocketry.fuelingstation.alt.2=§fRockets landing here will auto- tooltip.advancedrocketry.servicestation=§cInfrastructure tooltip.advancedrocketry.servicestation.shift.1=Repair rocket tooltip.advancedrocketry.servicestation.shift.2=§o(WIP) -tooltip.advancedrocketry.fuelingstation.alt.1=§fLink to §4Rocket Assembler/Dockingpad§f or §4Rocket ## // Infrastructure # Pressurized Fluid Tank +tooltip.advancedrocketry.fluidtank.empty=Empty +tooltip.advancedrocketry.fluidtank.fluid=Fluid: +tooltip.advancedrocketry.fluidtank.level=Level: tooltip.advancedrocketry.fluidtank.shift.1=§cConnects to tanks above or below to make a bigger tank # Wireless Transciever @@ -811,8 +958,7 @@ tooltip.advancedrocketry.orientationctrl.alt.1=§bCosmetic only§7 # Gravity Controller tooltip.advancedrocketry.gravityctrl=§cSpace Station Controller tooltip.advancedrocketry.gravityctrl.shift.1=Artificial gravity! -tooltip.advancedrocketry.gravityctrl.alt.1=§bCosmetic only§7 -tooltip.advancedrocketry.gravityctrl.alt.2=Redstone control +tooltip.advancedrocketry.gravityctrl.alt.1=Redstone control # Altitude Controller tooltip.advancedrocketry.altitudectrl=§cSpace Station Controller @@ -856,7 +1002,7 @@ tooltip.advancedrocketry.sealdetector=Detects if a block is airtight tooltip.advancedrocketry.sealdetector.shift.1=§fRight Click on block to use # Lens -tooltip.advancedrocketry.lens=§cPart of Observatory +tooltip.advancedrocketry.lens=§cPart of Multiblock tooltip.advancedrocketry.lens.shift.1=§bUse Holo-Projector! ## SPACE SUIT + COMPONENTS @@ -896,7 +1042,7 @@ tooltip.advancedrocketry.itemupgrade.0=§5Space Suit Component tooltip.advancedrocketry.itemupgrade.0.shift.1=§fEnables Jetpack hover mode tooltip.advancedrocketry.itemupgrade.0.shift.2=§dSlot: Helmet§7 tooltip.advancedrocketry.itemupgrade.0.alt.1=Requires a Jetpack installed in the chestplate. -tooltip.advancedrocketry.itemupgrade.0.alt.2=Stacking has no additional effect. +tooltip.advancedrocketry.itemupgrade.0.alt.2=§fSneak + Toggle Jetpack to activate # 1 = Flight Speed Control Upgrade tooltip.advancedrocketry.itemupgrade.1=§5Space Suit Component @@ -974,6 +1120,10 @@ tooltip.advancedrocketry.satfunc.weather.alt.1=Combine with Weather Remote when tooltip.advancedrocketry.weathercontrollerremote=§bShift-Right Click to open GUI tooltip.advancedrocketry.weathercontrollerremote.shift.1=§fRight-click in hand to use tooltip.advancedrocketry.weathercontrollerremote.alt.1=Combine with Weather Controller when assembling +tooltip.advancedrocketry.weathercontrollerremote.mode.rain=§eMode: Rain - Fills small basins in the terrain with water +tooltip.advancedrocketry.weathercontrollerremote.mode.dry=§eMode: Dry - Drys all water in a radius of 16 +tooltip.advancedrocketry.weathercontrollerremote.mode.flood=§eMode: Flood - Floods area with a radius of 16 with water + # Biome Changer Remote tooltip.advancedrocketry.biomechangerremote=§bShift-Right Click to open GUI @@ -1006,6 +1156,9 @@ tooltip.libvulpes.battery.1.shift.1=Increases Powerstorage tooltip.libvulpes.battery.1.shift.2=§fCapacity: §c40.000 §fRF§7 # Data Unit +tooltip.advancedrocketry.itemdata.header=§5Satellite Component +tooltip.advancedrocketry.itemdata.type=§fType: +tooltip.advancedrocketry.itemdata.data=§fData stored: tooltip.advancedrocketry.itemdataunit.shift.1=§fIncrease Satellite Data Storage by 1000 tooltip.advancedrocketry.itemdataunit.alt.1=§fWorks as Datastorage in inventory aswell @@ -1014,13 +1167,17 @@ tooltip.advancedrocketry.itemdataunit.alt.1=§fWorks as Datastorage in inventory tooltip.advancedrocketry.asteroidchip.shift.1=§bUsed for Mining Missions§7 tooltip.advancedrocketry.asteroidchip.shift.2=§fProgram in §cObservatory tooltip.advancedrocketry.asteroidchip.alt.1=§4Insert programmed Chip in Guidance Computer§7 +tooltip.advancedrocketry.asteroidchip.alt.2=§fYou get the chip back after Mission # Station Chip tooltip.advancedrocketry.stationchip=§bMake Backups! tooltip.advancedrocketry.stationchip.shift.1=§fProgram in Space Station Assembler +tooltip.advancedrocketry.stationchip.shift.2=§cCopied in Satellite Builder tooltip.advancedrocketry.stationchip.alt.1=§4Insert programmed Chip in Guidance Computer§7 +tooltip.advancedrocketry.stationchip.namelabel=Name: # Planet Chip +tooltip.advancedrocketry.planetidchip=§bReprogammable! tooltip.advancedrocketry.planetidchip.shift.1=§fInsert Chip in §4Guidance Computer§7 tooltip.advancedrocketry.planetidchip.shift.2=§fSet destination in Rocket GUI to program it. tooltip.advancedrocketry.planetidchip.alt.1=§4Doublecheck that this is programmed before Launch! @@ -1028,7 +1185,9 @@ tooltip.advancedrocketry.planetidchip.alt.1=§4Doublecheck that this is programm # Satellite Chip tooltip.advancedrocketry.satidchip=§bMake Backups! tooltip.advancedrocketry.satidchip.shift.1=§fStores a satellite’s ID. -tooltip.advancedrocketry.satidchip.alt.1=§4Use in Satellite Monitor to link or in the Microwave Receiver Multiblock (Input hatch). §8 (Planet: resolves if put in Terminal) +tooltip.advancedrocketry.satidchip.shift.2=§cCopied in Satellite Builder +tooltip.advancedrocketry.satidchip.alt.1=§4Use in Satellite Terminal to link or in the Microwave Receiver Multiblock (Input hatch). +tooltip.advancedrocketry.satidchip.alt.2=§8 (Planet: resolves if put in Terminal) # Elevator Chip tooltip.advancedrocketry.elevatorchip=Space Elevator Chip @@ -1109,9 +1268,21 @@ tooltip.advancedrocketry.observatory.shift.2=§bUse Holo-Projector! tooltip.advancedrocketry.observatory.alt.1=§fInsert §cAsteroid Chip tooltip.advancedrocketry.observatory.alt.2=§fNeeds §6Distance Data§f to operate (operates only at night) +# LibVulpes Hatches and Coal Generator +tooltip.advancedrocketry.libvulpes.hatch=§cPart of Multiblock +tooltip.advancedrocketry.libvulpes.hatch.shift.1=§bUse Holo-Projector! +tooltip.advancedrocketry.libvulpes.forgepoweroutput=§cPart of Multiblock +tooltip.advancedrocketry.libvulpes.forgepoweroutput.shift.1=§bUse Holo-Projector! +tooltip.advancedrocketry.libvulpes.forgepowerinput=§cPart of Multiblock +tooltip.advancedrocketry.libvulpes.forgepowerinput.shift.1=§bUse Holo-Projector! +tooltip.advancedrocketry.libvulpes.creativepowerbattery=§dInfinite Power +tooltip.advancedrocketry.libvulpes.creativepowerbattery.shift.1=§cPart of Multiblock +tooltip.advancedrocketry.libvulpes.creativepowerbattery.shift.2=§bUse Holo-Projector! +tooltip.advancedrocketry.libvulpes.coalgenerator=§cBurns solid fuels + # Planet Analyser -tooltip.advancedrocketry.planetanalyser=Processes planet scan data +tooltip.advancedrocketry.planetanalyser=Processeses data and writes it to Asteroid Chip tooltip.advancedrocketry.planetanalyser.shift.1=§bUse Holo-Projector! # Centrifuge @@ -1141,9 +1312,9 @@ tooltip.advancedrocketry.spaceelevatorctrl=Controls the Space Elevator tooltip.advancedrocketry.spaceelevatorctrl.shift.1=§bUse Holo-Projector! # Atmosphere Terraformer -tooltip.advancedrocketry.atmosterraformer=Changes Atmospheric pressure on an entire planet planet +tooltip.advancedrocketry.atmosterraformer=Changes Atmospheric pressure on an entire planet tooltip.advancedrocketry.atmosterraformer.shift.1=§bUse Holo-Projector! -tooltip.advancedrocketry.atmosterraformer.alt.1=Increase and decrease the Atmospheric pressure by using connected §cBiome Changer Remote. +tooltip.advancedrocketry.atmosterraformer.alt.1=§fIncrease and decrease the Atmospheric pressure by using connected §cBiome Changer Remote. # Area Gravity Controller tooltip.advancedrocketry.gravitymachine=Manipulates Gravity @@ -1153,10 +1324,11 @@ tooltip.advancedrocketry.gravitymachine.shift.2=§bUse Holo-Projector! # Orbital Last Drill tooltip.advancedrocketry.spacelaser=§cSpace Station Multiblock tooltip.advancedrocketry.spacelaser.shift.1=§bUse Holo-Projector! +tooltip.advancedrocketry.spacelaser.alt.1=§fRequires Redstone to run # Force Field Projector tooltip.advancedrocketry.forcefieldprojector=Projeccts up to 32 blocks away! -tooltip.advancedrocketry.forcefieldprojector.shift.1=Activate with Redstone +tooltip.advancedrocketry.forcefieldprojector.shift.1=§fActivate with Redstone # Vacuum Laser tooltip.advancedrocketry.vacuumlaser=§cPart of Multiblock @@ -1178,6 +1350,11 @@ tooltip.advancedrocketry.qcrucible=§cPart of Multiblock tooltip.advancedrocketry.qcrucible.shift.1=§bUse Holo-Projector! tooltip.advancedrocketry.sawblade=§cPart of Multiblock tooltip.advancedrocketry.sawblade.shift.1=§bUse Holo-Projector! +tooltip.libvulpes.structuremachine=§cPart of Multiblock +tooltip.libvulpes.structuremachine.shift.1=§bUse Holo-Projector! +tooltip.libvulpes.advstructuremachine=§cPart of Multiblock +tooltip.libvulpes.advstructuremachine.shift.1=§bUse Holo-Projector! + ## Assemblers # Rocket Assembler @@ -1193,7 +1370,7 @@ tooltip.advancedrocketry.stationassembler.alt.1=§fPlace this 1 block higher tha # Packet Station tooltip.advancedrocketry.packedstructure=Insert in §cSatellite Bay§7 to put in Orbit! -tooltip.advancedrocketry.packedstructure.shift.1=§eRemember to tell Rocket what planet it should deplay payload into Orbit! +tooltip.advancedrocketry.packedstructure.shift.1=§eRemember to set the rocket's target planet before launch! # Deployable Rocket Assembler tooltip.advancedrocketry.deployablerocketassembler=§cBuilds Rockets on Space Stations From 1697be5277050c54905355d093ff67a634a8f19a Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 18:02:41 +0100 Subject: [PATCH 370/424] Fix tooltip localization for hovercraft item From 792ac4212a72a4fa502a16bd1b4ae94862f717ad Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 18:03:16 +0100 Subject: [PATCH 371/424] Fix formatting issue in BlockThermiteTorch.java From 7d84c0ae03b2a203e32de994c2241cab03ec2165 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sun, 14 Dec 2025 18:03:49 +0100 Subject: [PATCH 372/424] Fix missing newline at end of ItemBiomeChanger.java From 14ddb050ddc709c42808134b1dcde6440feb9942 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 12:00:14 +0100 Subject: [PATCH 373/424] Add @SideOnly annotation to LIVE variable --- .../modules/ModuleContainerPanYOnlyWithScrollCache.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleContainerPanYOnlyWithScrollCache.java b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleContainerPanYOnlyWithScrollCache.java index 5e5265475..eb948a4a9 100644 --- a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleContainerPanYOnlyWithScrollCache.java +++ b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModuleContainerPanYOnlyWithScrollCache.java @@ -20,6 +20,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicInteger; +@SideOnly(Side.CLIENT) public class ModuleContainerPanYOnlyWithScrollCache extends ModuleContainerPanYOnly { // ===== Single-slot global cache (latest write wins; no memory growth) ===== @@ -27,7 +28,6 @@ public class ModuleContainerPanYOnlyWithScrollCache extends ModuleContainerPanYO private static final AtomicInteger GLOBAL_SCROLL = new AtomicInteger(NO_SCROLL); // ===== Track live instances so the event handler can find "this" without editing GuiModular ===== - @SideOnly(Side.CLIENT) private static final CopyOnWriteArrayList> LIVE = new CopyOnWriteArrayList<>(); From bcbcf841e6c12e58dc41228fa4738f2d97e5ea09 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 12:00:45 +0100 Subject: [PATCH 374/424] Enhance liquid container compatibility check Added compatibility check for liquid container blocks. --- .../zmaster587/advancedRocketry/util/StorageChunk.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/util/StorageChunk.java b/src/main/java/zmaster587/advancedRocketry/util/StorageChunk.java index bce2ccd3f..8d1833559 100644 --- a/src/main/java/zmaster587/advancedRocketry/util/StorageChunk.java +++ b/src/main/java/zmaster587/advancedRocketry/util/StorageChunk.java @@ -111,9 +111,17 @@ private static boolean isInventoryBlock(TileEntity tile) { } private static boolean isLiquidContainerBlock(TileEntity tile) { + // Prefer real sides for compatibility + for (EnumFacing f : EnumFacing.VALUES) { + if (tile.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, f)) { + return true; + } + } + // Fallback for unsided/internal handlers return tile.hasCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); } + public void setWeight(int weight) { this.weight = weight; } From ced4ca3c5e26bc9db4105683fce77bffad833b6a Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 12:01:31 +0100 Subject: [PATCH 375/424] Refactor TileRocketFluidLoader for clarity and efficiency --- .../infrastructure/TileRocketFluidLoader.java | 168 ++++++++++++++---- 1 file changed, 133 insertions(+), 35 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidLoader.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidLoader.java index f035f49cc..87bc377bf 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidLoader.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidLoader.java @@ -16,6 +16,7 @@ import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; import net.minecraftforge.fluids.capability.IFluidHandler; +import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.Side; import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; import zmaster587.advancedRocketry.api.EntityRocketBase; @@ -23,6 +24,7 @@ import zmaster587.advancedRocketry.api.IMission; import zmaster587.advancedRocketry.block.multiblock.BlockARHatch; import zmaster587.advancedRocketry.entity.EntityRocket; +import zmaster587.advancedRocketry.inventory.modules.ModuleSideSelectorTooltipOverlay; import zmaster587.advancedRocketry.tile.TileRocketAssemblingMachine; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.inventory.modules.*; @@ -35,6 +37,8 @@ import zmaster587.libVulpes.util.ZUtils.RedstoneState; import javax.annotation.Nonnull; +import javax.annotation.Nullable; + import java.util.List; public class TileRocketFluidLoader extends TileFluidHatch implements IInfrastructure, ITickable, IButtonInventory, INetworkMachine, IGuiCallback { @@ -45,27 +49,39 @@ public class TileRocketFluidLoader extends TileFluidHatch implements IInfrastruc RedstoneState state; ModuleRedstoneOutputButton inputRedstoneControl; RedstoneState inputstate; + private String[] sideStateNames; ModuleBlockSideSelector sideSelectorModule; + protected static final int TRANSFER_INTERVAL_TICKS = 20; + protected int transferCooldown = 0; public TileRocketFluidLoader() { - redstoneControl = new ModuleRedstoneOutputButton(174, 4, 0, "", this, LibVulpes.proxy.getLocalizedString("msg.fluidLoader.loadingState")); + redstoneControl = new ModuleRedstoneOutputButton(174, 4, 0, "", this, + LibVulpes.proxy.getLocalizedString("msg.fluidLoader.loadingState")); state = RedstoneState.ON; - inputRedstoneControl = new ModuleRedstoneOutputButton(174, 32, 1, "", this, LibVulpes.proxy.getLocalizedString("msg.fluidLoader.allowLoading")); + + inputRedstoneControl = new ModuleRedstoneOutputButton(174, 32, 1, "", this, + LibVulpes.proxy.getLocalizedString("msg.fluidLoader.allowLoading")); inputstate = RedstoneState.OFF; inputRedstoneControl.setRedstoneState(inputstate); - sideSelectorModule = new ModuleBlockSideSelector(90, 15, this, LibVulpes.proxy.getLocalizedString("msg.fluidLoader.none"), LibVulpes.proxy.getLocalizedString("msg.fluidLoader.allowredstoneoutput"), LibVulpes.proxy.getLocalizedString("msg.fluidLoader.allowredstoneinput")); + + initSideSelector(); } public TileRocketFluidLoader(int size) { super(size); - redstoneControl = new ModuleRedstoneOutputButton(174, 4, 0, "", this, LibVulpes.proxy.getLocalizedString("msg.fluidLoader.loadingState")); + redstoneControl = new ModuleRedstoneOutputButton(174, 4, 0, "", this, + LibVulpes.proxy.getLocalizedString("msg.fluidLoader.loadingState")); state = RedstoneState.ON; - inputRedstoneControl = new ModuleRedstoneOutputButton(174, 32, 1, "", this, LibVulpes.proxy.getLocalizedString("msg.fluidLoader.allowLoading")); + + inputRedstoneControl = new ModuleRedstoneOutputButton(174, 32, 1, "", this, + LibVulpes.proxy.getLocalizedString("msg.fluidLoader.allowLoading")); inputstate = RedstoneState.OFF; inputRedstoneControl.setRedstoneState(inputstate); - sideSelectorModule = new ModuleBlockSideSelector(90, 15, this, LibVulpes.proxy.getLocalizedString("msg.fluidLoader.none"), LibVulpes.proxy.getLocalizedString("msg.fluidLoader.allowredstoneoutput"), LibVulpes.proxy.getLocalizedString("msg.fluidLoader.allowredstoneinput")); + + initSideSelector(); } + @Override public void invalidate() { super.invalidate(); @@ -73,6 +89,15 @@ public void invalidate() { ((TileRocketAssemblingMachine) getMasterBlock()).removeConnectedInfrastructure(this); } + private void initSideSelector() { + sideStateNames = new String[] { + LibVulpes.proxy.getLocalizedString("msg.fluidLoader.none"), + LibVulpes.proxy.getLocalizedString("msg.fluidLoader.allowredstoneoutput"), + LibVulpes.proxy.getLocalizedString("msg.fluidLoader.allowredstoneinput") + }; + sideSelectorModule = new ModuleBlockSideSelector(90, 15, this, sideStateNames); + } + @Override public String getModularInventoryName() { return "tile.loader.5.name"; @@ -89,9 +114,15 @@ public List getModules(int ID, EntityPlayer player) { list.add(redstoneControl); list.add(inputRedstoneControl); list.add(sideSelectorModule); + + if (FMLCommonHandler.instance().getSide().isClient()) { + list.add(new ModuleSideSelectorTooltipOverlay(90, 15, sideSelectorModule, sideStateNames)); + } + return list; } + protected boolean getStrongPowerForSides(World world, BlockPos pos) { for (int i = 0; i < 6; i++) { if (sideSelectorModule.getStateForSide(i) == ALLOW_REDSTONEOUT && world.getRedstonePower(pos.offset(EnumFacing.VALUES[i]), EnumFacing.VALUES[i]) > 0) @@ -100,45 +131,112 @@ protected boolean getStrongPowerForSides(World world, BlockPos pos) { return false; } + @Nullable + protected static IFluidHandler getFluidHandlerAnySide(TileEntity te) { + IFluidHandler h = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); + if (h != null) return h; + + for (EnumFacing f : EnumFacing.VALUES) { + h = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, f); + if (h != null) return h; + } + return null; + } + @Nullable + protected static IFluidHandler getBestFillHandler(TileEntity te, @Nonnull FluidStack toInsert) { + // Try null side first + IFluidHandler h = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); + if (h != null) { + FluidStack probe = toInsert.copy(); + if (h.fill(probe, false) > 0) return h; + } + + // Then try all faces + for (EnumFacing f : EnumFacing.VALUES) { + h = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, f); + if (h == null) continue; + + FluidStack probe = toInsert.copy(); + if (h.fill(probe, false) > 0) return h; + } + + return null; + } + + @Nullable + protected static IFluidHandler getBestDrainHandler(TileEntity te) { + // For draining, side rules also exist; "null then faces" is usually OK. + IFluidHandler h = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); + if (h != null) return h; + + for (EnumFacing f : EnumFacing.VALUES) { + h = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, f); + if (h != null) return h; + } + return null; + } + + @Override public void update() { - //Move fluids - if (!world.isRemote && rocket != null) { - - boolean isAllowToOperate = (inputstate == RedstoneState.OFF || isStateActive(inputstate, getStrongPowerForSides(world, getPos()))); - - List tiles = rocket.storage.getFluidTiles(); - boolean rocketFluidFull = false; - - boolean doupdate = false; - //Function returns if something can be moved - for (TileEntity tile : tiles) { - IFluidHandler handler = tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); - - //See if we have anything to fill because redstone output - FluidStack rocketFluid = handler.drain(1, false); - if (handler.fill(rocketFluid, false) > 0) - rocketFluidFull = true; - - if (isAllowToOperate) { - rocketFluid = fluidTank.drain(fluidTank.getCapacity(), false); - if (rocketFluid != null && rocketFluid.amount > 0) { - fluidTank.drain(handler.fill(rocketFluid, true), true); - doupdate = true; - } + if (world.isRemote || rocket == null) return; + + if (transferCooldown > 0) { + transferCooldown--; + return; + } + transferCooldown = TRANSFER_INTERVAL_TICKS; + + boolean isAllowToOperate = (inputstate == RedstoneState.OFF + || isStateActive(inputstate, getStrongPowerForSides(world, getPos()))); + + List tiles = rocket.storage.getFluidTiles(); + boolean rocketHasFillCapacitySomewhere = false; + boolean doupdate = false; + + for (TileEntity tile : tiles) { + if (tile == null || tile.isInvalid()) continue; + + IFluidHandler drainHandler = getBestDrainHandler(tile); + if (drainHandler == null) continue; + + // --- redstone probe (keep your current semantics for now) + FluidStack probe = drainHandler.drain(1, false); + if (probe != null && probe.amount > 0) { + IFluidHandler fillProbeHandler = getBestFillHandler(tile, probe); + if (fillProbeHandler != null && fillProbeHandler.fill(probe, false) > 0) { + rocketHasFillCapacitySomewhere = true; } } - if (doupdate) { - PacketHandler.sendToNearby(new PacketEntity(rocket, (byte) 9987), world.provider.getDimension(), getPos(), 128); - } - //Update redstone state - setRedstoneState(!rocketFluidFull); + if (!isAllowToOperate) continue; + + FluidStack fromLoader = fluidTank.drain(fluidTank.getCapacity(), false); + if (fromLoader == null || fromLoader.amount <= 0) continue; + + IFluidHandler fillHandler = getBestFillHandler(tile, fromLoader); + if (fillHandler == null) continue; + + int accepted = fillHandler.fill(fromLoader, true); + if (accepted > 0) { + fluidTank.drain(accepted, true); + doupdate = true; + break; + } + } + if (doupdate) { + PacketHandler.sendToNearby(new PacketEntity(rocket, (byte) 9987), + world.provider.getDimension(), getPos(), 128); + markDirty(); } + + setRedstoneState(!rocketHasFillCapacitySomewhere); } + + @Override public SPacketUpdateTileEntity getUpdatePacket() { return new SPacketUpdateTileEntity(pos, getBlockMetadata(), getUpdateTag()); From 5f970146f4cd27a53d36ccf44274b490bfc5cd68 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 12:01:56 +0100 Subject: [PATCH 376/424] Refactor fluid handling in TileRocketFluidUnloader --- .../TileRocketFluidUnloader.java | 109 ++++++++++++------ 1 file changed, 73 insertions(+), 36 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidUnloader.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidUnloader.java index 60529a665..6331b1e61 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidUnloader.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidUnloader.java @@ -2,6 +2,7 @@ import micdoodle8.mods.galacticraft.core.network.PacketEntityUpdate; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumFacing; import net.minecraft.util.ITickable; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.CapabilityFluidHandler; @@ -16,6 +17,8 @@ import java.util.List; +import javax.annotation.Nullable; + public class TileRocketFluidUnloader extends TileRocketFluidLoader implements IInfrastructure, ITickable, IButtonInventory, INetworkMachine { public TileRocketFluidUnloader() { @@ -32,48 +35,82 @@ public String getModularInventoryName() { return "tile.loader.4.name"; } + @Nullable + private static IFluidHandler getBestDrainHandler(TileEntity te, int probeAmount) { + // Try null side first + IFluidHandler h = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); + if (h != null) { + FluidStack probe = h.drain(probeAmount, false); + if (probe != null && probe.amount > 0) return h; + } + + // Then try all faces + for (EnumFacing f : EnumFacing.VALUES) { + h = te.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, f); + if (h == null) continue; + + FluidStack probe = h.drain(probeAmount, false); + if (probe != null && probe.amount > 0) return h; + } + + return null; + } @Override public void update() { - //Move fluids - if (!world.isRemote && rocket != null) { - - boolean isAllowToOperate = (inputstate == RedstoneState.OFF || isStateActive(inputstate, getStrongPowerForSides(world, getPos()))); - - List tiles = rocket.storage.getFluidTiles(); - boolean rocketFluidFull = false; - - boolean doupdate = false; - //Function returns if something can be moved - for (TileEntity tile : tiles) { - IFluidHandler handler = tile.getCapability(CapabilityFluidHandler.FLUID_HANDLER_CAPABILITY, null); - - //See if we have anything to fill because redstone output - FluidStack rocketFluid = handler.drain(1, false); - if (handler.fill(rocketFluid, false) > 0) - rocketFluidFull = true; - - if (isAllowToOperate) { - boolean shouldOperate; - if (getFluidTank().getFluid() != null) - shouldOperate = getFluidTank().fill(handler.drain(new FluidStack(getFluidTank().getFluid(), getFluidTank().getCapacity() - getFluidTank().getFluidAmount()), false), false) > 0; - else - shouldOperate = getFluidTank().fill(handler.drain(getFluidTank().getCapacity(), false), false) > 0; - - if (shouldOperate) { - doupdate = true; - getFluidTank().fill(handler.drain(Math.max(50, getFluidTank().getCapacity() - getFluidTank().getFluidAmount()), true), true); - } - } - } - if (doupdate) { - PacketHandler.sendToNearby(new PacketEntity(rocket, (byte) 9987), world.provider.getDimension(), getPos(), 128); + if (world.isRemote || rocket == null) return; + + if (transferCooldown > 0) { + transferCooldown--; + return; + } + transferCooldown = TRANSFER_INTERVAL_TICKS; + + boolean isAllowToOperate = (inputstate == RedstoneState.OFF + || isStateActive(inputstate, getStrongPowerForSides(world, getPos()))); + + List tiles = rocket.storage.getFluidTiles(); + + boolean rocketHasDrainableFluidSomewhere = false; + boolean doupdate = false; + + for (TileEntity tile : tiles) { + if (tile == null || tile.isInvalid()) continue; + + IFluidHandler drainHandler = getBestDrainHandler(tile, 1); + if (drainHandler == null) continue; + + // redstone probe: does rocket have any drainable fluid? + FluidStack probe = drainHandler.drain(1, false); + if (probe != null && probe.amount > 0) { + rocketHasDrainableFluidSomewhere = true; } - //Update redstone state - setRedstoneState(!rocketFluidFull); + if (!isAllowToOperate) continue; + + int space = getFluidTank().getCapacity() - getFluidTank().getFluidAmount(); + if (space <= 0) continue; + + FluidStack simulated = drainHandler.drain(space, false); + if (simulated == null || simulated.amount <= 0) continue; + int accepted = getFluidTank().fill(simulated, false); + if (accepted <= 0) continue; + + FluidStack drained = drainHandler.drain(accepted, true); + if (drained != null && drained.amount > 0) { + getFluidTank().fill(drained, true); + doupdate = true; + break; // one transfer per 20 ticks + } } - } + if (doupdate) { + PacketHandler.sendToNearby(new PacketEntity(rocket, (byte) 9987), + world.provider.getDimension(), getPos(), 128); + markDirty(); + } + + setRedstoneState(!rocketHasDrainableFluidSomewhere); + } } From ece0124fddb6daf8339c681f53e5fae4a75ec8a7 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 12:05:37 +0100 Subject: [PATCH 377/424] Reduce transfer interval ticks from 20 to 10 --- .../tile/infrastructure/TileRocketFluidLoader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidLoader.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidLoader.java index 87bc377bf..6c0331c7b 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidLoader.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidLoader.java @@ -51,7 +51,7 @@ public class TileRocketFluidLoader extends TileFluidHatch implements IInfrastruc RedstoneState inputstate; private String[] sideStateNames; ModuleBlockSideSelector sideSelectorModule; - protected static final int TRANSFER_INTERVAL_TICKS = 20; + protected static final int TRANSFER_INTERVAL_TICKS = 10; protected int transferCooldown = 0; public TileRocketFluidLoader() { From 7343bfda892c1b7efea61dc64dea1a7bb5092695 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 12:05:50 +0100 Subject: [PATCH 378/424] Update comment for transfer interval in fluid unloader --- .../tile/infrastructure/TileRocketFluidUnloader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidUnloader.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidUnloader.java index 6331b1e61..bedab1e5b 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidUnloader.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketFluidUnloader.java @@ -101,7 +101,7 @@ public void update() { if (drained != null && drained.amount > 0) { getFluidTank().fill(drained, true); doupdate = true; - break; // one transfer per 20 ticks + break; // one transfer per ticks } } From 4842309ba5c0d24dd2a451bc4da98587f8c5b0fa Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 12:06:23 +0100 Subject: [PATCH 379/424] Replace ModuleContainerPanYOnlyWithScrollCache usage --- .../tile/TileOrbitalRegistry.java | 58 +++++++++---------- 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java b/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java index a904ff552..d6840c707 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java @@ -10,6 +10,7 @@ import net.minecraft.util.EnumFacing; import net.minecraftforge.common.util.Constants; import net.minecraftforge.fml.relauncher.Side; +import zmaster587.advancedRocketry.AdvancedRocketry; import zmaster587.advancedRocketry.api.SatelliteRegistry; import zmaster587.advancedRocketry.api.satellite.SatelliteBase; import zmaster587.advancedRocketry.api.satellite.SatelliteProperties; @@ -17,7 +18,6 @@ import zmaster587.advancedRocketry.dimension.DimensionManager; import zmaster587.advancedRocketry.dimension.DimensionProperties; import zmaster587.advancedRocketry.inventory.TextureResources; -import zmaster587.advancedRocketry.inventory.modules.ModuleContainerPanYOnlyWithScrollCache; import zmaster587.advancedRocketry.item.ItemOreScanner; import zmaster587.advancedRocketry.item.ItemSatelliteIdentificationChip; import zmaster587.advancedRocketry.item.ItemStationChip; @@ -849,20 +849,14 @@ private void buildSatelliteListWindow(List modules, } if (!satButtons.isEmpty()) { - ModuleContainerPanYOnlyWithScrollCache panLeft = - new ModuleContainerPanYOnlyWithScrollCache( - baseX, baseY, - satButtons, new LinkedList<>(), - null, - sizeX - 2, sizeY, - 0, -48, - 0, 72 - ); - modules.add(panLeft); + modules.add(AdvancedRocketry.proxy.createScrollListPan( + baseX, baseY, + satButtons, + sizeX, sizeY + )); } } - private void buildSatelliteDetailWindow(List modules, int startX, int startY) { int x = startX; int y = startY; @@ -982,19 +976,13 @@ private void buildStationListWindow(List modules, } if (!stationButtons.isEmpty()) { - ModuleContainerPanYOnlyWithScrollCache panLeft = - new ModuleContainerPanYOnlyWithScrollCache( - baseX, baseY, - stationButtons, new LinkedList<>(), - null, - sizeX - 2, sizeY, - 0, -48, - 0, 72 - ); - modules.add(panLeft); + modules.add(AdvancedRocketry.proxy.createScrollListPan( + baseX, baseY, + stationButtons, + sizeX, sizeY + )); } } - private void buildStationDetailWindow(List modules, int startX, int startY) { int x = startX; @@ -1121,12 +1109,16 @@ private void buildStationDetailWindow(List modules, int startX, int public void onInventoryButtonPressed(int buttonId) { // Client → server via PacketMachine if (world != null && world.isRemote) { - if (buttonId == GUI_BUTTON_WRITE) { - PacketHandler.sendToServer(new PacketMachine(this, NET_BUTTON_WRITE_CHIP)); - - } else if (buttonId == GUI_BUTTON_SCAN) { + if (buttonId == GUI_BUTTON_SCAN) { + // Reset scroll immediately on the client + AdvancedRocketry.proxy.clearScrollCache(); PacketHandler.sendToServer(new PacketMachine(this, NET_BUTTON_SCAN)); + return; + } + if (buttonId == GUI_BUTTON_WRITE) { + PacketHandler.sendToServer(new PacketMachine(this, NET_BUTTON_WRITE_CHIP)); + return; } else if (buttonId >= SAT_LIST_OFFSET && buttonId < STATION_LIST_OFFSET) { // NEW: update client-side selection immediately lastSatButton = buttonId; @@ -1235,8 +1227,6 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompou } else { rescanStations(); } - // List contents changed → reset scroll cache - ModuleContainerPanYOnlyWithScrollCache.clearScrollCache(); markDirty(); world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); @@ -1472,13 +1462,17 @@ public void invalidate() { lastStationButton = -1; // Critical: reset static scroll cache so containers don't reuse old offsets - ModuleContainerPanYOnlyWithScrollCache.clearScrollCache(); + if (world != null && world.isRemote) { + AdvancedRocketry.proxy.clearScrollCache(); + } + } @Override public void onChunkUnload() { super.onChunkUnload(); - ModuleContainerPanYOnlyWithScrollCache.clearScrollCache(); + if (world != null && world.isRemote) { + AdvancedRocketry.proxy.clearScrollCache(); + } } - } From fe02b3190e60adc764411bfb135e747b3214d95a Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 12:06:53 +0100 Subject: [PATCH 380/424] Add scroll list panel and cache management methods --- .../advancedRocketry/client/ClientProxy.java | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/client/ClientProxy.java b/src/main/java/zmaster587/advancedRocketry/client/ClientProxy.java index 6dda69fc8..1c8fc3434 100644 --- a/src/main/java/zmaster587/advancedRocketry/client/ClientProxy.java +++ b/src/main/java/zmaster587/advancedRocketry/client/ClientProxy.java @@ -50,6 +50,8 @@ import zmaster587.advancedRocketry.entity.fx.*; import zmaster587.advancedRocketry.event.PlanetEventHandler; import zmaster587.advancedRocketry.event.RocketEventHandler; +import zmaster587.advancedRocketry.inventory.modules.ModuleContainerPanYOnlyWithScrollCache; +import zmaster587.libVulpes.inventory.modules.ModuleBase; import zmaster587.advancedRocketry.stations.SpaceObjectManager; import zmaster587.advancedRocketry.tile.TileBrokenPart; import zmaster587.advancedRocketry.tile.TileFluidTank; @@ -72,6 +74,8 @@ import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.LinkedList; +import java.util.List; @Mod.EventBusSubscriber(value = Side.CLIENT) public class ClientProxy extends CommonProxy { @@ -479,6 +483,38 @@ protected ModelResourceLocation getModelResourceLocation(@Nullable IBlockState i } } + + @Override + public ModuleBase createScrollListPan( + int baseX, int baseY, + List list, + int sizeX, int sizeY + ) { + return new ModuleContainerPanYOnlyWithScrollCache( + baseX, baseY, + list, new LinkedList<>(), + null, + sizeX - 2, sizeY, + 0, -48, + 0, 72 + ); + } + + @Override + public void clearScrollCache() { + ModuleContainerPanYOnlyWithScrollCache.clearScrollCache(); + } + + @Override + public ModuleBase createObservatoryAsteroidListPan(int baseX, int baseY, List list2, int sizeX, int sizeY) { + return createScrollListPan(baseX, baseY, list2, sizeX, sizeY); + } + + @Override + public void clearObservatoryScrollCache() { + clearScrollCache(); + } + private static class FluidItemMeshDefinition implements ItemMeshDefinition { private final ModelResourceLocation location; From 0428f9e98d4716e19baf7436c8626eb9fd4de85c Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 12:07:27 +0100 Subject: [PATCH 381/424] Add methods for UI scroll cache management --- .../advancedRocketry/common/CommonProxy.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/main/java/zmaster587/advancedRocketry/common/CommonProxy.java b/src/main/java/zmaster587/advancedRocketry/common/CommonProxy.java index 4fdfd4965..80362f452 100644 --- a/src/main/java/zmaster587/advancedRocketry/common/CommonProxy.java +++ b/src/main/java/zmaster587/advancedRocketry/common/CommonProxy.java @@ -9,9 +9,13 @@ import net.minecraftforge.fml.common.FMLCommonHandler; import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.stations.ISpaceObject; +import zmaster587.libVulpes.inventory.modules.ModuleBase; +import zmaster587.libVulpes.inventory.modules.ModuleContainerPanYOnly; import zmaster587.advancedRocketry.network.PacketLaserGun; import zmaster587.advancedRocketry.network.PacketStationUpdate; import zmaster587.libVulpes.network.PacketHandler; +import java.util.List; +import java.util.LinkedList; public class CommonProxy { @@ -25,6 +29,36 @@ public void registerEventHandlers() { } + + public ModuleBase createScrollListPan( + int baseX, int baseY, + List list, + int sizeX, int sizeY + ) { + return new ModuleContainerPanYOnly( + baseX, baseY, + list, new LinkedList<>(), + null, + sizeX - 2, sizeY, + 0, -48, + 0, 72 + ); + } + + /** Generic clear for any UI scroll cache (no-op on server) */ + public void clearScrollCache() { + // no-op on server/common + } + + // Keep existing Observatory API working (optional wrappers) + public ModuleBase createObservatoryAsteroidListPan(int baseX, int baseY, List list2, int sizeX, int sizeY) { + return createScrollListPan(baseX, baseY, list2, sizeX, sizeY); + } + + public void clearObservatoryScrollCache() { + clearScrollCache(); + } + public void spawnParticle(String particle, World world, double x, double y, double z, double motionX, double motionY, double motionZ) { From 4f7e6e3ac2ba63642800b0a185519f7a7ade330a Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 12:07:56 +0100 Subject: [PATCH 382/424] Refactor TilePump to use localTick for timing --- .../advancedRocketry/tile/TilePump.java | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TilePump.java b/src/main/java/zmaster587/advancedRocketry/tile/TilePump.java index 3d487d76c..89efe5593 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TilePump.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TilePump.java @@ -37,6 +37,7 @@ public class TilePump extends TileEntityRFConsumer implements IFluidHandler, IMo private FluidTank tank; private List cache; private Fluid lastFluidType = null; + private int localTick = 0; public TilePump() { super(1000); @@ -49,10 +50,11 @@ public TilePump() { private final IFluidHandler fluidCap = new FluidCapability(this); private boolean shouldRunThisTick(int interval) { - // world time is long; 0 mod interval fires once per interval - return interval <= 1 || (world.getWorldTime() % interval) == 0; + return interval <= 1 || (localTick % interval) == 0; } + + public int getPowerPerOperation() { return 100; } @@ -74,8 +76,10 @@ public T getCapability(Capability capability, EnumFacing facing) { @Override public void update() { - if (world.isRemote) return; + if (world == null || world.isRemote) return; + localTick++; + if (localTick == Integer.MIN_VALUE) localTick = 0; // Drop stale plan if accepted fluid changed Fluid cur = tank.getFluid() == null ? null : tank.getFluid().getFluid(); if (cur != lastFluidType) { @@ -84,7 +88,6 @@ public void update() { } if (isRedstoneDisabled()) { - // optional: cache.clear(); return; } @@ -195,9 +198,14 @@ private BlockPos getNextBlockLocation() { if (!cache.isEmpty()) return cache.remove(0); - BlockPos currentPos = new MutableBlockPos(getPos().down()); - while (world.isAirBlock(currentPos)) - currentPos = currentPos.down(); + MutableBlockPos currentPos = new MutableBlockPos(pos); + currentPos.move(EnumFacing.DOWN); + + while (currentPos.getY() > 0 && world.isAirBlock(currentPos)) { + currentPos.move(EnumFacing.DOWN); + } + if (currentPos.getY() <= 0) return null; // nothing below + if (!world.isBlockLoaded(currentPos)) return null; Block worldBlock = world.getBlockState(currentPos).getBlock(); @@ -223,9 +231,14 @@ private void findFluidAtOrAbove(BlockPos pos, Fluid targetFluid) { while (!queue.isEmpty()) { BlockPos next = queue.poll(); + if (visited.contains(next) || next.getDistance(pos.getX(), pos.getY(), pos.getZ()) > RANGE) continue; + // Robust: never force-load chunks during a flood fill + if (!world.isBlockLoaded(next)) + continue; + IBlockState state = world.getBlockState(next); Block block = state.getBlock(); @@ -284,9 +297,14 @@ public boolean canPerformFunction() { // must have a drainable source available; if not, try to populate cache now (cheap probe) if (cache.isEmpty()) { // very small, one-shot version of your getNextBlockLocation() to populate cache - BlockPos currentPos = new MutableBlockPos(getPos().down()); - while (world.isAirBlock(currentPos)) - currentPos = ((MutableBlockPos) currentPos).down(); + MutableBlockPos currentPos = new MutableBlockPos(pos); + currentPos.move(EnumFacing.DOWN); + + while (currentPos.getY() > 0 && world.isAirBlock(currentPos)) { + currentPos.move(EnumFacing.DOWN); + } + if (currentPos.getY() <= 0) return false; // nothing below + if (!world.isBlockLoaded(currentPos)) return false; if (canFitFluid(currentPos)) { Fluid target = null; From a3e3776d1a0edeb4aa68b34fa5704bb1ab1073e5 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 12:08:43 +0100 Subject: [PATCH 383/424] Refactor TileObservatory for seed and button management Refactor observatory tile to manage button presses and seed synchronization. avoids desync in all my tests --- .../tile/multiblock/TileObservatory.java | 275 +++++++++++------- 1 file changed, 174 insertions(+), 101 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java index 733ebee33..b2851441c 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java @@ -13,6 +13,7 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraft.world.WorldServer; import net.minecraftforge.fml.relauncher.Side; import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; @@ -20,7 +21,6 @@ import zmaster587.advancedRocketry.api.DataStorage.DataType; import zmaster587.advancedRocketry.inventory.TextureResources; import zmaster587.advancedRocketry.inventory.modules.ModuleData; -import zmaster587.advancedRocketry.inventory.modules.ModuleContainerPanYOnlyWithScrollCache; import zmaster587.advancedRocketry.item.IDataItem; import zmaster587.advancedRocketry.item.ItemAsteroidChip; import zmaster587.advancedRocketry.item.ItemData; @@ -44,6 +44,9 @@ import javax.annotation.Nonnull; import javax.annotation.Nullable; + +import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -52,16 +55,12 @@ public class TileObservatory extends TileMultiPowerConsumer implements IModularInventory, IDataInventory, IGuiCallback { - // Dont allow duplicate chipwrites for the same seed + button - private java.util.HashSet printedButtonsThisSeed = new java.util.HashSet<>(); - private long printedSetSeed = -1; // track which seed the set belongs to - private final java.util.Map savedDataBusNbt = new java.util.HashMap<>(); final static int openTime = 100; final static int observationTime = 1000; private static final Block[] lens = {AdvancedRocketryBlocks.blockLens, Blocks.GLASS}; private static final Object[][][] structure = new Object[][][]{ - + {{null, null, null, null, null}, {null, LibVulpesBlocks.blockStructureBlock, lens, LibVulpesBlocks.blockStructureBlock, null}, {null, LibVulpesBlocks.blockStructureBlock, LibVulpesBlocks.blockStructureBlock, LibVulpesBlocks.blockStructureBlock, null}, @@ -96,7 +95,14 @@ public class TileObservatory extends TileMultiPowerConsumer implements IModularI private static final short LIST_OFFSET = 100; private static final byte PROCESS_CHIP = 12; private static final byte SEED_CHANGE = 13; - private final int dataConsumedPerRefresh = 100; + private static final byte SYNC_PRINTED = 14; + private static final byte REQUEST_REOPEN = 15; + private static final byte SYNC_SEED = 16; + private final int dataConsumedPerRefresh = 100; // Distance data consumed per scan + private boolean pendingReopenAfterSeedSync = false; + // Dont allow duplicate chipwrites for the same seed + button + private java.util.HashSet printedButtonsThisSeed = new java.util.HashSet<>(); + private long printedSetSeed = -1; // track which seed the set belongs to int openProgress; EmbeddedInventory inv = new EmbeddedInventory(5); private int viewDistance; @@ -336,6 +342,7 @@ protected void writeNetworkData(NBTTagCompound nbt) { @Override protected void readNetworkData(NBTTagCompound nbt) { + long prevSeed = this.lastSeed; super.readNetworkData(nbt); openProgress = nbt.getInteger("openProgress"); isOpen = nbt.getBoolean("isOpen"); @@ -348,9 +355,11 @@ protected void readNetworkData(NBTTagCompound nbt) { printedButtonsThisSeed.clear(); int[] arr = nbt.getIntArray("printedButtons"); if (arr != null) for (int v : arr) printedButtonsThisSeed.add(v); + if (world != null && world.isRemote && prevSeed != lastSeed) { + zmaster587.advancedRocketry.AdvancedRocketry.proxy.clearObservatoryScrollCache(); + } } - @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); @@ -421,29 +430,20 @@ public List getModules(int ID, EntityPlayer player) { 25, 120, 1, "", this, zmaster587.libVulpes.inventory.TextureResources.buttonNull, - // default tooltip (will be replaced conditionally below) LibVulpes.proxy.getLocalizedString("msg.observetory.text.processdiscovery"), 17, 17 ); - // `isOpen` is synchronized to client via writeNetworkData/readNetworkData, so safe to read here. boolean alreadyPrinted = (lastButton != -1) && printedButtonsThisSeed.contains(lastButton); if (!isOpen) { processBtn.setToolTipText(LibVulpes.proxy.getLocalizedString("msg.observetory.req.open")); - processBtn.setEnabled(true); } else if (alreadyPrinted) { processBtn.setToolTipText(LibVulpes.proxy.getLocalizedString("msg.observetory.print.already")); - processBtn.setEnabled(false); // <-- } else { processBtn.setToolTipText(LibVulpes.proxy.getLocalizedString("msg.observetory.text.processdiscovery")); - processBtn.setEnabled(true); } - - // Keep it enabled so the tooltip renders (ModuleButton.isMouseOver checks enabled) - processBtn.setEnabled(true); - modules.add(processBtn); ModuleButton scanButton = new ModuleButton(100, 120, 2, LibVulpes.proxy.getLocalizedString("msg.observetory.scan.button"), this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild, LibVulpes.proxy.getLocalizedString("msg.observetory.scan.tooltip"), 64, 18); @@ -485,10 +485,13 @@ public List getModules(int ID, EntityPlayer player) { int totalAmountAllowed = 10; float totalWeight = 0; + List keys = new ArrayList<>(ARConfiguration.getCurrentConfig().asteroidTypes.keySet()); + Collections.sort(keys); + List viableTypes = new LinkedList<>(); - for (String str : ARConfiguration.getCurrentConfig().asteroidTypes.keySet()) { + for (String str : keys) { Asteroid asteroid = ARConfiguration.getCurrentConfig().asteroidTypes.get(str); - if (asteroid.distance <= getMaxDistance()) { + if (asteroid != null && asteroid.distance <= getMaxDistance()) { totalWeight += asteroid.getProbability(); viableTypes.add(asteroid); } @@ -557,17 +560,12 @@ public List getModules(int ID, EntityPlayer player) { // ---- LEFT asteroid list: wheel-enabled + cached if (lastSeed != -1) { - ModuleContainerPanYOnlyWithScrollCache panLeft = new ModuleContainerPanYOnlyWithScrollCache( - baseX, baseY, - list2, new LinkedList<>(), - null, - sizeX - 2, sizeY, // (screen width minus 2 like original) - 0, -48, // paddingX, paddingY - 0, 72 // containerSizeX, containerSizeY - ); - modules.add(panLeft); // LEFT FIRST to consume wheel + modules.add(zmaster587.advancedRocketry.AdvancedRocketry.proxy + .createObservatoryAsteroidListPan(baseX, baseY, list2, sizeX, sizeY)); } + + // ---- RIGHT composition pane: parent class (drag-only; wheel will be 0 after left consumes it) ModuleContainerPanYOnly panRight = new ModuleContainerPanYOnly( compX, compY, @@ -632,7 +630,15 @@ public void onInventoryButtonPressed(int buttonId) { super.onInventoryButtonPressed(buttonId); if (buttonId == 1) { - //Begin discovery processing + // Client: prevent packet spam + if (world != null && world.isRemote) { + boolean alreadyPrinted = (lastButton != -1) && printedButtonsThisSeed.contains(lastButton); + if (!isOpen || alreadyPrinted || lastButton == -1) { + return; + } + } + + // Server-side protection is in PROCESS_CHIP PacketHandler.sendToServer(new PacketMachine(this, PROCESS_CHIP)); } @@ -641,103 +647,130 @@ public void onInventoryButtonPressed(int buttonId) { lastType = buttonType.get(lastButton - LIST_OFFSET); PacketHandler.sendToServer(new PacketMachine(this, BUTTON_PRESS)); } - if (buttonId == 2) { - PacketHandler.sendToServer(new PacketMachine(this, SEED_CHANGE)); - /*/for(TileDataBus bus : getDataBus()) { - if (extractData(dataConsumedPerRefresh, DataType.DISTANCE, EnumFacing.UP, false) == dataConsumedPerRefresh) { - lastSeed = world.getTotalWorldTime() / 100; - lastButton = -1; - lastType = ""; - PacketHandler.sendToServer(new PacketMachine(this, SEED_CHANGE)); + if (buttonId == 2) { + if (world != null && world.isRemote) { + pendingReopenAfterSeedSync = true; } - /}*/ + PacketHandler.sendToServer(new PacketMachine(this, SEED_CHANGE)); + } } @Override - public void useNetworkData(EntityPlayer player, Side side, byte id, - NBTTagCompound nbt) { + public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompound nbt) { super.useNetworkData(player, side, id, nbt); - if (id == -1) - storeData(-1); - if (id == -2) - loadData(-2); - else if (id == TAB_SWITCH && !world.isRemote) { - tabModule.setTab(nbt.getShort("tab")); - player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), getWorld(), pos.getX(), pos.getY(), pos.getZ()); - } - else if (id == BUTTON_PRESS && !world.isRemote) { - lastButton = nbt.getShort("button"); - lastType = buttonType.get(lastButton - LIST_OFFSET); - markDirty(); - world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); - player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), getWorld(), pos.getX(), pos.getY(), pos.getZ()); + if (id == SYNC_PRINTED && world != null && world.isRemote) { + printedSetSeed = nbt.getLong("ps"); + + printedButtonsThisSeed.clear(); + for (int v : nbt.getIntArray("pb")) printedButtonsThisSeed.add(v); + + lastSeed = nbt.getLong("ls"); + lastButton = nbt.getInteger("lb"); + isOpen = nbt.getBoolean("io"); + return; } - else if (id == SEED_CHANGE) { - if (extractData(dataConsumedPerRefresh, DataType.DISTANCE, EnumFacing.UP, false) >= dataConsumedPerRefresh) { - lastSeed = world.getTotalWorldTime() / 100; - lastButton = -1; - lastType = ""; - - printedButtonsThisSeed.clear(); - printedSetSeed = lastSeed; - - // Clear scroll cache when scanning new data - ModuleContainerPanYOnlyWithScrollCache.clearScrollCache(); - - extractData(dataConsumedPerRefresh, DataType.DISTANCE, EnumFacing.UP, true); - world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); - markDirty(); - player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), getWorld(), pos.getX(), pos.getY(), pos.getZ()); + if (id == SYNC_SEED && world != null && world.isRemote) { + lastSeed = nbt.getLong("ls"); + lastButton = nbt.getInteger("lb"); + lastType = ""; // since scan resets it + isOpen = nbt.getBoolean("io"); + + zmaster587.advancedRocketry.AdvancedRocketry.proxy.clearObservatoryScrollCache(); + + if (pendingReopenAfterSeedSync) { + pendingReopenAfterSeedSync = false; + PacketHandler.sendToServer(new PacketMachine(this, REQUEST_REOPEN)); } + return; } - else if (id == PROCESS_CHIP && !world.isRemote) { - // Keep printed set aligned with current seed (covers edge cases like load) - if (printedSetSeed != lastSeed) { - printedButtonsThisSeed.clear(); - printedSetSeed = lastSeed; - } + if (id == -1) { storeData(-1); return; } + if (id == -2) { loadData(-2); return; } - // Hard block duplicates for this scan/selection - if (lastButton != -1 && printedButtonsThisSeed.contains(lastButton)) { - // No status message; just refresh UI so tooltip updates - world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); + // --- server-side handlers only --- + if (!world.isRemote) { + + if (id == TAB_SWITCH) { + tabModule.setTab(nbt.getShort("tab")); + player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), + getWorld(), pos.getX(), pos.getY(), pos.getZ()); + } + else if (id == BUTTON_PRESS) { + lastButton = nbt.getShort("button"); + lastType = buttonType.get(lastButton - LIST_OFFSET); markDirty(); - if (player != null) { - player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); + player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), getWorld(), pos.getX(), pos.getY(), pos.getZ()); + } + else if (id == SEED_CHANGE) { + if (extractData(dataConsumedPerRefresh, DataType.DISTANCE, EnumFacing.UP, false) >= dataConsumedPerRefresh) { + lastSeed = world.getTotalWorldTime() / 100; + lastButton = -1; + lastType = ""; + + printedButtonsThisSeed.clear(); + printedSetSeed = lastSeed; + PacketHandler.sendToPlayer(new PacketMachine(this, SYNC_SEED), player); + extractData(dataConsumedPerRefresh, DataType.DISTANCE, EnumFacing.UP, true); + markDirty(); + IBlockState st = world.getBlockState(pos); + world.notifyBlockUpdate(pos, st, st, 2); } - return; } + else if (id == PROCESS_CHIP) { - if (inv.getStackInSlot(2).isEmpty() && isOpen && hasEnergy(500) && lastButton != -1) { - ItemStack stack = inv.decrStackSize(1, 1); - if (stack != ItemStack.EMPTY && stack.getItem() instanceof ItemAsteroidChip) { - ((ItemAsteroidChip)(stack.getItem())).setUUID(stack, lastSeed + lastButton); - ((ItemAsteroidChip)(stack.getItem())).setType(stack, lastType); - ((ItemAsteroidChip)(stack.getItem())).setMaxData(stack, 1000); - inv.setInventorySlotContents(2, stack); - - useEnergy(500); - - // Mark this selection as consumed for this seed - printedButtonsThisSeed.add(lastButton); + // Keep printed set aligned with current seed + if (printedSetSeed != lastSeed) { + printedButtonsThisSeed.clear(); + printedSetSeed = lastSeed; + } - // Sync + rebuild GUI so tooltip and button state update immediately - markDirty(); + // Hard block duplicates for this scan + if (lastButton != -1 && printedButtonsThisSeed.contains(lastButton)) { + // No status message; just refresh UI so tooltip updates world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); + markDirty(); if (player != null) { player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), getWorld(), pos.getX(), pos.getY(), pos.getZ()); } + return; } - } - } + if (inv.getStackInSlot(2).isEmpty() && isOpen && hasEnergy(500) && lastButton != -1) { + ItemStack stack = inv.decrStackSize(1, 1); + if (stack != ItemStack.EMPTY && stack.getItem() instanceof ItemAsteroidChip) { + ((ItemAsteroidChip)(stack.getItem())).setUUID(stack, lastSeed + lastButton); + ((ItemAsteroidChip)(stack.getItem())).setType(stack, lastType); + ((ItemAsteroidChip)(stack.getItem())).setMaxData(stack, 1000); + inv.setInventorySlotContents(2, stack); + + useEnergy(500); + + // Mark this selection as consumed for this seed + printedButtonsThisSeed.add(lastButton); + PacketHandler.sendToPlayer(new PacketMachine(this, SYNC_PRINTED), player); + + markDirty(); + world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); + // reopen 1 tick later to avoid cross-channel ordering race + ((WorldServer) world).addScheduledTask(() -> player.openGui( + LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), + getWorld(), pos.getX(), pos.getY(), pos.getZ() + )); + } + } + } + else if (id == REQUEST_REOPEN) { + player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), + getWorld(), pos.getX(), pos.getY(), pos.getZ()); + } + } } @Override @@ -748,6 +781,22 @@ public void writeDataToNetwork(ByteBuf out, byte id) { out.writeShort(tabModule.getTab()); else if (id == BUTTON_PRESS) out.writeShort(lastButton); + + if (id == SYNC_PRINTED) { + out.writeLong(printedSetSeed); + out.writeInt(printedButtonsThisSeed.size()); + for (int b : printedButtonsThisSeed) out.writeInt(b); + out.writeLong(lastSeed); + out.writeInt(lastButton); + out.writeBoolean(isOpen); + } + if (id == SYNC_SEED) { + out.writeLong(lastSeed); + out.writeInt(lastButton); + out.writeBoolean(isOpen); + out.writeBoolean(getMachineEnabled()); + // lastType optional; you set it "" on scan, so you can skip it + } } @Override @@ -760,6 +809,22 @@ public void readDataFromNetwork(ByteBuf in, byte packetId, else if (packetId == BUTTON_PRESS) nbt.setShort("button", in.readShort()); + if (packetId == SYNC_PRINTED) { + nbt.setLong("ps", in.readLong()); + int n = in.readInt(); + int[] arr = new int[n]; + for (int i=0;i Date: Thu, 18 Dec 2025 12:09:21 +0100 Subject: [PATCH 384/424] Add anchored warning module to TileStationOrientationController --- .../TileStationOrientationController.java | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationOrientationController.java b/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationOrientationController.java index 11eaa29ed..9bce3d6e7 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationOrientationController.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationOrientationController.java @@ -12,6 +12,7 @@ import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; import zmaster587.advancedRocketry.api.stations.ISpaceObject; import zmaster587.advancedRocketry.inventory.TextureResources; +import zmaster587.advancedRocketry.network.PacketSpaceStationInfo; import zmaster587.advancedRocketry.network.PacketStationUpdate; import zmaster587.advancedRocketry.stations.SpaceObjectManager; import zmaster587.advancedRocketry.stations.SpaceStationObject; @@ -29,13 +30,14 @@ public class TileStationOrientationController extends TileEntity implements ITic private int[] progress; private long lastRotSyncTick = -5; - + private ModuleText anchoredWarning; private ModuleText moduleAngularVelocity, numThrusters, maxAngularAcceleration, targetRotations; public TileStationOrientationController() { moduleAngularVelocity = new ModuleText(6, 15, LibVulpes.proxy.getLocalizedString("msg.stationorientctrl.alt"), 0xaa2020); //numThrusters = new ModuleText(10, 25, "Number Of Thrusters: ", 0xaa2020); targetRotations = new ModuleText(6, 25, LibVulpes.proxy.getLocalizedString("msg.stationorientctrl.tgtalt"), 0x202020); + anchoredWarning = new ModuleText(6, 35, "", 0xaa2020); progress = new int[3]; progress[0] = getTotalProgress(0) / 2; @@ -46,27 +48,35 @@ public TileStationOrientationController() { @Override public List getModules(int id, EntityPlayer player) { List modules = new LinkedList<>(); + if (!world.isRemote) { + ISpaceObject so = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); + if (so instanceof SpaceStationObject) { + PacketHandler.sendToPlayer(new PacketSpaceStationInfo(so.getId(), (SpaceStationObject) so), player); + } + } modules.add(moduleAngularVelocity); //modules.add(numThrusters); //modules.add(maxAngularAcceleration); modules.add(targetRotations); - + modules.add(anchoredWarning); + modules.add(new ModuleText(10, 54, "X:", 0x202020)); modules.add(new ModuleText(10, 69, "Y:", 0x202020)); //AYYYY modules.add(new ModuleSlider(24, 50, 0, TextureResources.doubleWarningSideBarIndicator, this)); modules.add(new ModuleSlider(24, 65, 1, TextureResources.doubleWarningSideBarIndicator, this)); - modules.add(new ModuleButton(25, 35, 2, LibVulpes.proxy.getLocalizedString("msg.spacelaser.reset"), this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild, 36, 15)); + modules.add(new ModuleButton(128, 35, 2, LibVulpes.proxy.getLocalizedString("msg.spacelaser.reset"), this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild, 36, 15)); //modules.add(new ModuleSlider(24, 35, 2, TextureResources.doubleWarningSideBarIndicator, (ISliderBar)this)); // inline updater that runs only while GUI is open modules.add(new ModuleBase(0, 0) { private SpaceStationObject cached; private int cachedId = Integer.MIN_VALUE; - + private int lastVelX = Integer.MIN_VALUE, lastVelY = Integer.MIN_VALUE, lastVelZ = Integer.MIN_VALUE; private int lastTgtX = Integer.MIN_VALUE, lastTgtY = Integer.MIN_VALUE, lastTgtZ = Integer.MIN_VALUE; - + private int lastAnchored = Integer.MIN_VALUE; + private final String anchoredText = LibVulpes.proxy.getLocalizedString("msg.station.anchored"); private final String prefixVel = LibVulpes.proxy.getLocalizedString("msg.stationorientctrl.alt"); private final String prefixTgt = LibVulpes.proxy.getLocalizedString("msg.stationorientctrl.tgtalt"); @@ -97,6 +107,13 @@ private boolean ensureStation() { public void renderBackground(GuiContainer gui, int x, int y, int mouseX, int mouseY, FontRenderer font) { if (!ensureStation()) return; + boolean anchored = cached.isAnchored(); + int anchoredKey = anchored ? 1 : 0; + if (anchoredKey != lastAnchored) { + anchoredWarning.setText(anchored ? anchoredText : ""); + lastAnchored = anchoredKey; + } + double dX = cached.getDeltaRotation(EnumFacing.EAST); double dY = cached.getDeltaRotation(EnumFacing.UP); double dZ = cached.getDeltaRotation(EnumFacing.NORTH); From fc1a60639fc03a77e0e1bf679c15d155b85e402a Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 12:09:42 +0100 Subject: [PATCH 385/424] Add anchored warning to TileStationAltitudeController Added anchored warning module to display station's anchored status. --- .../TileStationAltitudeController.java | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationAltitudeController.java b/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationAltitudeController.java index 205fb7f5b..eda5fadc3 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationAltitudeController.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/station/TileStationAltitudeController.java @@ -13,6 +13,7 @@ import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; import zmaster587.advancedRocketry.api.stations.ISpaceObject; import zmaster587.advancedRocketry.inventory.TextureResources; +import zmaster587.advancedRocketry.network.PacketSpaceStationInfo; import zmaster587.advancedRocketry.network.PacketStationUpdate; import zmaster587.advancedRocketry.stations.SpaceObjectManager; import zmaster587.advancedRocketry.stations.SpaceStationObject; @@ -36,8 +37,10 @@ public class TileStationAltitudeController extends TileEntity implements IModula private ModuleText moduleGrav, numGravPylons, maxGravBuildSpeed, targetGrav; private ModuleRedstoneOutputButton redstoneControl; private boolean wasChanging = false; + private ModuleText anchoredWarning; public TileStationAltitudeController() { moduleGrav = new ModuleText(6, 15, "Altitude: ", 0xaa2020); + anchoredWarning = new ModuleText(6, 45, "", 0xaa2020); //numGravPylons = new ModuleText(10, 25, "Number Of Thrusters: ", 0xaa2020); //maxGravBuildSpeed = new ModuleText(6, 25, LibVulpes.proxy.getLocalizedString("msg.stationaltctrl.maxaltrate"), 0xaa2020); targetGrav = new ModuleText(6, 35, LibVulpes.proxy.getLocalizedString("msg.stationaltctrl.tgtalt"), 0x202020); @@ -48,11 +51,17 @@ public TileStationAltitudeController() { @Override public List getModules(int id, EntityPlayer player) { List modules = new LinkedList<>(); + if (!world.isRemote) { + ISpaceObject so = SpaceObjectManager.getSpaceManager().getSpaceStationFromBlockCoords(pos); + if (so instanceof SpaceStationObject) { + PacketHandler.sendToPlayer(new PacketSpaceStationInfo(so.getId(), (SpaceStationObject) so), player); + } + } modules.add(moduleGrav); //modules.add(numThrusters); //modules.add(maxGravBuildSpeed); - modules.add(targetGrav); + modules.add(anchoredWarning); modules.add(new ModuleSlider(6, 60, 0, TextureResources.doubleWarningSideBarIndicator, this)); modules.add(redstoneControl); @@ -64,8 +73,10 @@ public List getModules(int id, EntityPlayer player) { // last shown keys (ints in Km) private int lastAltKm = Integer.MIN_VALUE; private int lastTgtKm = Integer.MIN_VALUE; + private int lastAnchored = Integer.MIN_VALUE; // localized prefixes (cache per GUI session) + private final String anchoredText = LibVulpes.proxy.getLocalizedString("msg.station.anchored"); private final String prefixAlt = LibVulpes.proxy.getLocalizedString("msg.stationaltctrl.alt"); private final String prefixTgt = LibVulpes.proxy.getLocalizedString("msg.stationaltctrl.tgtalt"); @@ -88,9 +99,16 @@ private boolean ensureStation() { @Override public void renderBackground(GuiContainer gui, int x, int y, int mouseX, int mouseY, FontRenderer font) { - // Only runs while the GUI is visible → zero idle cost when closed. if (!ensureStation()) return; + // Anchored status + boolean anchored = cached.isAnchored(); + int anchoredKey = anchored ? 1 : 0; + if (anchoredKey != lastAnchored) { + anchoredWarning.setText(anchored ? anchoredText : ""); + lastAnchored = anchoredKey; + } + // Compute display keys (Km as ints) int curAltKm = (int)Math.round(cached.getOrbitalDistance() * 200.0 + 100.0); int tgtAltKm = cached.targetOrbitalDistance * 200 + 100; From dbb97facbbef898b40e6c72171ca6a99ccff5c6c Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 12:10:51 +0100 Subject: [PATCH 386/424] Localize power and time labels in drawInfo method --- .../integration/jei/MachineRecipe.java | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/integration/jei/MachineRecipe.java b/src/main/java/zmaster587/advancedRocketry/integration/jei/MachineRecipe.java index 927b939f8..0116217d7 100644 --- a/src/main/java/zmaster587/advancedRocketry/integration/jei/MachineRecipe.java +++ b/src/main/java/zmaster587/advancedRocketry/integration/jei/MachineRecipe.java @@ -4,6 +4,7 @@ import mezz.jei.api.recipe.IRecipeWrapper; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.resources.I18n; import net.minecraft.item.ItemStack; import net.minecraftforge.fluids.FluidStack; import zmaster587.libVulpes.interfaces.IRecipe; @@ -81,14 +82,18 @@ public int getTime() { @Override public void drawInfo(Minecraft minecraft, int recipeWidth, - int recipeHeight, int mouseX, int mouseY) { + int recipeHeight, int mouseX, int mouseY) { - String powerString = String.format("Power: %d RF/t", energy); FontRenderer fontRendererObj = minecraft.fontRenderer; + + // Localized labels + String powerLabel = I18n.format("jei.machinerecipe.power"); + String timeLabel = I18n.format("jei.machinerecipe.time"); + + String powerString = String.format("%s %d RF/t", powerLabel, energy); fontRendererObj.drawString(powerString, 0, 55, Color.black.getRGB()); - String timeString = String.format("Time: %d s", time / 20); + String timeString = String.format("%s %d s", timeLabel, time / 20); fontRendererObj.drawString(timeString, recipeWidth - 55, 55, Color.black.getRGB()); - } } From 4265d4fa94670a16b941d9515eb7af4119ba7cce Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 12:11:23 +0100 Subject: [PATCH 387/424] Add newline at end of TileSatelliteBuilder.java Fix missing newline at end of file From 185b402c74fdfccb90e247c844c57e53d3455132 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 12:46:41 +0100 Subject: [PATCH 388/424] Update language --- .../assets/advancedrocketry/lang/en_US.lang | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index 76d1d241d..57ed3fe06 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -307,7 +307,7 @@ msg.observetory.text.observabledistance=Observable distance: msg.observetory.text.missionTime=Mission Time: msg.observetory.text.time=Time: msg.observetory.req.open=Observatory must be open (night, clear sky, sky access) or be in space! -msg.observetory.print.already=You already have a chip for this asteroid! +msg.observetory.print.already=You already printed a chip for this asteroid! # Atmosphere detector GUI labels msg.atmosphere.air=Normal Air @@ -381,9 +381,9 @@ msg.guidanceComputerHatch.ejectonstationlanding=Allow Ejection of Station Chips msg.guidanceComputerHatch.link=You program the linker with the fluid loader at msg.fluidLoader.loadingState=Loading State: msg.fluidLoader.allowLoading=Allow Loading: -msg.fluidLoader.allowredstoneinput=Allow redstone input -msg.fluidLoader.allowredstoneoutput=Allow redstone output -msg.fluidLoader.none=None +msg.fluidLoader.allowredstoneinput=Redstone Input (Red) +msg.fluidLoader.allowredstoneoutput=Redstone Output (Blue) +msg.fluidLoader.none=Disabled (Green) msg.fluidLoader.link=You program the linker with the fluid loader at: msg.rocketLoader.loadingState=Loading State: msg.rocketLoader.allowLoading=Allow Loading: @@ -457,12 +457,13 @@ msg.stationgravctrl.tgtalt=Target Gravity: msg.stationgravctrl.alt=Artificial Gravity: msg.stationorientctrl.alt=Angular Velocity: msg.stationorientctrl.tgtalt=Target Ang Vel: +msg.station.anchored=§cAnchored! msg.warpmon.tab.warp=Warp Selection msg.warpmon.tab.data=Data msg.warpmon.tab.tracking=Planet Tracking msg.warpmon.selectplanet=Select Planet msg.warpmon.corestatus=Core Status: -msg.warpmon.anchored=Station is anchored! +msg.warpmon.anchored=Anchored! msg.warpmon.nowhere=Nowhere to go msg.warpmon.missingart=Missing Artifact msg.warpmon.ready=Ready! @@ -1310,7 +1311,9 @@ tooltip.advancedrocketry.railgun.alt.1="The railgun is not powerful enough to tr # Space Elevator Controller tooltip.advancedrocketry.spaceelevatorctrl=Controls the Space Elevator tooltip.advancedrocketry.spaceelevatorctrl.shift.1=§bUse Holo-Projector! - +tooltip.advancedrocketry.spaceelevatorctrl.shift.2=§fAnchors station +tooltip.advancedrocketry.spaceelevatorctrl.alt.1=§fNeeds air above (Planetside), air below (Stationside) +tooltip.advancedrocketry.spaceelevatorctrl.alt.2=§cUse Linker # Atmosphere Terraformer tooltip.advancedrocketry.atmosterraformer=Changes Atmospheric pressure on an entire planet tooltip.advancedrocketry.atmosterraformer.shift.1=§bUse Holo-Projector! From fda890848ec4532aa1d1b9c407e049aef931ccef Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 12:57:36 +0100 Subject: [PATCH 389/424] Fix missing newline at end of TileOrbitalRegistry.java From 4299af2fbf65660737bb3193a747a9f94de8964d Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 13:45:37 +0100 Subject: [PATCH 390/424] Update changelog for versions 2.2.0 to 2.2.2 Added detailed changelog for versions 2.2.0 to 2.2.2, including new features, bug fixes, and performance improvements across various components. --- changelog.md | 245 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) create mode 100644 changelog.md diff --git a/changelog.md b/changelog.md new file mode 100644 index 000000000..2bec70de6 --- /dev/null +++ b/changelog.md @@ -0,0 +1,245 @@ +Changelog 2.2.0 + +- JEI Integration + - Satellite Builder: +Satellites + - Satellite Builder: +ChipCopy + +- Guidance Computer Access Hatch + - Fixed render glitch when emitting redstone + +- Satellite Builder + - Rejects invalid items during assembly (soft-fixes crash with invalid core module) + +- Rocket Assembler + - GUI correctly updates error codes/messages to player + - Idle GC craziness SHOULD be fixed; lowered overall GC + +- Station Assembler + - No more "rocket already assembled"; now shows specific failure (e.g., invalid launchpad) + - Correctly updates error codes to client/GUI + - Safer logic; fewer user errors + +- Satellite Terminal + - No more broadcasting UI updates to everyone in 16-block radius + - Send UI data only to actual viewer (less network churn / DDOS-y behavior) + - Downloading data requires power; one-time "Download" button + +- Wireless Transceiver + - Operations throttled to once per 20 ticks; multiple units are phased (don’t run same tick) + - Enable/disable actually turns it off + - GUI shows Network ID so you can verify which plug is connected + - Plugs place on targeted face; top & bottom faces valid + - Extract button toggles insert/extract + - Extract button auto-pulls from satellite to Satellite Terminal internal storage + - NOTE: Still has 100 internal data storage; not voided—stuck in transit if nowhere to go + +- Observatory + - Scrollbar won't reset when selecting an asteroid (may not work with modded container overrides) + - Mousewheel asteroid scrolling + - Process button tooltip explains why it’s not working (when observatory isn’t open) + - Asteroid Chips: + - Improved tooltips/names; choices closer to loot (kept old randomizer logic) + - Fix: chips no longer share same name until “New scan” + +- Rocket Monitor + - Stopped 20x/second polling + - Redstone now event-based (onNeighborChange) + - Fuel/height via rocket entity (delays: fuel 5 ticks, height 3 ticks) + +- Fuel Station + - Stopped all 20x/second behavior + - Early bailout logic to truly idle when idle + - Fix: mono tank could be filled with H2/O2 for 0 burn → infinite free launches + - Safe against overfilling/voiding + +- Rocket Entity + - GUI shows oxidizer bar only if oxidizer tank exists + - On dimension change: preloads 3×3 chunks for 60s from Launch event (reduces desync) + + + + + +solved bugs: +https://github.com/dercodeKoenig/AdvancedRocketry/issues/63 +https://github.com/dercodeKoenig/AdvancedRocketry/issues/62 +https://github.com/dercodeKoenig/AdvancedRocketry/issues/57 +https://github.com/dercodeKoenig/AdvancedRocketry/issues/50 + + +Changelog 2.2.1: + +- AsteroidChip + - Hides 3 unused datatypes from tooltip. + +- AtmosphereDetector + - Fixed GUI-background overlapping hotbar + +- Fuel Station + - Fixed nuclear working fluid filling. + - Smoother energy consumption while fueling. + - JEI integration (respects config per rocket type). + +- ItemSatellite + - Removed false tooltip error; now shows live build preview. + +- WorldServerNotMulti + - Removed super.init() to avoid per-world manager duplication and broken custom data. + +- WirelessTransceiver + - GUI now shows internal buffer. + - Auto-download support. + - Fixed stale states on load. + +- SatelliteTerminal + - Proper, lightweight AutoDownload (With Wireless tranceiver). + - Minor performance tweaks. + - Fixed stale states from last update. + +- Datastorage + - Clears to "Some Random Data" at 0 to avoid locked/stale states. + - Safer vs overriding/voiding types. + +- Observatory + - Each asteroid can only be printed once (no infinite asteroid chips). + - Conditional tooltip explains limit. + - Removed pointless data spending. + +- Pressurized Fluid Tank + - Better tower handling (fluids flow down when stacked). + - Drops and saves correct amount when broken. + +- Station Gravity Controller / Station Altitude Controller + - Performance improvements (less GC, networking, tick spam). + - Only calculates GUI info when open. + - Throttled packets to every 5 ticks. + +- Station Orientation Controller + - Performance improvements as above. + - Smoother rotation and fixed sync issues. + +- Unmanned Vehicle Assembler + - Behaves like Rocket Assembler: + - Rescans rocket stats after build. + - Uses same stat calculation. + - Supports all engine/tank types (compat-guarded). + - Advanced weight (respects config, falls back to block count). + - Rejects invalid rockets with new status messages. + - Updated status syncing. + - Correctly rotates all engines. + +- StationDeployedRocket + - Adopted rocket logic from normal rockets: + - GUI can show 2 fuel bars (biprop). + - Supports all engine/tank types. + +- StorageChunk + - Also checks liquid capacity and gas intake for gas missions. + +- Gas Missions + - New config: + - gasHarvestAmountMultiplier controls per-mission cap (64,000 mB × multiplier). + - gasHarvestInfinite fills all attached tanks up to free space, capped at int max. + - Duration now scales with harvested gas, storage and multipliers (no more multi-hour max runs). + +- GasChargePad + - Hides inherited 0-RF energy capability in Waila/OneProbe. + - Skips scans/lookups if internal tank is empty. + +- RocketMonitor + - Split status/mission into tabs. + - Mission tab shows useful mission details. + - Added Error / status Messages from linked rocket + - Stronger relink on load. + +- Rockets + - Stronger relink on load. + - Failed launch reasons posted to mounted player’s chat. (and linked monitor) + +- Engines + - Nuclear engines auto-stick to nuclear cores. + - Biprop engines stick to tanks (like monoprop). + +- ItemPressureTank + - Stack size increased to 8. + +- MicrowaveReceiver + - Uses same range/lookup logic as Satellite Terminal. + - Fixed NPE. + - Fixed voiding when assembling/disassembling multiblocks. + +- Pump + - Can pump water and lava. + - Now operates every 20 ticks instead of every tick. + - Can be turned off with redstone. + +- Other + - Small cleanups. + - Tooltips added for ~98% of blocks/items. + - JEI: CO2 Scrubber/Oxygen Vent, Fuel Station, Station Assembler. + +Changelog 2.2.1-1: + +-Terraforming Terminal: + - GUI: fixed header saying "Satellite Terminal" and polished text + - Hide internal RF Storage since it uses the satellites Power anyway (avoids confusion) +-Other + - Added more tooltips + - Polished tooltips from last update (thanks to Xonazeth!) + + +Changelog 2.2.2 + +- New Blocks + - Orbital Registry + - Scans existing stations/starships/satellites, shows info, prints new chips + - Prevents losing the last chip / reduces need for backups + - Only checks current dimension + - Advanced Databus + - Works like DataUnit AND Databus + - Stores more data (less transceiver spaghetti / better performance for buffers) + - Keeps data when broken (NOT a "Satellite Component") + +- Rocket + - Added hint: "Press to open GUI" when riding rockets + - Added more error messages for failed launches + - Removed GUI header (fixes fullscreen overlap top left) + - Planet stat bars fixed + +- Warp Controller + - Reduced GC churn + - Removed GUI header (fixes fullscreen overlap top left) + +- Terraforming Terminal + - No Controller = true idle + +- Orbital Laser Drill + - laserDrillPlanet=false: simpler GUI + "void cobble" toggle (huge performance boost) + - Early-outs when not constructed / no redstone etc (idle = idle) + +- Station Controllers + - GUI shows if station is anchored + +- Rocket Loader/Unloader + Fluid Loader/Unloader + - Accepts most modded tanks/inventories + - Added explanation for the 6 squares in GUI + +- Config + - nuclearRocketsRespectArtifactGating=true + - EnableOrbitalRegistry=true + +- Bugfix + - Docking pads blocking rocket dismantle + - Space-to-launch only triggers on "down" press (fixes heavy modpacks) + - Negative/null weather timers crash + - Observatory databuses: type could become undefined; now keeps contents on deconstruction + - Observatory server scan + stale asteroid list fixes + - Rare NPE when starID changes / missing + +- Tooltips + - Further polished + +- Translations + - Chinese updated + - English polished + - Many hardcoded English strings fixed From 3fb597a24f27a09f1deeb07b3f791ff6d904af0e Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 13:47:37 +0100 Subject: [PATCH 391/424] Update changelog to version 2.2.2 Updated changelog to version 2.2.2, adding new blocks, features, and bug fixes. --- changelog.md | 212 +++++++++++++++++++++++++-------------------------- 1 file changed, 106 insertions(+), 106 deletions(-) diff --git a/changelog.md b/changelog.md index 2bec70de6..6fce3bad6 100644 --- a/changelog.md +++ b/changelog.md @@ -1,71 +1,68 @@ -Changelog 2.2.0 - -- JEI Integration - - Satellite Builder: +Satellites - - Satellite Builder: +ChipCopy - -- Guidance Computer Access Hatch - - Fixed render glitch when emitting redstone - -- Satellite Builder - - Rejects invalid items during assembly (soft-fixes crash with invalid core module) - -- Rocket Assembler - - GUI correctly updates error codes/messages to player - - Idle GC craziness SHOULD be fixed; lowered overall GC +Changelog 2.2.2 -- Station Assembler - - No more "rocket already assembled"; now shows specific failure (e.g., invalid launchpad) - - Correctly updates error codes to client/GUI - - Safer logic; fewer user errors +- New Blocks + - Orbital Registry + - Scans existing stations/starships/satellites, shows info, prints new chips + - Prevents losing the last chip / reduces need for backups + - Only checks current dimension + - Advanced Databus + - Works like DataUnit AND Databus + - Stores more data (less transceiver spaghetti / better performance for buffers) + - Keeps data when broken (NOT a "Satellite Component") -- Satellite Terminal - - No more broadcasting UI updates to everyone in 16-block radius - - Send UI data only to actual viewer (less network churn / DDOS-y behavior) - - Downloading data requires power; one-time "Download" button +- Rocket + - Added hint: "Press to open GUI" when riding rockets + - Added more error messages for failed launches + - Removed GUI header (fixes fullscreen overlap top left) + - Planet stat bars fixed -- Wireless Transceiver - - Operations throttled to once per 20 ticks; multiple units are phased (don’t run same tick) - - Enable/disable actually turns it off - - GUI shows Network ID so you can verify which plug is connected - - Plugs place on targeted face; top & bottom faces valid - - Extract button toggles insert/extract - - Extract button auto-pulls from satellite to Satellite Terminal internal storage - - NOTE: Still has 100 internal data storage; not voided—stuck in transit if nowhere to go +- Warp Controller + - Reduced GC churn + - Removed GUI header (fixes fullscreen overlap top left) -- Observatory - - Scrollbar won't reset when selecting an asteroid (may not work with modded container overrides) - - Mousewheel asteroid scrolling - - Process button tooltip explains why it’s not working (when observatory isn’t open) - - Asteroid Chips: - - Improved tooltips/names; choices closer to loot (kept old randomizer logic) - - Fix: chips no longer share same name until “New scan” +- Terraforming Terminal + - No Controller = true idle -- Rocket Monitor - - Stopped 20x/second polling - - Redstone now event-based (onNeighborChange) - - Fuel/height via rocket entity (delays: fuel 5 ticks, height 3 ticks) +- Orbital Laser Drill + - laserDrillPlanet=false: simpler GUI + "void cobble" toggle (huge performance boost) + - Early-outs when not constructed / no redstone etc (idle = idle) -- Fuel Station - - Stopped all 20x/second behavior - - Early bailout logic to truly idle when idle - - Fix: mono tank could be filled with H2/O2 for 0 burn → infinite free launches - - Safe against overfilling/voiding +- Station Controllers + - GUI shows if station is anchored -- Rocket Entity - - GUI shows oxidizer bar only if oxidizer tank exists - - On dimension change: preloads 3×3 chunks for 60s from Launch event (reduces desync) +- Rocket Loader/Unloader + Fluid Loader/Unloader + - Accepts most modded tanks/inventories + - Added explanation for the 6 squares in GUI +- Config + - nuclearRocketsRespectArtifactGating=true + - EnableOrbitalRegistry=true +- Bugfix + - Docking pads blocking rocket dismantle + - Space-to-launch only triggers on "down" press (fixes heavy modpacks) + - Negative/null weather timers crash + - Observatory databuses: type could become undefined; now keeps contents on deconstruction + - Observatory server scan + stale asteroid list fixes + - Rare NPE when starID changes / missing +- Tooltips + - Further polished +- Translations + - Chinese updated + - English polished + - Many hardcoded English strings fixed + -solved bugs: -https://github.com/dercodeKoenig/AdvancedRocketry/issues/63 -https://github.com/dercodeKoenig/AdvancedRocketry/issues/62 -https://github.com/dercodeKoenig/AdvancedRocketry/issues/57 -https://github.com/dercodeKoenig/AdvancedRocketry/issues/50 +Changelog 2.2.1-1: +-Terraforming Terminal: + - GUI: fixed header saying "Satellite Terminal" and polished text + - Hide internal RF Storage since it uses the satellites Power anyway (avoids confusion) +-Other + - Added more tooltips + - Polished tooltips from last update (thanks to Xonazeth!) Changelog 2.2.1: @@ -178,68 +175,71 @@ Changelog 2.2.1: - Tooltips added for ~98% of blocks/items. - JEI: CO2 Scrubber/Oxygen Vent, Fuel Station, Station Assembler. -Changelog 2.2.1-1: --Terraforming Terminal: - - GUI: fixed header saying "Satellite Terminal" and polished text - - Hide internal RF Storage since it uses the satellites Power anyway (avoids confusion) --Other - - Added more tooltips - - Polished tooltips from last update (thanks to Xonazeth!) +Changelog 2.2.0 +- JEI Integration + - Satellite Builder: +Satellites + - Satellite Builder: +ChipCopy -Changelog 2.2.2 +- Guidance Computer Access Hatch + - Fixed render glitch when emitting redstone -- New Blocks - - Orbital Registry - - Scans existing stations/starships/satellites, shows info, prints new chips - - Prevents losing the last chip / reduces need for backups - - Only checks current dimension - - Advanced Databus - - Works like DataUnit AND Databus - - Stores more data (less transceiver spaghetti / better performance for buffers) - - Keeps data when broken (NOT a "Satellite Component") +- Satellite Builder + - Rejects invalid items during assembly (soft-fixes crash with invalid core module) -- Rocket - - Added hint: "Press to open GUI" when riding rockets - - Added more error messages for failed launches - - Removed GUI header (fixes fullscreen overlap top left) - - Planet stat bars fixed +- Rocket Assembler + - GUI correctly updates error codes/messages to player + - Idle GC craziness SHOULD be fixed; lowered overall GC -- Warp Controller - - Reduced GC churn - - Removed GUI header (fixes fullscreen overlap top left) +- Station Assembler + - No more "rocket already assembled"; now shows specific failure (e.g., invalid launchpad) + - Correctly updates error codes to client/GUI + - Safer logic; fewer user errors -- Terraforming Terminal - - No Controller = true idle +- Satellite Terminal + - No more broadcasting UI updates to everyone in 16-block radius + - Send UI data only to actual viewer (less network churn / DDOS-y behavior) + - Downloading data requires power; one-time "Download" button -- Orbital Laser Drill - - laserDrillPlanet=false: simpler GUI + "void cobble" toggle (huge performance boost) - - Early-outs when not constructed / no redstone etc (idle = idle) +- Wireless Transceiver + - Operations throttled to once per 20 ticks; multiple units are phased (don’t run same tick) + - Enable/disable actually turns it off + - GUI shows Network ID so you can verify which plug is connected + - Plugs place on targeted face; top & bottom faces valid + - Extract button toggles insert/extract + - Extract button auto-pulls from satellite to Satellite Terminal internal storage + - NOTE: Still has 100 internal data storage; not voided—stuck in transit if nowhere to go -- Station Controllers - - GUI shows if station is anchored +- Observatory + - Scrollbar won't reset when selecting an asteroid (may not work with modded container overrides) + - Mousewheel asteroid scrolling + - Process button tooltip explains why it’s not working (when observatory isn’t open) + - Asteroid Chips: + - Improved tooltips/names; choices closer to loot (kept old randomizer logic) + - Fix: chips no longer share same name until “New scan” -- Rocket Loader/Unloader + Fluid Loader/Unloader - - Accepts most modded tanks/inventories - - Added explanation for the 6 squares in GUI +- Rocket Monitor + - Stopped 20x/second polling + - Redstone now event-based (onNeighborChange) + - Fuel/height via rocket entity (delays: fuel 5 ticks, height 3 ticks) -- Config - - nuclearRocketsRespectArtifactGating=true - - EnableOrbitalRegistry=true +- Fuel Station + - Stopped all 20x/second behavior + - Early bailout logic to truly idle when idle + - Fix: mono tank could be filled with H2/O2 for 0 burn → infinite free launches + - Safe against overfilling/voiding -- Bugfix - - Docking pads blocking rocket dismantle - - Space-to-launch only triggers on "down" press (fixes heavy modpacks) - - Negative/null weather timers crash - - Observatory databuses: type could become undefined; now keeps contents on deconstruction - - Observatory server scan + stale asteroid list fixes - - Rare NPE when starID changes / missing +- Rocket Entity + - GUI shows oxidizer bar only if oxidizer tank exists + - On dimension change: preloads 3×3 chunks for 60s from Launch event (reduces desync) -- Tooltips - - Further polished -- Translations - - Chinese updated - - English polished - - Many hardcoded English strings fixed + + + +solved bugs: +https://github.com/dercodeKoenig/AdvancedRocketry/issues/63 +https://github.com/dercodeKoenig/AdvancedRocketry/issues/62 +https://github.com/dercodeKoenig/AdvancedRocketry/issues/57 +https://github.com/dercodeKoenig/AdvancedRocketry/issues/50 From 4aa95229a2de4240bf954b91aa3299a17595befb Mon Sep 17 00:00:00 2001 From: ZetaY <34602681+ZHAY10086@users.noreply.github.com> Date: Thu, 18 Dec 2025 21:05:06 +0800 Subject: [PATCH 392/424] Update zh_CN.lang --- .../assets/advancedrocketry/lang/zh_CN.lang | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index 0d62703a9..d3383291e 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -307,7 +307,7 @@ msg.observetory.text.observabledistance=可观测距离: msg.observetory.text.missionTime=任务时间: msg.observetory.text.time=时间: msg.observetory.req.open=瞭望台必须满足开放条件(夜晚、天气晴朗、可观测天空)或位于空间站中! -msg.observetory.print.already=此小行星已存在对应芯片! +msg.observetory.print.already=你已为此小行星写入了一个芯片! # Atmosphere detector GUI labels msg.atmosphere.air=正常空气 @@ -381,9 +381,9 @@ msg.guidanceComputerHatch.ejectonstationlanding=允许弹出空间站芯片 msg.guidanceComputerHatch.link=已将流体装载器写入链接器,位置: msg.fluidLoader.loadingState=装载状态: msg.fluidLoader.allowLoading=允许装载: -msg.fluidLoader.allowredstoneinput=允许红石输入 -msg.fluidLoader.allowredstoneoutput=允许红石输出 -msg.fluidLoader.none=无 +msg.fluidLoader.allowredstoneinput=红石输入(红色) +msg.fluidLoader.allowredstoneoutput=红石输出(蓝色) +msg.fluidLoader.none=已禁用(绿色) msg.fluidLoader.link=已将流体装载器写入链接器,位置: msg.rocketLoader.loadingState=装载状态: msg.rocketLoader.allowLoading=允许装载: @@ -457,12 +457,13 @@ msg.stationgravctrl.tgtalt=目标重力: msg.stationgravctrl.alt=人造重力: msg.stationorientctrl.alt=角速度: msg.stationorientctrl.tgtalt=目标角速度: +msg.station.anchored=§c已锚定! msg.warpmon.tab.warp=跃迁选择 msg.warpmon.tab.data=数据 msg.warpmon.tab.tracking=星球追踪 msg.warpmon.selectplanet=选择星球 msg.warpmon.corestatus=核心状态: -msg.warpmon.anchored=空间站已锚定! +msg.warpmon.anchored=已锚定! msg.warpmon.nowhere=无可用目的地 msg.warpmon.missingart=缺少工件 msg.warpmon.ready=就绪! @@ -1310,7 +1311,9 @@ tooltip.advancedrocketry.railgun.alt.1=“轨道炮的威力不足以在行星 # Space Elevator Controller tooltip.advancedrocketry.spaceelevatorctrl=用于控制太空电梯 tooltip.advancedrocketry.spaceelevatorctrl.shift.1=§b使用全息投影器! - +tooltip.advancedrocketry.spaceelevatorctrl.shift.2=§f锚定太空站 +tooltip.advancedrocketry.spaceelevatorctrl.alt.1=§f星球端需要上方有空气,空间站端需要下方有空气 +tooltip.advancedrocketry.spaceelevatorctrl.alt.2=§c使用链接器 # Atmosphere Terraformer tooltip.advancedrocketry.atmosterraformer=改变整颗星球的大气压 tooltip.advancedrocketry.atmosterraformer.shift.1=§b使用全息投影器! @@ -1408,4 +1411,4 @@ tooltip.advancedrocketry.circuitplate=§3合成用物品 tooltip.advancedrocketry.circuitic=§3合成用物品 tooltip.advancedrocketry.miscpart=§3合成用物品 tooltip.advancedrocketry.itemlens=§3合成用物品 -tooltip.advancedrocketry.misc=§3合成用物品 \ No newline at end of file +tooltip.advancedrocketry.misc=§3合成用物品 From f9b2fb497920f403c89726bb44698361491734c5 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Thu, 18 Dec 2025 14:06:30 +0100 Subject: [PATCH 393/424] Update changelog with launch issue fix details --- changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 6fce3bad6..db7bc5302 100644 --- a/changelog.md +++ b/changelog.md @@ -40,7 +40,7 @@ Changelog 2.2.2 - Bugfix - Docking pads blocking rocket dismantle - - Space-to-launch only triggers on "down" press (fixes heavy modpacks) + - Space-to-launch only triggers on "down" press (fixes heavy modpacks launching issues) - Negative/null weather timers crash - Observatory databuses: type could become undefined; now keeps contents on deconstruction - Observatory server scan + stale asteroid list fixes From f03f0cba7906dfec5d04f92284892013f946bb61 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Fri, 19 Dec 2025 09:29:08 +0100 Subject: [PATCH 394/424] Fix observatory databuses type handling in changelog --- changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index db7bc5302..2231fe6a6 100644 --- a/changelog.md +++ b/changelog.md @@ -42,7 +42,7 @@ Changelog 2.2.2 - Docking pads blocking rocket dismantle - Space-to-launch only triggers on "down" press (fixes heavy modpacks launching issues) - Negative/null weather timers crash - - Observatory databuses: type could become undefined; now keeps contents on deconstruction + - Observatory databuses: type could become LOCKED as undefined; now keeps contents on deconstruction - Observatory server scan + stale asteroid list fixes - Rare NPE when starID changes / missing From 5dfc9580fd367034c5075f14aed3da78059caf6a Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 20 Dec 2025 01:13:05 +0100 Subject: [PATCH 395/424] Implement chip planet info stamping Added functionality to stamp planet information onto chips based on satellite data. --- .../tile/TileOrbitalRegistry.java | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java b/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java index d6840c707..0eec16c08 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java @@ -125,6 +125,8 @@ public class TileOrbitalRegistry extends TileMultiPowerConsumer // Tab module (0 = satellites, 1 = stations) private final ModuleTab tabModule; + private static final String CHIP_PLANET_NAME_KEY = "name"; + private static class SatEntry { long id; int dimId; @@ -163,6 +165,24 @@ public TileOrbitalRegistry() { ); } + + private void stampChipPlanetInfo(@Nonnull ItemStack stack, @Nonnull SatelliteBase sat) { + if (stack.isEmpty()) return; + + NBTTagCompound nbt = stack.getTagCompound(); + if (nbt == null) nbt = new NBTTagCompound(); + + int dimId = sat.getDimensionId(); + nbt.setInteger("dimId", dimId); + + DimensionProperties props = + zmaster587.advancedRocketry.dimension.DimensionManager.getInstance().getDimensionProperties(dimId); + if (props != null) { + nbt.setString(CHIP_PLANET_NAME_KEY, props.getName()); + } + + stack.setTagCompound(nbt); + } /* ------------------------------------------------------------------------ * Multiblock basics * --------------------------------------------------------------------- */ @@ -191,16 +211,14 @@ public String getMachineName() { * --------------------------------------------------------------------- */ private int getEffectiveSatDim() { - if (world == null) { - return satDimId; - } + if (world == null) return satDimId; + int eff = DimensionManager.getEffectiveDimId(world, pos).getId(); - if (satDimId == 0) { - satDimId = eff; - } - return satDimId; + satDimId = eff; + return eff; } + // Blacklist for "satellites" that should not appear in the orbital registry private static final java.util.Set SAT_BLACKLIST = java.util.Collections.unmodifiableSet( @@ -275,7 +293,7 @@ private void rescanSatellites() { continue; } /* UNCOMMENT TO EXCLUDE MISSIONS FROM ORBITAL REGISTRY - BLACKLIST OVER SHOULD HOLD FOR NOW + ,but BLACKLIST OVER SHOULD HOLD FOR NOW if (sat instanceof zmaster587.advancedRocketry.api.IMission) { continue; } @@ -560,6 +578,7 @@ private void writeSatelliteChipFromSelection() { } scanner.setSatelliteID(source, selectedSatId); + stampChipPlanetInfo(source, sat); setInventorySlotContents(SLOT_CHIP_OUT, source); markDirty(); @@ -574,6 +593,7 @@ private void writeSatelliteChipFromSelection() { } ItemStack programmed = sat.getControllerItemStack(source, props); + stampChipPlanetInfo(programmed, sat); setInventorySlotContents(SLOT_CHIP_OUT, programmed); markDirty(); From 44138d623ce3e930913c2980d249a5c31c3cde7f Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 20 Dec 2025 01:14:30 +0100 Subject: [PATCH 396/424] Refactor energy transmission and dimension ID methods --- .../satellite/SatelliteMicrowaveEnergy.java | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteMicrowaveEnergy.java b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteMicrowaveEnergy.java index e7065c46b..d69999837 100644 --- a/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteMicrowaveEnergy.java +++ b/src/main/java/zmaster587/advancedRocketry/satellite/SatelliteMicrowaveEnergy.java @@ -48,20 +48,30 @@ public double failureChance() { } @Override - public int getEnergyMTU(EnumFacing side) { - return (int) (ARConfiguration.getCurrentConfig().microwaveRecieverMulitplier * battery.extractEnergy(battery.getMaxEnergyStored(), false)); + public void setDimensionId(World world) { + super.setDimensionId(world); } @Override - public void setDimensionId(World world) { - super.setDimensionId(world); + public int getEnergyMTU(EnumFacing side) { + return transmitEnergy(side, true); } @Override public int transmitEnergy(EnumFacing dir, boolean simulate) { - return getEnergyMTU(EnumFacing.DOWN); + + // cap by generation per tick (after upkeep) + int genPerTick = Math.max(0, getPowerPerTick() - 1); + + int maxSend = (int)Math.round( + ARConfiguration.getCurrentConfig().microwaveRecieverMulitplier * genPerTick + ); + + return battery.extractEnergy(maxSend, simulate); } + + @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); From 6b0f947a40e04ac763db7d5712297cca42630efd Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 20 Dec 2025 10:58:16 +0100 Subject: [PATCH 397/424] Add dataBusBigMultiplier configuration property --- .../java/zmaster587/advancedRocketry/api/ARConfiguration.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/api/ARConfiguration.java b/src/main/java/zmaster587/advancedRocketry/api/ARConfiguration.java index 33122417a..cd56c0681 100644 --- a/src/main/java/zmaster587/advancedRocketry/api/ARConfiguration.java +++ b/src/main/java/zmaster587/advancedRocketry/api/ARConfiguration.java @@ -69,6 +69,8 @@ public class ARConfiguration { public double asteroidTBIBurnMult = 1.0; @ConfigProperty(needsSync = true) public double warpTBIBurnMult = 10.0; + @ConfigProperty(needsSync = true) + public int dataBusBigMultiplier = 4; @ConfigProperty public int MoonId = Constants.INVALID_PLANET; @ConfigProperty(needsSync = true) @@ -374,6 +376,7 @@ public static void loadPreInit() { arConfig.blockTankCapacity = (float) config.get(Configuration.CATEGORY_GENERAL, "blockTankCapacity", 1.0f, "Multiplier for the pressurized tank's (block) capacity", 0, Float.MAX_VALUE).getDouble(); arConfig.blockEnergyHatchCapacityMultiplier = (float) config.get(Configuration.CATEGORY_GENERAL, "blockEnergyHatchCapacityMultiplier", 1.0f, "Multiplier for the energy hatch capacity", 0, Float.MAX_VALUE).getDouble(); arConfig.blockLiquidHatchCapacityMultiplier = (float) config.get(Configuration.CATEGORY_GENERAL, "blockLiquidHatchCapacityMultiplier", 1.0f, "Multiplier for the liquid hatch (in/out) capacity", 0, Float.MAX_VALUE).getDouble(); + arConfig.dataBusBigMultiplier = config.getInt("dataBusBigMultiplier", Configuration.CATEGORY_GENERAL, 4, 1, 20, "Multiplier applied to the Data Bus (Big) max data capacity. (Base=2000 -> default= 4 * 2000 = 8000)"); //Enriched Lava in the centrifuge arConfig.lavaCentrifugeOutputs = config.getStringList("lavaCentrifugeOutputs", Configuration.CATEGORY_GENERAL, new String[]{"nuggetCopper:100", "nuggetIron:100", "nuggetTin:100", "nuggetLead:100", "nuggetSilver:100", "nuggetGold:75", "nuggetDiamond:10", "nuggetUranium:10", "nuggetIridium:1"}, "Outputs and chances of objects from Enriched Lava in the Centrifuge. Format: :. Larger weights are more frequent"); @@ -529,7 +532,6 @@ public static void loadPreInit() { arConfig.generateVolcanos = config.get(WORLDGEN, "generateVolcanos", true, "If true then very hot planets planets will volcanos. Note: setting this option to false overrides 'generateVolcanos' in the planetDefs.xml").getBoolean(); arConfig.generateVanillaStructures = config.getBoolean("generateVanillaStructures", WORLDGEN, false, "Enable to allow structures like villages and mineshafts to generate on planets with a breathable atmosphere. Note, setting this to false will override 'generateStructures' in the planetDefs.xml"); - //Load laser dimid blacklists for (String s : str) { From c7efdd315205806f2a12f8cda47ab6821ba45fa5 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 20 Dec 2025 10:58:49 +0100 Subject: [PATCH 398/424] Replace static multiplier with configurable value Refactor TileDataBusBig to use configurable multiplier from ARConfiguration. --- .../tile/hatch/TileDataBusBig.java | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/hatch/TileDataBusBig.java b/src/main/java/zmaster587/advancedRocketry/tile/hatch/TileDataBusBig.java index e8854bba9..e1d0dc349 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/hatch/TileDataBusBig.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/hatch/TileDataBusBig.java @@ -1,10 +1,11 @@ package zmaster587.advancedRocketry.tile.hatch; import net.minecraft.nbt.NBTTagCompound; +import zmaster587.advancedRocketry.api.ARConfiguration; public class TileDataBusBig extends TileDataBus { - private static final int MULT = 4; + private static final int DEFAULT_MULT = 4; public TileDataBusBig() { super(); @@ -16,8 +17,27 @@ public TileDataBusBig(int number) { enforceBigCapacity(); } + private static int getConfiguredMultSafe() { + int mult = DEFAULT_MULT; + + try { + ARConfiguration cfg = ARConfiguration.getCurrentConfig(); + if (cfg != null) mult = cfg.dataBusBigMultiplier; + } catch (Throwable ignored) { + // If config isn't ready for any reason, fall back to default. + } + + if (mult < 1) mult = 1; + else if (mult > 20) mult = 20; + + return mult; + } + private void enforceBigCapacity() { - int max = BASE_MAX_DATA * MULT; + int mult = getConfiguredMultSafe(); + + long maxLong = (long) BASE_MAX_DATA * (long) mult; + int max = maxLong > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) maxLong; this.data.setMaxData(max); From 4715e6343c23d4e6ee436c6e8e9644060fc7cfd3 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 20 Dec 2025 10:59:34 +0100 Subject: [PATCH 399/424] Replace I18n.format with I18n.translateToLocalFormatted keep servers alive --- .../modules/ModulePlanetSelector.java | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModulePlanetSelector.java b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModulePlanetSelector.java index f453c8857..24a192f66 100644 --- a/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModulePlanetSelector.java +++ b/src/main/java/zmaster587/advancedRocketry/inventory/modules/ModulePlanetSelector.java @@ -8,11 +8,11 @@ import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; -import net.minecraft.client.resources.I18n; import net.minecraft.inventory.Container; import net.minecraft.inventory.IContainerListener; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.text.translation.I18n; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -105,17 +105,18 @@ public ModulePlanetSelector(int planetId, ResourceLocation backdrop, ISelectionN stellarView = false; staticModuleList.add(new ModuleButton(0, 0, Constants.INVALID_PLANET, - I18n.format("msg.advancedrocketry.planetselector.up"), + I18n.translateToLocal("msg.advancedrocketry.planetselector.up"), this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); staticModuleList.add(new ModuleButton(0, 18, Constants.INVALID_PLANET + 1, - I18n.format("msg.advancedrocketry.planetselector.select"), + I18n.translateToLocal("msg.advancedrocketry.planetselector.select"), this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); staticModuleList.add(new ModuleButton(0, 36, Constants.INVALID_PLANET + 2, - I18n.format("msg.advancedrocketry.planetselector.planet.list"), + I18n.translateToLocal("msg.advancedrocketry.planetselector.planet.list"), this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild)); + ModuleDualProgressBar progressBar; staticModuleList.add(progressBar = new ModuleDualProgressBar(100, 0, 0, @@ -218,9 +219,9 @@ private void renderGalaxyMap(IGalaxy galaxy, int posX, int posY, float distanceZ "", this, new ResourceLocation[]{star2.isBlackHole() ? TextureResources.locationBlackHole_icon : TextureResources.locationSunNew}, - I18n.format("msg.advancedrocketry.planetselector.star.tooltip.name", star2.getName()) + I18n.translateToLocalFormatted("msg.advancedrocketry.planetselector.star.tooltip.name", star2.getName()) + "\n" + - I18n.format("msg.advancedrocketry.planetselector.star.tooltip.number.of.planets", star.getNumPlanets()), + I18n.translateToLocalFormatted("msg.advancedrocketry.planetselector.star.tooltip.number.of.planets", star.getNumPlanets()), displaySize, displaySize)); button.setSound("buttonBlipA"); @@ -235,9 +236,9 @@ private void renderGalaxyMap(IGalaxy galaxy, int posX, int posY, float distanceZ "", this, new ResourceLocation[]{star.isBlackHole() ? TextureResources.locationBlackHole_icon : TextureResources.locationSunNew}, - I18n.format("msg.advancedrocketry.planetselector.star.tooltip.name", star.getName()) + I18n.translateToLocalFormatted("msg.advancedrocketry.planetselector.star.tooltip.name", star.getName()) + "\n" + - I18n.format("msg.advancedrocketry.planetselector.star.tooltip.number.of.planets", star.getNumPlanets()), + I18n.translateToLocalFormatted("msg.advancedrocketry.planetselector.star.tooltip.number.of.planets", star.getNumPlanets()), displaySize, displaySize)); @@ -278,9 +279,9 @@ private void renderStarSystem(StellarBody star, int posX, int posY, float distan "", this, new ResourceLocation[]{star2.isBlackHole() ? TextureResources.locationBlackHole_icon : TextureResources.locationSunNew}, - I18n.format("msg.advancedrocketry.planetselector.star.tooltip.name", star2.getName()) + I18n.translateToLocalFormatted("msg.advancedrocketry.planetselector.star.tooltip.name", star2.getName()) + "\n" + - I18n.format("msg.advancedrocketry.planetselector.star.tooltip.number.of.planets", star.getNumPlanets()), + I18n.translateToLocalFormatted("msg.advancedrocketry.planetselector.star.tooltip.number.of.planets", star.getNumPlanets()), displaySize, displaySize )); @@ -299,9 +300,9 @@ private void renderStarSystem(StellarBody star, int posX, int posY, float distan "", this, new ResourceLocation[]{star.isBlackHole() ? TextureResources.locationBlackHole_icon : TextureResources.locationSunNew}, - I18n.format("msg.advancedrocketry.planetselector.star.tooltip.name", star.getName()) + I18n.translateToLocalFormatted("msg.advancedrocketry.planetselector.star.tooltip.name", star.getName()) + "\n" + - I18n.format("msg.advancedrocketry.planetselector.star.tooltip.number.of.planets", star.getNumPlanets()), + I18n.translateToLocalFormatted("msg.advancedrocketry.planetselector.star.tooltip.number.of.planets", star.getNumPlanets()), displaySize, displaySize )); @@ -375,9 +376,9 @@ private void renderPlanets(DimensionProperties planet, int parentOffsetX, int pa planetList.add(button = new ModuleButtonPlanet( offsetX, offsetY, planet.getId(), "", this, planet, - I18n.format("msg.advancedrocketry.planetselector.planet.tooltip.name", planet.getName()) + I18n.translateToLocalFormatted("msg.advancedrocketry.planetselector.planet.tooltip.name", planet.getName()) + "\n" + - I18n.format("msg.advancedrocketry.planetselector.planet.tooltip.moons.count", planet.getChildPlanets().size()), + I18n.translateToLocalFormatted("msg.advancedrocketry.planetselector.planet.tooltip.moons.count", planet.getChildPlanets().size()), displaySize, displaySize)); button.setSound("buttonBlipA"); @@ -502,6 +503,7 @@ public void onMouseClicked(GuiModular gui, int x, int y, int button) { } @Override + @SideOnly(Side.CLIENT) public void renderForeground(int guiOffsetX, int guiOffsetY, int mouseX, int mouseY, float zLevel, GuiContainer gui, FontRenderer font) { super.renderForeground(guiOffsetX, guiOffsetY, mouseX, mouseY, zLevel, gui, From f3e001d537587a6a89fab6e43d282a3bbc18848b Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 20 Dec 2025 11:00:10 +0100 Subject: [PATCH 400/424] Improve satellite name localization in tooltip Updated satellite name handling to support translation. --- .../item/ItemSatelliteIdentificationChip.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemSatelliteIdentificationChip.java b/src/main/java/zmaster587/advancedRocketry/item/ItemSatelliteIdentificationChip.java index dc39132a1..c3cb9a4c6 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemSatelliteIdentificationChip.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemSatelliteIdentificationChip.java @@ -61,6 +61,8 @@ public void setSatellite(@Nonnull ItemStack stack, SatelliteBase satellite) { nbt.setString("satelliteName", satellite.getName()); nbt.setInteger("dimId", satellite.getDimensionId()); nbt.setLong("satelliteId", satellite.getId()); + + stack.setTagCompound(nbt); } /** @@ -127,7 +129,13 @@ public void addInformation(@Nonnull ItemStack stack, World player, List int worldId = getWorldId(stack); long satId = SatelliteRegistry.getSatelliteId(stack); - String satelliteName = getSatelliteName(stack); + String satelliteNameKey = getSatelliteName(stack); + String satelliteName = satelliteNameKey; + + // Translate if it's a lang key; if missing, translateToLocal returns the key + if (!satelliteNameKey.isEmpty()) { + satelliteName = net.minecraft.util.text.translation.I18n.translateToLocal(satelliteNameKey); + } if (satId != -1) { From cc681e578c040fe28c48724370e58f6e1cbb95e3 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 20 Dec 2025 11:00:47 +0100 Subject: [PATCH 401/424] Improve satellite item tooltip translation --- .../zmaster587/advancedRocketry/item/ItemSatellite.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java b/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java index 78fb03ce7..0f85dce74 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java @@ -106,7 +106,14 @@ public void addInformation(@Nonnull ItemStack stack, World world, List l int dataStorage, powerGeneration, powerStorage; float weight; - list.add(getName(stack)); + String display = getName(stack); // fallback (may be key) + SatelliteBase base = SatelliteRegistry.getNewSatellite(props.getSatelliteType()); + if (base != null) display = base.getName(); + + // translate if it’s a key; if not, returns input unchanged + display = net.minecraft.client.resources.I18n.format(display); + + list.add(display); list.add("ID: " + props.getId()); if (SatelliteProperties.Property.BATTERY.isOfType(props.getPropertyFlag())) { From 975ddb94dac528ee0dbd985ec16da05df47116ea Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 20 Dec 2025 11:01:40 +0100 Subject: [PATCH 402/424] Refactor NBT handling in ItemIdWithName class Refactor setName method to simplify NBT handling and improve addInformation method for translation --- .../advancedRocketry/item/ItemIdWithName.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemIdWithName.java b/src/main/java/zmaster587/advancedRocketry/item/ItemIdWithName.java index 308c366ff..1743f82b1 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemIdWithName.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemIdWithName.java @@ -15,12 +15,9 @@ public class ItemIdWithName extends Item { public void setName(@Nonnull ItemStack stack, String name) { - - if (stack.hasTagCompound()) { - NBTTagCompound nbt = stack.getTagCompound(); - nbt.setString("name", name); - stack.setTagCompound(nbt); - } + NBTTagCompound nbt = stack.hasTagCompound() ? stack.getTagCompound() : new NBTTagCompound(); + nbt.setString("name", name); + stack.setTagCompound(nbt); } public String getName(@Nonnull ItemStack stack) { @@ -38,8 +35,16 @@ public String getName(@Nonnull ItemStack stack) { public void addInformation(@Nonnull ItemStack stack, World player, List list, ITooltipFlag bool) { if (stack.getItemDamage() == -1) { list.add(ChatFormatting.GRAY + "Unprogrammed"); - } else { - list.add(getName(stack)); + return; } + + String keyOrName = getName(stack); + if (keyOrName == null || keyOrName.isEmpty()) { + return; + } + + // If it's a lang key, this becomes localized; if not, it returns the input unchanged. + String translated = net.minecraft.client.resources.I18n.format(keyOrName); + list.add(translated); } } From 728a3a5c466c7525ecdbfadbd1cbe143b46241a9 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 20 Dec 2025 11:02:36 +0100 Subject: [PATCH 403/424] Refactor artifact gating logic in EntityRocket --- .../advancedRocketry/entity/EntityRocket.java | 126 ++++++++---------- 1 file changed, 56 insertions(+), 70 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java b/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java index 740c377ee..952544266 100644 --- a/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java +++ b/src/main/java/zmaster587/advancedRocketry/entity/EntityRocket.java @@ -503,13 +503,6 @@ else if (!isInFlight()) return super.getTextOverlay(); } - // Artifact gating - private boolean isPlanetGated(DimensionProperties props) { - if (props == null) return false; - List req = props.getRequiredArtifacts(); - return req != null && !req.isEmpty(); - } - @Nullable private EntityPlayer getPilot() { for (Entity e : getPassengers()) { @@ -518,90 +511,78 @@ private EntityPlayer getPilot() { return null; } - private boolean pilotHasGateArtifacts(EntityPlayer pilot, DimensionProperties destProps) { - if (destProps == null) return false; + @Nonnull + private ItemStack getGateArtifact(@Nullable DimensionProperties destProps) { + if (destProps == null) return ItemStack.EMPTY; - List required = destProps.getRequiredArtifacts(); - if (required == null || required.isEmpty()) return true; + List req = destProps.getRequiredArtifacts(); + if (req == null || req.isEmpty()) return ItemStack.EMPTY; - for (ItemStack req : required) { - if (!hasRequiredStack(pilot, req)) return false; - } - return true; + // Contract: always exactly 1 artifact + return req.get(0); } - private boolean hasRequiredStack(EntityPlayer pilot, ItemStack req) { - if (req.isEmpty()) return true; + private boolean pilotHasArtifact(@Nullable EntityPlayer pilot, @Nonnull ItemStack req) { + if (pilot == null || req.isEmpty()) return false; - // main inventory - for (ItemStack have : pilot.inventory.mainInventory) { - if (matchesRequirement(have, req)) return true; - } - // armor - for (ItemStack have : pilot.inventory.armorInventory) { - if (matchesRequirement(have, req)) return true; - } - // offhand - for (ItemStack have : pilot.inventory.offHandInventory) { - if (matchesRequirement(have, req)) return true; - } + for (ItemStack have : pilot.inventory.mainInventory) if (matchesRequirement(have, req)) return true; + for (ItemStack have : pilot.inventory.armorInventory) if (matchesRequirement(have, req)) return true; + for (ItemStack have : pilot.inventory.offHandInventory) if (matchesRequirement(have, req)) return true; return false; } - private boolean matchesRequirement(ItemStack have, ItemStack req) { - return !have.isEmpty() - && have.getItem() == req.getItem() - && (req.getItemDamage() == OreDictionary.WILDCARD_VALUE - || have.getItemDamage() == req.getItemDamage()) - && have.getCount() >= req.getCount(); - } + private boolean matchesRequirement(@Nonnull ItemStack have, @Nonnull ItemStack req) { + if (have.isEmpty()) return false; + if (have.getItem() != req.getItem()) return false; - @Nullable - private ItemStack getFirstMissingGateArtifact(@Nullable EntityPlayer pilot, @Nullable DimensionProperties destProps) { - if (pilot == null || destProps == null) return null; + // meta / wildcard + int rMeta = req.getItemDamage(); + if (rMeta != OreDictionary.WILDCARD_VALUE && have.getItemDamage() != rMeta) return false; - List required = destProps.getRequiredArtifacts(); - if (required == null || required.isEmpty()) return null; + // OPTIONAL: require NBT match if your artifact uses NBT (uncomment if needed) + // if (req.hasTagCompound() && !NBTTagCompound.areNBTEquals(req.getTagCompound(), have.getTagCompound())) return false; - for (ItemStack req : required) { - if (!hasRequiredStack(pilot, req)) { - return req; - } - } - return null; + return have.getCount() >= req.getCount(); } - private String getGateArtifactError(@Nullable EntityPlayer pilot, @Nullable DimensionProperties destProps) { - String base = LibVulpes.proxy.getLocalizedString("error.rocket.gatedArtifactMissing"); - ItemStack missing = getFirstMissingGateArtifact(pilot, destProps); - if (missing == null || missing.isEmpty()) return base; + + private static String packReason(String key, Object... args) { + if (args == null || args.length == 0) return key; - // Keep it simple: show the in-game display name - return base + ": " + missing.getCount() + "x " + missing.getDisplayName(); + StringBuilder sb = new StringBuilder(key); + for (Object a : args) { + sb.append('|'); + String s = String.valueOf(a); + // Avoid breaking the delimiter if an arg contains '|' + sb.append(s.replace("|", "/")); + } + return sb.toString(); } - - private void setError(String error) { - this.errorStr = error; + private void setError(String key, Object... args) { + this.errorStr = key; this.lastErrorTime = this.world.getTotalWorldTime(); if (!world.isRemote) { - // notify riders only for (Entity e : this.getPassengers()) { if (e instanceof EntityPlayerMP) { - ((EntityPlayerMP) e).sendMessage(new TextComponentString(error)); + ((EntityPlayerMP) e).sendMessage( + new net.minecraft.util.text.TextComponentTranslation(key, args) + ); } } - // post an event the monitor already consumes - MinecraftForge.EVENT_BUS.post(new RocketEvent.RocketAbortEvent(this, error)); - // stop countdown if it was running + // send key + args to monitoring station + String packed = packReason(key, args); + MinecraftForge.EVENT_BUS.post(new RocketEvent.RocketAbortEvent(this, packed)); + this.dataManager.set(LAUNCH_COUNTER, -1); } } + @Override public void setPosition(double x, double y, double z) { @@ -2092,7 +2073,7 @@ public void launch() { destinationDimId = storage.getDestinationDimId(world.provider.getDimension(), (int) this.posX, (int) this.posZ); if (!(DimensionManager.getInstance().canTravelTo(destinationDimId) || (destinationDimId == Constants.INVALID_PLANET && storage.getSatelliteHatches().size() != 0))) { - setError(LibVulpes.proxy.getLocalizedString("error.rocket.cannotGetThere")); + setError("error.rocket.cannotGetThere"); return; } @@ -2107,7 +2088,7 @@ public void launch() { if (spaceObject != null) finalDest = spaceObject.getOrbitingPlanetId(); else { - setError(LibVulpes.proxy.getLocalizedString("error.rocket.destinationNotExist")); + setError("error.rocket.destinationNotExist"); return; } } @@ -2138,24 +2119,29 @@ public void launch() { } // Artifact gating: only when arriving from outside the planetary system - if (enforceGating && isPlanetGated(destProps) && outsidePlanetarySystem) { + ItemStack artifact = getGateArtifact(destProps); + + if (enforceGating && !artifact.isEmpty() && outsidePlanetarySystem) { EntityPlayer pilot = getPilot(); - if (pilot == null || !pilotHasGateArtifacts(pilot, destProps)) { - setError(getGateArtifactError(pilot, destProps)); + if (!pilotHasArtifact(pilot, artifact)) { + setError("error.rocket.gatedArtifactMissingWithItem", + artifact.getCount(), + artifact.getDisplayName()); return; } } + // Nuclear cannot cross stars if (isNuclear && !sameStar) { - setError(LibVulpes.proxy.getLocalizedString("error.rocket.outsideStarSystem")); + setError("error.rocket.outsideStarSystem"); return; } // Non-nuclear cannot go outside planetary system if (!isNuclear && outsidePlanetarySystem) { - setError(LibVulpes.proxy.getLocalizedString("error.rocket.outsidePlanetarySystem")); + setError("error.rocket.outsidePlanetarySystem"); return; } } @@ -2163,7 +2149,7 @@ public void launch() { if (this.stats.getWeight() >= this.stats.getThrust()) { - setError(LibVulpes.proxy.getLocalizedString("error.rocket.tooHeavy")); + setError("error.rocket.tooHeavy"); return; // hard stop; no silent fall-through } @@ -2173,7 +2159,7 @@ public void launch() { // Enough fuel for the mission? if (!hasMissionFuelFor(destinationDimId)) { - setError(LibVulpes.proxy.getLocalizedString("error.rocket.notEnoughMissionFuel")); + setError("error.rocket.notEnoughMissionFuel"); return; } From 023588375c7932fbb71cc8d5d7a2b04cbea94114 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 20 Dec 2025 11:03:07 +0100 Subject: [PATCH 404/424] Implement getConnectedSatellitesLive method Added method to retrieve currently connected satellites. --- .../energy/TileMicrowaveReciever.java | 55 +++++++++---------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/energy/TileMicrowaveReciever.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/energy/TileMicrowaveReciever.java index 9ead1c15a..39f602d4f 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/energy/TileMicrowaveReciever.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/energy/TileMicrowaveReciever.java @@ -143,6 +143,25 @@ public void onInventoryUpdated() { connectedSatellites = new LinkedList<>(new LinkedHashSet<>(list)); } + private List getConnectedSatellitesLive() { + if (itemInPorts == null) return java.util.Collections.emptyList(); + + // refresh TE references (libVulpes replaces TEs during multiblock build/load) + List ports = getItemInPorts(); + + java.util.LinkedHashSet set = new java.util.LinkedHashSet<>(); + for (IInventory inv : ports) { + if (inv == null) continue; + for (int i = 0; i < inv.getSizeInventory(); i++) { + ItemStack stack = inv.getStackInSlot(i); + if (!stack.isEmpty() && stack.getItem() instanceof ItemSatelliteIdentificationChip) { + set.add(SatelliteRegistry.getSatelliteId(stack)); + } + } + } + return new java.util.ArrayList<>(set); + } + @Override public boolean attemptCompleteStructure(IBlockState state) { if (!world.isRemote) { @@ -188,7 +207,6 @@ public void update() { } //Checks whenever a station changes dimensions or when the multiblock is intialized - ie any time the multipler could concieveably change - // --- BEGIN mirror SatelliteTerminal style) --- final int curDim = world.provider.getDimension(); final int spaceDim = ARConfiguration.getCurrentConfig().spaceDimId; @@ -220,7 +238,6 @@ public void update() { } } // If we're in space but station==null (early ticks), keep previous multiplier and carry on. - // --- END robust insolation block --- if (!isComplete()) return; @@ -252,7 +269,6 @@ public void update() { } } - // --- BEGIN (mirrors SatelliteTerminal) --- final int dimId = world.provider.getDimension(); final boolean dimOk = DimensionManager.getInstance().isDimensionCreated(dimId) || dimId == 0; @@ -268,31 +284,27 @@ public void update() { int energyReceived = 0; - if (enabled && props != null && connectedSatellites != null && !connectedSatellites.isEmpty()) { - // Snapshot to avoid concurrent modification - final LinkedHashSet sats = new LinkedHashSet<>(connectedSatellites); - - // Resolve “here” dim exactly like SatelliteTerminal - final int hereDim = DimensionManager.getEffectiveDimId(world, pos).getId(); + final List sats = enabled && props != null ? getConnectedSatellitesLive() : java.util.Collections.emptyList(); + if (!sats.isEmpty()) { for (long lng : sats) { final SatelliteBase sat = props.getSatellite(lng); if (sat == null) continue; - // Range/link check (same logic as Terminal) final int satDim = sat.getDimensionId(); - final boolean inRange = PlanetaryTravelHelper.isTravelAnywhereInPlanetarySystem(satDim, hereDim); - if (!inRange) continue; + final int hereDim = DimensionManager.getEffectiveDimId(world, pos).getId(); + if (!PlanetaryTravelHelper.isTravelAnywhereInPlanetarySystem(satDim, hereDim)) continue; if (sat instanceof IUniversalEnergyTransmitter) { energyReceived += ((IUniversalEnergyTransmitter) sat).transmitEnergy(EnumFacing.UP, false); } } - // 520W = 1 RF/t -> 2 RF/t @ 100%; scale by insolation - energyReceived = (int) Math.round(energyReceived * (2 * insolationPowerMultiplier)); + // scale by insolation (your existing logic) + energyReceived = (int)Math.round(energyReceived * (2 * insolationPowerMultiplier)); } + powerMadeLastTick = energyReceived; if (powerMadeLastTick != prevPowerMadeLastTick) { @@ -378,14 +390,6 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompou public NBTTagCompound writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); - // ---- satellites ---- - int[] intArray = new int[connectedSatellites.size() * 2]; - for (int i = 0; i < connectedSatellites.size() * 2; i += 2) { - intArray[i] = (connectedSatellites.get(i / 2)).intValue(); - intArray[i+1] = (int)((connectedSatellites.get(i / 2) >>> 32)); - } - nbt.setIntArray("satilliteList", intArray); - // ---- saved hatch inventories ---- NBTTagList hatchList = new NBTTagList(); if (savedHatchInv != null && !savedHatchInv.isEmpty()) { @@ -416,13 +420,6 @@ public NBTTagCompound writeToNBT(NBTTagCompound nbt) { public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); - // ---- satellites ---- - int[] intArray = nbt.getIntArray("satilliteList"); - connectedSatellites.clear(); - for (int i = 0; i < intArray.length; i += 2) { - connectedSatellites.add(intArray[i] | (((long) intArray[i + 1]) << 32)); - } - // ---- saved hatch inventories ---- savedHatchInv.clear(); From c6a5771bf8ecfa8151170208f27732b9bf24eb22 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 20 Dec 2025 11:04:29 +0100 Subject: [PATCH 405/424] Remove unnecessary comment in TileSatelliteTerminal --- .../advancedRocketry/tile/satellite/TileSatelliteTerminal.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java index a76a5f428..7128f0605 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/satellite/TileSatelliteTerminal.java @@ -453,7 +453,6 @@ public void onChunkUnload() { nextAutoDlTick = 0L; } - // Clear caches if the block/TE is invalidated (broken/replaced) @Override public void invalidate() { super.invalidate(); From 691354ace9276416c58e911a30ef6bc7cbf3f4a5 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 20 Dec 2025 11:05:07 +0100 Subject: [PATCH 406/424] Fix missing newline at end of TileOrbitalRegistry.java Added a newline at the end of the file for consistency. From afb8b9cce73fbc3b563be204ee68bba990c5d28b Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 20 Dec 2025 11:07:34 +0100 Subject: [PATCH 407/424] Add error message for missing required artifact Added a new error message for missing artifacts in player inventory. --- src/main/resources/assets/advancedrocketry/lang/en_US.lang | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index 57ed3fe06..a70de16a2 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -246,6 +246,7 @@ error.rocket.destinationNotExist=Selected space station does not exist. error.rocket.partsWornOut=Critical parts are worn out — launch aborted. error.rocket.aborted=Launch aborted. error.rocket.gatedArtifactMissing=Missing Artifact. (Player Inventory) +error.rocket.gatedArtifactMissingWithItem=Missing required artifact: %sx %s (Player Inventory) error.rocket.outsideStarSystem=Interstellar travel requires a Starship. error.rocket.outsidePlanetarySystem=Planetary travel requires a Nuclear Rocket. From 079a90861d12730fe818a1e3dd387041e325e20d Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 20 Dec 2025 11:08:46 +0100 Subject: [PATCH 408/424] Refactor ItemBlockDataBusBig for dynamic max data Refactor data handling in ItemBlockDataBusBig to use configurable multiplier and compute max data dynamically. --- .../item/ItemBlockDataBusBig.java | 32 +++++++++++++++++-- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemBlockDataBusBig.java b/src/main/java/zmaster587/advancedRocketry/item/ItemBlockDataBusBig.java index 44f0aac21..9e8f465fa 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemBlockDataBusBig.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemBlockDataBusBig.java @@ -15,6 +15,7 @@ import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import zmaster587.advancedRocketry.api.ARConfiguration; import zmaster587.advancedRocketry.api.DataStorage; import zmaster587.advancedRocketry.tile.hatch.TileDataBusBig; @@ -25,7 +26,8 @@ public class ItemBlockDataBusBig extends ItemBlock implements IDataItem { // Keep this local and explicit - private static final int BIG_MAX_DATA = 2000 * 4; + private static final int BASE_MAX_DATA = 2000; // match TileDataBus base + private static final int DEFAULT_MULT = 4; public ItemBlockDataBusBig(Block block) { super(block); @@ -35,11 +37,33 @@ public ItemBlockDataBusBig(Block block) { // ---- IDataItem ---- + private static int getConfiguredMultSafe() { + int mult = DEFAULT_MULT; + + try { + ARConfiguration cfg = ARConfiguration.getCurrentConfig(); + if (cfg != null) mult = cfg.dataBusBigMultiplier; + } catch (Throwable ignored) {} + + if (mult < 1) mult = 1; + else if (mult > 20) mult = 20; + + return mult; + } + + private static int computeMaxData() { + int mult = getConfiguredMultSafe(); + long maxLong = (long) BASE_MAX_DATA * (long) mult; + return maxLong > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) maxLong; + } + @Override public int getMaxData(@Nonnull ItemStack stack) { - return BIG_MAX_DATA; + return computeMaxData(); } + + @Override @Nonnull public DataStorage getDataStorage(@Nonnull ItemStack stack) { @@ -118,7 +142,9 @@ public boolean placeBlockAt(ItemStack stack, EntityPlayer player, World world, B NBTTagCompound tag = stack.getTagCompound(); if (tag != null) { - bus.getDataObject().readFromNBT(tag); + NBTTagCompound teTag = bus.writeToNBT(new NBTTagCompound()); + teTag.merge(tag); + bus.readFromNBT(teTag); bus.markDirty(); world.notifyBlockUpdate(pos, newState, newState, 3); } From f060029388206903ab02b885187c53f9d003ec3b Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 20 Dec 2025 11:09:29 +0100 Subject: [PATCH 409/424] Add client-side translation for abort reasons --- .../TileRocketMonitoringStation.java | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java index 4583bf22d..5a29505f1 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/infrastructure/TileRocketMonitoringStation.java @@ -14,6 +14,7 @@ import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.eventhandler.EventPriority; @@ -950,6 +951,41 @@ public String getModularInventoryName() { return "container.monitoringstation"; } + @SideOnly(Side.CLIENT) + private static String trAbortReason(String raw) { + if (raw == null || raw.isEmpty()) return ""; + + // Support "key|arg1|arg2" (easy to emit server-side) + final String delim = "|"; + String key = raw; + Object[] args = null; + + if (raw.indexOf(delim) >= 0) { + String[] parts = raw.split("\\|", -1); + if (parts.length > 0) { + key = parts[0]; + if (parts.length > 1) { + args = new Object[parts.length - 1]; + System.arraycopy(parts, 1, args, 0, args.length); + } + } + } + + String out; + if (args != null) { + out = net.minecraft.util.text.translation.I18n.translateToLocalFormatted(key, args); + } else { + out = net.minecraft.util.text.translation.I18n.translateToLocal(key); + } + + // If missing, vanilla returns the key unchanged — fall back to original raw + if (out == null || out.isEmpty() || out.equals(key)) { + return raw; + } + return out; + } + + @Override public float getNormallizedProgress(int id) { if (world.isRemote) { @@ -966,8 +1002,12 @@ public float getNormallizedProgress(int id) { case 3: header = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.orbit"); break; case 4: header = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.deorbiting"); break; case 5: header = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.landed"); break; - case 6: header = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.aborted"); - if (lastAbortReason != null && !lastAbortReason.isEmpty()) {detail = lastAbortReason;} break; + case 6: + header = LibVulpes.proxy.getLocalizedString("msg.monitoringStation.aborted"); + if (lastAbortReason != null && !lastAbortReason.isEmpty()) { + detail = trAbortReason(lastAbortReason); + } + break; default: header = ""; } From 47ae828a3bc7ed6e6aa70a0882b4927a1aa53912 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 20 Dec 2025 13:11:04 +0100 Subject: [PATCH 410/424] Add generatesData field to satellite entries Added generatesData field to satellite entries and updated serialization. --- .../tile/TileOrbitalRegistry.java | 44 +++++++++++++++++-- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java b/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java index 0eec16c08..e49b23820 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java @@ -21,6 +21,7 @@ import zmaster587.advancedRocketry.item.ItemOreScanner; import zmaster587.advancedRocketry.item.ItemSatelliteIdentificationChip; import zmaster587.advancedRocketry.item.ItemStationChip; +import zmaster587.advancedRocketry.satellite.SatelliteData; import zmaster587.advancedRocketry.stations.SpaceObjectManager; import zmaster587.advancedRocketry.stations.SpaceStationObject; import zmaster587.advancedRocketry.util.StationLandingLocation; @@ -134,6 +135,7 @@ private static class SatEntry { int powerGen; int powerStorage; long maxData; + boolean generatesData; } private static class StationEntry { @@ -209,7 +211,17 @@ public String getMachineName() { /* ------------------------------------------------------------------------ * Helpers / scans * --------------------------------------------------------------------- */ + private static int calcCollectionTimeTicks(int powerGeneration) { + if (powerGeneration <= 0) return 0; + int ct = (int) (200.0 / Math.sqrt(0.1 * (double) powerGeneration)); + return (ct == 0) ? 200 : ct; + } + private static double calcDataPerSecond(int powerGeneration) { + int ct = calcCollectionTimeTicks(powerGeneration); + if (ct <= 0) return 0.0; + return 20.0 / (double) ct; + } private int getEffectiveSatDim() { if (world == null) return satDimId; @@ -218,7 +230,10 @@ private int getEffectiveSatDim() { return eff; } - + private int peekEffectiveSatDimForDisplay() { + if (world == null) return satDimId; + return DimensionManager.getEffectiveDimId(world, pos).getId(); + } // Blacklist for "satellites" that should not appear in the orbital registry private static final java.util.Set SAT_BLACKLIST = java.util.Collections.unmodifiableSet( @@ -260,7 +275,7 @@ private void rescanSatellites() { entry.powerGen = 0; entry.powerStorage = 0; entry.maxData = 0; - + entry.generatesData = (sat instanceof SatelliteData); try { zmaster587.advancedRocketry.api.satellite.SatelliteProperties sProps = sat.getProperties(); if (sProps != null) { @@ -809,10 +824,14 @@ public List getModules(int ID, EntityPlayer player) { LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.satellites"), 0x2d2d2d )); + String detailsLabel = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.details"); + String dimLabel = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.dimid"); + String detailsTitle = detailsLabel + " " + dimLabel + " " + peekEffectiveSatDimForDisplay(); + modules.add(new ModuleText( OBS_DETAIL_BASE_X - 5, 18, - LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.details"), + detailsTitle, 0x2d2d2d )); @@ -919,11 +938,13 @@ private void buildSatelliteDetailWindow(List modules, int startX, in modules.add(new ModuleText(x, y, typeLine, 0x2d2d2d)); y += 10; + /* Moved to header for now // ----- Dim: ----- String dimLabel = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.dimid"); // "Dim:" String dimLine = dimLabel + " " + selected.dimId; modules.add(new ModuleText(x, y, dimLine, 0x2d2d2d)); y += 10; + */ // ----- Orbiting: ----- String orbitLabel = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.orbit"); // "Orbiting:" @@ -954,6 +975,19 @@ private void buildSatelliteDetailWindow(List modules, int startX, in modules.add(new ModuleText(x, y, maxDataLabel + " " + selected.maxData, 0x2d2d2d)); y += 10; } + // ----- Data gen: ----- (only if meaningful) + if (selected.generatesData && selected.powerGen > 0 && selected.maxData > 0) { + double dps = calcDataPerSecond(selected.powerGen); + String dpsStr = String.format(java.util.Locale.ROOT, "%.3f", dps); + + String prefix = LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.text.sat.datagen"); + if (prefix == null || prefix.isEmpty() || prefix.equals("msg.orbitalregistry.text.sat.datagen")) { + prefix = "Data gen:"; + } + + modules.add(new ModuleText(x, y, prefix + " " + dpsStr + "/s", 0x2d2d2d)); + y += 10; + } } @@ -1293,7 +1327,7 @@ private void writeCommonNBT(NBTTagCompound nbt) { nbt.setLong("selectedSatId", selectedSatId); nbt.setInteger("lastStationButton", lastStationButton); nbt.setInteger("selectedStationId", selectedStationId); - + // Satellite cache NBTTagList satList = new NBTTagList(); for (SatEntry e : satCache) { @@ -1304,6 +1338,7 @@ private void writeCommonNBT(NBTTagCompound nbt) { tag.setInteger("powerGen", e.powerGen); tag.setInteger("powerStorage", e.powerStorage); tag.setLong("maxData", e.maxData); + tag.setBoolean("generatesData", e.generatesData); satList.appendTag(tag); } nbt.setTag("satCache", satList); @@ -1345,6 +1380,7 @@ private void readCommonNBT(NBTTagCompound nbt) { e.powerGen = tag.getInteger("powerGen"); e.powerStorage= tag.getInteger("powerStorage"); e.maxData = tag.getLong("maxData"); + e.generatesData = tag.getBoolean("generatesData"); satCache.add(e); } } From f6129ba1cec02833e3dfd798891784d8d2306907 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 20 Dec 2025 13:11:21 +0100 Subject: [PATCH 411/424] Add data generation calculations to ItemSatellite --- .../advancedRocketry/item/ItemSatellite.java | 59 ++++++++++++++++++- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java b/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java index 0f85dce74..0722498da 100644 --- a/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java +++ b/src/main/java/zmaster587/advancedRocketry/item/ItemSatellite.java @@ -8,12 +8,14 @@ import zmaster587.advancedRocketry.api.SatelliteRegistry; import zmaster587.advancedRocketry.api.satellite.SatelliteBase; import zmaster587.advancedRocketry.api.satellite.SatelliteProperties; +import zmaster587.advancedRocketry.satellite.SatelliteData; import zmaster587.libVulpes.LibVulpes; import zmaster587.libVulpes.util.EmbeddedInventory; import zmaster587.libVulpes.util.ZUtils; import javax.annotation.Nonnull; import java.util.List; +import java.util.Locale; public class ItemSatellite extends ItemIdWithName { @@ -21,6 +23,39 @@ public class ItemSatellite extends ItemIdWithName { private static final int FIRST_MOD_SLOT = 1; private static final int LAST_MOD_SLOT = 6; + /** + * Math from SatelliteData: + * collectionTime = (int) (200 / Math.sqrt(0.1 * powerConsumption)); + * and fallback: + * if (collectionTime == 0) collectionTime = 200; + */ + private static int calcCollectionTimeTicks(int powerGeneration) { + if (powerGeneration <= 0) return 0; + int ct = (int) (200.0 / Math.sqrt(0.1 * (double) powerGeneration)); + return (ct == 0) ? 200 : ct; + } + + /** SatelliteData produces 1 data per collectionTime ticks; 20 ticks/sec. */ + private static double calcDataPerSecond(int powerGeneration) { + int ct = calcCollectionTimeTicks(powerGeneration); + if (ct <= 0) return 0.0; + return 20.0 / (double) ct; + } + + private static String makeDataGenLine(double dataPerSec) { + // Stable decimal separator regardless of OS locale + String val = String.format(Locale.ROOT, "%.3f", dataPerSec); + + // Preferred: vanilla I18n formatting (client-side tooltip) + String localized = net.minecraft.client.resources.I18n.format("msg.itemsatellite.datagen", val); + + // If lang key is missing, I18n returns the key itself; degrade gracefully + if ("msg.itemsatellite.datagen".equals(localized)) { + return "Data gen: " + val + "/s"; + } + return localized; + } + //Guarding inventory to ensure only valid items are placed in slots. public static class SatelliteModuleInventory extends EmbeddedInventory { public SatelliteModuleInventory() { super(7); } // slots 0-6 embedded from chassis @@ -136,7 +171,13 @@ public void addInformation(@Nonnull ItemStack stack, World world, List l ? LibVulpes.proxy.getLocalizedString("msg.itemsatellite.data") + ZUtils.formatNumber(dataStorage) : ChatFormatting.YELLOW + LibVulpes.proxy.getLocalizedString("msg.itemsatellite.nodata")); } + // Data gen line only meaningful when the satellite has BOTH power generation and data storage. + int pg = props.getPowerGeneration(); + int maxData = props.getMaxDataStorage(); + if (base instanceof SatelliteData && pg > 0 && maxData > 0) { + list.add(makeDataGenLine(calcDataPerSecond(pg))); + } weight = props.getWeight(); list.add((weight > 0f) ? LibVulpes.proxy.getLocalizedString("msg.itemsatellite.weight") + weight @@ -159,15 +200,21 @@ public void addInformation(@Nonnull ItemStack stack, World world, List l int flags = 0; int powerGen = 0, powerStor = 0, dataMax = 0; float weight = 0f; + boolean showDataGenPreview = false; // Core first: flags + preview type name (no weight from core) ItemStack core = inv.getStackInSlot(CORE_SLOT); + + String satType = ""; + SatelliteBase satBase = null; + if (!core.isEmpty()) { SatelliteProperties cp = SatelliteRegistry.getSatelliteProperty(core); if (cp != null) { flags |= cp.getPropertyFlag(); - String satType = cp.getSatelliteType(); - SatelliteBase satBase = SatelliteRegistry.getNewSatellite(satType); + satType = cp.getSatelliteType() == null ? "" : cp.getSatelliteType(); + satBase = SatelliteRegistry.getNewSatellite(satType); + if (satBase != null) { // Show same display name users will see after assembly list.add(satBase.getName()); @@ -175,6 +222,10 @@ public void addInformation(@Nonnull ItemStack stack, World world, List l } } + // Preview: show for "type empty" OR data collectors + showDataGenPreview = satType.isEmpty() || (satBase instanceof SatelliteData); + + // Modules: stats + weight for (int i = FIRST_MOD_SLOT; i <= LAST_MOD_SLOT; i++) { ItemStack s = inv.getStackInSlot(i); @@ -210,6 +261,10 @@ else if (f == SatelliteProperties.Property.DATA.getFlag()) ? LibVulpes.proxy.getLocalizedString("msg.itemsatellite.data") + ZUtils.formatNumber(dataMax) : ChatFormatting.YELLOW + LibVulpes.proxy.getLocalizedString("msg.itemsatellite.nodata")); } + // Preview data gen line (same semantics + same formula as runtime) + if (showDataGenPreview && powerGen > 0 && dataMax > 0) { + list.add(makeDataGenLine(calcDataPerSecond(powerGen))); + } if (weight > 0f) { list.add(LibVulpes.proxy.getLocalizedString("msg.itemsatellite.weight") + weight); } From 5ec69e44e99d9af60f6e0c331830301da163c47a Mon Sep 17 00:00:00 2001 From: kaduvill Date: Sat, 20 Dec 2025 13:12:49 +0100 Subject: [PATCH 412/424] Add data generation messages to lang file --- src/main/resources/assets/advancedrocketry/lang/en_US.lang | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index a70de16a2..1c63c9689 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -542,6 +542,7 @@ msg.itemsatellite.microwavestatus=Collecting Power msg.itemsatellite.data=Data Storage: msg.itemsatellite.nodata=No Data Storage! msg.itemsatellite.empty=Empty Chassis +msg.itemsatellite.datagen=Data gen: %s/s msg.itemsatellite.weight=Chassis weight: msg.itemsatellite.noweight=Error in weight calculation msg.itemsatellite.unassembled=Not assembled (preview) @@ -618,6 +619,7 @@ msg.chat.nostation1=You wake up on the space station with a lingering feeling th msg.chat.nostation2=Maybe you should think before overstepping clearly logical and absolute boundaries again then deciding it was a good idea and not your fault if things go wrong msg.chat.nostation3=You must be on a space station to be in this dimension, and none have been created! +# Orbital Registry msg.orbitalregistry.tab.satellites=Satellites: msg.orbitalregistry.tab.stations=Space Stations: msg.orbitalregistry.text.details=Details: @@ -625,6 +627,7 @@ msg.orbitalregistry.text.satellites=Satellites msg.orbitalregistry.text.stations=Space Stations msg.orbitalregistry.text.nosel=Select an object msg.orbitalregistry.text.notfound=Not found +msg.orbitalregistry.text.sat.datagen=Data gen: msg.orbitalregistry.scan.tooltip=Update this list msg.orbitalregistry.writechip.ok=Click to program chip! msg.orbitalregistry.writechip.no=Cannot program this @@ -651,6 +654,7 @@ msg.orbitalregistry.text.anchored.no=No msg.orbitalregistry.text.system=System: msg.orbitalregistry.text.system.none=None msg.orbitalregistry.text.system.unknown=Unknown + # SatelliteDetails power fields msg.orbitalregistry.text.sat.pwrgen=Pwr Gen: msg.orbitalregistry.text.sat.pwrstore=Pwr Store: From 507838810a590513ba1625e150626c6ce8108d95 Mon Sep 17 00:00:00 2001 From: ZetaY <34602681+ZHAY10086@users.noreply.github.com> Date: Sat, 20 Dec 2025 20:27:33 +0800 Subject: [PATCH 413/424] Update zh_CN.lang --- src/main/resources/assets/advancedrocketry/lang/zh_CN.lang | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index d3383291e..2f345b183 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -246,6 +246,7 @@ error.rocket.destinationNotExist=所选空间站不存在。 error.rocket.partsWornOut=关键部件损坏,发射中止。 error.rocket.aborted=发射中止。 error.rocket.gatedArtifactMissing=缺失工件。(玩家物品栏中) +error.rocket.gatedArtifactMissingWithItem=缺失所需工件:%sx %s(玩家物品栏中) error.rocket.outsideStarSystem=星际航行需要星际飞船。 error.rocket.outsidePlanetarySystem=行星航行需要核动力火箭。 @@ -541,6 +542,7 @@ msg.itemsatellite.microwavestatus=收集能量 msg.itemsatellite.data=数据存储: msg.itemsatellite.nodata=无数据存储! msg.itemsatellite.empty=空框架 +msg.itemsatellite.datagen=数据产出:%s/s msg.itemsatellite.weight=框架重量: msg.itemsatellite.noweight=重量计算错误 msg.itemsatellite.unassembled=未组装(预览) @@ -617,6 +619,7 @@ msg.chat.nostation1=你在空间站醒来,隐约觉得上次那场深空漫步 msg.chat.nostation2=也许你应该在再次越过明确合理且绝对的界限之前先思考一下,而不是在事情出错后自认为是个好主意且不是你的错 msg.chat.nostation3=你必须在空间站上才能进入此维度,但目前尚未建造任何空间站! +# Orbital Registry msg.orbitalregistry.tab.satellites=卫星: msg.orbitalregistry.tab.stations=空间站: msg.orbitalregistry.text.details=详细信息: @@ -624,6 +627,7 @@ msg.orbitalregistry.text.satellites=卫星 msg.orbitalregistry.text.stations=空间站 msg.orbitalregistry.text.nosel=选择一个对象 msg.orbitalregistry.text.notfound=未找到 +msg.orbitalregistry.text.sat.datagen=数据产出: msg.orbitalregistry.scan.tooltip=更新此列表 msg.orbitalregistry.writechip.ok=点击编程芯片! msg.orbitalregistry.writechip.no=无法为此对象编程 @@ -650,6 +654,7 @@ msg.orbitalregistry.text.anchored.no=否 msg.orbitalregistry.text.system=星系: msg.orbitalregistry.text.system.none=无 msg.orbitalregistry.text.system.unknown=未知 + # SatelliteDetails power fields msg.orbitalregistry.text.sat.pwrgen=能量产出: msg.orbitalregistry.text.sat.pwrstore=能量存储: From 08df7af7e963f1cba49704d20f58cc7b95ef94a7 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 22 Dec 2025 12:06:38 +0100 Subject: [PATCH 414/424] Update language file with improved tooltips --- .../assets/advancedrocketry/lang/en_US.lang | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index 1c63c9689..864777ff1 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -424,9 +424,9 @@ msg.biomescanner.gas=nyehhh, Gassy, ain't it? msg.biomescanner.star=If only my sensors had sunshades msg.gravitycontroller.radius=Radius: msg.gravitycontroller.targetgrav=Target Gravity: -msg.gravitycontroller.none=Unset -msg.gravitycontroller.activeset=Active: set -msg.gravitycontroller.activeadd=Active: add +msg.gravitycontroller.none=No Force +msg.gravitycontroller.activeadd=Add Force (combine sides) +msg.gravitycontroller.activeset=Add Force (combine sides) + lift msg.gravitycontroller.targetdir.1=Target-> msg.gravitycontroller.targetdir.2=Direction msg.railgun.transfermin=Min Transfer Size @@ -721,6 +721,7 @@ tooltip.advancedrocketry.oxidizerfueltank.alt.1=§fBipropellant Rocket requires # Nuclear Fuel Tank tooltip.advancedrocketry.nuclearfueltank=§cPart of Rocket +tooltip.advancedrocketry.nuclearfueltank.1=§6Allows planetary travel! tooltip.advancedrocketry.nuclearfueltank.shift.1=§fHolds: §b%s tooltip.advancedrocketry.nuclearfueltank.alt.1=§fRequires §bNuclear Core§f and §bNuclear Engine @@ -731,13 +732,15 @@ tooltip.advancedrocketry.monopropmotor.alt.1=Check Fueling Station JEI-page # Nuclear Core tooltip.advancedrocketry.nuclearcore=§cPart of Rocket +tooltip.advancedrocketry.nuclearcore.1=§6Allows planetary travel! tooltip.advancedrocketry.nuclearcore.shift.1=Needs to be directly on top of a tooltip.advancedrocketry.nuclearcore.shift.2=Nuclear Engine or another Nuclear Core. tooltip.advancedrocketry.nuclearcore.alt.1=Vertical placement rules doesn't apply tooltip.advancedrocketry.nuclearcore.alt.2=for Unmanned Vehicles (Gas Mission rockets) # Nuclear rocketengine -tooltip.advancedrocketry.nuclearmotor=§cPart of Rocket §6Allows planetary travel! +tooltip.advancedrocketry.nuclearmotor=§cPart of Rocket +tooltip.advancedrocketry.nuclearmotor.1=§6Allows planetary travel! tooltip.advancedrocketry.nuclearmotor.shift.1=§fUses §bWorking fluid tooltip.advancedrocketry.nuclearmotor.shift.2=Needs Nuclear Core directly above. tooltip.advancedrocketry.nuclearmotor.alt.1=Check Fueling Station JEI-page @@ -814,10 +817,10 @@ tooltip.advancedrocketry.monitoringstation.shift.2=§fLink to §4Rocket Assemble tooltip.advancedrocketry.monitoringstation.alt.1=§bMissions becomes active when orbit reached! # Satellite Terminal -tooltip.advancedrocketry.satellitemonitor=Communicates with Satellites -tooltip.advancedrocketry.satellitemonitor.shift.1=Insert Satellite Chip -tooltip.advancedrocketry.satellitemonitor.shift.2=Download Data -tooltip.advancedrocketry.satellitemonitor.alt.1=§fTransfer and Auto-Download Data with Wireless Tranciever or Data Unit +tooltip.advancedrocketry.satellitecontrolcenter=Communicates with Satellites +tooltip.advancedrocketry.satellitecontrolcenter.shift.1=Insert Satellite Chip +tooltip.advancedrocketry.satellitecontrolcenter.shift.2=Download Data +tooltip.advancedrocketry.satellitecontrolcenter.alt.1=§fTransfer and Auto-Download Data with Wireless Tranciever or Data Unit # Satellite Builder tooltip.advancedrocketry.satellitebuilder=Assembles Satellites @@ -829,10 +832,7 @@ tooltip.advancedrocketry.satellitebuilder.alt.2=core component + other component # Orbital Registry tooltip.advancedrocketry.orbitalregistry=Tracks man-made objects in space tooltip.advancedrocketry.orbitalregistry.shift.1=§fPrints new Chips! -tooltip.advancedrocketry.orbitalregistry.shift.2= tooltip.advancedrocketry.orbitalregistry.alt.1=§fTo destroy a Satellite use chip in §4Satellite Terminal -tooltip.advancedrocketry.orbitalregistry.alt.2= - ### Infrastructure ## BlockARHatch From e8e243cb987bb108e317e5e04d4fa2e96634d143 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 22 Dec 2025 12:11:26 +0100 Subject: [PATCH 415/424] explain 6 squares --- .../multiblock/TileAreaGravityController.java | 39 +++++++++++++------ 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileAreaGravityController.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileAreaGravityController.java index ce0354852..6b27cee81 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileAreaGravityController.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileAreaGravityController.java @@ -14,10 +14,12 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.Side; import zmaster587.advancedRocketry.AdvancedRocketry; import zmaster587.advancedRocketry.api.AdvancedRocketryBlocks; import zmaster587.advancedRocketry.inventory.TextureResources; +import zmaster587.advancedRocketry.inventory.modules.ModuleSideSelectorTooltipOverlay; import zmaster587.advancedRocketry.util.AudioRegistry; import zmaster587.advancedRocketry.util.GravityHandler; import zmaster587.libVulpes.LibVulpes; @@ -41,6 +43,7 @@ public class TileAreaGravityController extends TileMultiPowerConsumer implements {LibVulpesBlocks.blockAdvStructureBlock, 'P', LibVulpesBlocks.blockAdvStructureBlock}, {null, LibVulpesBlocks.blockAdvStructureBlock, null}} }; + int gravity; int progress; int radius; @@ -49,13 +52,20 @@ public class TileAreaGravityController extends TileMultiPowerConsumer implements private ModuleRedstoneOutputButton redstoneControl; private RedstoneState state; private ModuleText targetGrav, textRadius; + private String[] sideStateNames; private ModuleBlockSideSelector sideSelectorModule; public TileAreaGravityController() { - //numGravPylons = new ModuleText(10, 25, "Number Of Thrusters: ", 0xaa2020); textRadius = new ModuleText(6, 82, LibVulpes.proxy.getLocalizedString("msg.gravitycontroller.radius") + "5", 0x202020); targetGrav = new ModuleText(6, 110, LibVulpes.proxy.getLocalizedString("msg.gravitycontroller.targetgrav"), 0x202020); - sideSelectorModule = new ModuleBlockSideSelector(90, 15, this, LibVulpes.proxy.getLocalizedString("msg.gravitycontroller.none"), LibVulpes.proxy.getLocalizedString("msg.gravitycontroller.activeset"), LibVulpes.proxy.getLocalizedString("msg.gravitycontroller.activeadd")); + + sideStateNames = new String[] { + LibVulpes.proxy.getLocalizedString("msg.gravitycontroller.none"), + LibVulpes.proxy.getLocalizedString("msg.gravitycontroller.activeset"), + LibVulpes.proxy.getLocalizedString("msg.gravitycontroller.activeadd") + }; + + sideSelectorModule = new ModuleBlockSideSelector(90, 15, this, sideStateNames); redstoneControl = new ModuleRedstoneOutputButton(174, 4, 1, "", this); state = RedstoneState.OFF; @@ -75,24 +85,32 @@ public Object[][][] getStructure() { @Override public List getModules(int id, EntityPlayer player) { - List modules = new LinkedList<>();//super.getModules(id, player); - modules.add(toggleSwitch = new ModuleToggleSwitch(160, 5, 0, "", this, zmaster587.libVulpes.inventory.TextureResources.buttonToggleImage, 11, 26, getMachineEnabled())); + List modules = new LinkedList<>(); + modules.add(toggleSwitch = new ModuleToggleSwitch(160, 5, 0, "", this, + zmaster587.libVulpes.inventory.TextureResources.buttonToggleImage, 11, 26, getMachineEnabled())); modules.add(new ModulePower(18, 20, getBatteries())); modules.add(sideSelectorModule); - modules.add(redstoneControl); - modules.add(new ModuleSlider(6, 120, 0, TextureResources.doubleWarningSideBarIndicator, this)); modules.add(new ModuleSlider(6, 90, 1, TextureResources.doubleWarningSideBarIndicator, this)); - modules.add(new ModuleText(42, 20, LibVulpes.proxy.getLocalizedString("msg.gravitycontroller.targetdir.1") + "\n" + LibVulpes.proxy.getLocalizedString("msg.gravitycontroller.targetdir.2"), 0x202020)); + modules.add(new ModuleText(42, 20, + LibVulpes.proxy.getLocalizedString("msg.gravitycontroller.targetdir.1") + "\n" + + LibVulpes.proxy.getLocalizedString("msg.gravitycontroller.targetdir.2"), + 0x202020)); modules.add(targetGrav); modules.add(textRadius); + + if (FMLCommonHandler.instance().getSide().isClient()) { + modules.add(new ModuleSideSelectorTooltipOverlay(90, 15, sideSelectorModule, sideStateNames)); + } + updateText(); return modules; } + public int getRadius() { return radius + 10; } @@ -119,11 +137,10 @@ public void setGravityMultiplier(double multiplier) { } private void updateText() { - if (world.isRemote) { - textRadius.setText(String.format("%s%d", LibVulpes.proxy.getLocalizedString("msg.gravitycontroller.radius"), getRadius())); + if (world == null || !world.isRemote) return; + textRadius.setText(String.format("%s%d", LibVulpes.proxy.getLocalizedString("msg.gravitycontroller.radius"), getRadius())); - targetGrav.setText(String.format("%s %.2f/%.2f", LibVulpes.proxy.getLocalizedString("msg.gravitycontroller.targetgrav"), currentProgress, gravity / 100f)); - } + targetGrav.setText(String.format("%s %.2f/%.2f", LibVulpes.proxy.getLocalizedString("msg.gravitycontroller.targetgrav"), currentProgress, gravity / 100f)); } @Override From 90da322facabfb9cdd95018e07cc777658a4a5af Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 22 Dec 2025 12:11:48 +0100 Subject: [PATCH 416/424] Refactor scan button initialization in TileObservatory --- .../tile/multiblock/TileObservatory.java | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java index b2851441c..613537e31 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java @@ -424,8 +424,12 @@ public List getModules(int ID, EntityPlayer player) { //ADD io slots modules.add(new ModuleTexturedSlotArray(5, 120, this, 1, 2, TextureResources.idChip)); modules.add(new ModuleOutputSlotArray(45, 120, this, 2, 3)); + + ModuleButton scanButton = new ModuleButton(100, 120, 2, LibVulpes.proxy.getLocalizedString("msg.observetory.scan.button"), this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild, LibVulpes.proxy.getLocalizedString("msg.observetory.scan.tooltip"), 64, 18); + scanButton.setColor(extractData(dataConsumedPerRefresh, DataType.DISTANCE, EnumFacing.DOWN, false) == dataConsumedPerRefresh ? 0x00ff00 : 0xff0000); + modules.add(scanButton); + modules.add(new ModuleProgress(25, 120, 0, new ProgressBarImage(217, 0, 17, 17, 234, 0, EnumFacing.DOWN, TextureResources.progressBars), this)); - ModuleButton processBtn = new ModuleButton( 25, 120, 1, "", this, @@ -446,18 +450,10 @@ public List getModules(int ID, EntityPlayer player) { modules.add(processBtn); - ModuleButton scanButton = new ModuleButton(100, 120, 2, LibVulpes.proxy.getLocalizedString("msg.observetory.scan.button"), this, zmaster587.libVulpes.inventory.TextureResources.buttonBuild, LibVulpes.proxy.getLocalizedString("msg.observetory.scan.tooltip"), 64, 18); - - scanButton.setColor(extractData(dataConsumedPerRefresh, DataType.DISTANCE, EnumFacing.DOWN, false) == dataConsumedPerRefresh ? 0x00ff00 : 0xff0000); - - modules.add(scanButton); - - List list2 = new LinkedList<>(); List buttonList = new LinkedList<>(); buttonType.clear(); - int g = 0; Asteroid asteroidSmol; if (lastButton != -1 && lastType != null && !lastType.isEmpty() && (asteroidSmol = ARConfiguration.getCurrentConfig().asteroidTypes.get(lastType)) != null) { @@ -480,7 +476,6 @@ public List getModules(int ID, EntityPlayer player) { )); } - //Calculate Types int totalAmountAllowed = 10; float totalWeight = 0; @@ -507,7 +502,6 @@ public List getModules(int ID, EntityPlayer player) { } } - for (int i = 0; i < finalList.size(); i++) { Asteroid asteroid = finalList.get(i); @@ -521,11 +515,9 @@ public List getModules(int ID, EntityPlayer player) { buttonType.put(i, asteroid.getName()); } - modules.add(new ModuleText(10, 18, LibVulpes.proxy.getLocalizedString("msg.observetory.text.asteroids"), 0x2d2d2d)); modules.add(new ModuleText(105, 18, LibVulpes.proxy.getLocalizedString("msg.observetory.text.composition"), 0x2d2d2d)); - //Ore display int baseX = 122; int baseY = 32; From 872cdaf77178d4f435f43caa52e83be4ef3f9278 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 22 Dec 2025 12:12:12 +0100 Subject: [PATCH 417/424] Refactor TileOrbitalRegistry and improve scan handling Updated the structure comment and removed duplicate scan button code. Added a new network request for reopening after a scan. --- .../tile/TileOrbitalRegistry.java | 58 +++++++++++++------ 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java b/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java index e49b23820..77c1e03f0 100644 --- a/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java +++ b/src/main/java/zmaster587/advancedRocketry/tile/TileOrbitalRegistry.java @@ -62,7 +62,7 @@ public class TileOrbitalRegistry extends TileMultiPowerConsumer implements IModularInventory, IButtonInventory, IGuiCallback, IInventory { - // Simple 1x2 structure, same pattern as TileSatelliteBuilder + // Simple 1x1 structure public static final Object[][][] structure = new Object[][][] { { { 'c' } } }; @@ -105,7 +105,12 @@ public class TileOrbitalRegistry extends TileMultiPowerConsumer private static final byte NET_BUTTON_WRITE_CHIP = 12; private static final byte NET_BUTTON_SCAN = 13; private static final byte NET_BUTTON_SELECT_STAT = 14; + private static final byte NET_REQUEST_REOPEN = 15; + // Synced “version” that changes whenever scan results change + private int scanNonce = 0; + // Client-only flag + private boolean pendingReopenAfterScan = false; // Inventory private final EmbeddedInventory inv; @@ -728,7 +733,18 @@ public List getModules(int ID, EntityPlayer player) { this, SLOT_CHIP_OUT, SLOT_CHIP_OUT + 1)); - // Progress bar behind the write button + ModuleButton scanBtn = new ModuleButton( + 110, OBS_CHIP_Y, + GUI_BUTTON_SCAN, + LibVulpes.proxy.getLocalizedString("msg.observetory.scan.button"), + this, + zmaster587.libVulpes.inventory.TextureResources.buttonBuild, + LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.scan.tooltip"), + 64, 18 + ); + modules.add(scanBtn); + + // Progress bar modules.add(new ModuleProgress( OBS_CHIP_X + 20, OBS_CHIP_Y, 0, @@ -753,22 +769,9 @@ public List getModules(int ID, EntityPlayer player) { WriteCheck wc = checkWrite(); writeBtn.setToolTipText(LibVulpes.proxy.getLocalizedString(wc.tooltipKey)); - modules.add(writeBtn); - ModuleButton scanBtn = new ModuleButton( - 110, OBS_CHIP_Y, - GUI_BUTTON_SCAN, - LibVulpes.proxy.getLocalizedString("msg.observetory.scan.button"), - this, - zmaster587.libVulpes.inventory.TextureResources.buttonBuild, - LibVulpes.proxy.getLocalizedString("msg.orbitalregistry.scan.tooltip"), - 64, 18 - ); - modules.add(scanBtn); - // ----- WINDOWS (left list + right detail) ----- - final int listBaseX = OBS_LIST_BASE_X; final int listBaseY = OBS_LIST_BASE_Y; final int listSizeX = OBS_LIST_SIZE_X; @@ -1164,8 +1167,8 @@ public void onInventoryButtonPressed(int buttonId) { // Client → server via PacketMachine if (world != null && world.isRemote) { if (buttonId == GUI_BUTTON_SCAN) { - // Reset scroll immediately on the client AdvancedRocketry.proxy.clearScrollCache(); + pendingReopenAfterScan = true; PacketHandler.sendToServer(new PacketMachine(this, NET_BUTTON_SCAN)); return; } @@ -1281,9 +1284,15 @@ public void useNetworkData(EntityPlayer player, Side side, byte id, NBTTagCompou } else { rescanStations(); } - + scanNonce++; + selectedSatId = -1L; + lastSatButton = -1; + selectedStationId = -1; + lastStationButton = -1; markDirty(); world.notifyBlockUpdate(pos, world.getBlockState(pos), world.getBlockState(pos), 2); + //player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), getWorld(), pos.getX(), pos.getY(), pos.getZ()); + } else if (id == NET_REQUEST_REOPEN) { player.openGui(LibVulpes.instance, GuiHandler.guiId.MODULARNOINV.ordinal(), getWorld(), pos.getX(), pos.getY(), pos.getZ()); } @@ -1302,10 +1311,21 @@ protected void writeNetworkData(NBTTagCompound nbt) { @Override protected void readNetworkData(NBTTagCompound nbt) { + int prevNonce = this.scanNonce; super.readNetworkData(nbt); readCommonNBT(nbt); + + // Client: only reopen AFTER we have the new cache NBT + if (world != null && world.isRemote + && pendingReopenAfterScan + && prevNonce != this.scanNonce + && net.minecraft.client.Minecraft.getMinecraft().currentScreen instanceof zmaster587.libVulpes.inventory.GuiModular) { + pendingReopenAfterScan = false; + PacketHandler.sendToServer(new PacketMachine(this, NET_REQUEST_REOPEN)); + } } + @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); @@ -1327,7 +1347,7 @@ private void writeCommonNBT(NBTTagCompound nbt) { nbt.setLong("selectedSatId", selectedSatId); nbt.setInteger("lastStationButton", lastStationButton); nbt.setInteger("selectedStationId", selectedStationId); - + nbt.setInteger("scanNonce", scanNonce); // Satellite cache NBTTagList satList = new NBTTagList(); for (SatEntry e : satCache) { @@ -1367,7 +1387,7 @@ private void readCommonNBT(NBTTagCompound nbt) { selectedSatId = nbt.getLong("selectedSatId"); lastStationButton = nbt.getInteger("lastStationButton"); selectedStationId = nbt.getInteger("selectedStationId"); - + scanNonce = nbt.getInteger("scanNonce"); satCache.clear(); if (nbt.hasKey("satCache")) { NBTTagList satList = nbt.getTagList("satCache", Constants.NBT.TAG_COMPOUND); From a20f8cc6660413dfe3d6521d91d5c00e067baba8 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 22 Dec 2025 12:12:52 +0100 Subject: [PATCH 418/424] Refactor tooltip keys for advanced rocketry items more specific hooks avoid leaking --- .../client/TooltipInjector.java | 230 ++---------------- 1 file changed, 16 insertions(+), 214 deletions(-) diff --git a/src/main/java/zmaster587/advancedRocketry/client/TooltipInjector.java b/src/main/java/zmaster587/advancedRocketry/client/TooltipInjector.java index 68254fda8..342609804 100644 --- a/src/main/java/zmaster587/advancedRocketry/client/TooltipInjector.java +++ b/src/main/java/zmaster587/advancedRocketry/client/TooltipInjector.java @@ -43,32 +43,21 @@ private TooltipInjector() {} static { - // ---- CO2 Scrubber ---- - KEY_BY_ID.put("advancedrocketry:scrubber", "tooltip.advancedrocketry.scrubber"); - KEY_BY_SUFFIX.put("scrubber", "tooltip.advancedrocketry.scrubber"); - - // ---- Oxygen Vent ---- + // ---- CO2 Scrubber / Oxygen Vent ---- ---- + KEY_BY_ID.put("advancedrocketry:oxygenscrubber", "tooltip.advancedrocketry.scrubber"); KEY_BY_ID.put("advancedrocketry:oxygenvent", "tooltip.advancedrocketry.oxygenvent"); - KEY_BY_SUFFIX.put("oxygenVent", "tooltip.advancedrocketry.oxygenvent"); ARGS_BY_BASEKEY.put("tooltip.advancedrocketry.oxygenvent", s -> new Object[] { ARConfiguration.getCurrentConfig().oxygenVentSize }); - // ---- Carbon Scrubber Cartridge ---- KEY_BY_ID.put("advancedrocketry:carbonscrubbercartridge", "tooltip.advancedrocketry.scrubbercart"); - KEY_BY_SUFFIX.put("carbonScrubberCartridge", "tooltip.advancedrocketry.scrubbercart"); + // ---- Structure Tower ---- KEY_BY_ID.put("advancedrocketry:structuretower", "tooltip.advancedrocketry.structuretower"); - KEY_BY_SUFFIX.put("structuretower", "tooltip.advancedrocketry.structuretower"); - - // ---- Structure Machine ---- KEY_BY_ID.put("libvulpes:structuremachine", "tooltip.libvulpes.structuremachine"); - KEY_BY_SUFFIX.put("structuremachine", "tooltip.libvulpes.structuremachine"); - - // ---- Structure Tower ---- KEY_BY_ID.put("libvulpes:advstructuremachine", "tooltip.libvulpes.advstructuremachine"); - KEY_BY_SUFFIX.put("advstructuremachine", "tooltip.libvulpes.advstructuremachine"); + // --- ItemUpgrade (meta-based) 6 Space Suit Components--- KEY_RESOLVER_BY_ID.put("advancedrocketry:itemupgrade", @@ -78,64 +67,25 @@ private TooltipInjector() {} // ---- Guidance Computer ---- KEY_BY_ID.put("advancedrocketry:guidancecomputer", "tooltip.advancedrocketry.guidancecomputer"); - KEY_BY_ID.put("advancedrocketry:guidance_computer", "tooltip.advancedrocketry.guidancecomputer"); // just in case - KEY_BY_SUFFIX.put("guidanceComputer", "tooltip.advancedrocketry.guidancecomputer"); - - // ---- Service Monitor ---- KEY_BY_ID.put("advancedrocketry:servicemonitor", "tooltip.advancedrocketry.servicemonitor"); - KEY_BY_SUFFIX.put("servicemonitor", "tooltip.advancedrocketry.servicemonitor"); - - // ---- Service Station ---- KEY_BY_ID.put("advancedrocketry:servicestation", "tooltip.advancedrocketry.servicestation"); - KEY_BY_ID.put("advancedrocketry:serviceStation", "tooltip.advancedrocketry.servicestation"); - KEY_BY_SUFFIX.put("serviceStation", "tooltip.advancedrocketry.servicestation"); + KEY_BY_ID.put("advancedrocketry:oxygencharger", "tooltip.advancedrocketry.oxygencharger"); - // ---- Gas Charge Pad ---- - KEY_BY_ID.put("advancedrocketry:oxygenCharger", "tooltip.advancedrocketry.oxygencharger"); - KEY_BY_SUFFIX.put("oxygenCharger", "tooltip.advancedrocketry.oxygencharger"); // --- Station Controllers KEY_BY_ID.put("advancedrocketry:orientationcontroller", "tooltip.advancedrocketry.orientationctrl"); - KEY_BY_SUFFIX.put("orientationcontroller", "tooltip.advancedrocketry.orientationctrl"); - KEY_BY_SUFFIX.put("orientationController", "tooltip.advancedrocketry.orientationctrl"); - - KEY_BY_SUFFIX.put("gravityController", "tooltip.advancedrocketry.gravityctrl"); KEY_BY_ID.put("advancedrocketry:gravitycontroller", "tooltip.advancedrocketry.gravityctrl"); - KEY_BY_SUFFIX.put("gravitycontroller", "tooltip.advancedrocketry.gravityctrl"); - KEY_BY_ID.put("advancedrocketry:altitudecontroller", "tooltip.advancedrocketry.altitudectrl"); - KEY_BY_SUFFIX.put("altitudeController", "tooltip.advancedrocketry.altitudectrl"); - KEY_BY_SUFFIX.put("altitudecontroller", "tooltip.advancedrocketry.altitudectrl"); - // ---- Small Airlock Door (ItemDoor tied to blockAirLock) ---- - KEY_BY_ID.put("advancedrocketry:smallairlockdoor", "tooltip.advancedrocketry.smallairlock"); - // Fallback by unloc tail (you set setUnlocalizedName("smallAirlock")) - KEY_BY_SUFFIX.put("smallAirlock", "tooltip.advancedrocketry.smallairlock"); - // Planet Selectors + KEY_BY_ID.put("advancedrocketry:smallairlockdoor", "tooltip.advancedrocketry.smallairlock"); KEY_BY_ID.put("advancedrocketry:planetselector", "tooltip.advancedrocketry.planetselector"); - KEY_BY_SUFFIX.put("planetSelector", "tooltip.advancedrocketry.planetselector"); - KEY_BY_ID.put("advancedrocketry:planetholoselector", "tooltip.advancedrocketry.planetholoselector"); - KEY_BY_SUFFIX.put("planetHoloSelector", "tooltip.advancedrocketry.planetholoselector"); - - // ---- Station Light ---- KEY_BY_ID.put("advancedrocketry:circlelight", "tooltip.advancedrocketry.circlelight"); - KEY_BY_SUFFIX.put("circleLight", "tooltip.advancedrocketry.circlelight"); - - // ---- Monitoring Station ---- KEY_BY_ID.put("advancedrocketry:monitoringstation", "tooltip.advancedrocketry.monitoringstation"); - KEY_BY_ID.put("advancedrocketry:monitoring_station", "tooltip.advancedrocketry.monitoringstation"); - KEY_BY_SUFFIX.put("monitoringstation", "tooltip.advancedrocketry.monitoringstation"); - - // ---- Satellite Builder ---- KEY_BY_ID.put("advancedrocketry:satellitebuilder", "tooltip.advancedrocketry.satellitebuilder"); - KEY_BY_SUFFIX.put("satelliteBuilder", "tooltip.advancedrocketry.satellitebuilder"); + KEY_BY_ID.put("advancedrocketry:satellitecontrolcenter", "tooltip.advancedrocketry.satellitecontrolcenter"); - // ---- Satellite Control Terminal ---- - KEY_BY_ID.put("advancedrocketry:satellitemonitor", "tooltip.advancedrocketry.satellitemonitor"); - KEY_BY_ID.put("advancedrocketry:satellite_monitor", "tooltip.advancedrocketry.satellitemonitor"); - KEY_BY_SUFFIX.put("satelliteMonitor", "tooltip.advancedrocketry.satellitemonitor"); // --- Satellite Primary Function (metas 0..6) KEY_RESOLVER_BY_ID.put("advancedrocketry:satelliteprimaryfunction", s -> { @@ -150,7 +100,7 @@ private TooltipInjector() {} default: return null; } }); - // (optional camelCase fallback if you ever see it) + // camelCase fallback KEY_RESOLVER_BY_ID.put("advancedrocketry:satellitePrimaryFunction", KEY_RESOLVER_BY_ID.get("advancedrocketry:satelliteprimaryfunction")); @@ -170,56 +120,22 @@ private TooltipInjector() {} // ---- ID Chips / Chips ---- KEY_BY_ID.put("advancedrocketry:satelliteidchip", "tooltip.advancedrocketry.satidchip"); - KEY_BY_SUFFIX.put("satelliteIdChip", "tooltip.advancedrocketry.satidchip"); - KEY_BY_ID.put("advancedrocketry:planetidchip", "tooltip.advancedrocketry.planetidchip"); - KEY_BY_SUFFIX.put("planetIdChip", "tooltip.advancedrocketry.planetidchip"); - KEY_BY_ID.put("advancedrocketry:stationchip", "tooltip.advancedrocketry.stationchip"); - KEY_BY_SUFFIX.put("stationChip", "tooltip.advancedrocketry.stationchip"); - // registry sometimes: spaceStationChip KEY_BY_ID.put("advancedrocketry:spacestationchip", "tooltip.advancedrocketry.stationchip"); - KEY_BY_SUFFIX.put("spaceStationChip", "tooltip.advancedrocketry.stationchip"); - KEY_BY_ID.put("advancedrocketry:elevatorchip", "tooltip.advancedrocketry.elevatorchip"); - KEY_BY_SUFFIX.put("elevatorChip", "tooltip.advancedrocketry.elevatorchip"); - KEY_BY_ID.put("advancedrocketry:asteroidchip", "tooltip.advancedrocketry.asteroidchip"); - KEY_BY_SUFFIX.put("asteroidChip", "tooltip.advancedrocketry.asteroidchip"); - // ---- Energy multiblocks ---- - // Black Hole Generator + // ---- Energy multiblocks ---- KEY_BY_ID.put("advancedrocketry:blackholegenerator", "tooltip.advancedrocketry.blackholegen"); - KEY_BY_SUFFIX.put("blackholegenerator", "tooltip.advancedrocketry.blackholegen"); - - // Microwave Receiver (note: source uses the misspelling "Reciever"; cover both) KEY_BY_ID.put("advancedrocketry:microwavereciever", "tooltip.advancedrocketry.microwavereceiver"); - KEY_BY_ID.put("advancedrocketry:microwaveReciever", "tooltip.advancedrocketry.microwavereceiver"); - KEY_BY_SUFFIX.put("microwavereciever", "tooltip.advancedrocketry.microwavereceiver"); - KEY_BY_SUFFIX.put("microwaveReciever", "tooltip.advancedrocketry.microwavereceiver"); - // (optional safety if it ever gets corrected) - KEY_BY_ID.put("advancedrocketry:microwavereceiver", "tooltip.advancedrocketry.microwavereceiver"); - KEY_BY_SUFFIX.put("microwaveReceiver", "tooltip.advancedrocketry.microwavereceiver"); - - // ---- Solar Panel (part of multiblock) ---- KEY_BY_ID.put("advancedrocketry:solarpanel", "tooltip.advancedrocketry.solarpanel"); - KEY_BY_ID.put("advancedrocketry:solarPanel", "tooltip.advancedrocketry.solarpanel"); // just in case - KEY_BY_SUFFIX.put("solarpanel", "tooltip.advancedrocketry.solarpanel"); - KEY_BY_SUFFIX.put("solarPanel", "tooltip.advancedrocketry.solarpanel"); - - // Solar Array KEY_BY_ID.put("advancedrocketry:solararray", "tooltip.advancedrocketry.solararray"); - KEY_BY_SUFFIX.put("solararray", "tooltip.advancedrocketry.solararray"); - // Solar Array Panel KEY_BY_ID.put("advancedrocketry:solararraypanel", "tooltip.advancedrocketry.solararraypanel"); - KEY_BY_SUFFIX.put("solararraypanel", "tooltip.advancedrocketry.solararraypanel"); // Advanced Data Bus KEY_BY_ID.put("advancedrocketry:databusbig", "tooltip.advancedrocketry.databusbig"); - KEY_BY_SUFFIX.put("databusbig", "tooltip.advancedrocketry.databusbig"); - - // ---- BlockARHatch (registered as advancedrocketry:loader), meta 0..6 ---- KEY_RESOLVER_BY_ID.put("advancedrocketry:loader", s -> { final int v = s.getMetadata() & 7; // strip redstone/state bit @@ -236,159 +152,57 @@ private TooltipInjector() {} }); // ---- Processing / Machines / Multiblocks---- - KEY_BY_ID.put("advancedrocketry:electricarcfurnace", "tooltip.advancedrocketry.arcfurnace"); - KEY_BY_SUFFIX.put("electricArcFurnace", "tooltip.advancedrocketry.arcfurnace"); - + KEY_BY_ID.put("advancedrocketry:arcfurnace", "tooltip.advancedrocketry.arcfurnace"); KEY_BY_ID.put("advancedrocketry:rollingmachine", "tooltip.advancedrocketry.rollingmachine"); - KEY_BY_SUFFIX.put("rollingMachine", "tooltip.advancedrocketry.rollingmachine"); - KEY_BY_ID.put("advancedrocketry:lathe", "tooltip.advancedrocketry.lathe"); - KEY_BY_SUFFIX.put("lathe", "tooltip.advancedrocketry.lathe"); - KEY_BY_ID.put("advancedrocketry:crystallizer", "tooltip.advancedrocketry.crystallizer"); - KEY_BY_SUFFIX.put("Crystallizer", "tooltip.advancedrocketry.crystallizer"); // note capital C - KEY_BY_ID.put("advancedrocketry:cuttingmachine", "tooltip.advancedrocketry.cuttingmachine"); - KEY_BY_SUFFIX.put("cuttingMachine", "tooltip.advancedrocketry.cuttingmachine"); - KEY_BY_ID.put("advancedrocketry:precisionassemblingmachine", "tooltip.advancedrocketry.precisionassembler"); - KEY_BY_SUFFIX.put("precisionAssemblingMachine", "tooltip.advancedrocketry.precisionassembler"); - KEY_BY_ID.put("advancedrocketry:electrolyser", "tooltip.advancedrocketry.electrolyser"); - KEY_BY_SUFFIX.put("electrolyser", "tooltip.advancedrocketry.electrolyser"); - - KEY_BY_ID.put("advancedrocketry:chemreactor", "tooltip.advancedrocketry.chemreactor"); - KEY_BY_SUFFIX.put("chemreactor", "tooltip.advancedrocketry.chemreactor"); - + KEY_BY_ID.put("advancedrocketry:chemicalreactor", "tooltip.advancedrocketry.chemreactor"); KEY_BY_ID.put("advancedrocketry:precisionlaseretcher","tooltip.advancedrocketry.precisionlaseretcher"); - KEY_BY_SUFFIX.put("precisionlaseretcher", "tooltip.advancedrocketry.precisionlaseretcher"); - KEY_BY_ID.put("advancedrocketry:observatory", "tooltip.advancedrocketry.observatory"); - KEY_BY_SUFFIX.put("observatory", "tooltip.advancedrocketry.observatory"); - KEY_BY_ID.put("advancedrocketry:planetanalyser", "tooltip.advancedrocketry.planetanalyser"); - KEY_BY_SUFFIX.put("planetanalyser", "tooltip.advancedrocketry.planetanalyser"); - KEY_BY_ID.put("advancedrocketry:centrifuge", "tooltip.advancedrocketry.centrifuge"); - KEY_BY_SUFFIX.put("centrifuge", "tooltip.advancedrocketry.centrifuge"); - KEY_BY_ID.put("advancedrocketry:orbitalregistry", "tooltip.advancedrocketry.orbitalregistry"); - KEY_BY_SUFFIX.put("orbitalRegistry", "tooltip.advancedrocketry.orbitalregistry"); - - // ---- Aux / Huge ---- KEY_BY_ID.put("advancedrocketry:warpcore", "tooltip.advancedrocketry.warpcore"); - KEY_BY_SUFFIX.put("warpCore", "tooltip.advancedrocketry.warpcore"); - KEY_BY_ID.put("advancedrocketry:beacon", "tooltip.advancedrocketry.beacon"); - KEY_BY_SUFFIX.put("beacon", "tooltip.advancedrocketry.beacon"); - KEY_BY_ID.put("advancedrocketry:biomescanner", "tooltip.advancedrocketry.biomescan"); - KEY_BY_SUFFIX.put("biomeScanner", "tooltip.advancedrocketry.biomescan"); - KEY_BY_ID.put("advancedrocketry:railgun", "tooltip.advancedrocketry.railgun"); - KEY_BY_SUFFIX.put("railgun", "tooltip.advancedrocketry.railgun"); - KEY_BY_ID.put("advancedrocketry:spaceelevatorcontroller", "tooltip.advancedrocketry.spaceelevatorctrl"); - KEY_BY_SUFFIX.put("spaceElevatorController", "tooltip.advancedrocketry.spaceelevatorctrl"); + KEY_BY_ID.put("advancedrocketry:terraformer", "tooltip.advancedrocketry.atmosterraformer"); + KEY_BY_ID.put("advancedrocketry:gravitymachine", "tooltip.advancedrocketry.gravitymachine"); + KEY_BY_ID.put("advancedrocketry:spacelaser", "tooltip.advancedrocketry.spacelaser"); // ---- Building / components ---- KEY_BY_ID.put("advancedrocketry:concrete", "tooltip.advancedrocketry.concrete"); - KEY_BY_SUFFIX.put("concrete", "tooltip.advancedrocketry.concrete"); - KEY_BY_ID.put("advancedrocketry:blastbrick", "tooltip.advancedrocketry.blastbrick"); - KEY_BY_ID.put("advancedrocketry:blastBrick", "tooltip.advancedrocketry.blastbrick"); - KEY_BY_SUFFIX.put("blastbrick", "tooltip.advancedrocketry.blastbrick"); - KEY_BY_SUFFIX.put("blastBrick", "tooltip.advancedrocketry.blastbrick"); - - // Machines / misc - KEY_BY_ID.put("advancedrocketry:qcrucible", "tooltip.advancedrocketry.qcrucible"); - KEY_BY_SUFFIX.put("qcrucible", "tooltip.advancedrocketry.qcrucible"); - + KEY_BY_ID.put("advancedrocketry:iquartzcrucible", "tooltip.advancedrocketry.qcrucible"); KEY_BY_ID.put("advancedrocketry:sawblade", "tooltip.advancedrocketry.sawblade"); - KEY_BY_ID.put("advancedrocketry:sawBlade", "tooltip.advancedrocketry.sawblade"); - KEY_BY_SUFFIX.put("sawblade", "tooltip.advancedrocketry.sawblade"); - KEY_BY_SUFFIX.put("sawBlade", "tooltip.advancedrocketry.sawblade"); - - // Atmosphere Terraformer - KEY_BY_ID.put("advancedrocketry:terraformer", "tooltip.advancedrocketry.atmosterraformer"); - KEY_BY_SUFFIX.put("terraformer", "tooltip.advancedrocketry.atmosterraformer"); - - // Area Gravity Controller - KEY_BY_ID.put("advancedrocketry:gravitymachine", "tooltip.advancedrocketry.gravitymachine"); - KEY_BY_SUFFIX.put("gravityMachine", "tooltip.advancedrocketry.gravitymachine"); - KEY_BY_SUFFIX.put("gravitymachine", "tooltip.advancedrocketry.gravitymachine"); - - // Orbital Laser Drill (space laser) - KEY_BY_ID.put("advancedrocketry:spacelaser", "tooltip.advancedrocketry.spacelaser"); - KEY_BY_SUFFIX.put("spaceLaser", "tooltip.advancedrocketry.spacelaser"); - KEY_BY_SUFFIX.put("spacelaser", "tooltip.advancedrocketry.spacelaser"); - - // ---- Vacuum Laser ---- KEY_BY_ID.put("advancedrocketry:vacuumlaser", "tooltip.advancedrocketry.vacuumlaser"); - KEY_BY_SUFFIX.put("vacuumLaser", "tooltip.advancedrocketry.vacuumlaser"); - KEY_BY_SUFFIX.put("vacuumlaser", "tooltip.advancedrocketry.vacuumlaser"); // ---- Pump ---- - KEY_BY_ID.put("advancedrocketry:pump", "tooltip.advancedrocketry.pump"); - KEY_BY_SUFFIX.put("pump", "tooltip.advancedrocketry.pump"); + KEY_BY_ID.put("advancedrocketry:blockpump", "tooltip.advancedrocketry.pump"); // ---- Remotes ---- KEY_BY_ID.put("advancedrocketry:biomechanger", "tooltip.advancedrocketry.biomechangerremote"); - KEY_BY_SUFFIX.put("biomechanger", "tooltip.advancedrocketry.biomechangerremote"); - KEY_BY_ID.put("advancedrocketry:weathercontroller", "tooltip.advancedrocketry.weathercontrollerremote"); - KEY_BY_SUFFIX.put("weathercontroller", "tooltip.advancedrocketry.weathercontrollerremote"); - KEY_BY_ID.put("advancedrocketry:orescanner", "tooltip.advancedrocketry.orescanner"); - KEY_BY_SUFFIX.put("orescanner", "tooltip.advancedrocketry.orescanner"); - // ---- Crafting items ---- - // Iron Saw Blade KEY_BY_ID.put("advancedrocketry:sawbladeiron", "tooltip.advancedrocketry.sawbladeiron"); - KEY_BY_SUFFIX.put("sawbladeiron", "tooltip.advancedrocketry.sawbladeiron"); - - // Wafer KEY_BY_ID.put("advancedrocketry:wafer", "tooltip.advancedrocketry.wafer"); - KEY_BY_SUFFIX.put("wafer", "tooltip.advancedrocketry.wafer"); - - // Circuit Plate KEY_BY_ID.put("advancedrocketry:itemcircuitplate", "tooltip.advancedrocketry.circuitplate"); - KEY_BY_SUFFIX.put("itemcircuitplate", "tooltip.advancedrocketry.circuitplate"); - KEY_BY_SUFFIX.put("circuitplate", "tooltip.advancedrocketry.circuitplate"); - - // itemLens KEY_BY_ID.put("advancedrocketry:lens", "tooltip.advancedrocketry.itemlens"); - - // Integrated Circuit (IC) KEY_BY_ID.put("advancedrocketry:ic", "tooltip.advancedrocketry.circuitic"); - KEY_BY_SUFFIX.put("ic", "tooltip.advancedrocketry.circuitic"); - KEY_BY_SUFFIX.put("circuitIC", "tooltip.advancedrocketry.circuitic"); - - // Misc parts KEY_BY_ID.put("advancedrocketry:miscpart", "tooltip.advancedrocketry.miscpart"); - KEY_BY_SUFFIX.put("miscpart", "tooltip.advancedrocketry.miscpart"); - KEY_BY_ID.put("advancedrocketry:misc", "tooltip.advancedrocketry.misc"); - KEY_BY_SUFFIX.put("misc", "tooltip.advancedrocketry.misc"); - // ---- Assemblers ---- - // Rocket Assembler KEY_BY_ID.put("advancedrocketry:rocketbuilder", "tooltip.advancedrocketry.rocketassembler"); - KEY_BY_SUFFIX.put("rocketbuilder", "tooltip.advancedrocketry.rocketassembler"); - KEY_BY_SUFFIX.put("rocketAssembler", "tooltip.advancedrocketry.rocketassembler"); - - // Space Station Assembler KEY_BY_ID.put("advancedrocketry:stationbuilder", "tooltip.advancedrocketry.stationassembler"); - KEY_BY_SUFFIX.put("stationbuilder", "tooltip.advancedrocketry.stationassembler"); - KEY_BY_SUFFIX.put("stationAssembler", "tooltip.advancedrocketry.stationassembler"); - - // Station Deployable Rocket Assembler (Unmanned Vehicle) KEY_BY_ID.put("advancedrocketry:deployablerocketbuilder", "tooltip.advancedrocketry.deployablerocketassembler"); - KEY_BY_SUFFIX.put("deployablerocketbuilder", "tooltip.advancedrocketry.deployablerocketassembler"); - KEY_BY_SUFFIX.put("deployableRocketAssembler", "tooltip.advancedrocketry.deployablerocketassembler"); // ---- LibVulpes blocks ---- KEY_BY_ID.put("libvulpes:coalgenerator", "tooltip.advancedrocketry.libvulpes.coalgenerator"); @@ -398,22 +212,10 @@ private TooltipInjector() {} KEY_BY_ID.put("libvulpes:creativepowerbattery", "tooltip.advancedrocketry.libvulpes.creativepowerbattery"); // ---- Fuel Tanks ---- - // Monopropellant Fuel Tank KEY_BY_ID.put("advancedrocketry:fueltank", "tooltip.advancedrocketry.fueltank"); - KEY_BY_ID.put("advancedrocketry:fuelTank", "tooltip.advancedrocketry.fueltank"); - KEY_BY_SUFFIX.put("fuelTank", "tooltip.advancedrocketry.fueltank"); - - // Bipropellant Fuel Tank KEY_BY_ID.put("advancedrocketry:bipropellantfueltank", "tooltip.advancedrocketry.bipropfueltank"); - KEY_BY_SUFFIX.put("bipropellantfueltank", "tooltip.advancedrocketry.bipropfueltank"); - - // Oxidizer Fuel Tank KEY_BY_ID.put("advancedrocketry:oxidizerfueltank", "tooltip.advancedrocketry.oxidizerfueltank"); - KEY_BY_SUFFIX.put("oxidizerfueltank", "tooltip.advancedrocketry.oxidizerfueltank"); - - // Nuclear Fuel Tank KEY_BY_ID.put("advancedrocketry:nuclearfueltank", "tooltip.advancedrocketry.nuclearfueltank"); - KEY_BY_SUFFIX.put("nuclearfueltank", "tooltip.advancedrocketry.nuclearfueltank"); // Monoprop tank ARGS_BY_BASEKEY.put("tooltip.advancedrocketry.fueltank", From c2b0ad2b605486d220b3954ee418e63cc201415f Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 22 Dec 2025 12:19:45 +0100 Subject: [PATCH 419/424] Revise changelog for version 2.2.2 Updated changelog with new features, bug fixes, and improvements across various components. --- changelog.md | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/changelog.md b/changelog.md index 2231fe6a6..215f460d6 100644 --- a/changelog.md +++ b/changelog.md @@ -4,12 +4,15 @@ Changelog 2.2.2 - Orbital Registry - Scans existing stations/starships/satellites, shows info, prints new chips - Prevents losing the last chip / reduces need for backups - - Only checks current dimension + - Only checks current Dimension (spacestation ->body below) - Advanced Databus - Works like DataUnit AND Databus - - Stores more data (less transceiver spaghetti / better performance for buffers) + - Capacity= 2000 * 4 = 8000 (default) - Keeps data when broken (NOT a "Satellite Component") +-ItemSatellite + - Added to tooltip: "Data gen: x/s" + - Rocket - Added hint: "Press to open GUI" when riding rockets - Added more error messages for failed launches @@ -24,12 +27,20 @@ Changelog 2.2.2 - No Controller = true idle - Orbital Laser Drill - - laserDrillPlanet=false: simpler GUI + "void cobble" toggle (huge performance boost) + - laserDrillPlanet=false: simpler GUI + "void cobble" toggle (big performance boost) - Early-outs when not constructed / no redstone etc (idle = idle) - Station Controllers - GUI shows if station is anchored +- Observatory + - Databuses: type could become undefined; now keeps contents on deconstruction + - Server scanning fixed + - Stale lists fixed + +- Area Gravity Controller + - Added explanation for the 6 squares in GUI + - Rocket Loader/Unloader + Fluid Loader/Unloader - Accepts most modded tanks/inventories - Added explanation for the 6 squares in GUI @@ -37,14 +48,14 @@ Changelog 2.2.2 - Config - nuclearRocketsRespectArtifactGating=true - EnableOrbitalRegistry=true + - dataBusBigMultiplier = 4 - Bugfix - Docking pads blocking rocket dismantle - - Space-to-launch only triggers on "down" press (fixes heavy modpacks launching issues) + - Space-to-launch only triggers on "down" press (fixes heavy modpacks) - Negative/null weather timers crash - - Observatory databuses: type could become LOCKED as undefined; now keeps contents on deconstruction - - Observatory server scan + stale asteroid list fixes - - Rare NPE when starID changes / missing + - Rare NPE when corrupt / missing starID + - Solar Satellites sending wrong values to receiver - Tooltips - Further polished @@ -54,7 +65,6 @@ Changelog 2.2.2 - English polished - Many hardcoded English strings fixed - Changelog 2.2.1-1: -Terraforming Terminal: From 4e87c324ccafd7f48bbbe6fc29228d406e9dc8e9 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 22 Dec 2025 12:20:06 +0100 Subject: [PATCH 420/424] Update changelog with new features and hints --- changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 215f460d6..4d46c9497 100644 --- a/changelog.md +++ b/changelog.md @@ -10,7 +10,7 @@ Changelog 2.2.2 - Capacity= 2000 * 4 = 8000 (default) - Keeps data when broken (NOT a "Satellite Component") --ItemSatellite +- ItemSatellite - Added to tooltip: "Data gen: x/s" - Rocket From 5971ad5eeb0a2c9cd58278d72724e28dc32f3da0 Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 22 Dec 2025 12:25:11 +0100 Subject: [PATCH 421/424] Revise changelog for version updates and fixes Updated changelog with recent changes and acknowledgments. --- changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/changelog.md b/changelog.md index 4d46c9497..3b3756c26 100644 --- a/changelog.md +++ b/changelog.md @@ -65,6 +65,9 @@ Changelog 2.2.2 - English polished - Many hardcoded English strings fixed +thanks to (ZY, Hades, Xonazeth, and all reports and feedback) +(RoughlyEnoughIDs 2.2.4 is now compatible with AR again) thanks to jchung + Changelog 2.2.1-1: -Terraforming Terminal: From 44bcd53ef699f61b841c2aeb79b36cd8ff0d034c Mon Sep 17 00:00:00 2001 From: kaduvill Date: Mon, 22 Dec 2025 12:28:27 +0100 Subject: [PATCH 422/424] Update gravity controller messages for clarity --- src/main/resources/assets/advancedrocketry/lang/en_US.lang | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/en_US.lang b/src/main/resources/assets/advancedrocketry/lang/en_US.lang index 864777ff1..f48be615f 100644 --- a/src/main/resources/assets/advancedrocketry/lang/en_US.lang +++ b/src/main/resources/assets/advancedrocketry/lang/en_US.lang @@ -425,8 +425,8 @@ msg.biomescanner.star=If only my sensors had sunshades msg.gravitycontroller.radius=Radius: msg.gravitycontroller.targetgrav=Target Gravity: msg.gravitycontroller.none=No Force -msg.gravitycontroller.activeadd=Add Force (combine sides) -msg.gravitycontroller.activeset=Add Force (combine sides) + lift +msg.gravitycontroller.activeadd=Add Force (combine directions) +msg.gravitycontroller.activeset=Add Force (combine directions) + lift msg.gravitycontroller.targetdir.1=Target-> msg.gravitycontroller.targetdir.2=Direction msg.railgun.transfermin=Min Transfer Size From df5635e7c1a9d54fabce255b8e9a5d9307044c8f Mon Sep 17 00:00:00 2001 From: ZetaY <34602681+ZHAY10086@users.noreply.github.com> Date: Mon, 22 Dec 2025 19:29:22 +0800 Subject: [PATCH 423/424] Update zh_CN.lang --- .../assets/advancedrocketry/lang/zh_CN.lang | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang index 2f345b183..e8bdeb143 100644 --- a/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang +++ b/src/main/resources/assets/advancedrocketry/lang/zh_CN.lang @@ -424,9 +424,9 @@ msg.biomescanner.gas=哈,是气体环境,对吧? msg.biomescanner.star=要是我的传感器有遮阳板就好了 msg.gravitycontroller.radius=半径: msg.gravitycontroller.targetgrav=目标重力: -msg.gravitycontroller.none=复位 -msg.gravitycontroller.activeset=激活:设置 -msg.gravitycontroller.activeadd=激活:添加 +msg.gravitycontroller.none=无作用力 +msg.gravitycontroller.activeadd=添加作用力(合并各方向) +msg.gravitycontroller.activeset=添加作用力(合并各方向)+升力 msg.gravitycontroller.targetdir.1=目标-> msg.gravitycontroller.targetdir.2=方向 msg.railgun.transfermin=最小传输尺寸 @@ -721,6 +721,7 @@ tooltip.advancedrocketry.oxidizerfueltank.alt.1=§f双组元推进剂火箭需 # Nuclear Fuel Tank tooltip.advancedrocketry.nuclearfueltank=§c火箭的组成部分 +tooltip.advancedrocketry.nuclearfueltank.1=§6可进行行星航行! tooltip.advancedrocketry.nuclearfueltank.shift.1=§f可容纳:§b%s tooltip.advancedrocketry.nuclearfueltank.alt.1=§f需要§b核热堆芯§f和§b核热发动机 @@ -731,13 +732,15 @@ tooltip.advancedrocketry.monopropmotor.alt.1=查看加油站的JEI页面 # Nuclear Core tooltip.advancedrocketry.nuclearcore=§c火箭的组成部分 +tooltip.advancedrocketry.nuclearcore.1=§6可进行行星航行! tooltip.advancedrocketry.nuclearcore.shift.1=必须直接放置在核热发动机 tooltip.advancedrocketry.nuclearcore.shift.2=或其他核热堆芯正上方。 tooltip.advancedrocketry.nuclearcore.alt.1=垂直放置规则不适用于 tooltip.advancedrocketry.nuclearcore.alt.2=无人载具(气体任务火箭) # Nuclear rocketengine -tooltip.advancedrocketry.nuclearmotor=§c火箭的组成部分 §6可进行行星航行! +tooltip.advancedrocketry.nuclearmotor=§c火箭的组成部分 +tooltip.advancedrocketry.nuclearmotor.1=§6可进行行星航行! tooltip.advancedrocketry.nuclearmotor.shift.1=§f使用§b工质 tooltip.advancedrocketry.nuclearmotor.shift.2=正上方需存在核热堆芯。 tooltip.advancedrocketry.nuclearmotor.alt.1=查看加油站的JEI页面 @@ -814,10 +817,10 @@ tooltip.advancedrocketry.monitoringstation.shift.2=§f需连接至§4火箭组 tooltip.advancedrocketry.monitoringstation.alt.1=§b任务将在进入轨道后激活! # Satellite Terminal -tooltip.advancedrocketry.satellitemonitor=用于与卫星通信 -tooltip.advancedrocketry.satellitemonitor.shift.1=放入卫星芯片 -tooltip.advancedrocketry.satellitemonitor.shift.2=下载数据 -tooltip.advancedrocketry.satellitemonitor.alt.1=§f通过无线收发器或数据单元传输并自动下载数据 +tooltip.advancedrocketry.satellitecontrolcenter=用于与卫星通信 +tooltip.advancedrocketry.satellitecontrolcenter.shift.1=放入卫星芯片 +tooltip.advancedrocketry.satellitecontrolcenter.shift.2=下载数据 +tooltip.advancedrocketry.satellitecontrolcenter.alt.1=§f通过无线收发器或数据单元传输并自动下载数据 # Satellite Builder tooltip.advancedrocketry.satellitebuilder=用于组装卫星 @@ -829,10 +832,7 @@ tooltip.advancedrocketry.satellitebuilder.alt.2=核心组件+其他组件 # Orbital Registry tooltip.advancedrocketry.orbitalregistry=追踪太空中的人造物体 tooltip.advancedrocketry.orbitalregistry.shift.1=§f可写入新芯片! -tooltip.advancedrocketry.orbitalregistry.shift.2= tooltip.advancedrocketry.orbitalregistry.alt.1=§f在§4卫星终端§f中使用芯片以销毁卫星 -tooltip.advancedrocketry.orbitalregistry.alt.2= - ### Infrastructure ## BlockARHatch From 7034cd50b3d28aa91d1403694996590e09700f8b Mon Sep 17 00:00:00 2001 From: kaduvill Date: Wed, 7 Jan 2026 19:49:33 +0100 Subject: [PATCH 424/424] Update contributors in changelog.md --- changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.md b/changelog.md index 3b3756c26..4e7227f7d 100644 --- a/changelog.md +++ b/changelog.md @@ -65,7 +65,7 @@ Changelog 2.2.2 - English polished - Many hardcoded English strings fixed -thanks to (ZY, Hades, Xonazeth, and all reports and feedback) +thanks to (ZY, Hades21_21, Xonazeth, and all reports and feedback) (RoughlyEnoughIDs 2.2.4 is now compatible with AR again) thanks to jchung Changelog 2.2.1-1: