diff --git a/Datura/src/main/java/fns/datura/Datura.java b/Datura/src/main/java/fns/datura/Datura.java index 9309f77..862c130 100644 --- a/Datura/src/main/java/fns/datura/Datura.java +++ b/Datura/src/main/java/fns/datura/Datura.java @@ -43,11 +43,10 @@ public class Datura extends JavaPlugin // Punishment private final Halter halter = new Halter(); private final Locker locker = new Locker(); - private Cager cager; - // Features private final CommandSpy commandSpy = new CommandSpy(); private final Fuckoff fuckoff = new Fuckoff(); + private Cager cager; @Override public void onEnable() @@ -55,12 +54,20 @@ public class Datura extends JavaPlugin cager = new Cager(this); Registration.getServiceTaskRegistry() - .registerService(SubscriptionProvider.syncService(this, locker)); + .registerService(SubscriptionProvider.syncService(this, locker)); Registration.getServiceTaskRegistry() .registerService(SubscriptionProvider.syncService(this, cager)); Registration.getServiceTaskRegistry() .registerService(SubscriptionProvider.syncService(this, fuckoff)); + getSQL().createTable("bans", + "uuid VARCHAR(36) PRIMARY KEY", + "name VARCHAR(16)", + "issuer VARCHAR(16)", + "reason VARCHAR(255)", + "issued LONG", + "duration LONG"); + Bukkit.getPluginManager() .registerEvents(halter, this); Bukkit.getPluginManager() @@ -92,12 +99,12 @@ public class Datura extends JavaPlugin return cager; } - public CommandSpy getCommandSpy() + public CommandSpy getCommandSpy() { return commandSpy; } - public Fuckoff getFuckoff() + public Fuckoff getFuckoff() { return fuckoff; } diff --git a/Datura/src/main/java/fns/datura/punishment/SimpleBanEntry.java b/Datura/src/main/java/fns/datura/punishment/SimpleBanEntry.java new file mode 100644 index 0000000..ebdd367 --- /dev/null +++ b/Datura/src/main/java/fns/datura/punishment/SimpleBanEntry.java @@ -0,0 +1,98 @@ +/* + * This file is part of FreedomNetworkSuite - https://github.com/SimplexDevelopment/FreedomNetworkSuite + * Copyright (C) 2023 Simplex Development and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package fns.datura.punishment; + +import com.google.errorprone.annotations.Immutable; +import fns.patchwork.bans.BanEntry; +import fns.patchwork.kyori.PlainTextWrapper; +import java.net.Inet6Address; +import java.time.Duration; +import java.time.Instant; +import java.util.UUID; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +@Immutable +public class SimpleBanEntry implements BanEntry +{ + private final String username; + private final UUID uuid; + private final String ipv6; + private final String reason; + private final Instant issued; + private final Instant expires; + private final String issuer; + + public SimpleBanEntry(final Player target, + final CommandSender issuer, + final String reason, + final Instant issued, + final Duration duration) { + this.username = PlainTextWrapper.toPlainText(target.name()); + this.uuid = target.getUniqueId(); + if (target.getAddress() != null && target.getAddress().getAddress() instanceof Inet6Address address) + this.ipv6 = address.getHostAddress(); + else + this.ipv6 = "N/A"; + this.issued = issued; + this.expires = issued.plus(duration); + this.issuer = PlainTextWrapper.toPlainText(issuer.name()); + this.reason = reason; + } + + @Override + public String getUsername() { + return this.username; + } + + @Override + public UUID getUuid() { + return this.uuid; + } + + @Override + public String getIpv6() { + return this.ipv6; + } + + @Override + public String getReason() { + return this.reason; + } + + @Override + public Instant getIssued() { + return this.issued; + } + + @Override + public Instant getExpires() { + return this.expires; + } + + @Override + public String getIssuer() { + return this.issuer; + } +} diff --git a/Fossil/src/main/java/fns/fossil/Fossil.java b/Fossil/src/main/java/fns/fossil/Fossil.java index 22157e4..9d8102a 100644 --- a/Fossil/src/main/java/fns/fossil/Fossil.java +++ b/Fossil/src/main/java/fns/fossil/Fossil.java @@ -24,6 +24,7 @@ package fns.fossil; import fns.fossil.cmd.CakeCommand; +import fns.fossil.reactions.ReactionSystem; import fns.fossil.trail.Trailer; import fns.patchwork.base.Registration; import fns.patchwork.command.CommandHandler; @@ -33,6 +34,7 @@ import org.bukkit.plugin.java.JavaPlugin; public class Fossil extends JavaPlugin { private final Trailer trailer = new Trailer(); + @Override public void onEnable() { diff --git a/Fossil/src/main/java/fns/fossil/reactions/CopyCatReaction.java b/Fossil/src/main/java/fns/fossil/reactions/CopyCatReaction.java index 41921bf..4c8b669 100644 --- a/Fossil/src/main/java/fns/fossil/reactions/CopyCatReaction.java +++ b/Fossil/src/main/java/fns/fossil/reactions/CopyCatReaction.java @@ -37,11 +37,17 @@ import net.kyori.adventure.bossbar.BossBar; public final class CopyCatReaction extends Reaction { private final long reward; + private final BossBar bossBar; public CopyCatReaction(final long reward) { super(ReactionType.COPYCAT); this.reward = reward; + this.bossBar = BossBarDisplay.builder() + .setName(getRandomCharacterString()) + .setProgress(0.0F) + .setOverlay(BossBar.Overlay.NOTCHED_10) + .build(); } @Override @@ -53,16 +59,16 @@ public final class CopyCatReaction extends Reaction @Override public void display(final Audience audience) { - final BossBar bossBar = BossBarDisplay.builder() - .setName(getRandomCharacterString()) - .setProgress(0.0F) - .build(); + audience.showBossBar(bossBar); } @Override public void onReact(final EconomicEntity entity) { - // + entity.getEconomicData() + .addToBalance(getReward()); + + this.cancel(); } public String getRandomCharacterString() @@ -79,4 +85,16 @@ public final class CopyCatReaction extends Reaction return sb.toString(); } + + @Override + public void runTimer() + { + if (bossBar.progress() >= 1.0F) + { + this.cancel(); + return; + } + + bossBar.progress(bossBar.progress() + 0.1F); + } } diff --git a/Fossil/src/main/java/fns/fossil/reactions/ReactionSystem.java b/Fossil/src/main/java/fns/fossil/reactions/ReactionSystem.java new file mode 100644 index 0000000..726feaa --- /dev/null +++ b/Fossil/src/main/java/fns/fossil/reactions/ReactionSystem.java @@ -0,0 +1,59 @@ +/* + * This file is part of FreedomNetworkSuite - https://github.com/SimplexDevelopment/FreedomNetworkSuite + * Copyright (C) 2023 Simplex Development and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package fns.fossil.reactions; + +import fns.fossil.Fossil; +import fns.patchwork.base.Registration; +import fns.patchwork.base.Shortcuts; +import fns.patchwork.provider.SubscriptionProvider; +import fns.patchwork.service.Task; +import fns.patchwork.service.TaskSubscription; +import java.time.Duration; + +public class ReactionSystem +{ + public static void startCopyCat() + { + final Fossil fossil = Shortcuts.provideModule(Fossil.class); + final TaskSubscription subscription = + SubscriptionProvider.runSyncTask(fossil, new CopyCatReaction(25L)); + + Registration.getServiceTaskRegistry().registerTask(subscription); + Registration.getServiceTaskRegistry().startTask(CopyCatReaction.class); + } + + private static final class SystemTask extends Task + { + private SystemTask() + { + super("sys-task", 0L, Duration.ofMinutes(15L)); + } + + @Override + public void run() + { + ReactionSystem.startCopyCat(); + } + } +} diff --git a/Patchwork/src/main/java/fns/patchwork/bans/BanEntry.java b/Patchwork/src/main/java/fns/patchwork/bans/BanEntry.java new file mode 100644 index 0000000..aa3cc76 --- /dev/null +++ b/Patchwork/src/main/java/fns/patchwork/bans/BanEntry.java @@ -0,0 +1,43 @@ +package fns.patchwork.bans; + +import java.time.Instant; +import java.util.UUID; + +public interface BanEntry +{ + /** + * @return The username of the banned player. + */ + String getUsername(); + + /** + * @return The {@link UUID} of the banned player. + */ + UUID getUuid(); + + /** + * @return Either the IPv6 address of the banned player, if applicable, + * otherwise returns {@code "N/A"}. + */ + String getIpv6(); + + /** + * @return The reason for the ban. + */ + String getReason(); + + /** + * @return The {@link Instant} the ban was issued. + */ + Instant getIssued(); + + /** + * @return The {@link Instant} the ban expires. + */ + Instant getExpires(); + + /** + * @return The username of the individual who issued the ban. Can be {@code "CONSOLE"}. + */ + String getIssuer(); +} \ No newline at end of file diff --git a/Patchwork/src/main/java/fns/patchwork/base/Patchwork.java b/Patchwork/src/main/java/fns/patchwork/base/Patchwork.java index 60c9b55..6d97be6 100644 --- a/Patchwork/src/main/java/fns/patchwork/base/Patchwork.java +++ b/Patchwork/src/main/java/fns/patchwork/base/Patchwork.java @@ -27,8 +27,12 @@ import fns.patchwork.display.adminchat.AdminChatDisplay; import fns.patchwork.event.EventBus; import fns.patchwork.provider.ExecutorProvider; import fns.patchwork.provider.SubscriptionProvider; +import fns.patchwork.registry.ServiceTaskRegistry; +import fns.patchwork.service.Service; +import fns.patchwork.utils.logging.FNS4J; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; +import org.jetbrains.annotations.ApiStatus; /** * The base class for Patchwork. @@ -48,17 +52,8 @@ public class Patchwork extends JavaPlugin */ private AdminChatDisplay acdisplay; - @Override - public void onDisable() - { - Bukkit.getScheduler() - .runTaskLater(this, () -> Registration - .getServiceTaskRegistry() - .stopAllServices(), 1L); + private static final ServiceRunner runner = new ServiceRunner(); - Registration.getServiceTaskRegistry() - .unregisterService(EventBus.class); - } @Override public void onEnable() @@ -67,16 +62,39 @@ public class Patchwork extends JavaPlugin executor = new ExecutorProvider(this); acdisplay = new AdminChatDisplay(this); + Registration.getServiceTaskRegistry() + .registerService(SubscriptionProvider.asyncService(this, eventBus)); Registration.getServiceTaskRegistry() - .registerService(SubscriptionProvider.asyncService(this, eventBus)); + .registerService(SubscriptionProvider.asyncService(this, runner)); + // Will execute post-world getExecutor().getSync() - .execute(() -> Registration - .getServiceTaskRegistry() - .startAllServices()); + .execute(this::postWorld); Registration.getModuleRegistry().addModule(this); + + FNS4J.PATCHWORK.info("Successfully enabled Patchwork. API is ready to go."); + } + + @Override + public void onDisable() + { + Bukkit.getScheduler() + .runTaskLater(this, () -> Registration + .getServiceTaskRegistry() + .stopAllServices(), 1L); + + Registration.getServiceTaskRegistry() + .unregisterService(EventBus.class); + + FNS4J.PATCHWORK.info("Successfully disabled Patchwork. API is no longer available."); + } + + private void postWorld() + { + Registration.getServiceTaskRegistry() + .startAllServices(); } /** @@ -95,6 +113,7 @@ public class Patchwork extends JavaPlugin * * @return the {@link EventBus} */ + @ApiStatus.Experimental public EventBus getEventBus() { return eventBus; @@ -110,4 +129,34 @@ public class Patchwork extends JavaPlugin { return acdisplay; } + + @ApiStatus.Internal + private static final class ServiceRunner extends Service + { + public ServiceRunner() + { + super("srv-runner"); + } + + @Override + public void tick() + { + final ServiceTaskRegistry r = Registration.getServiceTaskRegistry(); + r.getServices().forEach(s -> + { + if (!s.isActive()) + { + r.unregisterService(s.getService().getClass()); + } + }); + + r.getTasks().forEach(t -> + { + if (!t.isActive()) + { + r.unregisterTask(t.getTask().getClass()); + } + }); + } + } } diff --git a/Patchwork/src/main/java/fns/patchwork/block/detector/NukerDetection.java b/Patchwork/src/main/java/fns/patchwork/block/detector/NukerDetection.java new file mode 100644 index 0000000..dc4fbb2 --- /dev/null +++ b/Patchwork/src/main/java/fns/patchwork/block/detector/NukerDetection.java @@ -0,0 +1,47 @@ +/* + * This file is part of FreedomNetworkSuite - https://github.com/SimplexDevelopment/FreedomNetworkSuite + * Copyright (C) 2023 Simplex Development and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package fns.patchwork.block.detector; + +import fns.patchwork.block.logger.TimedBlockLogger; +import java.util.Set; +import org.bukkit.entity.Player; + +public interface NukerDetection +{ + Set getTimedBlockLoggers(); + + boolean isNuking(); + + void addTimedBlockLogger(TimedBlockLogger timedBlockLogger); + + void removeTimedBlockLogger(TimedBlockLogger timedBlockLogger); + + default void ejectPlayer(final Player player) { + if (isNuking()) { + getTimedBlockLoggers().forEach(l -> { + + }); + } + } +} diff --git a/Patchwork/src/main/java/fns/patchwork/block/logger/BlockLogger.java b/Patchwork/src/main/java/fns/patchwork/block/logger/BlockLogger.java new file mode 100644 index 0000000..3071dbe --- /dev/null +++ b/Patchwork/src/main/java/fns/patchwork/block/logger/BlockLogger.java @@ -0,0 +1,51 @@ +/* + * This file is part of FreedomNetworkSuite - https://github.com/SimplexDevelopment/FreedomNetworkSuite + * Copyright (C) 2023 Simplex Development and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package fns.patchwork.block.logger; + +import java.util.UUID; +import org.bukkit.Bukkit; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; + +public interface BlockLogger +{ + UUID getUUID(); + + int getEditedBlockCount(); + + void incrementBlockCount(); + + void decrementBlockCount(); + + boolean greaterThan(final int p0); + + default boolean isPlayer() { + return Bukkit.getPlayer(this.getUUID()) != null; + } + + default boolean isTNT() { + final Entity entity = Bukkit.getEntity(this.getUUID()); + return entity != null && entity.getType() == EntityType.PRIMED_TNT; + } +} diff --git a/Patchwork/src/main/java/fns/patchwork/block/logger/TimedBlockLogger.java b/Patchwork/src/main/java/fns/patchwork/block/logger/TimedBlockLogger.java new file mode 100644 index 0000000..f373c01 --- /dev/null +++ b/Patchwork/src/main/java/fns/patchwork/block/logger/TimedBlockLogger.java @@ -0,0 +1,28 @@ +/* + * This file is part of FreedomNetworkSuite - https://github.com/SimplexDevelopment/FreedomNetworkSuite + * Copyright (C) 2023 Simplex Development and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package fns.patchwork.block.logger; + +public interface TimedBlockLogger extends BlockLogger +{ +} diff --git a/Patchwork/src/main/java/fns/patchwork/config/GenericConfiguration.java b/Patchwork/src/main/java/fns/patchwork/config/GenericConfiguration.java deleted file mode 100644 index 410e791..0000000 --- a/Patchwork/src/main/java/fns/patchwork/config/GenericConfiguration.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * This file is part of FreedomNetworkSuite - https://github.com/SimplexDevelopment/FreedomNetworkSuite - * Copyright (C) 2023 Simplex Development and contributors - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package fns.patchwork.config; - -import com.electronwill.nightconfig.core.Config; -import com.electronwill.nightconfig.core.ConfigFormat; -import com.electronwill.nightconfig.core.UnmodifiableConfig; -import fns.patchwork.utils.FileUtils; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.FileWriter; -import java.io.IOException; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; -import org.bukkit.plugin.java.JavaPlugin; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.annotations.Unmodifiable; - -public final class GenericConfiguration implements Configuration -{ - private final File configFile; - private final String fileName; - private final Config config; - private final ConfigType configType; - - public GenericConfiguration(@NotNull final ConfigType configType, - @Nullable final JavaPlugin plugin, - @NotNull final File dataFolder, - @NotNull final String fileName, - final boolean isConcurrent) throws IOException - { - if (!fileName.endsWith(configType.getExtension())) - throw new IllegalArgumentException("File name must end with " + configType.getExtension() + "!"); - - // Ternary just to piss off Allink :) - final Optional file = (plugin != null) ? - FileUtils.getOrCreateFileWithResource(dataFolder, fileName, plugin) : - FileUtils.getOrCreateFile(dataFolder, fileName); - - if (file.isEmpty()) - throw new FileNotFoundException(); - - this.configFile = file.get(); - this.fileName = fileName; - this.configType = configType; - - final ConfigFormat format = configType.getFormat(); - - // Another ternary just to piss off Allink :) - this.config = isConcurrent ? format.createConcurrentConfig() : format.createConfig(); - - this.load(); - } - - public GenericConfiguration(final ConfigType type, final File dataFolder, final String fileName) - throws IOException - { - this(type, null, dataFolder, fileName, false); - } - - public GenericConfiguration(final ConfigType type, final JavaPlugin plugin, final String fileName) - throws IOException - { - this(type, plugin, plugin.getDataFolder(), fileName, false); - } - - public GenericConfiguration(final ConfigType type, final File dataFolder, final String fileName, - final boolean isConcurrent) - throws IOException - { - this(type, null, dataFolder, fileName, isConcurrent); - } - - @Override - public void save() throws IOException - { - final File backup = new File(this.configFile.getParentFile(), this.fileName + ".bak"); - - if (backup.exists()) - Files.delete(backup.toPath()); - - Files.copy(this.configFile.toPath(), backup.toPath()); - - try (final FileWriter writer = new FileWriter(this.configFile)) - { - this.configType.getWriter().write(this.getConfig(), writer); - } - } - - @Override - public void load() throws IOException { - try (final FileReader reader = new FileReader(this.configFile)) { - this.config.clear(); - - final UnmodifiableConfig parsed = this.configType.getParser().parse(reader).unmodifiable(); - this.config.putAll(parsed); - } - } - - @Override - public String getFileName() - { - return fileName; - } - - @Override - public File getConfigurationFile() - { - return configFile; - } - - @Override - public String getString(final String path) - { - if (!(this.getConfig().get(path) instanceof String)) - throw new IllegalArgumentException(String.format("Value at path %s is not a string!", path)); - - return this.getConfig().get(path); - } - - @Override - public boolean getBoolean(String path) - { - if (!(this.getConfig().get(path) instanceof Boolean)) - throw new IllegalArgumentException(String.format("Value at path %s is not a boolean!", path)); - - return this.getConfig().get(path); - } - - @Override - @ApiStatus.Internal - public @Unmodifiable List getList(String path, Class clazz) - { - // TODO: Figure out how to parse lists with Night Config. - - return new ArrayList<>(); - } - - @Override - @ApiStatus.Internal - public @Unmodifiable List getStringList(String path) - { - // TODO: Figure out how to parse lists with Night Config. - - return new ArrayList<>(); - } - - @Override - public int getInt(String path) - { - return this.getConfig().getInt(path); - } - - @Override - public long getLong(String path) - { - return this.getConfig().getLong(path); - } - - @Override - public double getDouble(String path) - { - if (!(this.getConfig().get(path) instanceof Double)) - throw new IllegalArgumentException(String.format("Value at path %s is not a double!", path)); - - return this.getConfig().get(path); - } - - @Override - public Optional get(String path, Class clazz) - { - // I love ternary statements, sorry Allink :) - return clazz.isInstance(this.getConfig().get(path)) ? - Optional.of(clazz.cast(this.getConfig().get(path))) : - Optional.empty(); - } - - @Override - public T getOrDefault(String path, Class clazz, T fallback) - { - return this.get(path, clazz).orElse(fallback); - } - - @Override - public void set(final String path, final T value) { - this.config.set(path, value); - } - - private UnmodifiableConfig getConfig() - { - return config.unmodifiable(); - } - - public ConfigType getConfigType() - { - return configType; - } -} diff --git a/Patchwork/src/main/java/fns/patchwork/provider/SubscriptionProvider.java b/Patchwork/src/main/java/fns/patchwork/provider/SubscriptionProvider.java index c15bf5c..aeced8b 100644 --- a/Patchwork/src/main/java/fns/patchwork/provider/SubscriptionProvider.java +++ b/Patchwork/src/main/java/fns/patchwork/provider/SubscriptionProvider.java @@ -54,8 +54,8 @@ public final class SubscriptionProvider * @return The new {@link ServiceSubscription} object. */ @NotNull - @Contract(value = "_, _ -> new", pure = false) - public static final ServiceSubscription syncService(@NotNull final JavaPlugin plugin, + @Contract(value = "_, _ -> new") + public static ServiceSubscription syncService(@NotNull final JavaPlugin plugin, @NotNull final S service) { return new ServiceSubscription<>(plugin, service); @@ -73,7 +73,7 @@ public final class SubscriptionProvider */ @NotNull @Contract(value = "_,_,_ -> new", pure = false) - public static final ServiceSubscription syncService(@NotNull final JavaPlugin plugin, + public static ServiceSubscription syncService(@NotNull final JavaPlugin plugin, final long interval, @NotNull final S service) { @@ -91,7 +91,7 @@ public final class SubscriptionProvider */ @NotNull @Contract(value = "_, _ -> new", pure = false) - public static final ServiceSubscription asyncService(@NotNull final JavaPlugin plugin, + public static ServiceSubscription asyncService(@NotNull final JavaPlugin plugin, @NotNull final S service) { return new ServiceSubscription<>(plugin, service, true); @@ -109,7 +109,7 @@ public final class SubscriptionProvider */ @NotNull @Contract(value = "_,_,_ -> new", pure = false) - public static final ServiceSubscription asyncService(@NotNull final JavaPlugin plugin, + public static ServiceSubscription asyncService(@NotNull final JavaPlugin plugin, final long interval, @NotNull final S service) { @@ -127,7 +127,7 @@ public final class SubscriptionProvider */ @NotNull @Contract(value = "_, _ -> new", pure = false) - public static final TaskSubscription runSyncTask(@NotNull final JavaPlugin plugin, + public static TaskSubscription runSyncTask(@NotNull final JavaPlugin plugin, @NotNull final T task) { return new TaskSubscription<>(plugin, task, false); @@ -144,7 +144,7 @@ public final class SubscriptionProvider */ @NotNull @Contract(value = "_, _ -> new", pure = false) - public static final TaskSubscription runAsyncTask(@NotNull final JavaPlugin plugin, + public static TaskSubscription runAsyncTask(@NotNull final JavaPlugin plugin, @NotNull final T task) { return new TaskSubscription<>(plugin, task, true); diff --git a/Patchwork/src/main/java/fns/patchwork/registry/BanRegistry.java b/Patchwork/src/main/java/fns/patchwork/registry/BanRegistry.java new file mode 100644 index 0000000..9bc6bf7 --- /dev/null +++ b/Patchwork/src/main/java/fns/patchwork/registry/BanRegistry.java @@ -0,0 +1,57 @@ +/* + * This file is part of FreedomNetworkSuite - https://github.com/SimplexDevelopment/FreedomNetworkSuite + * Copyright (C) 2023 Simplex Development and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package fns.patchwork.registry; + +import fns.patchwork.bans.BanEntry; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import java.util.UUID; + +public class BanRegistry +{ + private final Set loadedBans = new HashSet<>(); + + public Optional getBan(final UUID uuid) + { + return loadedBans.stream() + .filter(b -> b.getUuid().equals(uuid)) + .findFirst(); + } + + public void addBan(final BanEntry entry) + { + this.loadedBans.add(entry); + } + + public void removeBan(final BanEntry entry) + { + this.loadedBans.remove(entry); + } + + public void clearLocalStorage() + { + this.loadedBans.clear(); + } +} diff --git a/Patchwork/src/main/java/fns/patchwork/registry/ServiceTaskRegistry.java b/Patchwork/src/main/java/fns/patchwork/registry/ServiceTaskRegistry.java index 00d7ffa..a343a7a 100644 --- a/Patchwork/src/main/java/fns/patchwork/registry/ServiceTaskRegistry.java +++ b/Patchwork/src/main/java/fns/patchwork/registry/ServiceTaskRegistry.java @@ -23,13 +23,16 @@ package fns.patchwork.registry; +import fns.patchwork.base.Registration; +import fns.patchwork.provider.SubscriptionProvider; import fns.patchwork.service.Service; import fns.patchwork.service.ServiceSubscription; -import fns.patchwork.provider.SubscriptionProvider; import fns.patchwork.service.Task; import fns.patchwork.service.TaskSubscription; import java.util.ArrayList; import java.util.List; +import java.util.Objects; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.Nullable; /** @@ -195,8 +198,18 @@ public class ServiceTaskRegistry */ public void startService(final Class clazz) { - this.getService(clazz) - .start(); + Objects.requireNonNull(this.getService(clazz)) + .start(); + } + + @ApiStatus.Internal + public List> getServices() { + return services; + } + + @ApiStatus.Internal + public List> getTasks() { + return tasks; } /** @@ -214,13 +227,12 @@ public class ServiceTaskRegistry * @see ServiceSubscription */ @Nullable + @SuppressWarnings("unchecked") public ServiceSubscription getService(final Class clazz) { for (final ServiceSubscription service : this.services) { - if (service.getService() - .getClass() - .equals(clazz)) + if (clazz.isInstance(service.getService())) { return (ServiceSubscription) service; } @@ -239,8 +251,8 @@ public class ServiceTaskRegistry */ public void stopService(final Class clazz) { - this.getService(clazz) - .stop(); + Objects.requireNonNull(this.getService(clazz)) + .stop(); } /** @@ -254,8 +266,8 @@ public class ServiceTaskRegistry */ public void startTask(final Class clazz) { - this.getTask(clazz) - .start(); + Objects.requireNonNull(this.getTask(clazz)) + .start(); } /** @@ -272,13 +284,11 @@ public class ServiceTaskRegistry * @see #registerTask(TaskSubscription) * @see TaskSubscription */ - public TaskSubscription getTask(final Class clazz) + public @Nullable TaskSubscription getTask(final Class clazz) { for (final TaskSubscription task : this.tasks) { - if (task.getTask() - .getClass() - .equals(clazz)) + if (clazz.isInstance(task.getTask())) { return (TaskSubscription) task; } @@ -297,8 +307,8 @@ public class ServiceTaskRegistry */ public void stopTask(final Class clazz) { - this.getTask(clazz) - .stop(); + Objects.requireNonNull(this.getTask(clazz)) + .stop(); } /** diff --git a/Patchwork/src/main/java/fns/patchwork/service/BukkitTimer.java b/Patchwork/src/main/java/fns/patchwork/service/BukkitTimer.java new file mode 100644 index 0000000..2c6e0b8 --- /dev/null +++ b/Patchwork/src/main/java/fns/patchwork/service/BukkitTimer.java @@ -0,0 +1,42 @@ +/* + * This file is part of FreedomNetworkSuite - https://github.com/SimplexDevelopment/FreedomNetworkSuite + * Copyright (C) 2023 Simplex Development and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package fns.patchwork.service; + +import java.time.Duration; +import java.time.Instant; +import java.util.Comparator; + +public class BukkitTimer extends TimedTask +{ + protected BukkitTimer(String name, Duration interval, Duration timeout) + { + super(name, interval, timeout); + } + + @Override + protected void runTimer() + { + + } +} diff --git a/Patchwork/src/main/java/fns/patchwork/service/ServiceSubscription.java b/Patchwork/src/main/java/fns/patchwork/service/ServiceSubscription.java index ef178d5..0406bbb 100644 --- a/Patchwork/src/main/java/fns/patchwork/service/ServiceSubscription.java +++ b/Patchwork/src/main/java/fns/patchwork/service/ServiceSubscription.java @@ -27,6 +27,7 @@ import java.util.concurrent.Executor; import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; /** @@ -61,11 +62,6 @@ public final class ServiceSubscription */ private final int serviceId; - /** - * Whether the service is currently running. - */ - private boolean isActive = false; - /** * Creates a new subscription for the given service. By default, this method will mark this service as a synchronous * service. This will also initialize the default interval to a single tick. @@ -79,7 +75,8 @@ public final class ServiceSubscription * @param plugin The plugin which owns the service. * @param service The service to subscribe to. */ - ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service) + @ApiStatus.Internal + public ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service) { this(plugin, service, 1L, false); } @@ -94,7 +91,8 @@ public final class ServiceSubscription * @param service The service to subscribe to. * @param async Whether the service should be scheduled asynchronously. */ - ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service, final boolean async) + @ApiStatus.Internal + public ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service, final boolean async) { this(plugin, service, 1L, async); } @@ -111,7 +109,8 @@ public final class ServiceSubscription * @param service The service to subscribe to. * @param interval The interval at which the service should be scheduled. */ - ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service, final long interval) + @ApiStatus.Internal + public ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service, final long interval) { this(plugin, service, interval, false); } @@ -126,8 +125,9 @@ public final class ServiceSubscription * @param interval The interval at which the service should be scheduled. * @param async Whether the service should be scheduled asynchronously. */ - ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service, - final long interval, final boolean async) + @ApiStatus.Internal + public ServiceSubscription(@NotNull final JavaPlugin plugin, @NotNull final T service, + final long interval, final boolean async) { this.service = service; this.async = async; @@ -142,7 +142,8 @@ public final class ServiceSubscription .runTaskTimerAsynchronously(plugin, r, 0, interval); tempId[0] = task.getTaskId(); }; - } else + } + else { this.executor = r -> { @@ -160,7 +161,6 @@ public final class ServiceSubscription */ public void start() { - this.isActive = true; this.executor.execute(service::tick); } @@ -169,7 +169,6 @@ public final class ServiceSubscription */ public void stop() { - this.isActive = false; Bukkit.getScheduler() .cancelTask(this.getServiceId()); } @@ -206,6 +205,9 @@ public final class ServiceSubscription */ public boolean isActive() { - return isActive; + return Bukkit.getScheduler() + .isQueued(this.getServiceId()) || + Bukkit.getScheduler() + .isCurrentlyRunning(this.getServiceId()); } } diff --git a/Patchwork/src/main/java/fns/patchwork/service/TaskSubscription.java b/Patchwork/src/main/java/fns/patchwork/service/TaskSubscription.java index 81aac2e..11388e2 100644 --- a/Patchwork/src/main/java/fns/patchwork/service/TaskSubscription.java +++ b/Patchwork/src/main/java/fns/patchwork/service/TaskSubscription.java @@ -29,6 +29,7 @@ import org.bukkit.Bukkit; import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.scheduler.BukkitTask; +import org.jetbrains.annotations.ApiStatus; /** * Represents a subscription to a task. Task subscriptions offer a nice wrapper for managing tasks, which are inevitably @@ -57,12 +58,6 @@ public final class TaskSubscription */ private final Executor executor; - /** - * True if the task is active, false otherwise. By default, this is set to false, and will be marked as true when - * the task is started. - */ - private boolean isActive = false; - /** * Creates a new task subscription. * @@ -70,7 +65,8 @@ public final class TaskSubscription * @param task The task that is being subscribed to. * @param async True if the task is async, false otherwise. */ - TaskSubscription(final JavaPlugin plugin, final T task, final boolean async) + @ApiStatus.Internal + public TaskSubscription(final JavaPlugin plugin, final T task, final boolean async) { this.task = task; this.async = async; @@ -184,7 +180,6 @@ public final class TaskSubscription */ public void start() { - this.isActive = true; executor.execute(task); } @@ -193,7 +188,6 @@ public final class TaskSubscription */ public void stop() { - this.isActive = false; Bukkit.getScheduler() .cancelTask(this.getTaskId()); } @@ -235,6 +229,8 @@ public final class TaskSubscription */ public boolean isActive() { - return isActive; + return !this.getTask().isCancelled() || + !Bukkit.getScheduler().isQueued(this.getTaskId()) && + !Bukkit.getScheduler().isCurrentlyRunning(this.getTaskId()); } } diff --git a/Patchwork/src/main/java/fns/patchwork/service/TimedTask.java b/Patchwork/src/main/java/fns/patchwork/service/TimedTask.java new file mode 100644 index 0000000..810111b --- /dev/null +++ b/Patchwork/src/main/java/fns/patchwork/service/TimedTask.java @@ -0,0 +1,55 @@ +/* + * This file is part of FreedomNetworkSuite - https://github.com/SimplexDevelopment/FreedomNetworkSuite + * Copyright (C) 2023 Simplex Development and contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +package fns.patchwork.service; + +import java.time.Duration; + +public abstract class TimedTask extends Task +{ + private final Duration timeout; + private long currentTimeSeconds = 0; + + protected TimedTask(final String name, final Duration interval, final Duration timeout) + { + super(name, 0, interval); + this.timeout = timeout; + } + + protected abstract void runTimer(); + + @Override + public void run() + { + if (this.currentTimeSeconds == 0) + this.currentTimeSeconds = System.currentTimeMillis() / 1000L; + + if (System.currentTimeMillis() / 1000L - this.currentTimeSeconds >= this.timeout.getSeconds()) + { + this.cancel(); + return; + } + + this.runTimer(); + } +} diff --git a/Patchwork/src/main/java/fns/patchwork/shop/Reaction.java b/Patchwork/src/main/java/fns/patchwork/shop/Reaction.java index 60480a6..08f3baa 100644 --- a/Patchwork/src/main/java/fns/patchwork/shop/Reaction.java +++ b/Patchwork/src/main/java/fns/patchwork/shop/Reaction.java @@ -23,13 +23,17 @@ package fns.patchwork.shop; +import fns.patchwork.service.Service; +import fns.patchwork.service.Task; +import fns.patchwork.service.TimedTask; import java.time.Duration; import net.kyori.adventure.text.Component; +import org.bukkit.event.Listener; /** * Represents a chat reaction that can be performed by a player. */ -public abstract class Reaction implements Reactable +public abstract class Reaction extends TimedTask implements Reactable { private final Duration reactionDuration; private final ReactionType reactionType; @@ -53,6 +57,9 @@ public abstract class Reaction implements Reactable protected Reaction(final Duration duration, final long reward, final ReactionType reactionType) { + super("CopyCatReaction", + Duration.ofSeconds(1), + Duration.ofSeconds(10)); this.reward = reward; this.reactionDuration = duration; this.reactionType = reactionType; diff --git a/Tyr/src/main/java/fns/tyr/data/SQLEntry.java b/Tyr/src/main/java/fns/tyr/data/SQLEntry.java index 9347c75..ffc6e4c 100644 --- a/Tyr/src/main/java/fns/tyr/data/SQLEntry.java +++ b/Tyr/src/main/java/fns/tyr/data/SQLEntry.java @@ -26,7 +26,6 @@ package fns.tyr.data; import fns.patchwork.base.Shortcuts; import fns.patchwork.utils.logging.FNS4J; import fns.tyr.oauth.Identity; -import java.sql.SQLException; public class SQLEntry { @@ -45,29 +44,22 @@ public class SQLEntry .thenApplyAsync(result -> { SQLEntry entry = null; - try + if (result.hasNext()) { - if (result.next()) - { - final String user = result.getString("user"); - final String secretKey = result.getString("secretKey"); + final String user = result.getString("user"); + final String secretKey = result.getString("secretKey"); - final Identity i = new Identity(user, secretKey); + final Identity i = new Identity(user, secretKey); - entry = new SQLEntry(i); - FNS4J.getLogger("Tyr") - .info("Loaded entry for " + username); - } - else - { - entry = new SQLEntry(Identity.of(username)); - FNS4J.getLogger("Tyr") - .info("Created a new entry for " + username); - } + entry = new SQLEntry(i); + FNS4J.getLogger("Tyr") + .info("Loaded entry for " + username); } - catch (SQLException ex) + else { - FNS4J.getLogger("Tyr").error(ex.getMessage()); + entry = new SQLEntry(Identity.of(username)); + FNS4J.getLogger("Tyr") + .info("Created a new entry for " + username); } return entry; }, Shortcuts.getExecutors() diff --git a/build.gradle b/build.gradle index 2d97049..dd20d62 100644 --- a/build.gradle +++ b/build.gradle @@ -14,6 +14,7 @@ subprojects { apply plugin: 'java-library' apply plugin: 'net.minecrell.plugin-yml.bukkit' + repositories { jcenter() mavenCentral()