@@ -2540,14 +2540,57 @@ private void handleTelescope(MinecraftServer server, ICommandSender sender, Stri
25402540 zmaster587.advancedRocketry.api.AdvancedRocketryItems.itemMemoryCrystal);
25412541 // A deliberately BLANK crystal: the starter addresses would make every count a test
25422542 // asserts depend on the world's planet list rather than on what the scan resolved.
2543- zmaster587.advancedRocketry.item.ItemMemoryCrystal.writeMemory(stack,
2544- new zmaster587.advancedRocketry.navigation.CrystalMemory());
2543+ zmaster587.advancedRocketry.navigation.CrystalMemory seeded =
2544+ new zmaster587.advancedRocketry.navigation.CrystalMemory();
2545+ // ...unless a caller names ONE world it must hold. A test that needs the deposit to be
2546+ // the only possible source of a piece of knowledge cannot use a crystal the survey
2547+ // filled, because the survey teaches this world as it goes.
2548+ if (args.length >= 6) {
2549+ int namedDim = parseIntOr(args[5], zmaster587.advancedRocketry.api.Constants.INVALID_PLANET);
2550+ if (namedDim != zmaster587.advancedRocketry.api.Constants.INVALID_PLANET) {
2551+ seeded.record(new zmaster587.advancedRocketry.navigation.CrystalEntry(
2552+ zmaster587.advancedRocketry.space.GalacticCoord.ofSectorLocal(
2553+ 7000L, 0L, 0L, 0L, 0L, 0L),
2554+ "probe-named-" + namedDim,
2555+ zmaster587.advancedRocketry.universe.SystemBodyKind.PLANET,
2556+ zmaster587.advancedRocketry.universe.InfoTier.TELESCOPE, 1L, namedDim));
2557+ }
2558+ }
2559+ zmaster587.advancedRocketry.item.ItemMemoryCrystal.writeMemory(stack, seeded);
25452560 scope.setInventorySlotContents(
25462561 zmaster587.advancedRocketry.tile.multiblock.TileObservatory.SLOT_CRYSTAL, stack);
25472562 send(sender, "{\"ok\":true,\"addresses\":" + crystalAddresses(scope) + "}");
25482563 return;
25492564 }
25502565
2566+ if ("deposit".equalsIgnoreCase(verb)) {
2567+ // The Deposit button's own path: read the crystal in the machine into what THIS world
2568+ // knows. Reported as landed/total because an address of a world nobody has landed on has
2569+ // nothing for tier-1 to fly to and is skipped.
2570+ java.util.List<Integer> before = new java.util.ArrayList<>();
2571+ for (zmaster587.advancedRocketry.navigation.CrystalEntry entry
2572+ : zmaster587.advancedRocketry.item.ItemMemoryCrystal.memoryOf(
2573+ scope.getStackInSlot(
2574+ zmaster587.advancedRocketry.tile.multiblock.TileObservatory
2575+ .SLOT_CRYSTAL)).list()) {
2576+ if (entry.namesBody()) {
2577+ before.add(entry.dimId());
2578+ }
2579+ }
2580+ int[] result = scope.uploadCrystalHere();
2581+ StringBuilder dims = new StringBuilder("[");
2582+ for (int i = 0; i < before.size(); i++) {
2583+ if (i > 0) dims.append(',');
2584+ dims.append(before.get(i));
2585+ }
2586+ dims.append(']');
2587+ // The dims are reported, not just the count: a test that could only read "3 landed" would
2588+ // have to guess WHICH worlds a pad here may now be aimed at.
2589+ send(sender, "{\"ok\":true,\"landed\":" + result[0] + ",\"total\":" + result[1]
2590+ + ",\"dims\":" + dims + "}");
2591+ return;
2592+ }
2593+
25512594 if ("abort".equalsIgnoreCase(verb)) {
25522595 boolean stopped = scope.abortRegionScan();
25532596 send(sender, "{\"ok\":" + stopped + telescopeScanFields(scope, scope.getActiveScan(), world) + "}");
@@ -2630,6 +2673,10 @@ private String telescopeScanFields(zmaster587.advancedRocketry.tile.multiblock.T
26302673 .append(",\"origin\":").append(origin == null ? "null" : "\"" + origin.cellKey() + "\"")
26312674 .append(",\"scanning\":").append(scan != null)
26322675 .append(",\"addresses\":").append(crystalAddresses(scope))
2676+ // WHICH worlds the crystal holds, read without touching anything. A test that had to
2677+ // call `deposit` to find out would have deposited them, and could no longer show
2678+ // that pressing the button is what teaches this world.
2679+ .append(",\"crystalDims\":").append(crystalDims(scope))
26332680 .append(",\"lastDiscoveries\":").append(scope.getLastScanDiscoveries())
26342681 // Where the OPERATOR has the instrument pointed — the tile's own pick, which is what
26352682 // a GUI click changes and what the next scan will use. Distinct from the region a
@@ -2694,6 +2741,29 @@ private int crystalAddresses(zmaster587.advancedRocketry.tile.multiblock.TileObs
26942741 return zmaster587.advancedRocketry.item.ItemMemoryCrystal.memoryOf(stack).size();
26952742 }
26962743
2744+ /** The dimensions the crystal in that slot names, as a JSON array. Reads nothing into anything. */
2745+ private String crystalDims(zmaster587.advancedRocketry.tile.multiblock.TileObservatory scope) {
2746+ net.minecraft.item.ItemStack stack = scope.getStackInSlot(
2747+ zmaster587.advancedRocketry.tile.multiblock.TileObservatory.SLOT_CRYSTAL);
2748+ if (!zmaster587.advancedRocketry.item.ItemMemoryCrystal.isCrystal(stack)) {
2749+ return "[]";
2750+ }
2751+ StringBuilder out = new StringBuilder("[");
2752+ boolean first = true;
2753+ for (zmaster587.advancedRocketry.navigation.CrystalEntry entry
2754+ : zmaster587.advancedRocketry.item.ItemMemoryCrystal.memoryOf(stack).list()) {
2755+ if (!entry.namesBody()) {
2756+ continue;
2757+ }
2758+ if (!first) {
2759+ out.append(',');
2760+ }
2761+ out.append(entry.dimId());
2762+ first = false;
2763+ }
2764+ return out.append(']').toString();
2765+ }
2766+
26972767 private zmaster587.advancedRocketry.tile.multiblock.TileObservatory observatoryAt(
26982768 net.minecraft.world.World world, BlockPos pos) {
26992769 net.minecraft.tileentity.TileEntity te = world.getTileEntity(pos);
@@ -5230,7 +5300,21 @@ private void handleSpace(MinecraftServer server, ICommandSender sender, String[]
52305300 zmaster587.advancedRocketry.space.GalacticCoord.ofSectorLocal(
52315301 parseIntOr(args[1], 0), parseIntOr(args[2], 0), parseIntOr(args[3], 0),
52325302 0L, 0L, 0L);
5233- int dimId = zmaster587.advancedRocketry.universe.PlanetRealizer.realize(server, cell);
5303+ // A cell names a family - a planet and the moons that share its address - so the probe
5304+ // states WHICH of them it means. Default 0, the planet, with an optional variant arg;
5305+ // a caller that wants the moon has to say so, exactly as a descent does.
5306+ int variant = args.length >= 5 ? parseIntOr(args[4], 0) : 0;
5307+ java.util.List<zmaster587.advancedRocketry.universe.SystemBody> family =
5308+ zmaster587.advancedRocketry.universe.UniverseRegistry.get(server) == null
5309+ ? java.util.Collections.<zmaster587.advancedRocketry.universe.SystemBody>emptyList()
5310+ : zmaster587.advancedRocketry.universe.UniverseRegistry.get(server)
5311+ .realizableBodiesAt(cell);
5312+ if (variant < 0 || variant >= family.size()) {
5313+ send(sender, "{\"ok\":false,\"reason\":\"no body with that variant in the cell\"}");
5314+ return;
5315+ }
5316+ int dimId = zmaster587.advancedRocketry.universe.PlanetRealizer.realize(server,
5317+ family.get(variant));
52345318 if (dimId == zmaster587.advancedRocketry.api.Constants.INVALID_PLANET) {
52355319 send(sender, "{\"ok\":false,\"reason\":\"nothing landable in that cell\"}");
52365320 return;
@@ -5993,6 +6077,36 @@ private void handleDim(ICommandSender sender, String[] args) {
59936077 // Planet/weather probes ----------------------------------------------
59946078
59956079 private void handlePlanet(ICommandSender sender, String[] args) {
6080+ // What a TIER-1 launch pad standing on one world may be aimed at, asked of the production
6081+ // gate rather than re-derived here: a real rocket in the standing world answers
6082+ // IPlanetDefiner.isPlanetKnown, and the two halves are reported beside it so a red test says
6083+ // WHICH of them moved - the pack's floor or what this body has learned.
6084+ if (args.length >= 3 && "knowledge".equalsIgnoreCase(args[0])) {
6085+ int standingDim = parseIntOr(args[1], Integer.MIN_VALUE);
6086+ int targetDim = parseIntOr(args[2], Integer.MIN_VALUE);
6087+ net.minecraft.world.World here = net.minecraftforge.common.DimensionManager
6088+ .getWorld(standingDim);
6089+ DimensionProperties target = DimensionManager.getInstance()
6090+ .getDimensionPropertiesOrNull(targetDim);
6091+ DimensionProperties standing = DimensionManager.getInstance()
6092+ .getDimensionPropertiesOrNull(standingDim);
6093+ if (here == null || target == null) {
6094+ send(sender, "{\"error\":\"standing world not loaded or unknown target\"}");
6095+ return;
6096+ }
6097+ zmaster587.advancedRocketry.entity.EntityRocket rocket =
6098+ new zmaster587.advancedRocketry.entity.EntityRocket(here);
6099+ send(sender, "{\"standing\":" + standingDim + ",\"target\":" + targetDim
6100+ + ",\"known\":" + rocket.isPlanetKnown(target)
6101+ + ",\"global\":" + DimensionManager.getInstance().isPlanetKnown(targetDim)
6102+ + ",\"local\":" + (standing != null && standing.isPlanetKnownHere(targetDim))
6103+ + ",\"research\":"
6104+ + zmaster587.advancedRocketry.api.ARConfiguration.getCurrentConfig()
6105+ .planetsMustBeDiscovered
6106+ + "}");
6107+ return;
6108+ }
6109+
59966110 if (args.length >= 2 && "info".equalsIgnoreCase(args[0])) {
59976111 int dim = parseIntOr(args[1], Integer.MIN_VALUE);
59986112 DimensionProperties props = DimensionManager.getInstance().getDimensionProperties(dim);
0 commit comments