Skip to content

Commit 66ed051

Browse files
authored
Merge pull request #162 from BentoBoxWorld/121-oneblock-phase-requirement
Add AOneBlock phase requirement for generators (#121)
2 parents aeade4f + c971095 commit 66ed051

7 files changed

Lines changed: 188 additions & 1 deletion

File tree

pom.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
<bentobox.version>3.14.0-SNAPSHOT</bentobox.version>
3939
<level.version>2.5.0</level.version>
4040
<bank.version>1.4.0</bank.version>
41+
<aoneblock.version>1.18.0</aoneblock.version>
4142
<!-- Test dependency versions -->
4243
<junit.version>5.10.2</junit.version>
4344
<mockito.version>5.11.0</mockito.version>
@@ -151,6 +152,12 @@
151152
<version>${bank.version}</version>
152153
<scope>provided</scope>
153154
</dependency>
155+
<dependency>
156+
<groupId>world.bentobox</groupId>
157+
<artifactId>aoneblock</artifactId>
158+
<version>${aoneblock.version}</version>
159+
<scope>provided</scope>
160+
</dependency>
154161
<dependency>
155162
<groupId>net.milkbowl.vault</groupId>
156163
<artifactId>VaultAPI</artifactId>

src/main/java/world/bentobox/magiccobblestonegenerator/database/objects/GeneratorTierObject.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,29 @@ public void setRequiredGeneratorTiers(Set<String> requiredGeneratorTiers)
229229
}
230230

231231

232+
/**
233+
* Method GeneratorTierObject#getRequiredPhase returns the AOneBlock phase that must be reached before this
234+
* generator becomes available.
235+
*
236+
* @return the requiredPhase (type String) of this object, or an empty string if none.
237+
*/
238+
public String getRequiredPhase()
239+
{
240+
return requiredPhase == null ? "" : requiredPhase;
241+
}
242+
243+
244+
/**
245+
* Method GeneratorTierObject#setRequiredPhase sets new value for the requiredPhase of this object.
246+
*
247+
* @param requiredPhase new value for this object.
248+
*/
249+
public void setRequiredPhase(String requiredPhase)
250+
{
251+
this.requiredPhase = requiredPhase == null ? "" : requiredPhase;
252+
}
253+
254+
232255
/**
233256
* Method GeneratorTierObject#getGeneratorTierCost returns the generatorTierCost of this object.
234257
*
@@ -572,6 +595,7 @@ public GeneratorTierObject clone()
572595
clone.setRequiredBiomes(new HashSet<>(this.requiredBiomes));
573596
clone.setRequiredPermissions(new HashSet<>(this.requiredPermissions));
574597
clone.setRequiredGeneratorTiers(new HashSet<>(this.getRequiredGeneratorTiers()));
598+
clone.setRequiredPhase(this.requiredPhase);
575599
clone.setGeneratorTierCost(this.generatorTierCost);
576600
clone.setActivationCost(this.activationCost);
577601
clone.setDeployed(this.deployed);
@@ -725,6 +749,12 @@ public boolean includes(GeneratorType type)
725749
@Expose
726750
private Set<String> requiredGeneratorTiers = Collections.emptySet();
727751

752+
/**
753+
* AOneBlock phase that must be reached before this generator becomes available. Empty means no phase requirement.
754+
*/
755+
@Expose
756+
private String requiredPhase = "";
757+
728758
/**
729759
* Cost to do buy current generator.
730760
*/

src/main/java/world/bentobox/magiccobblestonegenerator/managers/StoneGeneratorManager.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import world.bentobox.bank.BankResponse;
3333
import world.bentobox.bank.data.Money;
3434
import world.bentobox.bank.data.TxType;
35+
import world.bentobox.aoneblock.AOneBlock;
3536
import world.bentobox.bentobox.api.addons.GameModeAddon;
3637
import world.bentobox.bentobox.api.localization.TextVariables;
3738
import world.bentobox.bentobox.api.user.User;
@@ -877,6 +878,9 @@ public void checkGeneratorUnlockStatus(Island island, @Nullable User user, @Null
877878
// is unlocked earlier in this same pass and is visible here.
878879
filter(generator -> dataObject.getUnlockedTiers().containsAll(generator.getRequiredGeneratorTiers()))
879880
.
881+
// Filter out generators whose required AOneBlock phase has not been reached yet (#121).
882+
filter(generator -> this.isPhaseRequirementMet(island, generator))
883+
.
880884
// Now process each generator.
881885
forEach(generator -> this.unlockGenerator(dataObject, user, island, generator));
882886

@@ -1546,6 +1550,36 @@ public boolean isMembersOnline(Location location) {
15461550
return false;
15471551
}
15481552

1553+
/**
1554+
* This method returns whether the given generator's AOneBlock phase requirement is met for the given island. A
1555+
* generator with no required phase is always considered met. Otherwise the island's world must be an AOneBlock world
1556+
* and the island must have reached (block count) the required phase's starting block (#121).
1557+
*
1558+
* @param island the island.
1559+
* @param generator the generator tier to check.
1560+
* @return {@code true} if the phase requirement is met.
1561+
*/
1562+
private boolean isPhaseRequirementMet(@NotNull Island island, @NotNull GeneratorTierObject generator) {
1563+
final String requiredPhase = generator.getRequiredPhase();
1564+
1565+
if (requiredPhase == null || requiredPhase.isEmpty()) {
1566+
// No phase requirement.
1567+
return true;
1568+
}
1569+
1570+
Optional<GameModeAddon> gameMode = this.addon.getPlugin().getIWM().getAddon(island.getWorld());
1571+
1572+
if (gameMode.isEmpty() || !(gameMode.get() instanceof AOneBlock aoneBlock)) {
1573+
// Phase requirements only apply to AOneBlock worlds.
1574+
return false;
1575+
}
1576+
1577+
// The requirement is met once the island's block count has reached the required phase's starting block.
1578+
return aoneBlock.getOneBlockManager().getPhase(requiredPhase)
1579+
.map(phase -> aoneBlock.getOneBlocksIsland(island).getBlockNumber() >= phase.getBlockNumberValue())
1580+
.orElse(false);
1581+
}
1582+
15491583
/**
15501584
* This method returns long that represents given island level.
15511585
*

src/main/java/world/bentobox/magiccobblestonegenerator/panels/CommonPanel.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,6 +535,18 @@ private String generateRequirementsDescription(GeneratorTierObject generator,
535535
level = "";
536536
}
537537

538+
String phase;
539+
540+
if (!generator.getRequiredPhase().isEmpty() && !isUnlocked)
541+
{
542+
phase = this.user.getTranslationOrNothing(reference + "phase",
543+
TextVariables.NAME, generator.getRequiredPhase());
544+
}
545+
else
546+
{
547+
phase = "";
548+
}
549+
538550
StringBuilder permissions = new StringBuilder();
539551

540552
if (!generator.getRequiredPermissions().isEmpty() && !isUnlocked)
@@ -602,6 +614,7 @@ private String generateRequirementsDescription(GeneratorTierObject generator,
602614
return this.user.getTranslationOrNothing(reference + "description",
603615
"[biomes]", biomes.toString(),
604616
"[level]", level,
617+
"[phase]", phase,
605618
"[missing-permissions]", permissions.toString(),
606619
"[required-generators]", requiredGenerators.toString());
607620
}

src/main/resources/locales/en-US.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,10 +921,13 @@ stone-generator:
921921
description: |-
922922
[biomes]
923923
[level]
924+
[phase]
924925
[required-generators]
925926
[missing-permissions]
926927
# Generates [level] message.
927928
level: "<red><bold>Required Level: </bold></red><red>[number]</red>"
929+
# Generates [phase] message (AOneBlock only).
930+
phase: "<red><bold>Required Phase: </bold></red><red>[name]</red>"
928931
# Generates [required-generators] message title.
929932
required-generators-title: "<red><bold>Required Generators:</bold></red>"
930933
# Generates [required-generators] message values.

src/test/java/world/bentobox/magiccobblestonegenerator/database/objects/GeneratorTierObjectTest.java

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,39 @@
1212
import world.bentobox.magiccobblestonegenerator.CommonTestSetup;
1313

1414
/**
15-
* Tests for the requiredGeneratorTiers (#88) and activateOnUnlock (#106) fields of {@link GeneratorTierObject}.
15+
* Tests for the requiredGeneratorTiers (#88), activateOnUnlock (#106) and requiredPhase (#121) fields of
16+
* {@link GeneratorTierObject}.
1617
*/
1718
class GeneratorTierObjectTest extends CommonTestSetup {
1819

20+
@Test
21+
void testRequiredPhaseDefaultsToEmpty() {
22+
GeneratorTierObject tier = new GeneratorTierObject();
23+
assertTrue(tier.getRequiredPhase().isEmpty());
24+
}
25+
26+
@Test
27+
void testSetAndGetRequiredPhase() {
28+
GeneratorTierObject tier = new GeneratorTierObject();
29+
tier.setRequiredPhase("Underground");
30+
assertEquals("Underground", tier.getRequiredPhase());
31+
}
32+
33+
@Test
34+
void testSetRequiredPhaseNullNormalizedToEmpty() {
35+
GeneratorTierObject tier = new GeneratorTierObject();
36+
tier.setRequiredPhase(null);
37+
assertTrue(tier.getRequiredPhase().isEmpty());
38+
}
39+
40+
@Test
41+
void testCloneCopiesRequiredPhase() {
42+
GeneratorTierObject tier = new GeneratorTierObject();
43+
tier.setUniqueId("tier");
44+
tier.setRequiredPhase("Underground");
45+
assertEquals("Underground", tier.clone().getRequiredPhase());
46+
}
47+
1948
@Test
2049
void testRequiredGeneratorTiersDefaultsToEmpty() {
2150
GeneratorTierObject tier = new GeneratorTierObject();

src/test/java/world/bentobox/magiccobblestonegenerator/managers/StoneGeneratorManagerTest.java

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@
2727
import org.mockito.Mockito;
2828
import org.mockito.stubbing.Answer;
2929

30+
import world.bentobox.aoneblock.AOneBlock;
31+
import world.bentobox.aoneblock.dataobjects.OneBlockIslands;
32+
import world.bentobox.aoneblock.oneblocks.OneBlockPhase;
33+
import world.bentobox.aoneblock.oneblocks.OneBlocksManager;
3034
import world.bentobox.bentobox.api.addons.AddonDescription;
3135
import world.bentobox.bentobox.api.addons.GameModeAddon;
3236
import world.bentobox.bentobox.api.user.User;
@@ -571,6 +575,73 @@ void testCheckGeneratorUnlockStatusKeepsDependentLockedWhenPrerequisiteLocked()
571575
assertFalse(data.getUnlockedTiers().contains("magiccobblegenerator_gen2"));
572576
}
573577

578+
/**
579+
* Sets up an AOneBlock world whose island has reached the given block count, plus a phase "Underground" that starts
580+
* at block 100, and a phase-gated generator. Returns the island's data object (#121).
581+
*/
582+
private GeneratorDataObject seedPhaseGenerator(String tierId, int islandBlockCount, boolean aOneBlockWorld) {
583+
sgm.addWorld(world);
584+
when(island.getUniqueId()).thenReturn("island-121");
585+
when(island.getWorld()).thenReturn(world);
586+
when(island.isSpawn()).thenReturn(false);
587+
s.setNotifyUnlockedGenerators(false);
588+
589+
if (aOneBlockWorld) {
590+
AOneBlock aoneBlock = mock(AOneBlock.class);
591+
when(aoneBlock.getDescription()).thenReturn(
592+
new AddonDescription.Builder("", "AOneBlock", "1.0").build());
593+
OneBlockPhase phase = mock(OneBlockPhase.class);
594+
when(phase.getBlockNumberValue()).thenReturn(100);
595+
OneBlocksManager obManager = mock(OneBlocksManager.class);
596+
when(obManager.getPhase("Underground")).thenReturn(Optional.of(phase));
597+
when(aoneBlock.getOneBlockManager()).thenReturn(obManager);
598+
OneBlockIslands obIsland = mock(OneBlockIslands.class);
599+
when(obIsland.getBlockNumber()).thenReturn(islandBlockCount);
600+
when(aoneBlock.getOneBlocksIsland(island)).thenReturn(obIsland);
601+
when(iwm.getAddon(world)).thenReturn(Optional.of(aoneBlock));
602+
}
603+
// Otherwise the default (non-AOneBlock) game mode from CommonTestSetup is used.
604+
605+
GeneratorTierObject tier = prerequisiteTier(tierId, "Phase Gen", 10);
606+
when(tier.getRequiredPhase()).thenReturn("Underground");
607+
sgm.loadGeneratorTier(tier, true, null);
608+
609+
GeneratorDataObject data = sgm.getGeneratorData(island);
610+
assertNotNull(data);
611+
return data;
612+
}
613+
614+
@Test
615+
void testUnlocksPhaseGeneratorWhenPhaseReached() {
616+
// Island at block 150, past the phase's start block of 100.
617+
GeneratorDataObject data = seedPhaseGenerator("aoneblock_phasegen", 150, true);
618+
619+
sgm.checkGeneratorUnlockStatus(island, null, null);
620+
621+
assertTrue(data.getUnlockedTiers().contains("aoneblock_phasegen"));
622+
}
623+
624+
@Test
625+
void testKeepsPhaseGeneratorLockedWhenPhaseNotReached() {
626+
// Island at block 50, before the phase's start block of 100.
627+
GeneratorDataObject data = seedPhaseGenerator("aoneblock_phasegen", 50, true);
628+
629+
sgm.checkGeneratorUnlockStatus(island, null, null);
630+
631+
assertFalse(data.getUnlockedTiers().contains("aoneblock_phasegen"));
632+
}
633+
634+
@Test
635+
void testKeepsPhaseGeneratorLockedInNonAOneBlockWorld() {
636+
// Not an AOneBlock world: the phase requirement can never be satisfied. The tier id matches the default
637+
// game mode so it is still evaluated.
638+
GeneratorDataObject data = seedPhaseGenerator("magiccobblegenerator_phasegen", 150, false);
639+
640+
sgm.checkGeneratorUnlockStatus(island, null, null);
641+
642+
assertFalse(data.getUnlockedTiers().contains("magiccobblegenerator_phasegen"));
643+
}
644+
574645
@Test
575646
void testGetGeneratorDataIsland() {
576647
assertNotNull(sgm.getGeneratorData(island));

0 commit comments

Comments
 (0)