v1.2.4: Remove roguelike perks, update bStats to 3.2.1, add new game modes and lpschem system
- Removed roguelike perk system (double jump, magnet, shield, second chance) - Updated bStats dependency to 3.2.1 with proper relocation - Changed bStats plugin ID to 29754 - Added new game modes: Speedrun, Gravity Shift, Hardcore - Implemented .lpschem format with GZIP + JSON compression - Added JumpValidator for physics-based jump validation - Added JumpType system (neo-jump, head-hitter, fence, trapdoor, ladder) - Implemented Ghost system for recording/playback top players - Added loparkour-vilib as local dependency - Updated config with new mode settings and removed roguelike section - Cleaned up TODO.md roadmap
This commit is contained in:
parent
aecb03ccf8
commit
8aeb547897
68 changed files with 6186 additions and 163 deletions
172
src/main/java/dev/loki/loparkour/mode/GravityShiftMode.java
Normal file
172
src/main/java/dev/loki/loparkour/mode/GravityShiftMode.java
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
package dev.loki.loparkour.mode;
|
||||
|
||||
import dev.loki.loparkour.config.Config;
|
||||
import dev.loki.loparkour.config.Locales;
|
||||
import dev.loki.loparkour.generator.ParkourGenerator;
|
||||
import dev.loki.loparkour.leaderboard.Leaderboard;
|
||||
import dev.loki.loparkour.player.ParkourPlayer;
|
||||
import dev.loki.loparkour.session.Session;
|
||||
import dev.efnilite.vilib.inventory.item.Item;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class GravityShiftMode implements Mode {
|
||||
|
||||
private final Leaderboard leaderboard = new Leaderboard(getName(), Leaderboard.Sort.SCORE);
|
||||
private final Random random = new Random();
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return "gravity-shift";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Item getItem(String locale) {
|
||||
return Locales.getItem(locale, "play.single.gravity-shift");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Leaderboard getLeaderboard() {
|
||||
return leaderboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(Player player) {
|
||||
if (!Config.CONFIG.getBoolean("joining")) {
|
||||
player.sendMessage("Joining is currently disabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
ParkourPlayer pp = ParkourPlayer.getPlayer(player);
|
||||
if (pp != null && pp.session.generator != null && pp.session.generator.getMode() instanceof GravityShiftMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
player.closeInventory();
|
||||
|
||||
Session.create(session -> new GravityShiftGenerator(session), null, null, player);
|
||||
}
|
||||
|
||||
private static class GravityShiftGenerator extends ParkourGenerator {
|
||||
private int jumpsUntilShift;
|
||||
private final int shiftInterval;
|
||||
private PotionEffect currentEffect;
|
||||
|
||||
public GravityShiftGenerator(@NotNull Session session) {
|
||||
super(session);
|
||||
this.shiftInterval = Config.CONFIG.getInt("modes.gravity-shift.interval");
|
||||
this.jumpsUntilShift = shiftInterval;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void score() {
|
||||
super.score();
|
||||
|
||||
jumpsUntilShift--;
|
||||
|
||||
if (jumpsUntilShift <= 0) {
|
||||
applyRandomEffect();
|
||||
jumpsUntilShift = shiftInterval;
|
||||
}
|
||||
}
|
||||
|
||||
private void applyRandomEffect() {
|
||||
if (currentEffect != null) {
|
||||
player.player.removePotionEffect(currentEffect.getType());
|
||||
}
|
||||
|
||||
List<EffectData> effects = new ArrayList<>();
|
||||
|
||||
if (Config.CONFIG.getBoolean("modes.gravity-shift.effects.jump-boost.enabled")) {
|
||||
effects.add(new EffectData(
|
||||
PotionEffectType.JUMP,
|
||||
Config.CONFIG.getInt("modes.gravity-shift.effects.jump-boost.amplifier"),
|
||||
Config.CONFIG.getInt("modes.gravity-shift.effects.jump-boost.duration"),
|
||||
"Jump Boost"
|
||||
));
|
||||
}
|
||||
|
||||
if (Config.CONFIG.getBoolean("modes.gravity-shift.effects.speed.enabled")) {
|
||||
effects.add(new EffectData(
|
||||
PotionEffectType.SPEED,
|
||||
Config.CONFIG.getInt("modes.gravity-shift.effects.speed.amplifier"),
|
||||
Config.CONFIG.getInt("modes.gravity-shift.effects.speed.duration"),
|
||||
"Speed"
|
||||
));
|
||||
}
|
||||
|
||||
if (Config.CONFIG.getBoolean("modes.gravity-shift.effects.slowness.enabled")) {
|
||||
effects.add(new EffectData(
|
||||
PotionEffectType.SLOW,
|
||||
Config.CONFIG.getInt("modes.gravity-shift.effects.slowness.amplifier"),
|
||||
Config.CONFIG.getInt("modes.gravity-shift.effects.slowness.duration"),
|
||||
"Slowness"
|
||||
));
|
||||
}
|
||||
|
||||
if (Config.CONFIG.getBoolean("modes.gravity-shift.effects.levitation.enabled")) {
|
||||
effects.add(new EffectData(
|
||||
PotionEffectType.LEVITATION,
|
||||
Config.CONFIG.getInt("modes.gravity-shift.effects.levitation.amplifier"),
|
||||
Config.CONFIG.getInt("modes.gravity-shift.effects.levitation.duration"),
|
||||
"Levitation"
|
||||
));
|
||||
}
|
||||
|
||||
if (effects.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
EffectData selected = effects.get(new Random().nextInt(effects.size()));
|
||||
currentEffect = new PotionEffect(
|
||||
selected.type,
|
||||
selected.duration * 20,
|
||||
selected.amplifier - 1,
|
||||
false,
|
||||
true,
|
||||
true
|
||||
);
|
||||
|
||||
player.player.addPotionEffect(currentEffect);
|
||||
player.sendTranslated("modes.gravity-shift.effect-applied", selected.name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset(boolean regenerate) {
|
||||
if (currentEffect != null && player != null && player.player != null) {
|
||||
player.player.removePotionEffect(currentEffect.getType());
|
||||
}
|
||||
jumpsUntilShift = shiftInterval;
|
||||
super.reset(regenerate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mode getMode() {
|
||||
return Modes.GRAVITY_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
private static class EffectData {
|
||||
final PotionEffectType type;
|
||||
final int amplifier;
|
||||
final int duration;
|
||||
final String name;
|
||||
|
||||
EffectData(PotionEffectType type, int amplifier, int duration, String name) {
|
||||
this.type = type;
|
||||
this.amplifier = amplifier;
|
||||
this.duration = duration;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
}
|
||||
77
src/main/java/dev/loki/loparkour/mode/HardcoreMode.java
Normal file
77
src/main/java/dev/loki/loparkour/mode/HardcoreMode.java
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
package dev.loki.loparkour.mode;
|
||||
|
||||
import dev.loki.loparkour.config.Config;
|
||||
import dev.loki.loparkour.config.Locales;
|
||||
import dev.loki.loparkour.generator.ParkourGenerator;
|
||||
import dev.loki.loparkour.leaderboard.Leaderboard;
|
||||
import dev.loki.loparkour.player.ParkourPlayer;
|
||||
import dev.loki.loparkour.session.Session;
|
||||
import dev.efnilite.vilib.inventory.item.Item;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class HardcoreMode implements Mode {
|
||||
|
||||
private final Leaderboard leaderboard = new Leaderboard(getName(), Leaderboard.Sort.SCORE);
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return "hardcore";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Item getItem(String locale) {
|
||||
return Locales.getItem(locale, "play.single.hardcore");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Leaderboard getLeaderboard() {
|
||||
return leaderboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(Player player) {
|
||||
if (!Config.CONFIG.getBoolean("joining")) {
|
||||
player.sendMessage("Joining is currently disabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
ParkourPlayer pp = ParkourPlayer.getPlayer(player);
|
||||
if (pp != null && pp.session.generator != null && pp.session.generator.getMode() instanceof HardcoreMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
player.closeInventory();
|
||||
|
||||
Session.create(session -> new HardcoreGenerator(session), null, null, player);
|
||||
}
|
||||
|
||||
private static class HardcoreGenerator extends ParkourGenerator {
|
||||
|
||||
public HardcoreGenerator(@NotNull Session session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fall() {
|
||||
boolean resetRewards = Config.CONFIG.getBoolean("modes.hardcore.reset-rewards");
|
||||
|
||||
if (resetRewards) {
|
||||
player.sendTranslated("modes.hardcore.rewards-lost");
|
||||
}
|
||||
|
||||
player.sendTranslated("modes.hardcore.full-reset");
|
||||
|
||||
super.fall();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mode getMode() {
|
||||
return Modes.HARDCORE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -6,9 +6,15 @@ public class Modes {
|
|||
|
||||
public static DefaultMode DEFAULT;
|
||||
public static SpectatorMode SPECTATOR;
|
||||
public static SpeedrunMode SPEEDRUN;
|
||||
public static GravityShiftMode GRAVITY_SHIFT;
|
||||
public static HardcoreMode HARDCORE;
|
||||
|
||||
public static void init() {
|
||||
DEFAULT = (DefaultMode) Registry.getMode("default");
|
||||
SPECTATOR = (SpectatorMode) Registry.getMode("spectator");
|
||||
SPEEDRUN = (SpeedrunMode) Registry.getMode("speedrun");
|
||||
GRAVITY_SHIFT = (GravityShiftMode) Registry.getMode("gravity-shift");
|
||||
HARDCORE = (HardcoreMode) Registry.getMode("hardcore");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
112
src/main/java/dev/loki/loparkour/mode/SpeedrunMode.java
Normal file
112
src/main/java/dev/loki/loparkour/mode/SpeedrunMode.java
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
package dev.loki.loparkour.mode;
|
||||
|
||||
import dev.loki.loparkour.LoParkour;
|
||||
import dev.loki.loparkour.config.Config;
|
||||
import dev.loki.loparkour.config.Locales;
|
||||
import dev.loki.loparkour.generator.ParkourGenerator;
|
||||
import dev.loki.loparkour.leaderboard.Leaderboard;
|
||||
import dev.loki.loparkour.player.ParkourPlayer;
|
||||
import dev.loki.loparkour.session.Session;
|
||||
import dev.efnilite.vilib.inventory.item.Item;
|
||||
import dev.efnilite.vilib.util.Task;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.Sound;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SpeedrunMode implements Mode {
|
||||
|
||||
private final Leaderboard leaderboard = new Leaderboard(getName(), Leaderboard.Sort.SCORE);
|
||||
private final Map<Block, Long> blockTimestamps = new HashMap<>();
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return "speedrun";
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public Item getItem(String locale) {
|
||||
return Locales.getItem(locale, "play.single.speedrun");
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public Leaderboard getLeaderboard() {
|
||||
return leaderboard;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void create(Player player) {
|
||||
if (!Config.CONFIG.getBoolean("joining")) {
|
||||
player.sendMessage("Joining is currently disabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
ParkourPlayer pp = ParkourPlayer.getPlayer(player);
|
||||
if (pp != null && pp.session.generator != null && pp.session.generator.getMode() instanceof SpeedrunMode) {
|
||||
return;
|
||||
}
|
||||
|
||||
player.closeInventory();
|
||||
|
||||
Session.create(session -> new SpeedrunGenerator(session), null, null, player);
|
||||
}
|
||||
|
||||
public void onBlockTouch(@NotNull Block block, @NotNull ParkourPlayer player) {
|
||||
if (!blockTimestamps.containsKey(block)) {
|
||||
blockTimestamps.put(block, System.currentTimeMillis());
|
||||
scheduleBlockRemoval(player, block);
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleBlockRemoval(@NotNull ParkourPlayer player, @NotNull Block block) {
|
||||
double blockLifetime = Config.CONFIG.getDouble("modes.speedrun.block-lifetime");
|
||||
double warningTime = Config.CONFIG.getDouble("modes.speedrun.warning-time");
|
||||
|
||||
long removalTime = (long) (blockLifetime * 1000);
|
||||
long warningTimeMs = (long) (warningTime * 1000);
|
||||
|
||||
Task.create(LoParkour.getPlugin())
|
||||
.delay((int) ((removalTime - warningTimeMs) / 50))
|
||||
.execute(() -> {
|
||||
if (block.getType() != Material.AIR) {
|
||||
player.player.playSound(block.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, 1.0f, 2.0f);
|
||||
player.player.spawnParticle(Particle.FLAME, block.getLocation().add(0.5, 1, 0.5), 10, 0.3, 0.3, 0.3, 0.01);
|
||||
}
|
||||
})
|
||||
.run();
|
||||
|
||||
Task.create(LoParkour.getPlugin())
|
||||
.delay((int) (removalTime / 50))
|
||||
.execute(() -> {
|
||||
if (block.getType() != Material.AIR) {
|
||||
block.setType(Material.AIR);
|
||||
blockTimestamps.remove(block);
|
||||
}
|
||||
})
|
||||
.run();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
blockTimestamps.clear();
|
||||
}
|
||||
|
||||
private static class SpeedrunGenerator extends ParkourGenerator {
|
||||
public SpeedrunGenerator(@NotNull Session session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mode getMode() {
|
||||
return Modes.SPEEDRUN;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue