diff --git a/src/main/java/me/totalfreedom/totalfreedommod/PluginProvider.java b/src/main/java/me/totalfreedom/totalfreedommod/PluginProvider.java index 210684830..56996aa98 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/PluginProvider.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/PluginProvider.java @@ -37,8 +37,7 @@ public static void unbind() * caching the variable as in `var plugin = PluginProvider.get()` like in FCommand is fine, since the bind never changes during lifetime * and binding is the first thing that happens in the plugins lifecycle in onLoad() and everything else is registered and initialized in the onEnable() method. * - * This however should be avoided moving forward; I will replace plugin and server variable with overload getters that just return this get method instead. - * There are many locations in the code where this occurs, FCommand is the only one thats feasibly fixable in this scope. + * This however should be avoided moving forward. * * @return the live plugin instance. * @throws IllegalStateException if the plugin is not currently bound. diff --git a/src/main/java/me/totalfreedom/totalfreedommod/TotalFreedomMod.java b/src/main/java/me/totalfreedom/totalfreedommod/TotalFreedomMod.java index 1b7392412..1e8c528d9 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/TotalFreedomMod.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/TotalFreedomMod.java @@ -2,6 +2,7 @@ import java.io.File; import java.io.InputStream; +import java.util.Optional; import java.util.Properties; import org.bukkit.generator.ChunkGenerator; @@ -46,7 +47,7 @@ import me.totalfreedom.totalfreedommod.util.FLog; import me.totalfreedom.totalfreedommod.util.FUtil; import me.totalfreedom.totalfreedommod.util.MethodTimer; -import me.totalfreedom.totalfreedommod.world.CleanroomChunkGenerator; +import me.totalfreedom.totalfreedommod.world.GenerationService; import me.totalfreedom.totalfreedommod.world.WorldManager; public class TotalFreedomMod extends JavaPlugin @@ -66,6 +67,7 @@ public class TotalFreedomMod extends JavaPlugin public FreedomDatabase dm; // FreedomDatabase - Manages SQL database connections public SavedFlags sf; // SavedFlags - Stores saved flag states public WorldManager wm; // WorldManager - Manages world operations + public GenerationService gs; // GenerationService - Loads and serves world-generation profiles public AdminList al; // AdminList - Manages admin list and permissions public RankManager rm; // RankManager - Handles player ranks and display public TitleManager tm; // TitleManager - Flat, non-inheriting capability grants shown alongside ranks @@ -182,6 +184,8 @@ public void onEnable() dm = services.registerService(FreedomDatabase.class); sf = services.registerService(SavedFlags.class); + // Before WorldManager: profiles must be loaded before anything tries to spin up a world from one. + gs = services.registerService(GenerationService.class); wm = services.registerService(WorldManager.class); al = services.registerService(AdminList.class); @@ -290,20 +294,14 @@ public void onEnable() @Override public ChunkGenerator getDefaultWorldGenerator(String worldName, String id) { - if ("flatlands".equals(worldName)) + if (gs != null) { - String params; - if (config != null) - { - params = ConfigEntry.FLATLANDS_GENERATE_PARAMS.getString(); - } - else - { - saveDefaultConfig(); - params = getConfig().getString("flatlands.generate_params", "16|stone|32|dirt|1|grass_block"); - } - return new CleanroomChunkGenerator(params); + final Optional generator = gs.generatorFor(worldName); + + if (generator.isPresent()) + return generator.get(); } + return super.getDefaultWorldGenerator(worldName, id); } diff --git a/src/main/java/me/totalfreedom/totalfreedommod/admin/AdminList.java b/src/main/java/me/totalfreedom/totalfreedommod/admin/AdminList.java index 2b99c7a49..e69c311eb 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/admin/AdminList.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/admin/AdminList.java @@ -7,7 +7,6 @@ import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; import java.sql.SQLException; -import java.time.Duration; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -287,27 +286,19 @@ public Admin getAdmin(CommandSender sender) Admin admin = getEntryByName(player.getName()); // Admin by name - if (admin != null) + if (admin != null && (Bukkit.getOnlineMode() || admin.getIps().contains(ip))) { - // Check if we're in online mode, - // Or the players IP is in the admin entry - if (Bukkit.getOnlineMode() || admin.getIps().contains(ip)) + if (!admin.getIps().contains(ip)) { - if (!admin.getIps().contains(ip)) - { - // Add the new IP if we have to - admin.addIp(ip); - ipTable.put(ip, admin); - saveAdminAsync(admin); - } - return admin; + // Add the new IP if we have to + admin.addIp(ip); + ipTable.put(ip, admin); + saveAdminAsync(admin); } - // Impostor: the name is ours but the IP is not. Fall through to - // the IP lookup, which will not match this entry. + return admin; } - // Admin by ip admin = getEntryByIp(ip); if (admin != null) { @@ -500,9 +491,9 @@ public void updateTables() .filter(this::isAdmin) .forEach(onlineAdminPlayers::add); - if (plugin.wm != null && plugin.wm.adminworld != null) + if (plugin.wm != null) { - plugin.wm.adminworld.wipeAccessCache(); + plugin.wm.invalidateAccessCaches(); } } diff --git a/src/main/java/me/totalfreedom/totalfreedommod/blocking/BlockBlocker.java b/src/main/java/me/totalfreedom/totalfreedommod/blocking/BlockBlocker.java index 66b3e637e..911c17a1f 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/blocking/BlockBlocker.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/blocking/BlockBlocker.java @@ -127,7 +127,7 @@ public void onBlockPlace(BlockPlaceEvent event) } case SPAWNER: { - if (ConfigEntry.DISABLE_SPAWNER_PLACE.getBoolean()) + if (plugin.gs.blocking(event.getBlock().getWorld().getName()).spawnerPlace()) { player.sendMessage(Component.text("Spawners are currently disabled.", NamedTextColor.GRAY)); diff --git a/src/main/java/me/totalfreedom/totalfreedommod/blocking/EventBlocker.java b/src/main/java/me/totalfreedom/totalfreedommod/blocking/EventBlocker.java index d10bacef1..ef8924eaa 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/blocking/EventBlocker.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/blocking/EventBlocker.java @@ -1,5 +1,7 @@ package me.totalfreedom.totalfreedommod.blocking; +import java.util.Optional; + import io.papermc.paper.event.block.BlockPreDispenseEvent; import org.bukkit.GameMode; import org.bukkit.Material; @@ -229,7 +231,7 @@ public void onLeavesDecay(LeavesDecayEvent event) @EventHandler(priority = EventPriority.HIGH) public void onSpawnerSpawn(SpawnerSpawnEvent event) { - if (ConfigEntry.DISABLE_SPAWNERS.getBoolean()) + if (plugin.gs.blocking(event.getEntity().getWorld().getName()).spawners()) { event.setCancelled(true); } @@ -238,7 +240,22 @@ public void onSpawnerSpawn(SpawnerSpawnEvent event) @EventHandler(priority = EventPriority.HIGH) public void onTrialSpawnerSpawn(TrialSpawnerSpawnEvent event) { - if (ConfigEntry.DISABLE_SPAWNERS.getBoolean()) + if (plugin.gs.blocking(event.getEntity().getWorld().getName()).spawners()) + { + event.setCancelled(true); + } + } + + /** Reads {@code blocking.monsters} live on every natural spawn attempt rather than pushing it onto the world once at creation, so editing a profile takes effect on the very next spawn with nothing to reload. */ + @EventHandler(priority = EventPriority.HIGH) + public void onCreatureSpawn(CreatureSpawnEvent event) + { + if (event.getSpawnReason() != CreatureSpawnEvent.SpawnReason.NATURAL) + { + return; + } + + if (event.getEntity() instanceof Monster && plugin.gs.blocking(event.getEntity().getWorld().getName()).monsters()) { event.setCancelled(true); } @@ -247,7 +264,7 @@ public void onTrialSpawnerSpawn(TrialSpawnerSpawnEvent event) @EventHandler(priority = EventPriority.HIGH) public void onPortalCreate(PortalCreateEvent event) { - if (ConfigEntry.DISABLE_PORTAL_CREATE.getBoolean()) + if (plugin.gs.blocking(event.getWorld().getName()).portalCreate()) { event.setCancelled(true); } @@ -256,7 +273,7 @@ public void onPortalCreate(PortalCreateEvent event) @EventHandler(priority = EventPriority.HIGH) public void onPistonExtend(BlockPistonExtendEvent event) { - if (ConfigEntry.DISABLE_PISTONS.getBoolean() || redstoneBlocked()) + if (plugin.gs.blocking(event.getBlock().getWorld().getName()).pistons() || redstoneBlocked()) { event.setCancelled(true); } @@ -265,7 +282,7 @@ public void onPistonExtend(BlockPistonExtendEvent event) @EventHandler(priority = EventPriority.HIGH) public void onPistonRetract(BlockPistonRetractEvent event) { - if (ConfigEntry.DISABLE_PISTONS.getBoolean() || redstoneBlocked()) + if (plugin.gs.blocking(event.getBlock().getWorld().getName()).pistons() || redstoneBlocked()) { event.setCancelled(true); } @@ -274,7 +291,8 @@ public void onPistonRetract(BlockPistonRetractEvent event) @EventHandler(priority = EventPriority.NORMAL) public void onEntitySpawn(EntitySpawnEvent event) { - if (!ConfigEntry.DISABLE_ENTITY_SPAM.getBoolean()) + final Optional max = plugin.gs.blocking(event.getLocation().getWorld().getName()).entitySpamMax(); + if (max.isEmpty()) { return; } @@ -291,8 +309,7 @@ public void onEntitySpawn(EntitySpawnEvent event) return; } - final int max = ConfigEntry.DISABLE_ENTITY_SPAM_MAX.getInteger(); - if (max > 0 && event.getLocation().getWorld().getEntities().size() > max) + if (max.get() > 0 && event.getLocation().getWorld().getEntities().size() > max.get()) { event.setCancelled(true); } diff --git a/src/main/java/me/totalfreedom/totalfreedommod/blocking/spawner/SpawnerValidator.java b/src/main/java/me/totalfreedom/totalfreedommod/blocking/spawner/SpawnerValidator.java index e95c6a998..cf69f5dc1 100644 --- a/src/main/java/me/totalfreedom/totalfreedommod/blocking/spawner/SpawnerValidator.java +++ b/src/main/java/me/totalfreedom/totalfreedommod/blocking/spawner/SpawnerValidator.java @@ -148,7 +148,7 @@ private void blockWindChargeFromSpawner(SpawnerSpawnEvent event) private void blockHangingFromSpawner(EntitySpawnEvent event, String reason, String label) { - if (Boolean.TRUE.equals(ConfigEntry.DISABLE_SPAWNERS.getBoolean())) + if (plugin.gs.blocking(event.getEntity().getWorld().getName()).spawners()) { return; } diff --git a/src/main/java/me/totalfreedom/totalfreedommod/cmd/Command_adminworld.java b/src/main/java/me/totalfreedom/totalfreedommod/cmd/Command_adminworld.java deleted file mode 100644 index 876facc3a..000000000 --- a/src/main/java/me/totalfreedom/totalfreedommod/cmd/Command_adminworld.java +++ /dev/null @@ -1,120 +0,0 @@ -package me.totalfreedom.totalfreedommod.cmd; - -import org.bukkit.World; -import org.bukkit.command.CommandSender; -import org.bukkit.entity.Player; - -import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder; - -import me.totalfreedom.totalfreedommod.cmd.internal.annotation.*; -import me.totalfreedom.totalfreedommod.world.WorldTime; -import me.totalfreedom.totalfreedommod.world.WorldWeather; - -@Command(name = "adminworld", description = "Go to, or manage the AdminWorld.", usage = "/adminworld [guest ]", aliases = {"aw"}) -@Permission(permission = "tfm.world.adminworld") // default permission is op, and default source is BOTH -public class Command_adminworld extends FCommand -{ - - @Callback - @Permission(source = SourceType.ONLY_IN_GAME, permission = "tfm.world.adminworld") - public void moveToWorld(Player player) - { - World adminWorld = null; - try - { - adminWorld = plugin().wm.adminworld.getWorld(); - } - catch (Exception ignored) {} - - if (adminWorld == null || player.getWorld().getUID().equals(adminWorld.getUID())) - { - msg(player, "Going to the main world."); - player.teleport(server().getWorlds().get(0).getSpawnLocation().clone()); - } - else if (plugin().wm.adminworld.canAccessWorld(player)) - { - msg(player, "Going to the AdminWorld."); - plugin().wm.adminworld.sendToWorld(player); - } - else - { - msg(player, "You don't have permission to access the AdminWorld."); - } - } - - @Callback - @Subcommand("guest add") - @Permission(source = SourceType.ONLY_IN_GAME, permission = "tfm.world.adminworld.manage") - public void addGuest(Player sender, Player target) - { - if (plugin().wm.adminworld.addGuest(target, sender)) - { - adminAction(sender, "AdminWorld guest added: ", - Placeholder.unparsed("target", target.getName())); - return; - } - msg(sender, "Could not add player to guest list."); - } - - @Callback - @Subcommand("guest list") - @Permission(permission = "tfm.world.adminworld") - public void listGuests(CommandSender sender) - { - if (plugin().wm.adminworld.hasGuests()) - { - // TODO: Probably not use this weird guestListToString - msg(sender, "AdminWorld guest list: ", - Placeholder.parsed("list", plugin().wm.adminworld.guestListToString())); - return; - } - - msg(sender, "There are no AdminWorld guests."); - } - - @Callback - @Subcommand("guest remove") - @Permission(permission = "tfm.world.adminworld.manage") - public void removeGuest(CommandSender sender, Player target) - { - if (plugin().wm.adminworld.removeGuest(target)) - { - adminAction(sender, "AdminWorld guest removed: ", - Placeholder.unparsed("target", target.getName())); - } - else - { - msg(sender, "Can't find guest entry for .", - Placeholder.unparsed("target", target.getName())); - } - } - - @Callback - @Subcommand("guest purge") - @Permission(permission = "tfm.world.adminworld.manage") - public void purgeGuests(CommandSender sender) - { - plugin().wm.adminworld.purgeGuestList(); - adminAction(sender, "AdminWorld guest list purged."); - } - - @Callback - @Subcommand("time") - @Permission(permission = "tfm.world.adminworld.manage") - public void setTime(CommandSender sender, WorldTime time) - { - plugin().wm.adminworld.setTimeOfDay(time); - msg(sender, "AdminWorld time set to