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

Commit d805b3a

Browse files
committed
A beacon announces itself to its own system, not to the galaxy
- teach every body of the beacon's system, moons included - stop re-announcing to the global set on load; the local sets hold it - return who learned, so the caller owns the syncing
1 parent 46cb7de commit d805b3a

2 files changed

Lines changed: 104 additions & 3 deletions

File tree

src/main/java/zmaster587/advancedRocketry/dimension/DimensionProperties.java

Lines changed: 59 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -767,11 +767,64 @@ public void setHasRings(boolean value) {
767767
//Adds a beacon location to the planet's surface
768768
public void addBeaconLocation(World world, HashedBlockPosition pos) {
769769
beaconLocations.add(pos);
770-
DimensionManager.getInstance().knownPlanets.add(getId());
771770

772771
//LAAZZY
773-
if (!world.isRemote)
772+
if (!world.isRemote) {
773+
for (DimensionProperties taught : teachOwnSystem()) {
774+
PacketHandler.sendToAll(new PacketDimInfo(taught.getId(), taught));
775+
}
774776
PacketHandler.sendToAll(new PacketDimInfo(getId(), this));
777+
}
778+
}
779+
780+
/**
781+
* Tell the bodies of this body's own system that this place exists, and return the ones that
782+
* did not already know.
783+
*
784+
* <p><b>A beacon is a local announcement, not a galactic one.</b> It used to add this planet to
785+
* the GLOBAL known-set, so planting one anywhere made the place selectable from every launch pad
786+
* in the game. What is true is narrower and more interesting: the neighbours know, because they
787+
* can see it. So the beacon writes into the known-set of every body of its own system, and
788+
* nothing outside that system learns anything.</p>
789+
*
790+
* <p>It can never be the thing that first reveals a place - a beacon is planted by hand, so
791+
* somebody already flew here, which means the destination was already reachable. That is why
792+
* scoping it costs nothing: a beacon spreads knowledge inside reach and never creates reach.</p>
793+
*/
794+
public List<DimensionProperties> teachOwnSystem() {
795+
List<DimensionProperties> taught = new ArrayList<>();
796+
discoverPlanet(getId()); // the body it stands on, always - the degenerate system of one
797+
StellarBody star = getStar();
798+
if (star == null) {
799+
return taught; // a world with no star of its own: the beacon teaches only its own ground
800+
}
801+
for (IDimensionProperties sibling : star.getPlanets()) {
802+
DimensionProperties props = DimensionManager.getInstance()
803+
.getDimensionPropertiesOrNull(sibling.getId());
804+
if (props == null) {
805+
continue;
806+
}
807+
teach(props, taught);
808+
// A moon is a child of its planet rather than of the star, so the star's list alone
809+
// would leave every moon of the system ignorant of a beacon in it.
810+
for (int childId : props.getChildPlanets()) {
811+
DimensionProperties child = DimensionManager.getInstance()
812+
.getDimensionPropertiesOrNull(childId);
813+
if (child != null) {
814+
teach(child, taught);
815+
}
816+
}
817+
}
818+
return taught;
819+
}
820+
821+
/** Teach {@code body} about this place, collecting it when that changed anything. */
822+
private void teach(DimensionProperties body, List<DimensionProperties> taught) {
823+
if (body.getId() == getId() || body.isPlanetKnownHere(getId())) {
824+
return;
825+
}
826+
body.discoverPlanet(getId());
827+
taught.add(body);
775828
}
776829

777830
public HashSet<HashedBlockPosition> getBeacons() {
@@ -1692,7 +1745,10 @@ private void readFromTechnicalNBT(NBTTagCompound nbt) {
16921745
int[] location = list.getIntArrayAt(i);
16931746
beaconLocations.add(new HashedBlockPosition(location[0], location[1], location[2]));
16941747
}
1695-
DimensionManager.getInstance().knownPlanets.add(getId());
1748+
// No global add on load any more. What a beacon taught is held by the bodies it taught,
1749+
// in their own saved known-sets, so re-announcing this place to the whole game at every
1750+
// load would put back exactly the reach the scoping removed. A world whose beacons
1751+
// predate the local sets simply has nothing recorded - 3.0.0 carries no old saves.
16961752
} else
16971753
beaconLocations.clear();
16981754

src/test/java/zmaster587/advancedRocketry/test/integration/LocalKnowledgeBelongsToABodyTest.java

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
package zmaster587.advancedRocketry.test.integration;
22

3+
import java.util.List;
4+
35
import net.minecraft.nbt.NBTTagCompound;
46
import org.junit.BeforeClass;
57
import org.junit.Test;
8+
import zmaster587.advancedRocketry.api.dimension.solar.StellarBody;
9+
import zmaster587.advancedRocketry.dimension.DimensionManager;
610
import zmaster587.advancedRocketry.dimension.DimensionProperties;
711
import zmaster587.advancedRocketry.test.MinecraftBootstrap;
812

@@ -34,6 +38,47 @@ public static void bootstrap() {
3438
MinecraftBootstrap.ensure();
3539
}
3640

41+
@Test
42+
public void aBeaconTeachesItsOwnSystemAndNothingBeyondIt() {
43+
// A beacon used to add its planet to the GLOBAL known-set, so planting one made the place
44+
// selectable from every launch pad in the game. What is actually true is narrower: the
45+
// neighbours know, because they are the ones who can see it.
46+
StellarBody star = new StellarBody();
47+
star.setId(910);
48+
star.setName("Beacon-Test");
49+
star.setTemperature(100);
50+
DimensionManager.getInstance().addStar(star);
51+
52+
DimensionProperties beaconed = registerBody(9101, star);
53+
DimensionProperties sibling = registerBody(9102, star);
54+
DimensionProperties elsewhere = registerBody(9201, null);
55+
56+
List<DimensionProperties> taught = beaconed.teachOwnSystem();
57+
58+
assertTrue("the body the beacon stands on must know itself",
59+
beaconed.isPlanetKnownHere(9101));
60+
assertTrue("a body of the same system must learn it", sibling.isPlanetKnownHere(9101));
61+
assertFalse("a body outside the system must learn nothing",
62+
elsewhere.isPlanetKnownHere(9101));
63+
assertTrue("and the sibling must be reported as changed, so it can be synced",
64+
taught.contains(sibling));
65+
66+
List<DimensionProperties> again = beaconed.teachOwnSystem();
67+
assertTrue("a second beacon in the same system teaches nobody twice", again.isEmpty());
68+
}
69+
70+
/** A body registered with the planet layer, optionally orbiting {@code star}. */
71+
private static DimensionProperties registerBody(int dimId, StellarBody star) {
72+
DimensionProperties props = new DimensionProperties(dimId);
73+
props.setName("Body-" + dimId);
74+
if (star != null) {
75+
props.setStar(star);
76+
star.addPlanet(props);
77+
}
78+
DimensionManager.getInstance().registerDimNoUpdate(props, false);
79+
return props;
80+
}
81+
3782
@Test
3883
public void whatOneBodyLearnsIsNotKnownOnAnother() {
3984
DimensionProperties here = new DimensionProperties(101);

0 commit comments

Comments
 (0)