Skip to content
This repository was archived by the owner on Aug 31, 2026. It is now read-only.

Commit 63769ab

Browse files
committed
Pin the loop: an address deposited here is one a pad here can aim at
- probe the production gate through a real rocket in the standing world - probe the Deposit path and report which worlds landed, not just how many - mint the target for the negative case so nothing else can satisfy it
1 parent 8e7694c commit 63769ab

3 files changed

Lines changed: 218 additions & 1 deletion

File tree

‎src/main/java/zmaster587/advancedRocketry/command/test/TestProbeCommand.java‎

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2548,6 +2548,34 @@ private void handleTelescope(MinecraftServer server, ICommandSender sender, Stri
25482548
return;
25492549
}
25502550

2551+
if ("deposit".equalsIgnoreCase(verb)) {
2552+
// The Deposit button's own path: read the crystal in the machine into what THIS world
2553+
// knows. Reported as landed/total because an address of a world nobody has landed on has
2554+
// nothing for tier-1 to fly to and is skipped.
2555+
java.util.List<Integer> before = new java.util.ArrayList<>();
2556+
for (zmaster587.advancedRocketry.navigation.CrystalEntry entry
2557+
: zmaster587.advancedRocketry.item.ItemMemoryCrystal.memoryOf(
2558+
scope.getStackInSlot(
2559+
zmaster587.advancedRocketry.tile.multiblock.TileObservatory
2560+
.SLOT_CRYSTAL)).list()) {
2561+
if (entry.namesBody()) {
2562+
before.add(entry.dimId());
2563+
}
2564+
}
2565+
int[] result = scope.uploadCrystalHere();
2566+
StringBuilder dims = new StringBuilder("[");
2567+
for (int i = 0; i < before.size(); i++) {
2568+
if (i > 0) dims.append(',');
2569+
dims.append(before.get(i));
2570+
}
2571+
dims.append(']');
2572+
// The dims are reported, not just the count: a test that could only read "3 landed" would
2573+
// have to guess WHICH worlds a pad here may now be aimed at.
2574+
send(sender, "{\"ok\":true,\"landed\":" + result[0] + ",\"total\":" + result[1]
2575+
+ ",\"dims\":" + dims + "}");
2576+
return;
2577+
}
2578+
25512579
if ("abort".equalsIgnoreCase(verb)) {
25522580
boolean stopped = scope.abortRegionScan();
25532581
send(sender, "{\"ok\":" + stopped + telescopeScanFields(scope, scope.getActiveScan(), world) + "}");
@@ -6007,6 +6035,36 @@ private void handleDim(ICommandSender sender, String[] args) {
60076035
// Planet/weather probes ----------------------------------------------
60086036

60096037
private void handlePlanet(ICommandSender sender, String[] args) {
6038+
// What a TIER-1 launch pad standing on one world may be aimed at, asked of the production
6039+
// gate rather than re-derived here: a real rocket in the standing world answers
6040+
// IPlanetDefiner.isPlanetKnown, and the two halves are reported beside it so a red test says
6041+
// WHICH of them moved - the pack's floor or what this body has learned.
6042+
if (args.length >= 3 && "knowledge".equalsIgnoreCase(args[0])) {
6043+
int standingDim = parseIntOr(args[1], Integer.MIN_VALUE);
6044+
int targetDim = parseIntOr(args[2], Integer.MIN_VALUE);
6045+
net.minecraft.world.World here = net.minecraftforge.common.DimensionManager
6046+
.getWorld(standingDim);
6047+
DimensionProperties target = DimensionManager.getInstance()
6048+
.getDimensionPropertiesOrNull(targetDim);
6049+
DimensionProperties standing = DimensionManager.getInstance()
6050+
.getDimensionPropertiesOrNull(standingDim);
6051+
if (here == null || target == null) {
6052+
send(sender, "{\"error\":\"standing world not loaded or unknown target\"}");
6053+
return;
6054+
}
6055+
zmaster587.advancedRocketry.entity.EntityRocket rocket =
6056+
new zmaster587.advancedRocketry.entity.EntityRocket(here);
6057+
send(sender, "{\"standing\":" + standingDim + ",\"target\":" + targetDim
6058+
+ ",\"known\":" + rocket.isPlanetKnown(target)
6059+
+ ",\"global\":" + DimensionManager.getInstance().isPlanetKnown(targetDim)
6060+
+ ",\"local\":" + (standing != null && standing.isPlanetKnownHere(targetDim))
6061+
+ ",\"research\":"
6062+
+ zmaster587.advancedRocketry.api.ARConfiguration.getCurrentConfig()
6063+
.planetsMustBeDiscovered
6064+
+ "}");
6065+
return;
6066+
}
6067+
60106068
if (args.length >= 2 && "info".equalsIgnoreCase(args[0])) {
60116069
int dim = parseIntOr(args[1], Integer.MIN_VALUE);
60126070
DimensionProperties props = DimensionManager.getInstance().getDimensionProperties(dim);

‎src/main/java/zmaster587/advancedRocketry/tile/multiblock/TileObservatory.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1215,7 +1215,7 @@ public void onInventoryButtonPressed(int buttonId) {
12151215
*
12161216
* @return {@code {landed, total}}
12171217
*/
1218-
private int[] uploadCrystalHere() {
1218+
public int[] uploadCrystalHere() {
12191219
ItemStack crystal = getStackInSlot(SLOT_CRYSTAL);
12201220
if (!ItemMemoryCrystal.isCrystal(crystal)) {
12211221
return new int[] {0, 0};
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
package zmaster587.advancedRocketry.test.server;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
import org.junit.Test;
7+
8+
import static org.junit.Assert.assertEquals;
9+
import static org.junit.Assert.assertFalse;
10+
import static org.junit.Assert.assertTrue;
11+
12+
/**
13+
* The loop the two discovery systems exist to close, driven on a real server: an address is carried
14+
* to a world, deposited there, and a tier-1 launch pad standing on that world may then be aimed at
15+
* it.
16+
*
17+
* <p>The unit and integration tiers pin the pieces - a body carries its own known-set, one body's
18+
* finds never reach its neighbour, a beacon teaches its own system. What only a server can answer is
19+
* whether the PRODUCTION gate a rocket asks agrees: `IPlanetDefiner.isPlanetKnown` reading the world
20+
* it is standing in, with the pack's authored set as the floor beneath it.</p>
21+
*
22+
* <p>Both assertions here are stated against dims the probe itself reports, never against a literal
23+
* this test wrote down: which worlds a survey resolves depends on the server's own sky.</p>
24+
*
25+
* <p>Position-isolated at x=4900-4960 (clear of the survey fixtures at 4300-4660 and the observatory
26+
* multiblock fixtures at 4000-4060).</p>
27+
*/
28+
public class Tier1AimsAtWhatThisWorldKnowsE2ETest extends AbstractSharedServerTest {
29+
30+
private static final int CY = 64;
31+
private static final int CZ = 4900;
32+
private static final int X = 4900;
33+
34+
private String exec(String command) throws Exception {
35+
return String.join("\n", client().execute(command));
36+
}
37+
38+
private String where() {
39+
return "0 " + X + " " + CY + " " + CZ;
40+
}
41+
42+
/** Whether the gate a rocket standing in {@code standing} asks says {@code target} is known. */
43+
private boolean known(int standing, int target) throws Exception {
44+
String reply = exec("artest planet knowledge " + standing + " " + target);
45+
assertTrue("the knowledge probe failed: " + reply, reply.contains("\"known\":"));
46+
return reply.contains("\"known\":true");
47+
}
48+
49+
/** The same reply's two halves, so a red test says WHICH source moved. */
50+
private String halves(int standing, int target) throws Exception {
51+
return exec("artest planet knowledge " + standing + " " + target);
52+
}
53+
54+
/** A numeric field of a probe reply. */
55+
private static int intField(String json, String name) {
56+
String key = "\"" + name + "\":";
57+
int at = json.indexOf(key);
58+
assertTrue("probe reply has no field " + name + ": " + json, at >= 0);
59+
int from = at + key.length();
60+
int to = from;
61+
while (to < json.length() && "-0123456789".indexOf(json.charAt(to)) >= 0) {
62+
to++;
63+
}
64+
return Integer.parseInt(json.substring(from, to));
65+
}
66+
67+
private static List<Integer> ints(String json, String field) {
68+
String key = "\"" + field + "\":[";
69+
int at = json.indexOf(key);
70+
assertTrue("probe reply has no array " + field + ": " + json, at >= 0);
71+
int end = json.indexOf(']', at);
72+
String body = json.substring(at + key.length(), end).trim();
73+
List<Integer> out = new ArrayList<>();
74+
if (!body.isEmpty()) {
75+
for (String piece : body.split(",")) {
76+
out.add(Integer.parseInt(piece.trim()));
77+
}
78+
}
79+
return out;
80+
}
81+
82+
@Test
83+
public void withResearchOnAPadIsNotOfferedAWorldNobodyHasFoundHere() throws Exception {
84+
exec("artest config set planetsMustBeDiscovered true");
85+
86+
assertTrue("the overworld must always be known - it is the floor every pack starts from",
87+
known(0, 0));
88+
89+
// The target is MINTED for this test rather than picked out of the server's planet list: a
90+
// world that has just come into existence cannot be in anybody's known-set, so the assertion
91+
// below cannot be quietly satisfied by whatever another test taught this world earlier.
92+
try {
93+
String installed = exec("artest space gen-install 0.9 2000000 987654321");
94+
assertTrue("the procedural generator must install: " + installed,
95+
installed.contains("\"ok\":true"));
96+
String found = exec("artest space find-procedural 4");
97+
assertTrue("a dense procedural galaxy must offer a landable body: " + found,
98+
found.contains("\"ok\":true"));
99+
String cell = intField(found, "sx") + " " + intField(found, "sy") + " "
100+
+ intField(found, "sz");
101+
String realized = exec("artest space realize " + cell);
102+
assertTrue("realization must mint a world to ask about: " + realized,
103+
realized.contains("\"ok\":true"));
104+
int fresh = intField(realized, "dim");
105+
106+
String reply = halves(0, fresh);
107+
assertTrue("a freshly minted world must be in nobody's global set: " + reply,
108+
reply.contains("\"global\":false"));
109+
assertTrue("nor known on the world we are standing on: " + reply,
110+
reply.contains("\"local\":false"));
111+
assertFalse("and a pad here must therefore not be offered it: " + reply,
112+
known(0, fresh));
113+
} finally {
114+
exec("artest space gen-reset");
115+
}
116+
}
117+
118+
@Test
119+
public void anAddressDepositedHereBecomesSomethingAPadHereCanBeAimedAt() throws Exception {
120+
// The sweep runs with research OFF, where what the instrument reaches is resolved outright -
121+
// the pacing is a different mechanic with its own test, and waiting for it here would only
122+
// make this fixture slower and flakier. The GATE is then asked with research ON, which is
123+
// the mode the whole question exists in.
124+
exec("artest config set planetsMustBeDiscovered false");
125+
exec("artest config set telescopeLimitingMagnitude 30");
126+
exec("artest config set telescopePassiveRadiusSteps 1");
127+
128+
String placed = exec("artest telescope place " + where());
129+
assertTrue("could not place an observatory: " + placed, placed.contains("\"ok\":true"));
130+
String crystal = exec("artest telescope crystal " + where());
131+
assertTrue("the crystal must start blank: " + crystal, crystal.contains("\"addresses\":0"));
132+
133+
// The instrument watching its own neighbourhood: what it resolves are the bodies of the
134+
// system this observatory is standing in, which are the ones that have worlds to fly to.
135+
String swept = exec("artest telescope passive " + where());
136+
assertTrue("the passive sweep did not start: " + swept, swept.contains("\"ok\":true"));
137+
String afterSweep = exec("artest telescope info " + where());
138+
assertFalse("the sweep must be finished with research off: " + afterSweep,
139+
afterSweep.contains("\"scanning\":true"));
140+
exec("artest config set planetsMustBeDiscovered true");
141+
142+
String deposited = exec("artest telescope deposit " + where());
143+
List<Integer> landed = ints(deposited, "dims");
144+
assertFalse("the sweep resolved nothing with a world in it, so there is nothing to deposit"
145+
+ " and this fixture proves nothing: " + deposited, landed.isEmpty());
146+
147+
for (int dim : landed) {
148+
String reply = halves(0, dim);
149+
assertTrue("a deposited address must be known to a pad standing here: " + reply,
150+
reply.contains("\"known\":true"));
151+
assertTrue("and it must be known LOCALLY - the deposit may not touch the global floor: "
152+
+ reply, reply.contains("\"local\":true"));
153+
}
154+
155+
String depositedAgain = exec("artest telescope deposit " + where());
156+
assertEquals("depositing the same crystal twice must land the same addresses, not more",
157+
landed, ints(depositedAgain, "dims"));
158+
}
159+
}

0 commit comments

Comments
 (0)