Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
85356c5c8e | ||
|
|
55e4f04f16 |
@@ -1,6 +1,6 @@
|
|||||||
# Spigot Creeper Fear
|
# Spigot Creeper Fear
|
||||||
|
|
||||||
A Spigot 26.2 plugin that lets players earn six Creeper Aura ranks. Once unlocked, an aura prevents creeper explosions that hit the player from breaking blocks, trading that protection for rank-dependent player damage.
|
A Spigot 26.2 plugin that lets players earn six Creeper Aura ranks. Once unlocked, an aura prevents a creeper explosion within 25 blocks of the player from breaking blocks, whether or not the explosion hits the player. Players hit by the explosion receive rank-dependent damage.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ A Spigot 26.2 plugin that lets players earn six Creeper Aura ranks. Once unlocke
|
|||||||
|
|
||||||
## Progression
|
## Progression
|
||||||
|
|
||||||
Players earn one current-tier point when they kill a creeper directly, through a projectile, or through an owned tameable. A self-destructing creeper also awards one point to every player its explosion hits. Each tier defaults to 100 points and resets progress to zero when unlocked.
|
Players earn one current-tier point when they kill a creeper directly, through a projectile, or through an owned tameable. A self-destructing creeper also awards one point to every player its explosion hits. Rank I unlocks at 25 points by default; subsequent ranks require 100 points each. Progress resets to zero when a rank is unlocked.
|
||||||
|
|
||||||
| Rank | Creeper damage | Block damage |
|
| Rank | Creeper damage | Block damage |
|
||||||
| --- | ---: | --- |
|
| --- | ---: | --- |
|
||||||
@@ -55,7 +55,7 @@ Commands provide permission-aware tab completion for subcommands, online player
|
|||||||
```yaml
|
```yaml
|
||||||
progression:
|
progression:
|
||||||
requirements:
|
requirements:
|
||||||
I: 100
|
I: 25
|
||||||
II: 100
|
II: 100
|
||||||
III: 100
|
III: 100
|
||||||
IV: 100
|
IV: 100
|
||||||
|
|||||||
@@ -6,6 +6,11 @@ description: Chronological record of material changes to the Spigot Creeper Fear
|
|||||||
|
|
||||||
# Design Log
|
# Design Log
|
||||||
|
|
||||||
|
## 2026-08-11
|
||||||
|
|
||||||
|
- Updated US-002 so an unlocked player's aura protects blocks from any creeper explosion within 25 blocks, without requiring the explosion to hit the player.
|
||||||
|
- Updated US-002 and US-006 so rank I requires 25 creeper kills by default while later ranks continue to require 100.
|
||||||
|
|
||||||
## 2026-08-10
|
## 2026-08-10
|
||||||
|
|
||||||
- Completed US-008 with permission-aware command, online-player, and rank tab completion.
|
- Completed US-008 with permission-aware command, online-player, and rank tab completion.
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ As a **player**, I want Creeper Aura to become stronger as I defeat creepers so
|
|||||||
|
|
||||||
| Current state | Kills needed to unlock next rank | Damage to protected player | Creeper block damage |
|
| Current state | Kills needed to unlock next rank | Damage to protected player | Creeper block damage |
|
||||||
| --- | ---: | ---: | --- |
|
| --- | ---: | ---: | --- |
|
||||||
| Locked | 100 to unlock I | 1× | Normal |
|
| Locked | 25 to unlock I | 1× | Normal |
|
||||||
| Creeper Aura I | 100 to unlock II | 3× | Prevented |
|
| Creeper Aura I | 100 to unlock II | 3× | Prevented |
|
||||||
| Creeper Aura II | 100 to unlock III | 2× | Prevented |
|
| Creeper Aura II | 100 to unlock III | 2× | Prevented |
|
||||||
| Creeper Aura III | 100 to unlock IV | 1.5× | Prevented |
|
| Creeper Aura III | 100 to unlock IV | 1.5× | Prevented |
|
||||||
@@ -23,11 +23,13 @@ As a **player**, I want Creeper Aura to become stronger as I defeat creepers so
|
|||||||
|
|
||||||
## Acceptance criteria
|
## Acceptance criteria
|
||||||
|
|
||||||
- [x] A player unlocks the next rank after earning the configured number of kills within their current tier.
|
- [x] A player unlocks rank I after 25 kills by default; subsequent ranks require 100 kills each by default.
|
||||||
- [x] Unlocking a rank resets current-tier progress to zero.
|
- [x] Unlocking a rank resets current-tier progress to zero.
|
||||||
- [x] A player below rank I receives normal creeper explosion behavior.
|
- [x] A player below rank I receives normal creeper explosion behavior.
|
||||||
- [x] An aura activates when an unlocked player would have been hit by the creeper explosion, even when armor or another modifier would reduce the eventual damage to zero.
|
- [x] An aura protects blocks when a player with rank I or higher is within 25 blocks of a creeper at explosion time, including at exactly 25 blocks.
|
||||||
|
- [x] Block protection does not require the aura player to be hit by or have line of sight to the explosion.
|
||||||
- [x] An activated aura prevents that creeper explosion from breaking or removing blocks for everyone affected by the explosion.
|
- [x] An activated aura prevents that creeper explosion from breaking or removing blocks for everyone affected by the explosion.
|
||||||
|
- [x] Players beyond 25 blocks and players whose aura is locked do not activate block protection.
|
||||||
- [x] Other nearby players and entities continue to receive their normal creeper explosion effects unless they have their own aura damage modifier.
|
- [x] Other nearby players and entities continue to receive their normal creeper explosion effects unless they have their own aura damage modifier.
|
||||||
- [x] The protected player's rank multiplier is applied to vanilla creeper explosion damage before armor, enchantments, resistance, and difficulty mitigation.
|
- [x] The protected player's rank multiplier is applied to vanilla creeper explosion damage before armor, enchantments, resistance, and difficulty mitigation.
|
||||||
- [x] At rank VI, the protected player's creeper explosion damage event is cancelled so that damage and knockback are nullified.
|
- [x] At rank VI, the protected player's creeper explosion damage event is cancelled so that damage and knockback are nullified.
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ As a **server administrator**, I want to configure progression and aura behavior
|
|||||||
|
|
||||||
## Acceptance criteria
|
## Acceptance criteria
|
||||||
|
|
||||||
- [x] Configuration provides documented defaults for the six per-rank kill requirements and six unlocked-rank damage multipliers.
|
- [x] Configuration defaults to 25 kills for rank I, 100 kills for each subsequent rank, and the documented six unlocked-rank damage multipliers.
|
||||||
- [x] Rank requirements are positive integers.
|
- [x] Rank requirements are positive integers.
|
||||||
- [x] Damage multipliers are finite and non-negative.
|
- [x] Damage multipliers are finite and non-negative.
|
||||||
- [x] Progress boss-bar duration and player-facing rank messages are configurable.
|
- [x] Progress boss-bar duration and player-facing rank messages are configurable.
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public final class AuraRules {
|
|||||||
public static AuraRules defaults() {
|
public static AuraRules defaults() {
|
||||||
Map<AuraRank, Integer> requirements = new EnumMap<>(AuraRank.class);
|
Map<AuraRank, Integer> requirements = new EnumMap<>(AuraRank.class);
|
||||||
for (AuraRank rank : AuraRank.values()) {
|
for (AuraRank rank : AuraRank.values()) {
|
||||||
if (!rank.isMaximum()) requirements.put(rank, 100);
|
if (!rank.isMaximum()) requirements.put(rank, rank == AuraRank.LOCKED ? 25 : 100);
|
||||||
}
|
}
|
||||||
Map<AuraRank, Double> multipliers = new EnumMap<>(AuraRank.class);
|
Map<AuraRank, Double> multipliers = new EnumMap<>(AuraRank.class);
|
||||||
multipliers.put(AuraRank.LOCKED, 1.0);
|
multipliers.put(AuraRank.LOCKED, 1.0);
|
||||||
|
|||||||
@@ -3,11 +3,10 @@ package games.dmg.creeperfear.aura;
|
|||||||
import games.dmg.creeperfear.progress.AuraRank;
|
import games.dmg.creeperfear.progress.AuraRank;
|
||||||
import games.dmg.creeperfear.progress.PlayerProgress;
|
import games.dmg.creeperfear.progress.PlayerProgress;
|
||||||
import games.dmg.creeperfear.progress.ProgressService;
|
import games.dmg.creeperfear.progress.ProgressService;
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import org.bukkit.Location;
|
||||||
import org.bukkit.entity.Creeper;
|
import org.bukkit.entity.Creeper;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
@@ -18,16 +17,10 @@ import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
|
|||||||
import org.bukkit.event.entity.EntityExplodeEvent;
|
import org.bukkit.event.entity.EntityExplodeEvent;
|
||||||
|
|
||||||
public final class CreeperAuraListener implements Listener {
|
public final class CreeperAuraListener implements Listener {
|
||||||
private static final int RECENT_EXPLOSION_LIMIT = 1024;
|
private static final double BLOCK_PROTECTION_RADIUS_SQUARED = 25.0 * 25.0;
|
||||||
|
|
||||||
private final Function<UUID, Optional<PlayerProgress>> progressLookup;
|
private final Function<UUID, Optional<PlayerProgress>> progressLookup;
|
||||||
private final AuraRules rules;
|
private final AuraRules rules;
|
||||||
private final Map<UUID, Boolean> protectedExplosions = new LinkedHashMap<>(64, 0.75f, true) {
|
|
||||||
@Override
|
|
||||||
protected boolean removeEldestEntry(Map.Entry<UUID, Boolean> eldest) {
|
|
||||||
return size() > RECENT_EXPLOSION_LIMIT;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public CreeperAuraListener(ProgressService progressService, AuraRules rules) {
|
public CreeperAuraListener(ProgressService progressService, AuraRules rules) {
|
||||||
this(progressService::cached, rules);
|
this(progressService::cached, rules);
|
||||||
@@ -52,7 +45,6 @@ public final class CreeperAuraListener implements Listener {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
markProtected(creeper.getUniqueId());
|
|
||||||
AuraRank rank = progress.rank();
|
AuraRank rank = progress.rank();
|
||||||
if (rank.isMaximum()) {
|
if (rank.isMaximum()) {
|
||||||
event.setCancelled(true);
|
event.setCancelled(true);
|
||||||
@@ -63,17 +55,23 @@ public final class CreeperAuraListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
|
||||||
public void onCreeperExplode(EntityExplodeEvent event) {
|
public void onCreeperExplode(EntityExplodeEvent event) {
|
||||||
if (event.getEntity() instanceof Creeper creeper && takeProtected(creeper.getUniqueId())) {
|
if (event.getEntity() instanceof Creeper creeper && hasNearbyAuraPlayer(creeper)) {
|
||||||
event.blockList().clear();
|
event.blockList().clear();
|
||||||
event.setYield(0.0f);
|
event.setYield(0.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void markProtected(UUID creeperId) {
|
private boolean hasNearbyAuraPlayer(Creeper creeper) {
|
||||||
protectedExplosions.put(creeperId, Boolean.TRUE);
|
Location creeperLocation = creeper.getLocation();
|
||||||
}
|
for (Player player : creeper.getWorld().getPlayers()) {
|
||||||
|
if (player.getLocation().distanceSquared(creeperLocation) <= BLOCK_PROTECTION_RADIUS_SQUARED
|
||||||
private synchronized boolean takeProtected(UUID creeperId) {
|
&& progressLookup.apply(player.getUniqueId())
|
||||||
return protectedExplosions.remove(creeperId) != null;
|
.map(PlayerProgress::rank)
|
||||||
|
.filter(AuraRank::isUnlocked)
|
||||||
|
.isPresent()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
progression:
|
progression:
|
||||||
requirements:
|
requirements:
|
||||||
I: 100
|
I: 25
|
||||||
II: 100
|
II: 100
|
||||||
III: 100
|
III: 100
|
||||||
IV: 100
|
IV: 100
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ class AuraRulesTest {
|
|||||||
private final AuraRules rules = AuraRules.defaults();
|
private final AuraRules rules = AuraRules.defaults();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void unlocksOneRankAndResetsTierProgressAtOneHundredKills() {
|
void unlocksFirstRankAndResetsTierProgressAtTwentyFiveKills() {
|
||||||
PlayerProgress progress = new PlayerProgress(UUID.randomUUID(), "Player", AuraRank.LOCKED, 100);
|
PlayerProgress progress = new PlayerProgress(UUID.randomUUID(), "Player", AuraRank.LOCKED, 25);
|
||||||
|
|
||||||
PlayerProgress advanced = rules.advanceIfEarned(progress);
|
PlayerProgress advanced = rules.advanceIfEarned(progress);
|
||||||
|
|
||||||
@@ -20,6 +20,12 @@ class AuraRulesTest {
|
|||||||
assertEquals(0, advanced.tierKills());
|
assertEquals(0, advanced.tierKills());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void usesOneHundredKillsForLaterRanksByDefault() {
|
||||||
|
assertEquals(100, rules.requirementForCurrentRank(AuraRank.I));
|
||||||
|
assertEquals(100, rules.requirementForCurrentRank(AuraRank.V));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void appliesTheDefaultDamageMultipliers() {
|
void appliesTheDefaultDamageMultipliers() {
|
||||||
assertEquals(3.0, rules.damageMultiplier(AuraRank.I));
|
assertEquals(3.0, rules.damageMultiplier(AuraRank.I));
|
||||||
|
|||||||
@@ -1,15 +1,20 @@
|
|||||||
package games.dmg.creeperfear.aura;
|
package games.dmg.creeperfear.aura;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import games.dmg.creeperfear.progress.AuraRank;
|
import games.dmg.creeperfear.progress.AuraRank;
|
||||||
import games.dmg.creeperfear.progress.PlayerProgress;
|
import games.dmg.creeperfear.progress.PlayerProgress;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.entity.Creeper;
|
import org.bukkit.entity.Creeper;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
@@ -20,31 +25,94 @@ import org.junit.jupiter.api.Test;
|
|||||||
|
|
||||||
class CreeperAuraListenerTest {
|
class CreeperAuraListenerTest {
|
||||||
@Test
|
@Test
|
||||||
void multipliesPlayerDamageAndClearsBlocksForTheExplosion() {
|
void multipliesDamageForAnAuraPlayerHitByACreeperExplosion() {
|
||||||
UUID playerId = UUID.randomUUID();
|
UUID playerId = UUID.randomUUID();
|
||||||
UUID creeperId = UUID.randomUUID();
|
|
||||||
Player player = mock(Player.class);
|
Player player = mock(Player.class);
|
||||||
Creeper creeper = mock(Creeper.class);
|
Creeper creeper = mock(Creeper.class);
|
||||||
EntityDamageByEntityEvent damage = mock(EntityDamageByEntityEvent.class);
|
EntityDamageByEntityEvent damage = mock(EntityDamageByEntityEvent.class);
|
||||||
EntityExplodeEvent explosion = mock(EntityExplodeEvent.class);
|
|
||||||
ArrayList<Block> blocks = new ArrayList<>();
|
|
||||||
blocks.add(mock(Block.class));
|
|
||||||
when(player.getUniqueId()).thenReturn(playerId);
|
when(player.getUniqueId()).thenReturn(playerId);
|
||||||
when(creeper.getUniqueId()).thenReturn(creeperId);
|
|
||||||
when(damage.getEntity()).thenReturn(player);
|
when(damage.getEntity()).thenReturn(player);
|
||||||
when(damage.getDamager()).thenReturn(creeper);
|
when(damage.getDamager()).thenReturn(creeper);
|
||||||
when(damage.getCause()).thenReturn(DamageCause.ENTITY_EXPLOSION);
|
when(damage.getCause()).thenReturn(DamageCause.ENTITY_EXPLOSION);
|
||||||
when(damage.getDamage()).thenReturn(10.0);
|
when(damage.getDamage()).thenReturn(10.0);
|
||||||
|
PlayerProgress progress = new PlayerProgress(playerId, "Player", AuraRank.I, 0);
|
||||||
|
CreeperAuraListener listener = new CreeperAuraListener(id -> Optional.of(progress), AuraRules.defaults());
|
||||||
|
|
||||||
|
listener.onCreeperDamage(damage);
|
||||||
|
|
||||||
|
verify(damage).setDamage(30.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void protectsBlocksWhenAuraPlayerIsExactly25BlocksAwayWithoutBeingHit() {
|
||||||
|
UUID playerId = UUID.randomUUID();
|
||||||
|
Player player = mock(Player.class);
|
||||||
|
Creeper creeper = mock(Creeper.class);
|
||||||
|
World world = mock(World.class);
|
||||||
|
EntityExplodeEvent explosion = mock(EntityExplodeEvent.class);
|
||||||
|
ArrayList<Block> blocks = blocksToBreak();
|
||||||
|
when(player.getUniqueId()).thenReturn(playerId);
|
||||||
|
when(player.getLocation()).thenReturn(new Location(world, 25.0, 64.0, 0.0));
|
||||||
|
when(creeper.getWorld()).thenReturn(world);
|
||||||
|
when(creeper.getLocation()).thenReturn(new Location(world, 0.0, 64.0, 0.0));
|
||||||
|
when(world.getPlayers()).thenReturn(List.of(player));
|
||||||
when(explosion.getEntity()).thenReturn(creeper);
|
when(explosion.getEntity()).thenReturn(creeper);
|
||||||
when(explosion.blockList()).thenReturn(blocks);
|
when(explosion.blockList()).thenReturn(blocks);
|
||||||
PlayerProgress progress = new PlayerProgress(playerId, "Player", AuraRank.I, 0);
|
PlayerProgress progress = new PlayerProgress(playerId, "Player", AuraRank.I, 0);
|
||||||
CreeperAuraListener listener = new CreeperAuraListener(id -> Optional.of(progress), AuraRules.defaults());
|
CreeperAuraListener listener = new CreeperAuraListener(id -> Optional.of(progress), AuraRules.defaults());
|
||||||
|
|
||||||
listener.onCreeperDamage(damage);
|
|
||||||
listener.onCreeperExplode(explosion);
|
listener.onCreeperExplode(explosion);
|
||||||
|
|
||||||
verify(damage).setDamage(30.0);
|
|
||||||
assertTrue(blocks.isEmpty());
|
assertTrue(blocks.isEmpty());
|
||||||
|
verify(explosion).setYield(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void leavesBlocksWhenAuraPlayerIsBeyond25Blocks() {
|
||||||
|
UUID playerId = UUID.randomUUID();
|
||||||
|
Player player = mock(Player.class);
|
||||||
|
Creeper creeper = mock(Creeper.class);
|
||||||
|
World world = mock(World.class);
|
||||||
|
EntityExplodeEvent explosion = mock(EntityExplodeEvent.class);
|
||||||
|
ArrayList<Block> blocks = blocksToBreak();
|
||||||
|
when(player.getUniqueId()).thenReturn(playerId);
|
||||||
|
when(player.getLocation()).thenReturn(new Location(world, 25.01, 64.0, 0.0));
|
||||||
|
when(creeper.getWorld()).thenReturn(world);
|
||||||
|
when(creeper.getLocation()).thenReturn(new Location(world, 0.0, 64.0, 0.0));
|
||||||
|
when(world.getPlayers()).thenReturn(List.of(player));
|
||||||
|
when(explosion.getEntity()).thenReturn(creeper);
|
||||||
|
when(explosion.blockList()).thenReturn(blocks);
|
||||||
|
PlayerProgress progress = new PlayerProgress(playerId, "Player", AuraRank.I, 0);
|
||||||
|
CreeperAuraListener listener = new CreeperAuraListener(id -> Optional.of(progress), AuraRules.defaults());
|
||||||
|
|
||||||
|
listener.onCreeperExplode(explosion);
|
||||||
|
|
||||||
|
assertFalse(blocks.isEmpty());
|
||||||
|
verify(explosion, never()).setYield(0.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void leavesBlocksWhenNearbyPlayerHasNotUnlockedAura() {
|
||||||
|
UUID playerId = UUID.randomUUID();
|
||||||
|
Player player = mock(Player.class);
|
||||||
|
Creeper creeper = mock(Creeper.class);
|
||||||
|
World world = mock(World.class);
|
||||||
|
EntityExplodeEvent explosion = mock(EntityExplodeEvent.class);
|
||||||
|
ArrayList<Block> blocks = blocksToBreak();
|
||||||
|
when(player.getUniqueId()).thenReturn(playerId);
|
||||||
|
when(player.getLocation()).thenReturn(new Location(world, 1.0, 64.0, 0.0));
|
||||||
|
when(creeper.getWorld()).thenReturn(world);
|
||||||
|
when(creeper.getLocation()).thenReturn(new Location(world, 0.0, 64.0, 0.0));
|
||||||
|
when(world.getPlayers()).thenReturn(List.of(player));
|
||||||
|
when(explosion.getEntity()).thenReturn(creeper);
|
||||||
|
when(explosion.blockList()).thenReturn(blocks);
|
||||||
|
PlayerProgress progress = new PlayerProgress(playerId, "Player", AuraRank.LOCKED, 0);
|
||||||
|
CreeperAuraListener listener = new CreeperAuraListener(id -> Optional.of(progress), AuraRules.defaults());
|
||||||
|
|
||||||
|
listener.onCreeperExplode(explosion);
|
||||||
|
|
||||||
|
assertFalse(blocks.isEmpty());
|
||||||
|
verify(explosion, never()).setYield(0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -64,4 +132,10 @@ class CreeperAuraListenerTest {
|
|||||||
|
|
||||||
verify(damage).setCancelled(true);
|
verify(damage).setCancelled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ArrayList<Block> blocksToBreak() {
|
||||||
|
ArrayList<Block> blocks = new ArrayList<>();
|
||||||
|
blocks.add(mock(Block.class));
|
||||||
|
return blocks;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,10 +4,25 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
import games.dmg.creeperfear.progress.AuraRank;
|
import games.dmg.creeperfear.progress.AuraRank;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
class AuraConfigLoaderTest {
|
class AuraConfigLoaderTest {
|
||||||
|
@Test
|
||||||
|
void bundledConfigurationDefaultsFirstRankToTwentyFiveKills() throws Exception {
|
||||||
|
try (InputStream stream = getClass().getResourceAsStream("/config.yml")) {
|
||||||
|
YamlConfiguration config = YamlConfiguration.loadConfiguration(
|
||||||
|
new InputStreamReader(stream, StandardCharsets.UTF_8));
|
||||||
|
AuraConfiguration configuration = new AuraConfigLoader().load(config);
|
||||||
|
|
||||||
|
assertEquals(25, configuration.rules().requirementForCurrentRank(AuraRank.LOCKED));
|
||||||
|
assertEquals(100, configuration.rules().requirementForCurrentRank(AuraRank.I));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void loadsPerRankRequirementsMultipliersAndFeedback() throws Exception {
|
void loadsPerRankRequirementsMultipliersAndFeedback() throws Exception {
|
||||||
AuraConfiguration configuration = new AuraConfigLoader().load(validConfiguration());
|
AuraConfiguration configuration = new AuraConfigLoader().load(validConfiguration());
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ class ProgressDisplayTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
void describesLockedCurrentTierProgress() {
|
void describesLockedCurrentTierProgress() {
|
||||||
PlayerProgress progress = new PlayerProgress(UUID.randomUUID(), "Player", AuraRank.LOCKED, 42);
|
PlayerProgress progress = new PlayerProgress(UUID.randomUUID(), "Player", AuraRank.LOCKED, 12);
|
||||||
|
|
||||||
ProgressDisplay.State state = display.forProgress(progress);
|
ProgressDisplay.State state = display.forProgress(progress);
|
||||||
|
|
||||||
assertEquals("Creeper Aura: Locked — 42 / 100", state.text());
|
assertEquals("Creeper Aura: Locked — 12 / 25", state.text());
|
||||||
assertEquals(0.42, state.fraction(), 0.0001);
|
assertEquals(0.48, state.fraction(), 0.0001);
|
||||||
assertTrue(state.visible());
|
assertTrue(state.visible());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user