Skip to content

Commit ce6e7a2

Browse files
tastybentoclaude
andcommitted
Revert "fix: first /level after zero scan adopts live total as canonical baseline"
This reverts commit 178d85a. The overwrite was wrong: it made the first regular /level after a zero scan adopt the live totalPoints as the baseline, which absorbed any blocks the player had placed before that /level into the handicap. A fresh SkyBlock island with three diamond blocks reported level 0, defeating the entire point of the level addon. Kept in place (still correct, addresses real bugs): - per-chunk handicap reconcile + addHandicapChunk (22f20bb) - results.initialCount refresh in tidyUp (f254f04) - 30s zero-scan delay + drift diagnostic logging (7715a12) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 178d85a commit ce6e7a2

4 files changed

Lines changed: 2 additions & 111 deletions

File tree

src/main/java/world/bentobox/level/LevelsManager.java

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -749,14 +749,9 @@ public long reconcileHandicapChunks(@NonNull Island island,
749749
if (zeroScan) {
750750
// Hard reset — the new baseline is everything the scan saw. The
751751
// initial count is rewritten separately by the caller, since a
752-
// zero scan is meant to be the canonical re-baseline. Flag
753-
// handicapPending so the next regular scan adopts its live total
754-
// as the final baseline — that's what absorbs decoration
755-
// evolution, spawner/chest follow-up values, and any
756-
// listener-deferred chunks the per-chunk capture missed.
752+
// zero scan is meant to be the canonical re-baseline.
757753
persisted.clear();
758754
persisted.putAll(scannedChunkValues);
759-
data.setHandicapPending(Boolean.TRUE);
760755
handler.saveObjectAsync(data);
761756
return 0L;
762757
}
@@ -767,22 +762,11 @@ public long reconcileHandicapChunks(@NonNull Island island,
767762
// feature existed. The existing initialCount already covers
768763
// every chunk currently on disk, so seeding the map without
769764
// touching initialCount keeps the level stable while moving
770-
// future drift detection onto the per-chunk path. Don't
771-
// flip handicapPending here — that would wipe established
772-
// player progress on the next /level.
765+
// future drift detection onto the per-chunk path.
773766
persisted.putAll(scannedChunkValues);
774767
handler.saveObjectAsync(data);
775768
return 0L;
776769
}
777-
// Fresh island whose zero scan either hasn't run yet, hasn't
778-
// finalised yet (waiting on awaitPendingZeros), or finished
779-
// out-of-order with this regular scan. Flag handicapPending so
780-
// tidyUp's baseline finalisation adopts the live total as the
781-
// canonical baseline. Without this, the per-chunk reconcile
782-
// below seeds the map with block-only values, leaving the
783-
// spawner/chest follow-up values floating in totalPoints and
784-
// appearing as level on a fresh island.
785-
data.setHandicapPending(Boolean.TRUE);
786770
}
787771
long delta = 0L;
788772
int newChunks = 0;

src/main/java/world/bentobox/level/calculators/IslandLevelCalculator.java

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -925,28 +925,6 @@ public void tidyUp() {
925925
long blockAndDeathPoints = this.results.rawBlockCount.get();
926926
this.results.totalPoints.set(blockAndDeathPoints);
927927

928-
// First regular scan after a zero scan: adopt the live total as the
929-
// canonical baseline. The zero scan set handicapPending=true; this
930-
// overwrite absorbs decoration evolution, listener-deferred chunks,
931-
// spawner/chest follow-up values, and any race between zero scan
932-
// and regular scan into one consistent number, so the player sees
933-
// level=0 on a fresh island. Subsequent regular scans see
934-
// handicapPending=false and use the normal frozen-once handicap so
935-
// player builds count toward level.
936-
if (!zeroIsland && addon.getSettings().isZeroNewIslandLevels()
937-
&& !addon.getSettings().isDonationsOnly()) {
938-
world.bentobox.level.objects.IslandLevels data =
939-
addon.getManager().getLevelsData(island);
940-
if (data != null && Boolean.TRUE.equals(data.getHandicapPending())) {
941-
long total = this.results.totalPoints.get();
942-
addon.getManager().setInitialIslandCount(island, total);
943-
data.setHandicapPending(Boolean.FALSE);
944-
results.initialCount.set(total);
945-
addon.log("Handicap baseline finalised at " + total
946-
+ " for island " + island.getUniqueId());
947-
}
948-
}
949-
950928
if (this.addon.getSettings().getDeathPenalty() > 0) {
951929
// Proper death penalty calculation.
952930
blockAndDeathPoints -= this.results.deathHandicap.get() * this.addon.getSettings().getDeathPenalty();

src/main/java/world/bentobox/level/objects/IslandLevels.java

Lines changed: 0 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -119,22 +119,6 @@ public class IslandLevels implements DataObject {
119119
@Expose
120120
private Map<String, Long> handicapChunks;
121121

122-
/**
123-
* Set to {@code true} when a zero scan has just populated the handicap
124-
* map but the player hasn't run {@code /level} yet; the next regular
125-
* scan adopts its live total as the canonical baseline, absorbing any
126-
* decoration evolution, listener-deferred chunks, and spawner/chest
127-
* follow-up values that fell outside the per-chunk capture. Cleared
128-
* back to {@code false} on that overwrite so subsequent scans see the
129-
* normal frozen-once handicap.
130-
* <p>
131-
* Null on legacy data — treated as false, so existing islands aren't
132-
* accidentally rebaselined on upgrade (which would wipe player
133-
* progress).
134-
*/
135-
@Expose
136-
private Boolean handicapPending;
137-
138122
/**
139123
* Constructor for new island
140124
* @param islandUUID - island UUID
@@ -409,22 +393,6 @@ public void setHandicapChunks(Map<String, Long> handicapChunks) {
409393
this.handicapChunks = handicapChunks;
410394
}
411395

412-
/**
413-
* @return {@code true} if a zero scan has just finished and the next
414-
* regular scan should adopt its live total as the baseline.
415-
* Null on legacy data (treated as false by callers).
416-
*/
417-
public Boolean getHandicapPending() {
418-
return handicapPending;
419-
}
420-
421-
/**
422-
* @param handicapPending the handicapPending to set
423-
*/
424-
public void setHandicapPending(Boolean handicapPending) {
425-
this.handicapPending = handicapPending;
426-
}
427-
428396
/**
429397
* @return the initialLevel
430398
* @deprecated only used for backwards compatibility. Use {@link #getInitialCount()} instead

src/test/java/world/bentobox/level/LevelsManagerTest.java

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -528,45 +528,6 @@ void testReconcileHandicapChunksLegacyMigration() throws Exception {
528528
assertEquals(100L, legacy.getHandicapChunks().get("world:1"));
529529
}
530530

531-
/**
532-
* Pin down that zero-scan reconcile sets handicapPending=true and a
533-
* fresh-island reconcile (empty map + zero initialCount) does the same.
534-
* tidyUp will then adopt the live scan total as the canonical baseline.
535-
* Legacy migration (empty map + positive initialCount) must NOT set the
536-
* flag — flipping it on an old island would wipe established player
537-
* progress on the next /level.
538-
*/
539-
@Test
540-
void testReconcileSetsHandicapPendingForBaselineFinalisation() throws Exception {
541-
// Zero scan: pending=true so first regular scan overwrites.
542-
IslandLevels zeroScanData = new IslandLevels(uuid.toString());
543-
when(handler.loadObject(uuid.toString())).thenReturn(zeroScanData);
544-
lm.reconcileHandicapChunks(island, Map.of("world:1", 100L), true);
545-
assertEquals(Boolean.TRUE, zeroScanData.getHandicapPending(),
546-
"zero scan flags the next regular scan for baseline overwrite");
547-
548-
// Fresh island, no prior scan: pending=true so the very first regular
549-
// scan establishes the baseline correctly even if zero scan raced.
550-
UUID otherId = UUID.randomUUID();
551-
when(island.getUniqueId()).thenReturn(otherId.toString());
552-
IslandLevels freshData = new IslandLevels(otherId.toString());
553-
when(handler.loadObject(otherId.toString())).thenReturn(freshData);
554-
lm.reconcileHandicapChunks(island, Map.of("world:1", 100L), false);
555-
assertEquals(Boolean.TRUE, freshData.getHandicapPending(),
556-
"fresh-island regular scan flags itself for baseline overwrite");
557-
558-
// Legacy migration: pending stays null. Old islands keep their
559-
// established progress across the upgrade.
560-
UUID legacyId = UUID.randomUUID();
561-
when(island.getUniqueId()).thenReturn(legacyId.toString());
562-
IslandLevels legacyData = new IslandLevels(legacyId.toString());
563-
legacyData.setInitialCount(5000L);
564-
when(handler.loadObject(legacyId.toString())).thenReturn(legacyData);
565-
lm.reconcileHandicapChunks(island, Map.of("world:1", 100L), false);
566-
assertEquals(null, legacyData.getHandicapPending(),
567-
"legacy migration does NOT flag baseline overwrite");
568-
}
569-
570531
/**
571532
* Zero-scan reconciliation hard-resets the map and returns 0 (the caller
572533
* rewrites initialCount separately via setInitialIslandCount).

0 commit comments

Comments
 (0)