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