diff --git a/pom.xml b/pom.xml index 5cb3fe3..38fc361 100644 --- a/pom.xml +++ b/pom.xml @@ -156,5 +156,10 @@ 2.11.2 provided + + com.zaxxer + HikariCP + 6.2.1 + diff --git a/src/main/java/xyz/soukup/ecoCraftCore/EcoCraftCore.java b/src/main/java/xyz/soukup/ecoCraftCore/EcoCraftCore.java index 93c70d4..380c6df 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/EcoCraftCore.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/EcoCraftCore.java @@ -5,10 +5,13 @@ import com.github.retrooper.packetevents.event.PacketListenerPriority; import com.infernalsuite.asp.api.AdvancedSlimePaperAPI; import com.infernalsuite.asp.api.world.SlimeWorldInstance; import com.j256.ormlite.dao.DaoManager; +import com.j256.ormlite.jdbc.DataSourceConnectionSource; import com.j256.ormlite.jdbc.JdbcConnectionSource; import com.j256.ormlite.stmt.UpdateBuilder; import com.j256.ormlite.support.ConnectionSource; import com.j256.ormlite.table.TableUtils; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder; import io.papermc.paper.plugin.lifecycle.event.LifecycleEventManager; import org.bukkit.Bukkit; @@ -27,6 +30,8 @@ import xyz.soukup.ecoCraftCore.player.OnKill; import xyz.soukup.ecoCraftCore.player.PreparePlayer; import xyz.soukup.ecoCraftCore.player.TeleportRequestsHandler; import xyz.soukup.ecoCraftCore.positionMarker.MarkerCommand; +import xyz.soukup.ecoCraftCore.regions.RegionAdminCommand; +import xyz.soukup.ecoCraftCore.regions.RegionEvents; import xyz.soukup.ecoCraftCore.shop.ShopCommand; import io.papermc.paper.plugin.lifecycle.event.types.LifecycleEvents; import xyz.soukup.ecoCraftCore.inventory.VirtualChest; @@ -187,7 +192,18 @@ public final class EcoCraftCore extends JavaPlugin { String databasePassword = config.getString("database.password"); String databaseUrl = "jdbc:mysql://" + databaseHost + ":" + databasePort + "/" + databaseName; - connectionSource = new JdbcConnectionSource(databaseUrl, databaseUsername, databasePassword); + + HikariConfig hikariConfig = new HikariConfig(); + hikariConfig.setJdbcUrl(databaseUrl); + hikariConfig.setUsername(databaseUsername); + hikariConfig.setPassword(databasePassword); + hikariConfig.setMaximumPoolSize(5); + hikariConfig.setKeepaliveTime(60000); + hikariConfig.setMaxLifetime(1800000); + + HikariDataSource dataSource = new HikariDataSource(hikariConfig); + + connectionSource = new DataSourceConnectionSource(dataSource, databaseUrl); Logger.getLogger("com.j256.ormlite.table.TableUtils").setLevel(Level.OFF); TableUtils.createTableIfNotExists(connectionSource, ActiveServer.class); @@ -245,6 +261,7 @@ public final class EcoCraftCore extends JavaPlugin { lm.registerEventHandler(LifecycleEvents.COMMANDS, event -> event.registrar().register(MoneyCommand.getCommand().build())); lm.registerEventHandler(LifecycleEvents.COMMANDS, event -> event.registrar().register(IslandAdminCommand.getCommand().build())); lm.registerEventHandler(LifecycleEvents.COMMANDS, event -> event.registrar().register(IslandSelectorCommand.getCommand().build())); + lm.registerEventHandler(LifecycleEvents.COMMANDS, event -> event.registrar().register(RegionAdminCommand.getCommand().build())); } private void registerEvents(){ @@ -256,6 +273,7 @@ public final class EcoCraftCore extends JavaPlugin { pm.registerEvents(new VirtualChestLogic(), this); pm.registerEvents(new ShopLogic(), this); pm.registerEvents(new PreparePlayer(), this); + pm.registerEvents(new RegionEvents(), this); EventManager events = PacketEvents.getAPI().getEventManager(); diff --git a/src/main/java/xyz/soukup/ecoCraftCore/database/objects/Region.java b/src/main/java/xyz/soukup/ecoCraftCore/database/objects/Region.java index 212a496..ea06c7c 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/database/objects/Region.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/database/objects/Region.java @@ -29,12 +29,18 @@ public class Region { @DatabaseField(canBeNull = false) private int y1; + @DatabaseField(canBeNull = false) + private int z1; + @DatabaseField(canBeNull = false) private int x2; @DatabaseField(canBeNull = false) private int y2; + @DatabaseField(canBeNull = false) + private int z2; + @ForeignCollectionField(eager = true) private ForeignCollection regionMembers; @@ -45,15 +51,20 @@ public class Region { } - public Region(String island, int regionType, int x1, int y1, int x2, int y2) { + public Region(String island, int regionType, int x1, int y1, int z1, int x2, int y2, int z2) { this.island = island; this.regionType = regionType; this.x1 = Math.min(x1, x2); this.y1 = Math.min(y1, y2); - this.x2 = Math.max(x1, x2) ; + this.x2 = Math.max(x1, x2); this.y2 = Math.max(y1, y2); + this.z1 = Math.min(z1, z2); + this.z2 = Math.max(z1, z2); } + public int getId() { + return id; + } public int getRegionType() { return regionType; @@ -63,6 +74,14 @@ public class Region { return x1; } + public int getZ1() { + return z1; + } + + public int getZ2() { + return z2; + } + public int getY1() { return y1; } @@ -101,7 +120,16 @@ public class Region { public void save(){ try { + DaoRegistry.getRegionDao().createOrUpdate(this); + List regions = cache.get(island); + + if (regions == null) { + return; + } + + regions.removeIf(region -> region.getId() == this.id); + regions.add(this); } catch (Exception e) { e.printStackTrace(); } @@ -110,10 +138,21 @@ public class Region { public void addRegionMember(String memberType, String member, String membershipType){ RegionMember regionMember = new RegionMember(this, memberType, member, membershipType); regionMember.save(); + + Region updatedRegion = Region.findById(this.id); + List regions = cache.get(island); + + if (regions == null) { + return; + } + + regions.removeIf(region -> region.getId() == this.id); + regions.add(updatedRegion); + } - public boolean isInside(int x, int y) { - return x >= this.x1 && x <= this.x2 && y >= this.y1 && y <= this.y2; + public boolean isInside(int x, int y, int z) { + return x >= this.x1 && x <= this.x2 && y >= this.y1 && y <= this.y2 && z >= this.z1 && z <= this.z2; } public static Region findById(int id) { @@ -136,7 +175,7 @@ public class Region { } } - public static Region findRegion(int x, int y, String island) { + public static Region findRegion(int x, int y, int z, String island) { Region region = null; int highestType = -1; @@ -146,7 +185,7 @@ public class Region { } for (Region cachedRegion : cache.get(island)) { - if (!cachedRegion.isInside(x, y)) { + if (!cachedRegion.isInside(x, y, z)) { continue; } if (highestType >= cachedRegion.getRegionType()){ @@ -160,6 +199,15 @@ public class Region { } + public void changeBoundaries(int x1, int y1, int z1, int x2, int y2, int z2){ + this.x1 = Math.min(x1, x2); + this.y1 = Math.min(y1, y2); + this.x2 = Math.max(x1, x2); + this.y2 = Math.max(y1, y2); + this.z1 = Math.min(z1, z2); + this.z2 = Math.max(z1, z2); + } + } diff --git a/src/main/java/xyz/soukup/ecoCraftCore/islands/IslandManager.java b/src/main/java/xyz/soukup/ecoCraftCore/islands/IslandManager.java index 12ee841..301594f 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/islands/IslandManager.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/islands/IslandManager.java @@ -19,6 +19,7 @@ import org.bukkit.entity.Player; import org.bukkit.persistence.PersistentDataType; import xyz.soukup.ecoCraftCore.database.objects.Island; import xyz.soukup.ecoCraftCore.database.DaoRegistry; +import xyz.soukup.ecoCraftCore.database.objects.Region; import xyz.soukup.ecoCraftCore.database.objects.TeleportRequest; import xyz.soukup.ecoCraftCore.utilities.PDC; @@ -82,6 +83,8 @@ public class IslandManager { }); } catch (Exception e) { e.printStackTrace(); } + createWorldRegion(uuid, owner, ownerType, type); + return uuid; } @@ -238,6 +241,20 @@ public class IslandManager { return future; } + + private void createWorldRegion(String uuid, String owner, String ownerType, String islandType) { + int x1 = -32; + int x2 = 31; + int y1 = -64; + int y2 = 320; + int z1 = -32; + int z2 = 31; + + + Region region = new Region(uuid, -1, x1, y1, z1, x2, y2, z2); + region.save(); + region.addRegionMember(ownerType, owner, "owner"); + } public void changeSpawn(Location location, String uuid) { SlimeWorld slimeWorld = asp.getLoadedWorld(uuid); @@ -369,10 +386,7 @@ public class IslandManager { } } - PDC.setUniversal(world, "borderx1", x1, PersistentDataType.INTEGER); - PDC.setUniversal(world, "borderx2", x2, PersistentDataType.INTEGER); - PDC.setUniversal(world, "bordery1", z1, PersistentDataType.INTEGER); - PDC.setUniversal(world, "bordery2", z2, PersistentDataType.INTEGER); + changeBoundaries(world, x1, x2, z1, z2); int chunkMaxX = ((Math.max(x1, x2) + 15) & ~15) + 16; int chunkMinX = (Math.min(x1, x2) & ~15) - 16; @@ -397,6 +411,26 @@ public class IslandManager { ; } + private void changeBoundaries(World world, int x1, int x2, int z1, int z2){ + PDC.setUniversal(world, "borderx1", x1, PersistentDataType.INTEGER); + PDC.setUniversal(world, "borderx2", x2, PersistentDataType.INTEGER); + PDC.setUniversal(world, "bordery1", z1, PersistentDataType.INTEGER); + PDC.setUniversal(world, "bordery2", z2, PersistentDataType.INTEGER); + + QueryBuilder queryBuilder = DaoRegistry.getRegionDao().queryBuilder(); + try { + queryBuilder.where() + .eq("island", world.getName()) + .and() + .eq("region_type", 0); + Region region = queryBuilder.queryForFirst(); + region.changeBoundaries(x1, 320, z1, x2,-64, z2); + region.save(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + diff --git a/src/main/java/xyz/soukup/ecoCraftCore/regions/RegionAdminCommand.java b/src/main/java/xyz/soukup/ecoCraftCore/regions/RegionAdminCommand.java index 0817148..a9c9b6d 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/regions/RegionAdminCommand.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/regions/RegionAdminCommand.java @@ -1,21 +1,64 @@ package xyz.soukup.ecoCraftCore.regions; +import com.j256.ormlite.stmt.QueryBuilder; 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 org.bukkit.command.CommandSender; import org.bukkit.entity.Player; +import xyz.soukup.ecoCraftCore.database.DaoRegistry; +import xyz.soukup.ecoCraftCore.database.objects.Region; import xyz.soukup.ecoCraftCore.messages.Messages; +import java.sql.SQLException; +import java.util.List; + +import static xyz.soukup.ecoCraftCore.EcoCraftCore.plugin; + public class RegionAdminCommand { - public static LiteralArgumentBuilder createCommand() { + public static LiteralArgumentBuilder getCommand() { LiteralArgumentBuilder create = Commands.literal("create") - .then(Commands.argument("type", IntegerArgumentType.integer(0, 1))) - .executes(RegionAdminCommand::createRegion); + .then(Commands.argument("type", IntegerArgumentType.integer(0, 1)) + .executes(RegionAdminCommand::createRegion)); + + LiteralArgumentBuilder addMember = Commands.literal("addMember") + .then(Commands.argument("id", IntegerArgumentType.integer()) + .suggests((context, builder) -> { + try { + QueryBuilder queryBuilder = DaoRegistry.getRegionDao().queryBuilder(); + queryBuilder.selectColumns("id"); + List regions = queryBuilder.query(); + for (Region region : regions) { + builder.suggest(region.getId()); + } + return builder.buildFuture(); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }) + .then(Commands.argument("player", StringArgumentType.word()) + .suggests((context, builder) -> { + for (Player onlinePlayer : plugin.getServer().getOnlinePlayers()) { + builder.suggest(onlinePlayer.getName()); + } + return builder.buildFuture(); + }) + .then(Commands.argument("membership", StringArgumentType.word()) + .suggests(((context, builder) -> { + builder.suggest("owner"); + builder.suggest("editor"); + builder.suggest("member"); + return builder.buildFuture(); + })) + .executes(RegionAdminCommand::addMember)))); + return Commands.literal("region") - .then(create); + .then(create) + .then(addMember); } private static int createRegion(CommandContext context) { @@ -35,4 +78,20 @@ public class RegionAdminCommand { return 0; } + + private static int addMember(CommandContext context) { + Integer id = context.getArgument("id", Integer.class); + String player = context.getArgument("player", String.class); + String membership = context.getArgument("membership", String.class); + CommandSender commandSender = context.getSource().getSender(); + + int status = RegionManager.addMember(id, "player", player, membership); + switch (status){ + case 0 -> Messages.send(commandSender, "generic.success.created"); + case 1 -> Messages.send(commandSender, "region.error.not-exist"); + } + return 0; + } + + } diff --git a/src/main/java/xyz/soukup/ecoCraftCore/regions/RegionEvents.java b/src/main/java/xyz/soukup/ecoCraftCore/regions/RegionEvents.java index 1e5f8ad..151a597 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/regions/RegionEvents.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/regions/RegionEvents.java @@ -1,10 +1,13 @@ package xyz.soukup.ecoCraftCore.regions; +import org.bukkit.block.Block; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.player.*; +import org.bukkit.inventory.ItemStack; import xyz.soukup.ecoCraftCore.database.objects.Region; import xyz.soukup.ecoCraftCore.database.objects.RegionMember; @@ -12,25 +15,119 @@ public class RegionEvents implements Listener { @EventHandler public void onPlayerInteract(PlayerInteractEvent event){ - event.setCancelled(!isRegionMember(event.getClickedBlock().getWorld().getName(), event.getPlayer(), event.getClickedBlock().getX(), event.getClickedBlock().getY())); + switch (event.getAction()) { + case RIGHT_CLICK_BLOCK: + case LEFT_CLICK_BLOCK: + break; + default: + return; + } + + + Block block = event.getClickedBlock(); + ItemStack item = event.getItem(); + if (block == null) return; + + if (item != null && item.getType().isBlock() && !block.getType().isInteractable()) { + return; + } + + boolean allowed = isAllowedToInteract( + block.getWorld().getName(), + event.getPlayer(), + block.getX(), + block.getY(), + block.getZ() + ); + + event.setCancelled(!allowed); } + @EventHandler + public void onBlockPlace(BlockPlaceEvent event) { + Block block = event.getBlockPlaced(); - private boolean isRegionMember(String island, Player player, int x, int y){ - Region region = Region.findRegion(x, y, island); + boolean allowed = isAllowedToInteract( + block.getWorld().getName(), + event.getPlayer(), + block.getX(), + block.getY(), + block.getZ() + ); - if (region == null){ - return false; - } + event.setCancelled(!allowed); + } - String name = player.getName(); + @EventHandler + public void onBlockBreak(BlockBreakEvent event) { - for (RegionMember regionMember : region.getRegionMembers()){ - if (regionMember.getMembertype().equals("player") && regionMember.getName().equals(name)){ - return true; - } - } + Block block = event.getBlock(); + + boolean allowed = isAllowedToInteract( + block.getWorld().getName(), + event.getPlayer(), + block.getX(), + block.getY(), + block.getZ() + ); + + event.setCancelled(!allowed); + } + @EventHandler + public void onBucketUse(PlayerBucketEmptyEvent event) { + Block clickedBlock = event.getBlockClicked(); + + boolean allowed = isAllowedToInteract( + clickedBlock.getWorld().getName(), + event.getPlayer(), + clickedBlock.getX(), + clickedBlock.getY(), + clickedBlock.getZ() + ); + + event.setCancelled(!allowed); + } + + @EventHandler + public void onBucketUse(PlayerBucketFillEvent event) { + Block clickedBlock = event.getBlockClicked(); + + boolean allowed = isAllowedToInteract( + clickedBlock.getWorld().getName(), + event.getPlayer(), + clickedBlock.getX(), + clickedBlock.getY(), + clickedBlock.getZ() + ); + + event.setCancelled(!allowed); + } + + + + private boolean isAllowedToInteract(String island, Player player, int x, int y, int z){ + if (player.isOp()){ + return true; + } + + Region region = Region.findRegion(x, y, z, island); + + if (region == null){ return false; + } + + String name = player.getName(); + + for (RegionMember regionMember : region.getRegionMembers()){ + + if (regionMember.getMembertype().equals("player") && regionMember.getName().equals(name)){ + return true; + } + } + + return false; } + + } diff --git a/src/main/java/xyz/soukup/ecoCraftCore/regions/RegionManager.java b/src/main/java/xyz/soukup/ecoCraftCore/regions/RegionManager.java index 47800c0..14c480d 100644 --- a/src/main/java/xyz/soukup/ecoCraftCore/regions/RegionManager.java +++ b/src/main/java/xyz/soukup/ecoCraftCore/regions/RegionManager.java @@ -20,15 +20,29 @@ public class RegionManager { String worldName = primaryLocation.getWorld().getName(); int x1 = primaryLocation.getBlockX(); - int y1 = primaryLocation.getBlockZ(); + int y1 = primaryLocation.getBlockY(); + int z1 = primaryLocation.getBlockZ(); int x2 = secondaryLocation.getBlockX(); - int y2 = secondaryLocation.getBlockZ(); + int y2 = secondaryLocation.getBlockY(); + int z2 = secondaryLocation.getBlockZ(); - Region region = new Region(worldName, type, x1, y1, x2, y2); + Region region = new Region(worldName, type, x1, y1, z1, x2, y2, z2); region.save(); region.addRegionMember(ownerType, owner, "owner"); return 0; } + + public static int addMember(int id, String memberType, String member, String membershipType){ + Region region = Region.findById(id); + + if (region == null){ + return 1; + } + + region.addRegionMember(memberType, member, membershipType); + + return 0; + } } diff --git a/src/main/resources/messages.yml b/src/main/resources/messages.yml index f8336df..2ccf9e7 100644 --- a/src/main/resources/messages.yml +++ b/src/main/resources/messages.yml @@ -15,6 +15,7 @@ generic: region: error: not-marked: "Musíš nejprve označit pozice" + not-exist: "Region neexistuje" shop: error: already-shop: "Tato cedule již je obchod"