From 8002ad6ec84b67137b6d7d6c84b32c4c2904fd6a Mon Sep 17 00:00:00 2001 From: jakub Date: Thu, 5 Mar 2026 00:38:55 +0100 Subject: [PATCH] =?UTF-8?q?-=20datab=C3=A1zov=C3=A9=20=C3=BAdaje=20z=20con?= =?UTF-8?q?figu=20-=20templates=20v=20resources=20-=20fix=20active=5Fon=20?= =?UTF-8?q?-=20default=20spawn=20server?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 13 ++++ .../xyz/soukup/ecoCraftCore/EcoCraftCore.java | 26 ++++++-- .../ecoCraftCore/islands/ChunkModifier.java | 1 + ...ndCommand.java => IslandAdminCommand.java} | 62 ++++++++++++------ .../ecoCraftCore/islands/IslandManager.java | 28 ++++---- .../soukup/ecoCraftCore/player/OnKill.java | 27 ++++++++ .../player/TeleportRequestsHandler.java | 12 +++- src/main/resources/config.yml | 4 +- .../island_templates/flat_grass.slime | Bin 0 -> 3414 bytes .../island_templates/flat_hell.slime | Bin 0 -> 6325 bytes .../island_templates/flat_sand.slime | Bin 0 -> 3450 bytes 11 files changed, 135 insertions(+), 38 deletions(-) rename src/main/java/xyz/soukup/ecoCraftCore/islands/{IslandCommand.java => IslandAdminCommand.java} (85%) create mode 100644 src/main/java/xyz/soukup/ecoCraftCore/player/OnKill.java create mode 100644 src/main/resources/island_templates/flat_grass.slime create mode 100644 src/main/resources/island_templates/flat_hell.slime create mode 100644 src/main/resources/island_templates/flat_sand.slime diff --git a/pom.xml b/pom.xml index ab470a8..757f316 100644 --- a/pom.xml +++ b/pom.xml @@ -79,9 +79,22 @@ + src/main/resources true + + **/*.yml + + + + + + src/main/resources + false + + **/*.slime + diff --git a/src/main/java/xyz/soukup/ecoCraftCore/EcoCraftCore.java b/src/main/java/xyz/soukup/ecoCraftCore/EcoCraftCore.java index 4cf19e7..8839e05 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/EcoCraftCore.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/EcoCraftCore.java @@ -20,8 +20,9 @@ import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import org.jetbrains.annotations.NotNull; import xyz.soukup.ecoCraftCore.database.objects.*; -import xyz.soukup.ecoCraftCore.islands.IslandCommand; +import xyz.soukup.ecoCraftCore.islands.IslandAdminCommand; import xyz.soukup.ecoCraftCore.money.MoneyCommand; +import xyz.soukup.ecoCraftCore.player.OnKill; import xyz.soukup.ecoCraftCore.player.PreparePlayer; import xyz.soukup.ecoCraftCore.player.TeleportRequestsHandler; import xyz.soukup.ecoCraftCore.positionMarker.RulerCommand; @@ -64,6 +65,7 @@ public final class EcoCraftCore extends JavaPlugin { PacketEvents.getAPI().init(); try { + saveIslandTemplates(); saveDefaultConfig(); Messages.init(); prepareDatabase(); @@ -87,6 +89,7 @@ public final class EcoCraftCore extends JavaPlugin { @Override public void onDisable() { + plugin.saveConfig(); VirtualChest.saveCache(); saveSlimeWorlds(); adiosDatabase(); @@ -166,9 +169,23 @@ public final class EcoCraftCore extends JavaPlugin { } } + private void saveIslandTemplates(){ + plugin.saveResource("island_templates/flat_grass.slime", false); + plugin.saveResource("island_templates/flat_sand.slime", false); + plugin.saveResource("island_templates/flat_hell.slime", false); + + + } + private void prepareDatabase() throws SQLException { - String databaseUrl = "jdbc:mysql://localhost:3306/ecc"; - connectionSource = new JdbcConnectionSource(databaseUrl, "ecc", "ecc"); + String databaseHost = config.getString("database.host"); + String databasePort = config.getString("database.port"); + String databaseName = config.getString("database.database"); + String databaseUsername = config.getString("database.user"); + String databasePassword = config.getString("database.password"); + + String databaseUrl = "jdbc:mysql://" + databaseHost + ":" + databasePort + "/" + databaseName; + connectionSource = new JdbcConnectionSource(databaseUrl, databaseUsername, databasePassword); Logger.getLogger("com.j256.ormlite.table.TableUtils").setLevel(Level.OFF); TableUtils.createTableIfNotExists(connectionSource, ActiveServer.class); @@ -213,13 +230,14 @@ public final class EcoCraftCore extends JavaPlugin { lm.registerEventHandler(LifecycleEvents.COMMANDS, event -> event.registrar().register(ShopCommand.createCommand().build())); lm.registerEventHandler(LifecycleEvents.COMMANDS, event -> event.registrar().register(RulerCommand.createCommand().build())); lm.registerEventHandler(LifecycleEvents.COMMANDS, event -> event.registrar().register(MoneyCommand.createCommand().build())); - lm.registerEventHandler(LifecycleEvents.COMMANDS, event -> event.registrar().register(IslandCommand.createCommand().build())); + lm.registerEventHandler(LifecycleEvents.COMMANDS, event -> event.registrar().register(IslandAdminCommand.createCommand().build())); } private void registerEvents(){ PluginManager pm = this.getServer().getPluginManager(); pm.registerEvents(new TeleportRequestsHandler(), this); + pm.registerEvents(new OnKill(), this); pm.registerEvents(new RulerMarking(), this); pm.registerEvents(new VirtualChestLogic(), this); pm.registerEvents(new ShopLogic(), this); diff --git a/src/main/java/xyz/soukup/ecoCraftCore/islands/ChunkModifier.java b/src/main/java/xyz/soukup/ecoCraftCore/islands/ChunkModifier.java index 0a333a1..2ae90a1 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/islands/ChunkModifier.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/islands/ChunkModifier.java @@ -52,6 +52,7 @@ public class ChunkModifier implements PacketListener { PersistentDataContainer pdc = world.getPersistentDataContainer(); String type = pdc.get(keyType, PersistentDataType.STRING); + if (type == null) return; String block; diff --git a/src/main/java/xyz/soukup/ecoCraftCore/islands/IslandCommand.java b/src/main/java/xyz/soukup/ecoCraftCore/islands/IslandAdminCommand.java similarity index 85% rename from src/main/java/xyz/soukup/ecoCraftCore/islands/IslandCommand.java rename to src/main/java/xyz/soukup/ecoCraftCore/islands/IslandAdminCommand.java index 8589957..ee6ada0 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/islands/IslandCommand.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/islands/IslandAdminCommand.java @@ -3,14 +3,12 @@ package xyz.soukup.ecoCraftCore.islands; import com.infernalsuite.asp.api.AdvancedSlimePaperAPI; import com.infernalsuite.asp.api.world.SlimeWorld; import com.j256.ormlite.stmt.QueryBuilder; -import com.mojang.brigadier.Message; import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import io.papermc.paper.command.brigadier.CommandSourceStack; import io.papermc.paper.command.brigadier.Commands; -import net.kyori.adventure.text.Component; import org.bukkit.Location; import org.bukkit.NamespacedKey; import org.bukkit.entity.Player; @@ -24,9 +22,10 @@ import java.io.IOException; import java.sql.SQLException; import java.util.List; +import static xyz.soukup.ecoCraftCore.EcoCraftCore.config; import static xyz.soukup.ecoCraftCore.EcoCraftCore.plugin; -public class IslandCommand { +public class IslandAdminCommand { private final AdvancedSlimePaperAPI asp = AdvancedSlimePaperAPI.instance(); @@ -35,7 +34,7 @@ public class IslandCommand { LiteralArgumentBuilder tp = Commands.literal("tp") .then(Commands.argument("uuid", StringArgumentType.word()) - .executes(IslandCommand::teleport) + .executes(IslandAdminCommand::teleport) .suggests(((context, builder) -> { try { QueryBuilder queryBuilder = DaoRegistry.getIslandDao().queryBuilder(); @@ -66,7 +65,7 @@ public class IslandCommand { })) .then(Commands.argument("display_name", StringArgumentType.string()) .then(Commands.argument("description", StringArgumentType.greedyString()) - .executes(IslandCommand::createWorld)))); + .executes(IslandAdminCommand::createWorld)))); LiteralArgumentBuilder load = Commands.literal("load") .then(Commands.argument("uuid", StringArgumentType.word()) @@ -83,7 +82,7 @@ public class IslandCommand { throw new RuntimeException(e); } })) - .executes(IslandCommand::loadWorld)); + .executes(IslandAdminCommand::loadWorld)); LiteralArgumentBuilder loadTemplate = Commands.literal("loadTemplate") .then(Commands.argument("name", StringArgumentType.word()) @@ -100,7 +99,7 @@ public class IslandCommand { } return builder.buildFuture(); })) - .executes(IslandCommand::loadTemplate)); + .executes(IslandAdminCommand::loadTemplate)); LiteralArgumentBuilder template = Commands.literal("template") .then(Commands.argument("uuid", StringArgumentType.word()) @@ -118,31 +117,31 @@ public class IslandCommand { } }) .then(Commands.argument("templateName", StringArgumentType.word()) - .executes(IslandCommand::createTemplate))); + .executes(IslandAdminCommand::createTemplate))); LiteralArgumentBuilder metadata = Commands.literal("metadata") .then(Commands.argument("key", StringArgumentType.word()) .then(Commands.argument("value", IntegerArgumentType.integer()) - .executes(IslandCommand::setMetadata))); + .executes(IslandAdminCommand::setMetadata))); LiteralArgumentBuilder metadataString = Commands.literal("metadataString") .then(Commands.argument("key", StringArgumentType.word()) .then(Commands.argument("value", StringArgumentType.string()) - .executes(IslandCommand::setMetadataString))); + .executes(IslandAdminCommand::setMetadataString))); LiteralArgumentBuilder expand = Commands.literal("expand") .then(Commands.argument("lenght", IntegerArgumentType.integer()) - .executes(IslandCommand::expandIsland)); + .executes(IslandAdminCommand::expandIsland)); LiteralArgumentBuilder listMetadata = Commands.literal("listMetadata") - .executes(IslandCommand::readAllMetadata); + .executes(IslandAdminCommand::readAllMetadata); LiteralArgumentBuilder spawn = Commands.literal("spawn") - .executes(IslandCommand::setSpawn); + .executes(IslandAdminCommand::setSpawn); LiteralArgumentBuilder enviroment = Commands.literal("environment") .then(Commands.argument("environment", StringArgumentType.word()) - .executes(IslandCommand::setEnvironment) + .executes(IslandAdminCommand::setEnvironment) .suggests(((context, builder) -> { builder.suggest("normal"); builder.suggest("nether"); @@ -150,7 +149,11 @@ public class IslandCommand { return builder.buildFuture(); }))); - return Commands.literal("island") + LiteralArgumentBuilder setDefaultIsland = Commands.literal("setDefaultIsland") + .executes(IslandAdminCommand::setDefualtIsland); + + return Commands.literal("island-admin") + .requires(commandSourceStack -> commandSourceStack.getSender().isOp()) .then(tp) .then(create) .then(load) @@ -161,8 +164,20 @@ public class IslandCommand { .then(loadTemplate) .then(spawn) .then(enviroment) - .then(expand); + .then(expand) + .then(setDefaultIsland); + + + } + + private static int setDefualtIsland(CommandContext context){ + if (!(context.getSource().getSender() instanceof Player player)) return 0; + String uuid = player.getWorld().getName(); + config.set("islands.spawn", uuid); + plugin.saveConfig(); + player.sendMessage("done."); + return 0; } @@ -191,7 +206,8 @@ public class IslandCommand { private static int teleport(CommandContext context) { IslandManager islandManager = new IslandManager(); try { - islandManager.teleport((Player) context.getSource().getSender(), context.getArgument("uuid", String.class)); + Integer status = islandManager.teleport((Player) context.getSource().getSender(), context.getArgument("uuid", String.class)); + context.getSource().getSender().sendMessage(String.valueOf(status)); } catch (Exception e) { throw new RuntimeException(e); } @@ -203,19 +219,23 @@ public class IslandCommand { String type = context.getArgument("type", String.class); String displayName = context.getArgument("display_name", String.class); String description = context.getArgument("description", String.class); - islandManager.createIsland(type, displayName, description, "n", "n"); + String uuid = islandManager.createIsland(type, displayName, description, "n", "n"); + context.getSource().getSender().sendMessage("Created island: " + uuid); + return 0; } private static int loadWorld(CommandContext context) { IslandManager islandManager = new IslandManager(); islandManager.loadIsland(context.getArgument("uuid", String.class)); + context.getSource().getSender().sendMessage("done."); return 0; } private static int loadTemplate(CommandContext context) { IslandManager islandManager = new IslandManager(); islandManager.loadIslandTemplate(context.getArgument("name", String.class)); + context.getSource().getSender().sendMessage("done."); return 0; } @@ -235,9 +255,8 @@ public class IslandCommand { String keyName = StringArgumentType.getString(context, "key"); Integer value = IntegerArgumentType.getInteger(context, "value"); - - player.getWorld().getPersistentDataContainer().set(new NamespacedKey(plugin, keyName), PersistentDataType.INTEGER, value); + context.getSource().getSender().sendMessage(keyName + " set to " + value); return 1; } @@ -248,7 +267,8 @@ public class IslandCommand { String value = StringArgumentType.getString(context, "value"); player.getWorld().getPersistentDataContainer().set(new NamespacedKey(plugin, keyName), PersistentDataType.STRING, value); - + context.getSource().getSender().sendMessage(keyName + " set to " + value); + return 1; } diff --git a/src/main/java/xyz/soukup/ecoCraftCore/islands/IslandManager.java b/src/main/java/xyz/soukup/ecoCraftCore/islands/IslandManager.java index 9cbaec9..12ee841 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/islands/IslandManager.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/islands/IslandManager.java @@ -16,7 +16,6 @@ import com.j256.ormlite.stmt.QueryBuilder; import com.j256.ormlite.stmt.UpdateBuilder; import org.bukkit.*; import org.bukkit.entity.Player; -import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; import xyz.soukup.ecoCraftCore.database.objects.Island; import xyz.soukup.ecoCraftCore.database.DaoRegistry; @@ -75,8 +74,6 @@ public class IslandManager { props.setValue(SlimeProperties.SPAWN_Z, 0); slimeWorld = asp.createEmptyWorld(uuid, false, props, databaseLoader); - - asp.saveWorld(slimeWorld); } @@ -90,25 +87,32 @@ public class IslandManager { - public void teleport(Player player, String uuid) throws Exception { - teleport(player, uuid, null, null, null, null, null); + public int teleport(Player player, String uuid) throws Exception { + return teleport(player, uuid, null, null, null, null, null); + } - public void teleport(Player player, String uuid, Integer x, Integer y, Integer z, Float yaw, Float pitch) throws Exception { + public int teleport(Player player, String uuid, Integer x, Integer y, Integer z, Float yaw, Float pitch) throws Exception { + + if(uuid == null) return 4; + if (Bukkit.getWorld(uuid) != null){ teleportLocally(player, uuid, x, y, z, yaw, pitch); + return 2; } String whereIsActive = whereIsActive(uuid); - if (whereIsActive != null){ + if (whereIsActive != null && !whereIsActive.isEmpty()){ + plugin.getLogger().info("dd: "+ whereIsActive); sendPlayerAway(player, whereIsActive, uuid, x, y, z, yaw, pitch); + return 3; } QueryBuilder queryBuilder = dao.queryBuilder().setCountOf(true); queryBuilder.where().eq("uuid", uuid); if (dao.countOf(queryBuilder.prepare()) < 1){ - return; + return 1; } if (player.getVirtualHost() != null){ @@ -120,6 +124,7 @@ public class IslandManager { } teleportLocally(player, uuid, x, y, z, yaw, pitch); + return 0; } @@ -271,7 +276,7 @@ public class IslandManager { switch (islandType){ case "flat_grass" -> flatExpander(world, yaw, lenght, Material.GRASS_BLOCK, Material.STONE, Material.WATER); case "flat_sand" -> flatExpander(world, yaw, lenght, Material.SAND, Material.STONE, Material.WATER); - case "flat_hell" -> flatExpander(world, yaw, lenght, Material.SOUL_SOIL, Material.NETHERRACK, Material.LAVA); + case "flat_hell" -> flatExpander(world, yaw, lenght, Material.SOUL_SAND, Material.NETHERRACK, Material.LAVA); } @@ -384,8 +389,9 @@ public class IslandManager { if ((x >= xMin && x <= xMax) && (z >= zMin && z <= zMax)) { continue; } - world.setType(x, y, z, surrounding); - world.setType(x, y+1, z, surrounding); + world.getBlockAt(x,y,z).setType(surrounding, false); + world.getBlockAt(x,y+1,z).setType(surrounding, false); + } } ; diff --git a/src/main/java/xyz/soukup/ecoCraftCore/player/OnKill.java b/src/main/java/xyz/soukup/ecoCraftCore/player/OnKill.java new file mode 100644 index 0000000..51bfd46 --- /dev/null +++ b/src/main/java/xyz/soukup/ecoCraftCore/player/OnKill.java @@ -0,0 +1,27 @@ +package xyz.soukup.ecoCraftCore.player; + +import com.destroystokyo.paper.event.player.PlayerPostRespawnEvent; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.PlayerDeathEvent; +import org.bukkit.event.player.PlayerRespawnEvent; +import xyz.soukup.ecoCraftCore.islands.IslandManager; + +import static xyz.soukup.ecoCraftCore.EcoCraftCore.config; + +public class OnKill implements Listener { + @EventHandler + public void spawnTeleportOnKill(PlayerPostRespawnEvent event){ + Player player = event.getPlayer(); + + String uuid = config.getString("islands.spawn"); + + IslandManager islandManager = new IslandManager(); + try { + islandManager.teleport(player, uuid); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/src/main/java/xyz/soukup/ecoCraftCore/player/TeleportRequestsHandler.java b/src/main/java/xyz/soukup/ecoCraftCore/player/TeleportRequestsHandler.java index 99ac37b..56a7c25 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/player/TeleportRequestsHandler.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/player/TeleportRequestsHandler.java @@ -1,9 +1,11 @@ package xyz.soukup.ecoCraftCore.player; +import com.google.common.eventbus.DeadEvent; import com.j256.ormlite.stmt.QueryBuilder; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.player.PlayerJoinEvent; import xyz.soukup.ecoCraftCore.database.DaoRegistry; import xyz.soukup.ecoCraftCore.database.objects.TeleportRequest; @@ -11,6 +13,8 @@ import xyz.soukup.ecoCraftCore.islands.IslandManager; import java.sql.SQLException; +import static xyz.soukup.ecoCraftCore.EcoCraftCore.config; + public class TeleportRequestsHandler implements Listener { @EventHandler @@ -23,11 +27,14 @@ public class TeleportRequestsHandler implements Listener { TeleportRequest teleportRequest = queryBuilder.queryForFirst(); + IslandManager islandManager = new IslandManager(); + + if (teleportRequest == null){ + islandManager.teleport(player, config.getString("islands.spawn")); return; } - IslandManager islandManager = new IslandManager(); islandManager.teleportLocally(player, teleportRequest.getWorld(), teleportRequest.getX(), teleportRequest.getY(), teleportRequest.getY(), teleportRequest.getYaw(), teleportRequest.getPitch()); @@ -35,6 +42,9 @@ public class TeleportRequestsHandler implements Listener { } catch (SQLException e) { throw new RuntimeException(e); + } catch (Exception e) { + throw new RuntimeException(e); } } + } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index af80369..3d9ced4 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -9,4 +9,6 @@ database: password: "ecc" database: "ecc" cache: - save-interval: 6000 \ No newline at end of file + save-interval: 6000 +islands: + spawn: null \ No newline at end of file diff --git a/src/main/resources/island_templates/flat_grass.slime b/src/main/resources/island_templates/flat_grass.slime new file mode 100644 index 0000000000000000000000000000000000000000..7345ce4f750e20b75025bc4c8416d220b61a6f1e GIT binary patch literal 3414 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 z