212 lines
7.7 KiB
Java
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
|
|
);
|
|
}
|
|
}
|
|
}
|