diff --git a/.github/workflows/build-and-release.yml b/.github/workflows/build-and-release.yml index 740da95..8b844d7 100644 --- a/.github/workflows/build-and-release.yml +++ b/.github/workflows/build-and-release.yml @@ -35,13 +35,14 @@ jobs: - name: Check if release commit id: check_release + shell: bash run: | if [[ "${{ steps.commit_message.outputs.message }}" =~ ^release:\ [0-9]+\.[0-9]+\.[0-9]+$ ]]; then - echo "is_release=true" >> $GITHUB_OUTPUT - echo "version=$(echo '${{ steps.commit_message.outputs.message }}' | sed 's/release: //')" >> $GITHUB_OUTPUT + echo "is_release=true" >> "$GITHUB_OUTPUT" + echo "version=$(echo '${{ steps.commit_message.outputs.message }}' | sed 's/release: //')" >> "$GITHUB_OUTPUT" else - echo "is_release=false" >> $GITHUB_OUTPUT - echo "version=beta-${{ github.run_number }}" >> $GITHUB_OUTPUT + echo "is_release=false" >> "$GITHUB_OUTPUT" + echo "version=beta-${{ github.run_number }}" >> "$GITHUB_OUTPUT" fi - name: Update version in pom.xml @@ -59,11 +60,12 @@ jobs: uses: actions/upload-artifact@v4 with: name: skyeblock-${{ steps.check_release.outputs.version }} - path: target/*.jar + path: target/SkyeBlock-${{ steps.check_release.outputs.version }}.jar retention-days: 90 - name: Create Beta Release - if: steps.check_release.outputs.is_release == 'false' + if: github.event_name == 'push' && steps.check_release.outputs.is_release == 'false' + id: create_beta_release uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -83,18 +85,18 @@ jobs: prerelease: true - name: Upload Beta Release Asset - if: steps.check_release.outputs.is_release == 'false' + if: github.event_name == 'push' && steps.check_release.outputs.is_release == 'false' uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_beta_release.outputs.upload_url }} - asset_path: target/skyeblock-${{ steps.check_release.outputs.version }}.jar - asset_name: skyeblock-beta-${{ github.run_number }}.jar + asset_path: target/SkyeBlock-${{ steps.check_release.outputs.version }}.jar + asset_name: SkyeBlock-${{ steps.check_release.outputs.version }}.jar asset_content_type: application/java-archive - name: Generate Changelog - if: steps.check_release.outputs.is_release == 'true' + if: github.event_name == 'push' && steps.check_release.outputs.is_release == 'true' id: changelog run: | # Get the previous release tag @@ -121,7 +123,7 @@ jobs: echo "EOF" >> $GITHUB_OUTPUT - name: Create Release - if: steps.check_release.outputs.is_release == 'true' + if: github.event_name == 'push' && steps.check_release.outputs.is_release == 'true' id: create_release uses: actions/create-release@v1 env: @@ -134,14 +136,14 @@ jobs: prerelease: false - name: Upload Release Asset - if: steps.check_release.outputs.is_release == 'true' + if: github.event_name == 'push' && steps.check_release.outputs.is_release == 'true' uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.create_release.outputs.upload_url }} - asset_path: target/skyeblock-${{ steps.check_release.outputs.version }}.jar - asset_name: skyeblock-${{ steps.check_release.outputs.version }}.jar + asset_path: target/SkyeBlock-${{ steps.check_release.outputs.version }}.jar + asset_name: SkyeBlock-${{ steps.check_release.outputs.version }}.jar asset_content_type: application/java-archive code-quality: diff --git a/.gitignore b/.gitignore index 0887fd5..179489a 100644 --- a/.gitignore +++ b/.gitignore @@ -134,6 +134,8 @@ target/maven-status/ target/generated-sources/ target/classes/ target/original-*.jar +target/* +target/classes/* # META-INF directory in target target/META-INF/ \ No newline at end of file diff --git a/permissions.md b/permissions.md new file mode 100644 index 0000000..46c3103 --- /dev/null +++ b/permissions.md @@ -0,0 +1,70 @@ +# SkyeBlock Permissions + +This document lists all permissions defined in the plugin and the defaults shipped in `plugin.yml`. + +## Roles / Bundles + +| Role / Node | Includes | Default | +| --- | --- | --- | +| `skyeblock.*` | Everything in this file | `op` | +| `skyeblock.player` | All player commands and warps (no gamerule admin bypass) | `true` | +| `skyeblock.admin` | Admin commands (/sba), high-level management | `op` | +| `skyeblock.gamerule.*` | All gamerule nodes (must be explicitly granted) | `false` | + +## Core Commands + +| Command | Permission | Default | +| --- | --- | --- | +| `/sb`, `/island`, `/is` | `skyeblock.island` | `true` | +| `/visit` | `skyeblock.island.visit` | `true` | +| `/island vote` | `skyeblock.island.vote` | `true` | +| `/island edit` (title/desc/icon) | `skyeblock.island.edit` | `true` | +| `/island coop` | `skyeblock.island.coop` | `true` | +| `/island lock` / `unlock` | `skyeblock.island.lock` | `true` | +| `/island set home|visit` | `skyeblock.island.set` | `true` | +| `/delete` (self delete) | `skyeblock.island.delete` | `true` | +| `/islandpermissions` | `skyeblock.island.permissions` | `true` | +| `/hub` | `skyeblock.hub` | `true` | +| `/spawn` | `skyeblock.spawn` | `true` | +| `/warp` | `skyeblock.warp` | `true` | +| `/createisland` | `skyeblock.island.create` | `true` | + +## Warp Permissions + +| Permission | Use | Default | +| --- | --- | --- | +| `skyeblock.warp.spawn` | Spawn warp | `true` | +| `skyeblock.warp.nether` | Nether resource world warp | `true` | +| `skyeblock.warp.end` | End resource world warp | `true` | +| `skyeblock.warp.pvp` | PvP arena warp | `true` | +| `skyeblock.warp.shop` | Shop/market warp | `true` | +| `skyeblock.admin.warp` | Admin warp management (/warpadmin) | `op` | + +## Admin / Staff + +| Command | Permission | Default | +| --- | --- | --- | +| `/sba ...` (admin suite) | `skyeblock.admin` | `op` | +| `/convertislands` | `skyeblock.admin.convert` | `op` | +| `/warpadmin ...` | `skyeblock.admin.warp` | `op` | +| `/mobspawning ...` | `skyeblock.admin.mobspawning` | `op` | + +## Gamerule Access + +- Global bypass: `skyeblock.gamerules.adminbypass` (see all gamerules) — default `op`. +- Common bundle: `skyeblock.settings.gamerules` — default `false`, grants the listed gamerules below. +- Full bundle: `skyeblock.gamerule.*` — default `false` (must be explicitly granted). + +### Individual Gamerule Nodes (all default `false`) +`skyeblock.gamerule.dodaylightcycle`, `skyeblock.gamerule.doweathercycle`, `skyeblock.gamerule.keepinventory`, `skyeblock.gamerule.mobgriefing`, `skyeblock.gamerule.domobspawning`, `skyeblock.gamerule.dofiretick`, `skyeblock.gamerule.falldamage`, `skyeblock.gamerule.firedamage`, `skyeblock.gamerule.drowningdamage`, `skyeblock.gamerule.doinsomnia`, `skyeblock.gamerule.doimmediaterespawn`, `skyeblock.gamerule.announceadvancements`, `skyeblock.gamerule.disableelytraMovementcheck`, `skyeblock.gamerule.dolimitedcrafting`, `skyeblock.gamerule.naturalregeneration`, `skyeblock.gamerule.reduceddebuginfo`, `skyeblock.gamerule.sendcommandfeedback`, `skyeblock.gamerule.showdeathmessages`, `skyeblock.gamerule.doentitydrops`, `skyeblock.gamerule.dotiledrops`, `skyeblock.gamerule.domobloot`, `skyeblock.gamerule.dopatrolspawning`, `skyeblock.gamerule.dotraderSpawning`, `skyeblock.gamerule.forgivedeadplayers`, `skyeblock.gamerule.universalanger`, `skyeblock.gamerule.randomtickspeed`, `skyeblock.gamerule.spawnradius`, `skyeblock.gamerule.maxentitycramming`, `skyeblock.gamerule.maxcommandchainlength`, `skyeblock.gamerule.playerssleepingpercentage`. + +## Quick Assignment Examples + +- **Default players**: grant `skyeblock.player` (already default `true`). +- **Trusted players with gamerules**: grant `skyeblock.settings.gamerules` or specific `skyeblock.gamerule.*` entries. +- **Admins**: grant `skyeblock.admin` (includes /sba) plus `skyeblock.admin.warp` and `skyeblock.admin.mobspawning` as needed. +- **Everything**: grant `skyeblock.*` (OPs have this by default). + +## Source of Truth + +All permission definitions are declared in [src/main/resources/plugin.yml](src/main/resources/plugin.yml). \ No newline at end of file diff --git a/pom.xml b/pom.xml index ae27d76..af6c955 100644 --- a/pom.xml +++ b/pom.xml @@ -36,8 +36,12 @@ https://repo.codemc.org/repository/maven-public/ - dmulloy2-repo - https://repo.dmulloy2.net/repository/public/ + spigot-repo + https://hub.spigotmc.org/nexus/content/repositories/public/ + + + jitpack.io + https://jitpack.io/ @@ -68,7 +72,7 @@ - com.comphenix.protocol + com.github.dmulloy2 ProtocolLib 5.3.0 provided @@ -90,6 +94,16 @@ src/main/resources true + + **/*.schem + + + + src/main/resources + false + + **/*.schem + diff --git a/src/main/java/skyeblock/nobleskye/dev/skyeblock/SkyeBlockPlugin.java b/src/main/java/skyeblock/nobleskye/dev/skyeblock/SkyeBlockPlugin.java index 8b68039..5145f04 100644 --- a/src/main/java/skyeblock/nobleskye/dev/skyeblock/SkyeBlockPlugin.java +++ b/src/main/java/skyeblock/nobleskye/dev/skyeblock/SkyeBlockPlugin.java @@ -65,6 +65,9 @@ public void onEnable() { // Save default config saveDefaultConfig(); + // Perform config migration if needed + migrateConfig(); + // Initialize warp configuration loadWarpConfig(); @@ -393,6 +396,30 @@ public void reloadWarpConfig() { } } + /** + * Migrate configuration from older versions to current version + */ + private void migrateConfig() { + String currentVersion = "2.0.0"; + String configVersion = getConfig().getString("version", "1.0.0"); + + if (!configVersion.equals(currentVersion)) { + getLogger().info("Migrating configuration from version " + configVersion + " to " + currentVersion); + + // Ensure visiting is disabled by default (safety feature) + if (!getConfig().contains("island.visiting.enabled")) { + getConfig().set("island.visiting.enabled", false); + getLogger().info("Set island.visiting.enabled to false (default)"); + } + + // Update version + getConfig().set("version", currentVersion); + saveConfig(); + + getLogger().info("Configuration migration completed successfully!"); + } + } + /** * Override reloadConfig to ensure config exists but not overwrite existing config */ diff --git a/src/main/java/skyeblock/nobleskye/dev/skyeblock/commands/SkyeBlockAdminCommand.java b/src/main/java/skyeblock/nobleskye/dev/skyeblock/commands/SkyeBlockAdminCommand.java index 0a1f30d..b5c0b06 100644 --- a/src/main/java/skyeblock/nobleskye/dev/skyeblock/commands/SkyeBlockAdminCommand.java +++ b/src/main/java/skyeblock/nobleskye/dev/skyeblock/commands/SkyeBlockAdminCommand.java @@ -1,6 +1,7 @@ package skyeblock.nobleskye.dev.skyeblock.commands; import skyeblock.nobleskye.dev.skyeblock.SkyeBlockPlugin; +import skyeblock.nobleskye.dev.skyeblock.models.Island; import org.bukkit.command.Command; import org.bukkit.command.CommandExecutor; import org.bukkit.command.CommandSender; @@ -82,8 +83,43 @@ public boolean onCommand(CommandSender sender, Command command, String label, St } } + /** + * Get the island the admin is currently on by checking their world + */ + private Island getIslandFromAdminLocation(Player admin) { + String worldName = admin.getWorld().getName(); + + // Check if the world is an island world + Island island = plugin.getIslandManager().getIslandById(worldName); + + // If direct match fails, check if it's a nether island world (ends with _nether) + if (island == null && worldName.endsWith("_nether")) { + String mainIslandId = worldName.substring(0, worldName.length() - "_nether".length()); + island = plugin.getIslandManager().getIslandById(mainIslandId); + } + + return island; + } + private boolean handleAdminIslandCommand(CommandSender sender, String[] args) { // Admin island management - bypasses all restrictions + if (sender instanceof Player) { + Player admin = (Player) sender; + Island currentIsland = getIslandFromAdminLocation(admin); + + if (currentIsland != null) { + sender.sendMessage(Component.text("Executing island command for the island you're on (" + + currentIsland.getIslandId() + ") with admin privileges...", NamedTextColor.YELLOW)); + + // Temporarily set the admin's UUID to the island owner's UUID for the command context + // Note: This approach maintains the admin's actual identity but operates on the current island + return islandCommand.onCommand(sender, null, "sba", args); + } else { + sender.sendMessage(Component.text("You are not currently on an island! Go to an island first, then use /sba island.", NamedTextColor.RED)); + return true; + } + } + sender.sendMessage(Component.text("Executing island command with admin privileges...", NamedTextColor.YELLOW)); return islandCommand.onCommand(sender, null, "sba", args); } diff --git a/src/main/java/skyeblock/nobleskye/dev/skyeblock/listeners/VisitorPacketListener.java b/src/main/java/skyeblock/nobleskye/dev/skyeblock/listeners/VisitorPacketListener.java index 5a5433a..6f06e48 100644 --- a/src/main/java/skyeblock/nobleskye/dev/skyeblock/listeners/VisitorPacketListener.java +++ b/src/main/java/skyeblock/nobleskye/dev/skyeblock/listeners/VisitorPacketListener.java @@ -21,14 +21,14 @@ public class VisitorPacketListener extends PacketAdapter { new java.util.concurrent.ConcurrentHashMap()); public VisitorPacketListener(SkyeBlockPlugin plugin) { - super(plugin, ListenerPriority.LOWEST, // Use LOWEST to ensure we get packets first + super(plugin, ListenerPriority.HIGHEST, // Container interaction PacketType.Play.Client.WINDOW_CLICK, PacketType.Play.Client.CLOSE_WINDOW, PacketType.Play.Client.HELD_ITEM_SLOT, // Block interaction PacketType.Play.Client.USE_ENTITY, - PacketType.Play.Client.BLOCK_PLACE, + PacketType.Play.Client.USE_ITEM_ON, PacketType.Play.Client.BLOCK_DIG, // Item interaction PacketType.Play.Client.SET_CREATIVE_SLOT, diff --git a/src/main/java/skyeblock/nobleskye/dev/skyeblock/managers/WorldManager.java b/src/main/java/skyeblock/nobleskye/dev/skyeblock/managers/WorldManager.java index 5fa63b6..178c8a9 100644 --- a/src/main/java/skyeblock/nobleskye/dev/skyeblock/managers/WorldManager.java +++ b/src/main/java/skyeblock/nobleskye/dev/skyeblock/managers/WorldManager.java @@ -612,8 +612,10 @@ public World getIslandWorld(String islandId) { } // Apply island settings to the world if found and it's not the main world + // This ensures gamerules are always correct when getting an island world if (world != null && !world.equals(skyBlockWorld)) { plugin.getIslandSettingsManager().applySettingsToWorld(islandId, world); + plugin.getLogger().fine("Reapplied gamerules to island world: " + islandId); } return world != null ? world : skyBlockWorld; @@ -637,6 +639,9 @@ public World getOrLoadIslandWorld(String islandId) { plugin.getLogger().info("Successfully loaded island world for " + islandId + ": " + loadedWorld.getName()); // Apply current mob spawning settings to the newly loaded world applyMobSpawningSettings(loadedWorld); + // Apply island-specific gamerules from settings + plugin.getIslandSettingsManager().applySettingsToWorld(islandId, loadedWorld); + plugin.getLogger().info("Applied gamerules to newly loaded world: " + islandId); return loadedWorld; } else { plugin.getLogger().warning("Failed to load island world for " + islandId + " - using default world"); @@ -644,6 +649,8 @@ public World getOrLoadIslandWorld(String islandId) { } else if (world != null && !world.equals(skyBlockWorld)) { // Apply current mob spawning settings to existing loaded world applyMobSpawningSettings(world); + // Reapply island-specific gamerules to ensure they're correct + plugin.getIslandSettingsManager().applySettingsToWorld(islandId, world); } return world; diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 035037a..d01bb70 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -95,7 +95,7 @@ island: # Island visiting settings visiting: - # Whether island visiting is enabled globally + # Whether island visiting is enabled globally (auto-disabled for security) enabled: false # Messages (using MiniMessage format) diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index fdd2c31..bde688b 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -175,7 +175,7 @@ permissions: skyeblock.gamerule.disableelytraMovementcheck: true skyeblock.gamerule.*: description: All gamerule permissions - default: true + default: false children: skyeblock.gamerule.dodaylightcycle: true skyeblock.gamerule.doweathercycle: true @@ -210,94 +210,94 @@ permissions: # Individual gamerule permissions (default true, set to false to deny) skyeblock.gamerule.dodaylightcycle: description: Allow modifying daylight cycle gamerule - default: true + default: false skyeblock.gamerule.doweathercycle: description: Allow modifying weather cycle gamerule - default: true + default: false skyeblock.gamerule.keepinventory: description: Allow modifying keep inventory gamerule - default: true + default: false skyeblock.gamerule.mobgriefing: description: Allow modifying mob griefing gamerule - default: true + default: false skyeblock.gamerule.domobspawning: description: Allow modifying mob spawning gamerule - default: true + default: false skyeblock.gamerule.dofiretick: description: Allow modifying fire tick gamerule - default: true + default: false skyeblock.gamerule.falldamage: description: Allow modifying fall damage gamerule - default: true + default: false skyeblock.gamerule.firedamage: description: Allow modifying fire damage gamerule - default: true + default: false skyeblock.gamerule.drowningdamage: description: Allow modifying drowning damage gamerule - default: true + default: false skyeblock.gamerule.doinsomnia: description: Allow modifying insomnia gamerule - default: true + default: false skyeblock.gamerule.doimmediaterespawn: description: Allow modifying immediate respawn gamerule - default: true + default: false skyeblock.gamerule.announceadvancements: description: Allow modifying announce advancements gamerule - default: true + default: false skyeblock.gamerule.disableelytraMovementcheck: description: Allow modifying elytra movement check gamerule - default: true + default: false skyeblock.gamerule.dolimitedcrafting: description: Allow modifying limited crafting gamerule - default: true + default: false skyeblock.gamerule.naturalregeneration: description: Allow modifying natural regeneration gamerule - default: true + default: false skyeblock.gamerule.reduceddebuginfo: description: Allow modifying reduced debug info gamerule - default: true + default: false skyeblock.gamerule.sendcommandfeedback: description: Allow modifying send command feedback gamerule - default: true + default: false skyeblock.gamerule.showdeathmessages: description: Allow modifying show death messages gamerule - default: true + default: false skyeblock.gamerule.doentitydrops: description: Allow modifying entity drops gamerule - default: true + default: false skyeblock.gamerule.dotiledrops: description: Allow modifying tile drops gamerule - default: true + default: false skyeblock.gamerule.domobloot: description: Allow modifying mob loot gamerule - default: true + default: false skyeblock.gamerule.dopatrolspawning: description: Allow modifying patrol spawning gamerule - default: true + default: false skyeblock.gamerule.dotraderSpawning: description: Allow modifying trader spawning gamerule - default: true + default: false skyeblock.gamerule.forgivedeadplayers: description: Allow modifying forgive dead players gamerule - default: true + default: false skyeblock.gamerule.universalanger: description: Allow modifying universal anger gamerule - default: true + default: false skyeblock.gamerule.randomtickspeed: description: Allow modifying random tick speed gamerule - default: true + default: false skyeblock.gamerule.spawnradius: description: Allow modifying spawn radius gamerule - default: true + default: false skyeblock.gamerule.maxentitycramming: description: Allow modifying max entity cramming gamerule - default: true + default: false skyeblock.gamerule.maxcommandchainlength: description: Allow modifying max command chain length gamerule - default: true + default: false skyeblock.gamerule.playerssleepingpercentage: description: Allow modifying players sleeping percentage gamerule - default: true + default: false # Warp System Permissions skyeblock.warp: description: Access to warp GUI and teleportation diff --git a/target/classes/skyeblock/nobleskye/dev/skyeblock/SkyeBlockPlugin.class b/target/classes/skyeblock/nobleskye/dev/skyeblock/SkyeBlockPlugin.class index 8f07a19..6691388 100644 Binary files a/target/classes/skyeblock/nobleskye/dev/skyeblock/SkyeBlockPlugin.class and b/target/classes/skyeblock/nobleskye/dev/skyeblock/SkyeBlockPlugin.class differ diff --git a/target/classes/skyeblock/nobleskye/dev/skyeblock/managers/WorldManager.class b/target/classes/skyeblock/nobleskye/dev/skyeblock/managers/WorldManager.class index abb08a4..ad010a2 100644 Binary files a/target/classes/skyeblock/nobleskye/dev/skyeblock/managers/WorldManager.class and b/target/classes/skyeblock/nobleskye/dev/skyeblock/managers/WorldManager.class differ