diff --git a/src/main/java/city/thefloating/floatyplugin/FloatyPlugin.java b/src/main/java/city/thefloating/floatyplugin/FloatyPlugin.java index 1dd07f5..020a71d 100644 --- a/src/main/java/city/thefloating/floatyplugin/FloatyPlugin.java +++ b/src/main/java/city/thefloating/floatyplugin/FloatyPlugin.java @@ -44,6 +44,8 @@ import city.thefloating.floatyplugin.server.RulesCommand; import city.thefloating.floatyplugin.server.ServerPingListener; import city.thefloating.floatyplugin.server.VoteCommand; +import city.thefloating.floatyplugin.soul.Charon; +import city.thefloating.floatyplugin.soul.Otzar; import city.thefloating.floatyplugin.tag.TagCommand; import city.thefloating.floatyplugin.tag.TagListener; import city.thefloating.floatyplugin.transportation.FlightListener; @@ -114,6 +116,17 @@ public void onEnable() { @Override public void onDisable() { this.injector.getInstance(Nate.class).killNextbots(); + + try { + this.injector.getInstance(Charon.class).save(); + } catch (final ConfigurateException e) { + this.getSLF4JLogger().error( + "An error occurred while saving config file {}. Please ensure that the file is valid.", + this.injector.getInstance(Otzar.class).configurateWrapper().filePath() + ); + this.getSLF4JLogger().error("Printing stack trace:", e); + } + this.getServer().getScheduler().cancelTasks(this); } @@ -133,6 +146,7 @@ public boolean loadConfiguration() { this.saveResourceSilently("piano-notes.conf"); final List configsToLoad = List.of( + this.injector.getInstance(Otzar.class), this.injector.getInstance(BooksConfig.class), this.injector.getInstance(ConfigConfig.class), this.injector.getInstance(EmotesConfig.class), @@ -177,7 +191,7 @@ private boolean initCommands() { ); } catch (final Exception e) { this.getSLF4JLogger().error("Failed to create the CommandManager."); - this.getSLF4JLogger().error("Printing stack trace, please send this to the developers:", e); + this.getSLF4JLogger().error("Printing stack trace. Please send this to the developers:", e); return false; } diff --git a/src/main/java/city/thefloating/floatyplugin/fun/ElevatorMusicJockey.java b/src/main/java/city/thefloating/floatyplugin/fun/ElevatorMusicJockey.java index f474d80..2157e0c 100644 --- a/src/main/java/city/thefloating/floatyplugin/fun/ElevatorMusicJockey.java +++ b/src/main/java/city/thefloating/floatyplugin/fun/ElevatorMusicJockey.java @@ -45,7 +45,7 @@ public void start() { } private void refresh(final Player player) { - final Soul soul = this.charon.getSoul(player); + final Soul soul = this.charon.grab(player); if (player.getFallDistance() >= MIN_FALL_DIST) { if (!soul.elevatorMusicPlaying()) { player.stopSound(SoundCategory.MUSIC); diff --git a/src/main/java/city/thefloating/floatyplugin/inject/SingletonModule.java b/src/main/java/city/thefloating/floatyplugin/inject/SingletonModule.java index c96bf17..5915af0 100644 --- a/src/main/java/city/thefloating/floatyplugin/inject/SingletonModule.java +++ b/src/main/java/city/thefloating/floatyplugin/inject/SingletonModule.java @@ -10,6 +10,7 @@ import city.thefloating.floatyplugin.realm.Transposer; import city.thefloating.floatyplugin.realm.WorldService; import city.thefloating.floatyplugin.soul.Charon; +import city.thefloating.floatyplugin.soul.Otzar; import city.thefloating.floatyplugin.tag.TagGame; import city.thefloating.floatyplugin.transportation.FlightService; import city.thefloating.floatyplugin.transportation.PortalListener; @@ -27,13 +28,12 @@ protected void configure() { this.bind(Transposer.class).asEagerSingleton(); this.bind(Nate.class).asEagerSingleton(); this.bind(PortalListener.class).asEagerSingleton(); - - // configs. this.bind(BooksConfig.class).asEagerSingleton(); this.bind(ConfigConfig.class).asEagerSingleton(); this.bind(EmotesConfig.class).asEagerSingleton(); this.bind(PianoNotesConfig.class).asEagerSingleton(); this.bind(LangConfig.class).asEagerSingleton(); + this.bind(Otzar.class).asEagerSingleton(); } } diff --git a/src/main/java/city/thefloating/floatyplugin/piano/PianoCommand.java b/src/main/java/city/thefloating/floatyplugin/piano/PianoCommand.java index 2a12767..4bae292 100644 --- a/src/main/java/city/thefloating/floatyplugin/piano/PianoCommand.java +++ b/src/main/java/city/thefloating/floatyplugin/piano/PianoCommand.java @@ -67,7 +67,7 @@ public void register(final PaperCommandManager commandManager) { .senderType(Player.class) .handler(c -> { final Player sender = (Player) c.getSender(); - if (this.charon.getSoul(sender).piano().toggleEnabled()) { + if (this.charon.grab(sender).piano().toggleEnabled()) { sender.sendMessage(this.langConfig.c(NodePath.path("piano", "enabled"))); } else { sender.sendMessage(this.langConfig.c(NodePath.path("piano", "disabled"))); @@ -110,7 +110,7 @@ public void register(final PaperCommandManager commandManager) { final Instrument inst = c.get("instrument"); final Player sender = (Player) c.getSender(); - this.charon.getSoul(sender).piano().instrument(inst); + this.charon.grab(sender).piano().instrument(inst); sender.sendMessage(this.langConfig.c( NodePath.path("piano", "instrument-change"), Placeholder.unparsed("instrument", inst.toString()) diff --git a/src/main/java/city/thefloating/floatyplugin/piano/PianoPlayListener.java b/src/main/java/city/thefloating/floatyplugin/piano/PianoPlayListener.java index ffe28cb..e06530e 100644 --- a/src/main/java/city/thefloating/floatyplugin/piano/PianoPlayListener.java +++ b/src/main/java/city/thefloating/floatyplugin/piano/PianoPlayListener.java @@ -36,7 +36,7 @@ public PianoPlayListener( public void onItemHeld(final PlayerItemHeldEvent event) { final Player player = event.getPlayer(); if (!player.hasPermission(Permission.PIANO) - || !this.charon.getSoul(player).piano().enabled()) { + || !this.charon.grab(player).piano().enabled()) { return; } @@ -83,7 +83,7 @@ private void tryPlay(final Player player, final ItemStack item) { player.getWorld().playSound( player.getEyeLocation(), - this.charon.getSoul(player).piano().instrument().sound(), + this.charon.grab(player).piano().instrument().sound(), SoundCategory.MASTER, 3, pitch diff --git a/src/main/java/city/thefloating/floatyplugin/soul/Charon.java b/src/main/java/city/thefloating/floatyplugin/soul/Charon.java index 02039ba..5661cc4 100644 --- a/src/main/java/city/thefloating/floatyplugin/soul/Charon.java +++ b/src/main/java/city/thefloating/floatyplugin/soul/Charon.java @@ -1,6 +1,8 @@ package city.thefloating.floatyplugin.soul; +import com.google.inject.Inject; import org.bukkit.entity.Player; +import org.spongepowered.configurate.ConfigurateException; import java.util.HashMap; import java.util.Map; @@ -11,14 +13,36 @@ */ public final class Charon { - private final Map soulMap = new HashMap<>(); + private final Otzar otzar; - public Soul getSoul(final UUID uuid) { - return this.soulMap.computeIfAbsent(uuid, Soul::new); + private final Map souls = new HashMap<>(); + + @Inject + public Charon(final Otzar otzar) { + this.otzar = otzar; + } + + public Soul grab(final UUID uuid) { + return this.souls.computeIfAbsent(uuid, (u) -> { + final var soul = new Soul(uuid); + if (this.otzar.spirits().containsKey(uuid)) { + final var spirit = this.otzar.spirits().get(uuid); + soul.netherInfractions(spirit.netherInfractions()); + } + return soul; + }); + } + + public Soul grab(final Player player) { + return this.grab(player.getUniqueId()); } - public Soul getSoul(final Player player) { - return this.getSoul(player.getUniqueId()); + public void save() throws ConfigurateException { + for (final var soul : this.souls.values()) { + final var spirit = new Otzar.Data.Spirit(soul.netherInfractions()); + this.otzar.spirits().put(soul.getUuid(), spirit); + } + this.otzar.save(); } } diff --git a/src/main/java/city/thefloating/floatyplugin/soul/Otzar.java b/src/main/java/city/thefloating/floatyplugin/soul/Otzar.java new file mode 100644 index 0000000..2a80d98 --- /dev/null +++ b/src/main/java/city/thefloating/floatyplugin/soul/Otzar.java @@ -0,0 +1,57 @@ +package city.thefloating.floatyplugin.soul; + +import city.thefloating.floatyplugin.config.HoconConfigurateWrapper; +import com.google.inject.Inject; +import com.google.inject.name.Named; +import dev.tehbrian.tehlib.configurate.AbstractDataConfig; +import org.spongepowered.configurate.CommentedConfigurationNode; +import org.spongepowered.configurate.ConfigurateException; +import org.spongepowered.configurate.hocon.HoconConfigurationLoader; +import org.spongepowered.configurate.objectmapping.ConfigSerializable; + +import java.nio.file.Path; +import java.util.Map; +import java.util.Objects; +import java.util.UUID; + +/** + * Stores persistent data for souls via a YAML config. + *

+ * If you're curious about the name. + */ +public final class Otzar extends AbstractDataConfig { + + @Inject + public Otzar(final @Named("dataFolder") Path dataFolder) { + super(new HoconConfigurateWrapper(dataFolder.resolve("otzar.conf"), HoconConfigurationLoader.builder() + .path(dataFolder.resolve("otzar.conf")) + .defaultOptions(opts -> opts.implicitInitialization(true)) + .build())); + } + + public void save() throws ConfigurateException { + final CommentedConfigurationNode rootNode = Objects.requireNonNull(this.configurateWrapper.get()); + rootNode.set(this.getDataClass(), this.data); + this.configurateWrapper.save(); + } + + public Map spirits() { + return this.data().spirits(); + } + + @Override + protected Class getDataClass() { + return Otzar.Data.class; + } + + @ConfigSerializable + public record Data(Map spirits) { + + @ConfigSerializable + public record Spirit(int netherInfractions) { + + } + + } + +} diff --git a/src/main/java/city/thefloating/floatyplugin/soul/Soul.java b/src/main/java/city/thefloating/floatyplugin/soul/Soul.java index 4f1069f..4906244 100644 --- a/src/main/java/city/thefloating/floatyplugin/soul/Soul.java +++ b/src/main/java/city/thefloating/floatyplugin/soul/Soul.java @@ -9,7 +9,7 @@ public final class Soul { private final UUID uuid; private boolean flyBypassEnabled = false; - private int netherBlindnessCount = 0; + private int netherInfractions = 0; private boolean elevatorMusicPlaying = false; private final Piano piano = new Piano(false, Instrument.HARP); @@ -35,12 +35,12 @@ public boolean toggleFlyBypassEnabled() { return this.flyBypassEnabled(); } - public int netherSprintCount() { - return this.netherBlindnessCount; + public int netherInfractions() { + return this.netherInfractions; } - public void netherSprintCount(final int netherBlindnessCount) { - this.netherBlindnessCount = netherBlindnessCount; + public void netherInfractions(final int netherBlindnessCount) { + this.netherInfractions = netherBlindnessCount; } public boolean elevatorMusicPlaying() { diff --git a/src/main/java/city/thefloating/floatyplugin/transportation/FlightService.java b/src/main/java/city/thefloating/floatyplugin/transportation/FlightService.java index 8da9c12..4a992ff 100644 --- a/src/main/java/city/thefloating/floatyplugin/transportation/FlightService.java +++ b/src/main/java/city/thefloating/floatyplugin/transportation/FlightService.java @@ -32,7 +32,7 @@ public void checkFlight(final Player player) { } public boolean canFly(final Player player) { - return player.hasPermission(Permission.FLY) && this.charon.getSoul(player).flyBypassEnabled(); + return player.hasPermission(Permission.FLY) && this.charon.grab(player).flyBypassEnabled(); } public void enableFlight(final Player player) { diff --git a/src/main/java/city/thefloating/floatyplugin/transportation/FlyCommand.java b/src/main/java/city/thefloating/floatyplugin/transportation/FlyCommand.java index a8070b5..4d5f8ec 100644 --- a/src/main/java/city/thefloating/floatyplugin/transportation/FlyCommand.java +++ b/src/main/java/city/thefloating/floatyplugin/transportation/FlyCommand.java @@ -34,7 +34,7 @@ public void register(final PaperCommandManager commandManager) { .senderType(Player.class) .handler(c -> { final Player sender = (Player) c.getSender(); - if (this.charon.getSoul(sender).toggleFlyBypassEnabled()) { + if (this.charon.grab(sender).toggleFlyBypassEnabled()) { sender.sendMessage(this.langConfig.c(NodePath.path("fly", "enabled"))); this.flightService.enableFlight(sender); } else { diff --git a/src/main/java/city/thefloating/floatyplugin/transportation/TransportationListener.java b/src/main/java/city/thefloating/floatyplugin/transportation/TransportationListener.java index a962465..5992630 100644 --- a/src/main/java/city/thefloating/floatyplugin/transportation/TransportationListener.java +++ b/src/main/java/city/thefloating/floatyplugin/transportation/TransportationListener.java @@ -207,16 +207,19 @@ public void onSprint(final PlayerToggleSprintEvent event) { if (Realm.of(player) == Realm.NETHER) { // nether watcher time! - final Soul soul = this.charon.getSoul(player); - switch (soul.netherSprintCount()) { - case 0, 2, 5, 10 -> player.sendMessage(this.langConfig.c(NodePath.path("no-sprint", "1"))); - case 20 -> player.sendMessage(this.langConfig.c(NodePath.path("no-sprint", "2"))); - case 30 -> player.sendMessage(this.langConfig.c(NodePath.path("no-sprint", "3"))); - case 40 -> player.sendMessage(this.langConfig.c(NodePath.path("no-sprint", "4"))); - case 50 -> player.sendMessage(this.langConfig.c(NodePath.path("no-sprint", "5"))); - case 60 -> player.sendMessage(this.langConfig.c(NodePath.path("no-sprint", "6"))); - case 70 -> player.sendMessage(this.langConfig.c(NodePath.path("no-sprint", "7"))); - case 90 -> { + final Soul soul = this.charon.grab(player); + + soul.netherInfractions(soul.netherInfractions() + 1); + + switch (soul.netherInfractions()) { + case 1, 2, 3, 5, 8, 10, 15, 20, 25 -> player.sendMessage(this.langConfig.c(NodePath.path("no-sprint", "1"))); + case 30 -> player.sendMessage(this.langConfig.c(NodePath.path("no-sprint", "2"))); + case 40 -> player.sendMessage(this.langConfig.c(NodePath.path("no-sprint", "3"))); + case 50 -> player.sendMessage(this.langConfig.c(NodePath.path("no-sprint", "4"))); + case 60 -> player.sendMessage(this.langConfig.c(NodePath.path("no-sprint", "5"))); + case 70 -> player.sendMessage(this.langConfig.c(NodePath.path("no-sprint", "6"))); + case 80 -> player.sendMessage(this.langConfig.c(NodePath.path("no-sprint", "7"))); + case 100 -> { player.sendMessage(this.langConfig.c(NodePath.path("no-sprint", "8"))); final BundleBuilder bundleBuilder = BundleBuilder.ofBundle() @@ -229,7 +232,7 @@ public void onSprint(final PlayerToggleSprintEvent event) { .addPage(Component.text(""" listen. i appreciate you giving me company, but holy shit. the whole point of the nether is *not* to sprint, - yet you somehow managed to do it upwards of 50 times!? + yet you somehow managed to do it a hundred times!? have you got something wrong in the head? take this, and fuck off. """).color(NamedTextColor.DARK_GRAY)) .addPage(Component.text(""" @@ -258,8 +261,6 @@ public void onSprint(final PlayerToggleSprintEvent event) { default -> { } } - - soul.netherSprintCount(soul.netherSprintCount() + 1); } }