@@ -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
0 commit comments