Files
spigot-base/src/main/java/games/dmg/spigotbase/AdminProgressionService.java
T
dmg 259ea9410c
Release / release (push) Successful in 2m16s
CI / build (push) Successful in 1m3s
feat(spawning): add spawnable block overlay
2026-08-10 22:46:02 -04:00

212 lines
7.7 KiB
Java

package games.dmg.spigotbase;
public final class AdminProgressionService {
private final PluginSettingsProvider settings;
public AdminProgressionService() {
this(new PluginSettingsProvider(PluginSettings.from(java.util.Map.of())));
}
public AdminProgressionService(PluginSettingsProvider settings) {
this.settings = settings;
}
public PlayerState setLevel(PlayerState player, ProgressionPath path, int level) {
int base = player.baseLevel();
int size = player.sizeLevel();
int flight = player.flightLevel();
int warmup = player.warmupLevel();
int cooldown = player.cooldownLevel();
switch (path) {
case BASE -> {
requireRange(level, 0, 4, "base");
base = level;
if (base < 3) {
warmup = 0;
cooldown = 0;
}
if (base < 1) {
size = 0;
flight = 0;
}
}
case SIZE -> {
requireRange(level, 0, 3, "size");
size = level;
if (level > 0) {
base = Math.max(base, 1);
}
}
case FLIGHT -> {
requireRange(level, 0, 3, "flight");
flight = level;
if (level > 0) {
base = Math.max(base, 1);
}
}
case WARMUP -> {
requireRange(level, 0, 3, "warm-up");
warmup = level;
if (level > 0) {
base = Math.max(base, 3);
}
}
case COOLDOWN -> {
requireRange(level, 0, 4, "cooldown");
cooldown = level;
if (level > 0) {
base = Math.max(base, 3);
}
}
}
boolean navigationEnabled = base >= 2 && player.navigationEnabled();
boolean flightEnabled = flight > 0 && player.flightEnabled();
boolean visitorsEnabled = base >= 4 && player.visitorsEnabled();
if (path == ProgressionPath.BASE) {
navigationEnabled = base >= 2;
visitorsEnabled = base >= 4;
}
if (path == ProgressionPath.FLIGHT) {
flightEnabled = flight > 0;
}
return player.withAdministrativeLevels(
base,
size,
flight,
warmup,
cooldown,
navigationEnabled,
flightEnabled,
visitorsEnabled
);
}
public PlayerState setProgress(PlayerState player, ProgressCounter counter, long amount) {
if (amount < 0) {
throw new IllegalArgumentException("progress amount must not be negative");
}
long grassDirt = player.grassAndDirtBroken();
long stone = player.stoneBroken();
long deepslate = player.deepslateBroken();
long obsidian = player.obsidianBroken();
long placements = player.blocksPlacedInBase();
long totalPlacements = player.totalBlocksPlaced();
long baseBreaks = player.blocksBrokenInBase();
switch (counter) {
case GRASS_DIRT -> grassDirt = amount;
case STONE -> stone = amount;
case DEEPSLATE -> deepslate = amount;
case OBSIDIAN -> obsidian = amount;
case PLACEMENTS -> placements = amount;
case TOTAL_PLACEMENTS -> totalPlacements = amount;
case BASE_BREAKS -> baseBreaks = amount;
}
PluginSettings configured = settings.current();
int base = player.baseLevel();
if (grassDirt >= configured.navigationUnlockBlocks()) {
base = Math.max(base, 2);
} else if (grassDirt >= configured.baseUnlockBlocks()) {
base = Math.max(base, 1);
}
int size = player.sizeLevel();
if (stone >= configured.stoneExpansionBlocks()) {
base = Math.max(base, 1);
size = Math.max(size, 1);
}
if (deepslate >= configured.deepslateExpansionBlocks()) {
base = Math.max(base, 1);
size = Math.max(size, 2);
}
if (obsidian >= configured.obsidianExpansionBlocks()) {
base = Math.max(base, 1);
size = Math.max(size, 3);
}
int warmup = player.warmupLevel();
if (placements >= configured.teleportUnlockPlacements()) {
base = Math.max(base, 3);
}
if (placements >= configured.instantWarmupPlacements()) {
warmup = Math.max(warmup, 3);
} else if (placements >= configured.thirdWarmupPlacements()) {
warmup = Math.max(warmup, 2);
} else if (placements >= configured.secondWarmupPlacements()) {
warmup = Math.max(warmup, 1);
}
int cooldown = player.cooldownLevel();
if (baseBreaks >= configured.firstCooldownBreaks()) {
base = Math.max(base, 3);
}
if (baseBreaks >= configured.instantCooldownBreaks()) {
cooldown = Math.max(cooldown, 4);
} else if (baseBreaks >= configured.thirdCooldownBreaks()) {
cooldown = Math.max(cooldown, 3);
} else if (baseBreaks >= configured.secondCooldownBreaks()) {
cooldown = Math.max(cooldown, 2);
} else if (baseBreaks >= configured.firstCooldownBreaks()) {
cooldown = Math.max(cooldown, 1);
}
PlayerState updated = player.withProgressCounters(
grassDirt, stone, deepslate, obsidian, placements, baseBreaks
).withTotalBlocksPlaced(totalPlacements);
if (totalPlacements < configured.spawnableOverlayUnlockPlacements()
&& updated.spawnableOverlayEnabled()) {
updated = updated.withSpawnableOverlayEnabled(false);
}
return updated.withAdministrativeLevels(
base,
size,
updated.flightLevel(),
warmup,
cooldown,
updated.navigationEnabled(),
updated.flightEnabled(),
updated.visitorsEnabled()
);
}
public PlayerState resetPath(PlayerState player, ProgressionPath path) {
if (path == ProgressionPath.BASE) {
return PlayerState.newPlayer(player.playerId(), player.latestName());
}
PlayerState cleared = switch (path) {
case SIZE -> player.withProgressCounters(
player.grassAndDirtBroken(),
0,
0,
0,
player.blocksPlacedInBase(),
player.blocksBrokenInBase()
);
case WARMUP -> player.withProgressCounters(
player.grassAndDirtBroken(),
player.stoneBroken(),
player.deepslateBroken(),
player.obsidianBroken(),
player.baseLevel() >= 3 ? settings.current().teleportUnlockPlacements() : 0,
player.blocksBrokenInBase()
);
case COOLDOWN -> player.withProgressCounters(
player.grassAndDirtBroken(),
player.stoneBroken(),
player.deepslateBroken(),
player.obsidianBroken(),
player.blocksPlacedInBase(),
0
);
case FLIGHT -> player;
case BASE -> throw new IllegalStateException("base reset already handled");
};
return setLevel(cleared, path, 0);
}
private static void requireRange(int value, int minimum, int maximum, String path) {
if (value < minimum || value > maximum) {
throw new IllegalArgumentException(
path + " level must be between " + minimum + " and " + maximum
);
}
}
}