Compare commits

...

10 Commits

Author SHA1 Message Date
099bbe58a9 Set the PlayerHomes Feature to only op to prevent any gliches
Some checks failed
Preview Release / build (push) Has been cancelled
2025-10-19 17:28:58 +02:00
0aa9f3a189 Added PlayerHomes (similar to PlayerWarps, public homes other players can visit) 2025-10-15 07:04:50 +02:00
fccb19aec0 Added PlayerHomes (similar to PlayerWarps, public homes other players can visit) 2025-10-15 07:03:04 +02:00
43fa614632 Merge remote-tracking branch 'origin/dev' into dev 2025-10-14 18:27:09 +02:00
4e23747d5c Some minor changes 2025-10-14 18:26:44 +02:00
D.L.
9d909aaf31 Update release-on-merge.yml 2025-10-14 18:20:23 +02:00
D.L.
1b72598b60 Update preview-release.yml 2025-10-14 18:20:03 +02:00
D.L.
5e7190397d Update preview-release.yml 2025-10-14 17:44:36 +02:00
D.L.
494258168f Create release-on-merge.yml 2025-10-14 17:38:15 +02:00
D.L.
859474896e Delete .github/workflows/static.yml 2025-10-14 17:37:44 +02:00
8 changed files with 353 additions and 94 deletions

View File

@@ -3,33 +3,31 @@ name: Preview Release
on:
push:
branches:
- dev # Trigger auf Push zur dev-Branch
- dev # Trigger bei Push auf dev-Branch
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
# 🧾 Schritt 1: Repository auschecken
# Schritt 1: Code auschecken
- name: Checkout Repository
uses: actions/checkout@v4
# Schritt 2: Java einrichten
# Schritt 2: Java einrichten (notwendig für Build)
- name: Set up Java
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
# 🛠️ Schritt 3: Gradle Wrapper Berechtigungen setzen (falls nötig)
- name: Grant execute permission for Gradle Wrapper
run: chmod +x gradlew
# Schritt 3: Build mit Gradle
- name: Build Plugin with Gradle
run: ./gradlew clean build
# 🧱 Schritt 4: Plugin mit Gradle bauen
- name: Build Plugin
run: ./gradlew clean build -x test
# 🚀 Schritt 5: Preview Release erstellen
# Schritt 4: Preview Release erstellen
- name: Create Preview Release
uses: softprops/action-gh-release@v2
with:
@@ -44,7 +42,7 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# 🧹 Schritt 6: Alte Preview Releases löschen (nur 10 behalten)
# Schritt 5: Alte Preview Releases bereinigen (nur 10 neuste behalten)
- name: Cleanup old Preview Releases
run: |
echo "Deleting old Preview Releases, keeping only the 10 newest..."

50
.github/workflows/release-on-merge.yml vendored Normal file
View File

@@ -0,0 +1,50 @@
name: Release on Merge to Master
on:
push:
branches:
- master # oder "main", je nach Repo
paths-ignore:
- '**.md' # ignoriert reine Dokumentationsänderungen
- '.github/**' # ignoriert Änderungen an Actions selbst
jobs:
build-and-release:
runs-on: ubuntu-latest
permissions:
contents: write # Berechtigung für Releases hinzufügen
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '21'
- name: Build with Gradle
run: ./gradlew clean build
- name: Get version
id: get_version
run: |
# Extrahiere die Version aus der build.gradle
VERSION=$(./gradlew properties -q | grep "version:" | awk '{print $2}')
echo "version=$VERSION" >> $GITHUB_OUTPUT
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ steps.get_version.outputs.version }}
name: "Release v${{ steps.get_version.outputs.version }}"
body: |
**v${{ steps.get_version.outputs.version }}**
- Commit: ${{ github.sha }}
- Branch: ${{ github.ref_name }}
- Version: v${{ steps.get_version.outputs.version }}
files: |
build/libs/*.jar
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,43 +0,0 @@
# Simple workflow for deploying static content to GitHub Pages
name: Deploy static content to Pages
on:
# Runs on pushes targeting the default branch
push:
branches: ["master"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
# Single deploy job since we're just deploying
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
# Upload entire repository
path: './web'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

View File

@@ -3,7 +3,7 @@ plugins {
}
group = "com.user404_"
version = "1.2+"
version = "1.3+-preview"
repositories {
mavenCentral()

View File

@@ -28,11 +28,14 @@ public class InfiniteHomes extends JavaPlugin implements TabCompleter {
private Map<UUID, Map<String, Location>> homes;
private Map<String, Location> globalHomes;
private Map<String, PlayerHomeData> playerHomes;
private Map<UUID, Long> cooldowns;
private FileConfiguration homesConfig;
private File homesFile;
private FileConfiguration globalHomesConfig;
private File globalHomesFile;
private FileConfiguration playerHomesConfig;
private File playerHomesFile;
private Map<String, FileConfiguration> translations;
private File translationsDir;
@@ -40,13 +43,16 @@ public class InfiniteHomes extends JavaPlugin implements TabCompleter {
public void onEnable() {
homes = new HashMap<>();
globalHomes = new HashMap<>();
playerHomes = new HashMap<>();
cooldowns = new HashMap<>();
translations = new HashMap<>();
setupHomesConfig();
setupGlobalHomesConfig();
setupPlayerHomesConfig();
loadHomesFromConfig();
loadGlobalHomesFromConfig();
loadPlayerHomesFromConfig();
setupTranslations();
// Standardkonfiguration erstellen, falls nicht vorhanden
@@ -60,26 +66,31 @@ public class InfiniteHomes extends JavaPlugin implements TabCompleter {
getCommand("delhome").setTabCompleter(this);
getCommand("globalhome").setTabCompleter(this);
getCommand("delglobalhome").setTabCompleter(this);
getCommand("playerhome").setTabCompleter(this);
getCommand("delplayerhome").setTabCompleter(this);
getLogger().info("InfiniteHomes plugin enabled!");
getLogger().info("InfiniteHomes plugin by User404 enabled!");
}
@Override
public void onDisable() {
saveHomesToConfig();
saveGlobalHomesToConfig();
getLogger().info("InfiniteHomes plugin disabled!");
savePlayerHomesToConfig();
getLogger().info("InfiniteHomes plugin by User404 disabled!");
}
@Override
public List<String> onTabComplete(CommandSender sender, Command command, String alias, String[] args) {
List<String> completions = new ArrayList<>();
// Nur für Spieler und für die Befehle home, delhome, globalhome und delglobalhome
// Nur für Spieler und für die relevanten Befehle
if (!(sender instanceof Player) || (!command.getName().equalsIgnoreCase("home") &&
!command.getName().equalsIgnoreCase("delhome") &&
!command.getName().equalsIgnoreCase("globalhome") &&
!command.getName().equalsIgnoreCase("delglobalhome"))) {
!command.getName().equalsIgnoreCase("delglobalhome") &&
!command.getName().equalsIgnoreCase("playerhome") &&
!command.getName().equalsIgnoreCase("delplayerhome"))) {
return completions;
}
@@ -89,18 +100,15 @@ public class InfiniteHomes extends JavaPlugin implements TabCompleter {
// Home-Namen des Spielers holen
UUID playerUuid = player.getUniqueId();
// Wenn der Spieler keine Homes hat, leere Liste zurückgeben
if (!homes.containsKey(playerUuid) || homes.get(playerUuid).isEmpty()) {
return completions;
}
Set<String> homeNames = homes.get(playerUuid).keySet();
// Wenn kein Argument vorhanden ist, alle Home-Namen zurückgeben
if (args.length == 0 || args[0].isEmpty()) {
completions.addAll(homeNames);
} else {
// Home-Namen filtern, die mit dem eingegebenen Text beginnen
String input = args[0].toLowerCase();
for (String home : homeNames) {
if (home.toLowerCase().startsWith(input)) {
@@ -116,11 +124,9 @@ public class InfiniteHomes extends JavaPlugin implements TabCompleter {
Set<String> globalHomeNames = globalHomes.keySet();
// Wenn kein Argument vorhanden ist, alle globalen Home-Namen zurückgeben
if (args.length == 0 || args[0].isEmpty()) {
completions.addAll(globalHomeNames);
} else {
// Globale Home-Namen filtern, die mit dem eingegebenen Text beginnen
String input = args[0].toLowerCase();
for (String home : globalHomeNames) {
if (home.toLowerCase().startsWith(input)) {
@@ -128,6 +134,24 @@ public class InfiniteHomes extends JavaPlugin implements TabCompleter {
}
}
}
} else if (command.getName().equalsIgnoreCase("playerhome") || command.getName().equalsIgnoreCase("delplayerhome")) {
// PlayerHome-Namen holen
if (playerHomes.isEmpty()) {
return completions;
}
Set<String> playerHomeNames = playerHomes.keySet();
if (args.length == 0 || args[0].isEmpty()) {
completions.addAll(playerHomeNames);
} else {
String input = args[0].toLowerCase();
for (String home : playerHomeNames) {
if (home.toLowerCase().startsWith(input)) {
completions.add(home);
}
}
}
}
return completions;
@@ -169,6 +193,24 @@ public class InfiniteHomes extends JavaPlugin implements TabCompleter {
globalHomesConfig = YamlConfiguration.loadConfiguration(globalHomesFile);
}
private void setupPlayerHomesConfig() {
if (!getDataFolder().exists()) {
getDataFolder().mkdirs();
}
playerHomesFile = new File(getDataFolder(), "playerhomes.yml");
if (!playerHomesFile.exists()) {
try {
playerHomesFile.createNewFile();
} catch (IOException e) {
getLogger().log(Level.SEVERE, "Could not create playerhomes.yml", e);
}
}
playerHomesConfig = YamlConfiguration.loadConfiguration(playerHomesFile);
}
private void setupTranslations() {
translationsDir = new File(getDataFolder(), "translations");
if (!translationsDir.exists()) {
@@ -177,6 +219,7 @@ public class InfiniteHomes extends JavaPlugin implements TabCompleter {
// Standard-Übersetzung (Englisch) aus Ressourcen laden
saveResource("translations/texts_en.yml", false);
saveResource("translations/texts_de.yml", false);
// Verfügbare Übersetzungen laden
loadTranslations();
@@ -214,6 +257,18 @@ public class InfiniteHomes extends JavaPlugin implements TabCompleter {
getLogger().log(Level.WARNING, "Error loading default English translation", e);
}
}
if (!translations.containsKey("de")) {
try {
InputStream stream = getResource("translations/texts_de.yml");
if (stream != null) {
FileConfiguration config = YamlConfiguration.loadConfiguration(
new InputStreamReader(stream, StandardCharsets.UTF_8));
translations.put("en", config);
}
} catch (Exception e) {
getLogger().log(Level.WARNING, "Error loading default German translation", e);
}
}
}
private String getMessage(Player player, String key) {
@@ -323,6 +378,46 @@ public class InfiniteHomes extends JavaPlugin implements TabCompleter {
}
}
private void loadPlayerHomesFromConfig() {
try {
playerHomes.clear();
for (String homeName : playerHomesConfig.getKeys(false)) {
ConfigurationSection section = playerHomesConfig.getConfigurationSection(homeName);
if (section != null) {
UUID owner = UUID.fromString(section.getString("owner"));
Location location = section.getLocation("location");
if (location != null) {
playerHomes.put(homeName, new PlayerHomeData(owner, location));
}
}
}
} catch (Exception e) {
getLogger().log(Level.WARNING, "Error loading player homes from config", e);
}
}
private void savePlayerHomesToConfig() {
try {
// Clear existing data
for (String key : playerHomesConfig.getKeys(false)) {
playerHomesConfig.set(key, null);
}
// Save all player homes
for (Map.Entry<String, PlayerHomeData> entry : playerHomes.entrySet()) {
String homeName = entry.getKey();
PlayerHomeData data = entry.getValue();
playerHomesConfig.set(homeName + ".owner", data.getOwner().toString());
playerHomesConfig.set(homeName + ".location", data.getLocation());
}
playerHomesConfig.save(playerHomesFile);
} catch (Exception e) {
getLogger().log(Level.SEVERE, "Could not save player homes to config", e);
}
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String label, String[] args) {
if (!(sender instanceof Player)) {
@@ -571,6 +666,110 @@ public class InfiniteHomes extends JavaPlugin implements TabCompleter {
return true;
}
// PlayerHome Commands
if (cmd.getName().equalsIgnoreCase("setplayerhome") || cmd.getName().equalsIgnoreCase("sph")) {
if (!player.hasPermission("infinitehomes.playerhomes.allowed")) {
player.sendMessage(getMessage(player, "no_permission"));
return true;
}
if (args.length != 1) {
player.sendMessage(getMessage(player, "usage.setplayerhome"));
return true;
}
String homeName = args[0].toLowerCase();
// Check if player home name already exists
if (playerHomes.containsKey(homeName)) {
player.sendMessage(getMessage(player, "playerhome.already_exists").replace("{home}", homeName));
return true;
}
playerHomes.put(homeName, new PlayerHomeData(playerUuid, player.getLocation()));
savePlayerHomesToConfig();
player.sendMessage(getMessage(player, "playerhome.set").replace("{home}", homeName));
return true;
}
if (cmd.getName().equalsIgnoreCase("playerhome") || cmd.getName().equalsIgnoreCase("ph")) {
if (args.length != 1) {
player.sendMessage(getMessage(player, "usage.playerhome"));
return true;
}
String homeName = args[0].toLowerCase();
if (playerHomes.containsKey(homeName)) {
player.teleport(playerHomes.get(homeName).getLocation());
player.sendMessage(getMessage(player, "playerhome.teleport").replace("{home}", homeName));
} else {
player.sendMessage(getMessage(player, "playerhome.not_exist").replace("{home}", homeName));
}
return true;
}
if (cmd.getName().equalsIgnoreCase("playerhomes") || cmd.getName().equalsIgnoreCase("phs")) {
if (playerHomes.isEmpty()) {
player.sendMessage(getMessage(player, "playerhomes.none"));
return true;
}
Set<String> homeNames = playerHomes.keySet();
player.sendMessage(getMessage(player, "playerhomes.list.header"));
StringBuilder homesList = new StringBuilder();
for (String home : homeNames) {
if (homesList.length() > 0) {
homesList.append(", ");
}
homesList.append(home);
}
player.sendMessage(getMessage(player, "playerhomes.list.items").replace("{homes}", homesList.toString()));
return true;
}
if (cmd.getName().equalsIgnoreCase("delplayerhome") || cmd.getName().equalsIgnoreCase("dph")) {
if (args.length != 1) {
player.sendMessage(getMessage(player, "usage.delplayerhome"));
return true;
}
String homeName = args[0].toLowerCase();
if (playerHomes.containsKey(homeName)) {
// Nur Spieler mit der Delete-Permission können PlayerHomes löschen
if (player.hasPermission("infinitehomes.playerhomes.delete")) {
playerHomes.remove(homeName);
savePlayerHomesToConfig();
player.sendMessage(getMessage(player, "playerhome.deleted").replace("{home}", homeName));
} else {
player.sendMessage(getMessage(player, "playerhome.contact_server_team"));
}
} else {
player.sendMessage(getMessage(player, "playerhome.not_exist").replace("{home}", homeName));
}
return true;
}
return false;
}
// Innere Klasse für PlayerHome-Daten
private static class PlayerHomeData {
private UUID owner;
private Location location;
public PlayerHomeData(UUID owner, Location location) {
this.owner = owner;
this.location = location;
}
public UUID getOwner() {
return owner;
}
public Location getLocation() {
return location;
}
}
}

View File

@@ -1,7 +1,7 @@
name: InfiniteHomesPLUS
version: 1.2+
version: 1.3+-preview
main: com.user404_.infinitehomes.InfiniteHomes
website: https://github.com/deutschich/InfiniteHomes/tree/%2B
website: https://github.com/deutschich/InfiniteHomesPLUS/
api-version: 1.21
commands:
sethome:
@@ -40,4 +40,27 @@ commands:
delglobalhome:
description: Delete a global home (OP only)
usage: /delglobalhome <name>
aliases: [deleteglobalhome, dgh]
aliases: [deleteglobalhome, dgh]
setplayerhome:
description: Set a player home accessible to all players
usage: /setplayerhome <name>
aliases: [sph]
playerhome:
description: Teleport to a player home
usage: /playerhome <name>
aliases: [ph]
playerhomes:
description: List all player homes
usage: /playerhomes
aliases: [phs, listplayerhomes]
delplayerhome:
description: Delete a player home (Team members only)
usage: /delplayerhome <name>
aliases: [dph, deleteplayerhome]
permissions:
infinitehomes.playerhomes.allowed:
description: Allows setting player homes
default: true
infinitehomes.playerhomes.delete:
description: Allows deleting player homes (Team members only)
default: op

View File

@@ -1,48 +1,64 @@
# InfiniteHomes - Übersetzungsdatei
# Du kannst Übersetzungen für verschiedene Sprachen im translations-Ordner erstellen
# InfiniteHomesPLUS - Übersetzungsdatei
# Du kannst Übersetzungen für verschiedene Sprachen im translations-Ordner erstellen.
# Benenne die Dateien texts_[lang].yml (z. B. texts_de.yml für Deutsch)
# Allgemeine Nachrichten
no_permission: "§cDu hast keine Berechtigung, diesen Befehl zu verwenden."
invalid_number: "§cBitte gib eine gültige Zahl ein."
cooldown.range: "§cDer Cooldown muss zwischen -1 und 60 Sekunden liegen."
cooldown.range: "§cDie Abklingzeit muss zwischen -1 und 60 Sekunden liegen."
# Befehlsnutzung
usage.sethome: "§cBenutzung: /sethome <Name>"
usage.delhome: "§cBenutzung: /delhome <Name>"
usage.home: "§cBenutzung: /home <Name>"
usage.homecount: "§cBenutzung: /homecount <Zahl>"
usage.homecooldown: "§cBenutzung: /homecooldown <Sekunden>"
usage.setglobalhome: "§cBenutzung: /setglobalhome <Name>"
usage.globalhome: "§cBenutzung: /globalhome <Name>"
usage.delglobalhome: "§cBenutzung: /delglobalhome <Name>"
# Befehlsverwendung
usage.sethome: "§cVerwendung: /sethome <Name>"
usage.delhome: "§cVerwendung: /delhome <Name>"
usage.home: "§cVerwendung: /home <Name>"
usage.homecount: "§cVerwendung: /homecount <Zahl>"
usage.homecooldown: "§cVerwendung: /homecooldown <Sekunden>"
usage.setglobalhome: "§cVerwendung: /setglobalhome <Name>"
usage.globalhome: "§cVerwendung: /globalhome <Name>"
usage.delglobalhome: "§cVerwendung: /delglobalhome <Name>"
usage.setplayerhome: "§cVerwendung: /setplayerhome <Name>"
usage.playerhome: "§cVerwendung: /playerhome <Name>"
usage.delplayerhome: "§cVerwendung: /delplayerhome <Name>"
# Home-Nachrichten
home.set: "§aHome '{home}' gesetzt!"
home.deleted: "§aHome '{home}' gelöscht!"
home.set: "§aHome '{home}' wurde gesetzt!"
home.deleted: "§aHome '{home}' wurde gelöscht!"
home.not_exist: "§cHome '{home}' existiert nicht."
home.teleport: "§aTeleportiert zum Home '{home}'!"
home.teleport: "§aDu wurdest zu Home '{home}' teleportiert!"
home.cooldown: "§cDu musst {time} Sekunden warten, bevor du /home erneut verwenden kannst."
# Globale Home-Nachrichten
globalhome.set: "§aGlobales Home '{home}' gesetzt!"
globalhome.deleted: "§aGlobales Home '{home}' gelöscht!"
globalhome.set: "§aGlobales Home '{home}' wurde gesetzt!"
globalhome.deleted: "§aGlobales Home '{home}' wurde gelöscht!"
globalhome.not_exist: "§cGlobales Home '{home}' existiert nicht."
globalhome.teleport: "§aTeleportiert zum globalen Home '{home}'!"
globalhome.teleport: "§aDu wurdest zu globalem Home '{home}' teleportiert!"
# Home-Liste Nachrichten
# Spieler-Home-Nachrichten
playerhome.set: "§aSpieler-Home '{home}' wurde gesetzt!"
playerhome.deleted: "§aSpieler-Home '{home}' wurde gelöscht!"
playerhome.not_exist: "§cSpieler-Home '{home}' existiert nicht."
playerhome.teleport: "§aDu wurdest zu Spieler-Home '{home}' teleportiert!"
playerhome.already_exists: "§cEin Spieler-Home mit dem Namen '{home}' existiert bereits."
playerhome.contact_server_team: "§cDu kannst keine Spieler-Homes löschen. Bitte kontaktiere das Server-Team."
# Home-Liste
homes.none: "§cDu hast keine Homes gesetzt."
homes.unlimited: "unbegrenzt"
homes.list.header: "§aDeine Homes (§e{current}§a/§e{max}§a):"
homes.list.items: "§e{homes}"
homes.limit.reached: "§cDu hast die maximale Anzahl an Homes erreicht ({max})."
homes.limit.set: "§aGlobales Home-Limit auf {max} gesetzt."
homes.limit.set: "§aGlobales Home-Limit wurde auf {max} gesetzt."
# Globale Home-Liste Nachrichten
globalhomes.none: "§cEs sind keine globalen Homes gesetzt."
# Globale Home-Liste
globalhomes.none: "§cEs wurden keine globalen Homes gesetzt."
globalhomes.list.header: "§aVerfügbare globale Homes:"
globalhomes.list.items: "§e{homes}"
# Cooldown-Nachrichten
cooldown.set: "§aGlobaler Home-Cooldown auf {time} Sekunden gesetzt."
cooldown.disabled: "§aHome-Cooldown deaktiviert."
# Spieler-Home-Liste
playerhomes.none: "§cEs wurden keine Spieler-Homes gesetzt."
playerhomes.list.header: "§aVerfügbare Spieler-Homes:"
playerhomes.list.items: "§e{homes}"
# Abklingzeit-Nachrichten
cooldown.set: "§aGlobale Home-Abklingzeit wurde auf {time} Sekunden gesetzt."
cooldown.disabled: "§aHome-Abklingzeit deaktiviert."

View File

@@ -1,4 +1,4 @@
# InfiniteHomes - Translation File
# InfiniteHomesPLUS - Translation File
# You can create translations for different languages in the translations folder
# Name the files texts_[lang].yml (e.g., texts_de.yml for German)
@@ -16,6 +16,9 @@ usage.homecooldown: "§cUsage: /homecooldown <seconds>"
usage.setglobalhome: "§cUsage: /setglobalhome <name>"
usage.globalhome: "§cUsage: /globalhome <name>"
usage.delglobalhome: "§cUsage: /delglobalhome <name>"
usage.setplayerhome: "§cUsage: /setplayerhome <name>"
usage.playerhome: "§cUsage: /playerhome <name>"
usage.delplayerhome: "§cUsage: /delplayerhome <name>"
# Home messages
home.set: "§aHome '{home}' set!"
@@ -30,6 +33,14 @@ globalhome.deleted: "§aGlobal home '{home}' deleted!"
globalhome.not_exist: "§cGlobal home '{home}' does not exist."
globalhome.teleport: "§aTeleported to global home '{home}'!"
# Player home messages
playerhome.set: "§aPlayer home '{home}' set!"
playerhome.deleted: "§aPlayer home '{home}' deleted!"
playerhome.not_exist: "§cPlayer home '{home}' does not exist."
playerhome.teleport: "§aTeleported to player home '{home}'!"
playerhome.already_exists: "§cA player home with the name '{home}' already exists."
playerhome.contact_server_team: "§cYou cannot delete player homes. Please contact the server team."
# Homes list messages
homes.none: "§cYou don't have any homes set."
homes.unlimited: "unlimited"
@@ -43,6 +54,11 @@ globalhomes.none: "§cThere are no global homes set."
globalhomes.list.header: "§aAvailable global homes:"
globalhomes.list.items: "§e{homes}"
# Player homes list messages
playerhomes.none: "§cThere are no player homes set."
playerhomes.list.header: "§aAvailable player homes:"
playerhomes.list.items: "§e{homes}"
# Cooldown messages
cooldown.set: "§aGlobal home cooldown set to {time} seconds."
cooldown.disabled: "§aHome cooldown disabled."