Added Language manager (untested)

This commit is contained in:
DaTTV 2025-02-19 17:31:13 +01:00
parent a2c1eb155d
commit 4678cf5fdd
14 changed files with 581 additions and 441 deletions

View file

@ -8,6 +8,7 @@ import me.freezy.plugins.papermc.blazesmp.command.ReportCommand;
import me.freezy.plugins.papermc.blazesmp.listener.*;
import me.freezy.plugins.papermc.blazesmp.module.manager.Clans;
import me.freezy.plugins.papermc.blazesmp.module.manager.Homes;
import me.freezy.plugins.papermc.blazesmp.module.manager.L4M4;
import me.freezy.plugins.papermc.blazesmp.module.manager.ProtectedBlocks;
import me.freezy.plugins.papermc.blazesmp.tasks.PlayerNameUpdate;
import org.bukkit.configuration.file.FileConfiguration;
@ -47,6 +48,10 @@ public final class BlazeSMP extends JavaPlugin {
saveConfig();
this.log.info("Loaded config!");
this.log.info("Loading L4M4...");
L4M4.init();
this.log.info("Loaded L4M4!");
this.log.info("Loaded BlazeSMP!");
}

View file

@ -5,6 +5,7 @@ import me.freezy.plugins.papermc.blazesmp.command.util.SimpleCommand;
import me.freezy.plugins.papermc.blazesmp.listener.ChunkInventoryManager;
import me.freezy.plugins.papermc.blazesmp.module.Clan;
import me.freezy.plugins.papermc.blazesmp.module.manager.Clans;
import me.freezy.plugins.papermc.blazesmp.module.manager.L4M4;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.Chunk;
import org.bukkit.command.Command;
@ -27,12 +28,12 @@ public class ClaimCommand extends SimpleCommand {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player player)) {
sender.sendMessage(MiniMessage.miniMessage().deserialize("<red>You must be a player to use this command!"));
sender.sendMessage(MiniMessage.miniMessage().deserialize(L4M4.get("error.not_a_player")));
return true;
}
UUID playerUUID = player.getUniqueId();
if (!clans.isInClan(playerUUID)) {
player.sendMessage(MiniMessage.miniMessage().deserialize("<red>You must be in a clan to claim/unclaim chunks!"));
player.sendMessage(MiniMessage.miniMessage().deserialize(L4M4.get("error.not_in_clan")));
return true;
} else {
if (label.equalsIgnoreCase("claim")) {
@ -41,21 +42,21 @@ public class ClaimCommand extends SimpleCommand {
return true;
}
Clan playerClan = clans.getClanByMember(playerUUID);
LinkedHashMap<UUID, LinkedList<Chunk>> existingClaims=clans.getClanChunks(playerClan);
LinkedHashMap<UUID, LinkedList<Chunk>> existingClaims = clans.getClanChunks(playerClan);
if (!existingClaims.containsKey(playerUUID)) {
existingClaims.put(playerUUID, new LinkedList<>());
}
LinkedList<Chunk> playerClaims = existingClaims.get(playerUUID);
int MAX_CLAIMS = 50;
if (playerClaims.size() >= MAX_CLAIMS) {
player.sendMessage(MiniMessage.miniMessage().deserialize("<red>You have reached the maximum amount of claims!"));
player.sendMessage(MiniMessage.miniMessage().deserialize(L4M4.get("error.max_claims_reached")));
} else {
Chunk playerChunk = player.getLocation().getChunk();
if (clans.isChunkClaimed(playerChunk)) {
player.sendMessage(MiniMessage.miniMessage().deserialize("<red>This chunk is already claimed!"));
player.sendMessage(MiniMessage.miniMessage().deserialize(L4M4.get("error.chunk_already_claimed")));
} else {
playerClaims.add(playerChunk);
player.sendMessage(MiniMessage.miniMessage().deserialize("<green>Claimed chunk!"));
player.sendMessage(MiniMessage.miniMessage().deserialize(L4M4.get("success.chunk_claimed")));
existingClaims.put(playerUUID, playerClaims);
clans.setClanChunks(playerClan, existingClaims);
playerClan.save();
@ -65,19 +66,19 @@ public class ClaimCommand extends SimpleCommand {
return true;
} else if (label.equalsIgnoreCase("unclaim")) {
Clan playerClan = clans.getClanByMember(playerUUID);
LinkedHashMap<UUID, LinkedList<Chunk>> existingClaims=clans.getClanChunks(playerClan);
LinkedHashMap<UUID, LinkedList<Chunk>> existingClaims = clans.getClanChunks(playerClan);
if (existingClaims.containsKey(playerUUID)) {
LinkedList<Chunk> playerClaims = existingClaims.get(playerUUID);
Chunk playerChunk = player.getLocation().getChunk();
if (playerClaims.contains(playerChunk)) {
playerClaims.remove(playerChunk);
player.sendMessage(MiniMessage.miniMessage().deserialize("<green>Unclaimed chunk!"));
player.sendMessage(MiniMessage.miniMessage().deserialize(L4M4.get("success.chunk_unclaimed")));
existingClaims.put(playerUUID, playerClaims);
clans.setClanChunks(playerClan, existingClaims);
playerClan.save();
clans.saveAllClans();
} else {
player.sendMessage(MiniMessage.miniMessage().deserialize("<red>You do not own this chunk!"));
player.sendMessage(MiniMessage.miniMessage().deserialize(L4M4.get("error.chunk_not_owned")));
}
return true;
}

View file

@ -3,6 +3,7 @@ package me.freezy.plugins.papermc.blazesmp.command;
import me.freezy.plugins.papermc.blazesmp.BlazeSMP;
import me.freezy.plugins.papermc.blazesmp.command.util.SimpleCommand;
import me.freezy.plugins.papermc.blazesmp.module.manager.Homes;
import me.freezy.plugins.papermc.blazesmp.module.manager.L4M4;
import me.freezy.plugins.papermc.blazesmp.tasks.PlayerTeleportHomeTimer;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.command.Command;
@ -14,6 +15,7 @@ import org.jetbrains.annotations.Nullable;
import java.util.List;
public class HomeCommand extends SimpleCommand {
public HomeCommand() {
super("home", List.of("sethome", "delhome"));
}
@ -21,25 +23,34 @@ public class HomeCommand extends SimpleCommand {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player player)) {
sender.sendMessage(MiniMessage.miniMessage().deserialize("<red>You must be a player to use this command!</red>"));
sender.sendMessage(MiniMessage.miniMessage().deserialize(
L4M4.get("home.error.not_a_player")
));
return true;
}
Homes homes = BlazeSMP.getInstance().getHomes();
if (label.equalsIgnoreCase("sethome")) {
homes.setHome(player);
player.sendMessage(MiniMessage.miniMessage().deserialize("<green>Home set!</green>"));
player.sendMessage(MiniMessage.miniMessage().deserialize(
L4M4.get("home.sethome.success")
));
} else if (label.equalsIgnoreCase("delhome")) {
homes.removeHome(player);
player.sendMessage(MiniMessage.miniMessage().deserialize("<red>Home removed!</red>"));
player.sendMessage(MiniMessage.miniMessage().deserialize(
L4M4.get("home.delhome.success")
));
} else {
if (homes.hasHome(player)) {
// Informiere den Spieler, dass der Teleport-Vorgang gestartet wird
player.sendMessage(MiniMessage.miniMessage().deserialize("<yellow>Teleporting to home!</yellow>"));
player.sendMessage(MiniMessage.miniMessage().deserialize(
L4M4.get("home.teleport.start")
));
new PlayerTeleportHomeTimer(player).runTaskTimer(BlazeSMP.getInstance(), 0, 1);
} else {
homes.setHome(player);
player.sendMessage(MiniMessage.miniMessage().deserialize("<green>Home set!</green>"));
player.sendMessage(MiniMessage.miniMessage().deserialize(
L4M4.get("home.sethome.success")
));
}
}
return true;

View file

@ -2,6 +2,7 @@ package me.freezy.plugins.papermc.blazesmp.command;
import me.freezy.plugins.papermc.blazesmp.BlazeSMP;
import me.freezy.plugins.papermc.blazesmp.command.util.SimpleCommand;
import me.freezy.plugins.papermc.blazesmp.module.manager.L4M4;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
@ -31,24 +32,25 @@ public class ReportCommand extends SimpleCommand {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command cmd, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player reporter)) {
sender.sendMessage(miniMessage.deserialize("<b><i><color:#ff002f>Du darfst das nicht</color></i></b>"));
sender.sendMessage(miniMessage.deserialize(L4M4.get("report.error.not_a_player")));
return true;
}
if (args.length < 2) {
sender.sendMessage(miniMessage.deserialize("<i><color:#ff0048>Benutze bitte:</color> <color:#ff00ee>/report</color> <blue><Spieler></blue> <dark_green><Grund></dark_green></i>"));
reporter.sendMessage(miniMessage.deserialize(L4M4.get("report.usage")));
return true;
}
OfflinePlayer reportedPlayer = Bukkit.getOfflinePlayer(args[0]);
if (!reportedPlayer.hasPlayedBefore() && !reportedPlayer.isOnline()) {
reporter.sendMessage(miniMessage.deserialize("<color:#ff002f>Der Spieler existiert nicht oder war noch nie online!</color>"));
reporter.sendMessage(miniMessage.deserialize(L4M4.get("report.error.invalid_player")));
return true;
}
String reason = String.join(" ", Arrays.copyOfRange(args, 1, args.length));
reporter.sendMessage(miniMessage.deserialize(String.format("<green>Du hast</green> <white><b>%s</b></white> <green>erfolgreich wegen</green> <light_purple><i>%s</i></light_purple> <green>gemeldet</green>", reportedPlayer.getName(), reason)));
reporter.sendMessage(miniMessage.deserialize(String.format(L4M4.get("report.success.reported"),
reportedPlayer.getName(), reason)));
sendReportToDiscord(reporter.getName(), reportedPlayer.getName(), reason, reporter.getUniqueId());
@ -57,21 +59,20 @@ public class ReportCommand extends SimpleCommand {
private void sendReportToDiscord(String reporter, String reported, String reason, UUID reporterUUID) {
try {
String thumbnailUrl = "http://209.25.141.65:40018/v1/head/getHead/";
String thumbnailUrl = L4M4.get("report.discord.thumbnail_url_base");
String jsonPayload = "{"
+ "\"username\": \"ReportBot\","
+ "\"username\": \"" + L4M4.get("report.discord.username") + "\","
+ "\"embeds\": [{"
+ "\"title\": \"Neuer Report\","
+ "\"color\": 16711680," // Red color
+ "\"thumbnail\": {\"url\": \"" + thumbnailUrl+reporterUUID.toString() + "\"}," // Thumbnail
+ "\"title\": \"" + L4M4.get("report.discord.title") + "\","
+ "\"color\": 16711680,"
+ "\"thumbnail\": {\"url\": \"" + thumbnailUrl + reporterUUID.toString() + "\"},"
+ "\"fields\": ["
+ "{\"name\": \"Reporter\", \"value\": \"" + reporter + "\", \"inline\": true},"
+ "{\"name\": \"Gemeldeter Spieler\", \"value\": \"" + reported + "\", \"inline\": true},"
+ "{\"name\": \"Grund\", \"value\": \"" + reason + "\", \"inline\": false}"
+ "{\"name\": \"" + L4M4.get("report.discord.field.reporter") + "\", \"value\": \"" + reporter + "\", \"inline\": true},"
+ "{\"name\": \"" + L4M4.get("report.discord.field.reported") + "\", \"value\": \"" + reported + "\", \"inline\": true},"
+ "{\"name\": \"" + L4M4.get("report.discord.field.reason") + "\", \"value\": \"" + reason + "\", \"inline\": false}"
+ "]"
+ "}]"
+ "}";
HttpURLConnection connection = getHttpURLConnection(jsonPayload);
int responseCode = connection.getResponseCode();
@ -82,13 +83,15 @@ public class ReportCommand extends SimpleCommand {
}
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
BlazeSMP.getInstance().getLog().error("Failed to send report to Discord: {}", e.getMessage());
}
}
private static @NotNull HttpURLConnection getHttpURLConnection(String jsonPayload) throws IOException {
String webhookUrl = BlazeSMP.getInstance().getConfig().getString("discord-report-webhook");
assert webhookUrl != null;
if (webhookUrl == null) {
throw new IOException("Discord report webhook URL not set in config!");
}
URL url = new URL(webhookUrl);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
@ -112,4 +115,4 @@ public class ReportCommand extends SimpleCommand {
}
return List.of();
}
}
}

View file

@ -13,8 +13,6 @@ import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
@ -29,7 +27,9 @@ public class ChunkInventoryManager implements Listener {
public static void openInv(Player player) {
Clan clan = BlazeSMP.getInstance().getClans().getClanByMember(player.getUniqueId());
if (clan == null) {
player.sendMessage(MiniMessage.miniMessage().deserialize("<red>Du bist in keinem Clan.</red>"));
player.sendMessage(MiniMessage.miniMessage().deserialize(
me.freezy.plugins.papermc.blazesmp.module.manager.L4M4.get("chunk.error.no_clan")
));
return;
}
new ChunkInventoryManager().chunksInv(player, clan);
@ -44,7 +44,7 @@ public class ChunkInventoryManager implements Listener {
*/
private void chunksInv(Player player, Clan clan) {
// Erstelle eine Liste der Map-Einträge (Chunk -> Besitzer UUID) aus dem Clan
List<Map.Entry<Chunk, java.util.UUID>> chunkEntries = new ArrayList<>(clan.getChunkOwnerMap().entrySet());
List<Map.Entry<Chunk, UUID>> chunkEntries = new ArrayList<>(clan.getChunkOwnerMap().entrySet());
int itemsPerPage = 45; // Plätze 0-44 für Items, untere Reihe für Navigation
int totalPages = (int) Math.ceil(chunkEntries.size() / (double) itemsPerPage);
int currentPage = 0;
@ -60,13 +60,15 @@ public class ChunkInventoryManager implements Listener {
* @param currentPage Aktuelle Seite.
* @param totalPages Gesamtzahl der Seiten.
* @param itemsPerPage Items pro Seite (hier 45).
* @param clan Der Clan, dessen Chunks angezeigt werden.
* @param ignoredClan Der Clan, dessen Chunks angezeigt werden.
*/
private void openChunksMenu(Player player, List<Map.Entry<Chunk, java.util.UUID>> chunkEntries,
private void openChunksMenu(Player player, List<Map.Entry<Chunk, UUID>> chunkEntries,
int currentPage, int totalPages, int itemsPerPage,
Clan clan) {
Clan ignoredClan) {
// Erstelle ein 54-Slot Inventar mit farbigem Titel (Adventure Component)
Component title = MiniMessage.miniMessage().deserialize("<gold>Clan Chunks</gold>");
Component title = MiniMessage.miniMessage().deserialize(
me.freezy.plugins.papermc.blazesmp.module.manager.L4M4.get("chunk.title")
);
Inventory inv = Bukkit.createInventory(null, 54, title);
// Berechne Start- und Endindex für die aktuelle Seite
@ -84,7 +86,6 @@ public class ChunkInventoryManager implements Listener {
ItemStack head = new ItemStack(Material.PLAYER_HEAD);
SkullMeta skullMeta = (SkullMeta) head.getItemMeta();
skullMeta.setOwningPlayer(ownerPlayer);
// Titel als Component und dann in reinen Text umwandeln, falls nötig
Component itemName = MiniMessage.miniMessage().deserialize("<aqua>Chunk [" + chunk.getX() + ", " + chunk.getZ() + "]</aqua>");
skullMeta.displayName(itemName);
List<Component> lore = new ArrayList<>();
@ -103,13 +104,17 @@ public class ChunkInventoryManager implements Listener {
// Vorherige Seite (Slot 45)
if (currentPage > 0) {
ItemStack prev = new ItemStack(Material.ARROW);
prev.editMeta(meta -> meta.displayName(MiniMessage.miniMessage().deserialize("<green>Previous Page</green>")));
prev.editMeta(meta -> meta.displayName(MiniMessage.miniMessage().deserialize(
me.freezy.plugins.papermc.blazesmp.module.manager.L4M4.get("chunk.navigation.previous")
)));
inv.setItem(45, prev);
}
// Nächste Seite (Slot 53)
if (currentPage < totalPages - 1) {
ItemStack next = new ItemStack(Material.ARROW);
next.editMeta(meta -> meta.displayName(MiniMessage.miniMessage().deserialize("<green>Next Page</green>")));
next.editMeta(meta -> meta.displayName(MiniMessage.miniMessage().deserialize(
me.freezy.plugins.papermc.blazesmp.module.manager.L4M4.get("chunk.navigation.next")
)));
inv.setItem(53, next);
}
}
@ -118,38 +123,33 @@ public class ChunkInventoryManager implements Listener {
player.openInventory(inv);
}
// Listener für Inventarklicks mit Paper-Event (Adventure Components)
@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
if (!(event.getWhoClicked() instanceof Player player)) return;
// Verwende Paper's getView() um den Titel als Component zu erhalten
Component invTitle = event.getView().title();
Component expectedTitle = MiniMessage.miniMessage().deserialize("<gold>Clan Chunks</gold>");
// Vergleiche die reinen Texte der Components
Component expectedTitle = MiniMessage.miniMessage().deserialize(
me.freezy.plugins.papermc.blazesmp.module.manager.L4M4.get("chunk.title")
);
if (!PlainTextComponentSerializer.plainText().serialize(invTitle)
.equals(PlainTextComponentSerializer.plainText().serialize(expectedTitle))) {
return;
}
event.setCancelled(true); // Standardverhalten verhindern
event.setCancelled(true);
ItemStack clickedItem = event.getCurrentItem();
if (clickedItem == null || !clickedItem.hasItemMeta()) return;
// Holen des angezeigten Namens als reiner Text
Component itemNameComp = clickedItem.getItemMeta().displayName();
assert itemNameComp != null;
if (itemNameComp == null) return;
String displayName = PlainTextComponentSerializer.plainText().serialize(itemNameComp);
// Hole den Clan des Spielers (angenommen, der Spieler ist in einem Clan)
me.freezy.plugins.papermc.blazesmp.module.Clan clan = BlazeSMP.getInstance().getClans().getClanByMember(player.getUniqueId());
Clan clan = BlazeSMP.getInstance().getClans().getClanByMember(player.getUniqueId());
if (clan == null) return;
// Hole alle Einträge (Chunks) des Clans
List<Map.Entry<Chunk, java.util.UUID>> chunkEntries = new ArrayList<>(clan.getChunkOwnerMap().entrySet());
List<Map.Entry<Chunk, UUID>> chunkEntries = new ArrayList<>(clan.getChunkOwnerMap().entrySet());
int itemsPerPage = 45;
int totalPages = (int) Math.ceil(chunkEntries.size() / (double) itemsPerPage);
int currentPage = paginatedData.getPage(player.getUniqueId());
// Navigation behandeln
if (displayName.contains("Previous Page")) {
if (currentPage > 0) {
currentPage--;
@ -163,26 +163,26 @@ public class ChunkInventoryManager implements Listener {
openChunksMenu(player, chunkEntries, currentPage, totalPages, itemsPerPage, clan);
}
} else {
// Reagiere auf Klicks auf einzelne Chunk-Items
player.sendMessage(MiniMessage.miniMessage().deserialize("<yellow>Du hast Chunk-Item: " + displayName + " angeklickt.</yellow>"));
// Nutze den zentralen Nachrichtentext für Klicks
String msg = String.format(
me.freezy.plugins.papermc.blazesmp.module.manager.L4M4.get("chunk.clicked"),
displayName
);
player.sendMessage(MiniMessage.miniMessage().deserialize(msg));
}
}
// Listener, um die gespeicherten Seiteninformationen aufzuräumen
@EventHandler
public void onInventoryClose(InventoryCloseEvent event) {
public void onInventoryClose(org.bukkit.event.inventory.InventoryCloseEvent event) {
if (!(event.getPlayer() instanceof Player player)) return;
paginatedData.removePage(player.getUniqueId());
}
@EventHandler
public void onPlayerQuit(PlayerQuitEvent event) {
public void onPlayerQuit(org.bukkit.event.player.PlayerQuitEvent event) {
paginatedData.removePage(event.getPlayer().getUniqueId());
}
/**
* Hilfsklasse zur Verwaltung der aktuellen Seite pro Spieler.
*/
private static class PaginatedData {
private final Map<UUID, Integer> playerPages = new HashMap<>();

View file

@ -3,7 +3,7 @@ package me.freezy.plugins.papermc.blazesmp.listener;
import me.freezy.plugins.papermc.blazesmp.BlazeSMP;
import me.freezy.plugins.papermc.blazesmp.module.Clan;
import me.freezy.plugins.papermc.blazesmp.module.manager.Clans;
import net.kyori.adventure.text.Component;
import me.freezy.plugins.papermc.blazesmp.module.manager.L4M4;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
@ -13,17 +13,12 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockPlaceEvent;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.PlayerInteractAtEntityEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.inventory.Inventory;
public class PlayerClaimListener implements Listener {
Component title = MiniMessage.miniMessage().deserialize("<gold>Clan Chunks</gold>");
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
Location location = event.getBlock().getLocation();
@ -108,25 +103,24 @@ public class PlayerClaimListener implements Listener {
Clan oldClan = clans.getClanByChunk(fromChunk);
Clan newClan = clans.getClanByChunk(toChunk);
if (oldClan != null && (!oldClan.equals(newClan))) {
player.sendActionBar(
MiniMessage.miniMessage().deserialize(
"<red>You left the claim of <white>" + oldClan.getName() + "</white>!</red>"
)
// Falls der Spieler den Claim wechselt (verlassen)
if (oldClan != null && newClan != null && !oldClan.equals(newClan)) {
String msg = String.format(
L4M4.get("claim.entered"),
newClan.getName()
);
player.sendActionBar(MiniMessage.miniMessage().deserialize(msg));
}
if (newClan != null && (!newClan.equals(oldClan))) {
player.sendActionBar(
MiniMessage.miniMessage().deserialize(
"<red>Territory of <white>" + newClan.getName() + "</white> - <white>" +
Bukkit.getOfflinePlayer(newClan.getChunkOwnerMap().get(toChunk)).getName() +
"!</white></red>"
)
// Falls der Spieler in einen neuen Claim eintritt
if (newClan != null && !newClan.equals(oldClan)) {
String ownerName = Bukkit.getOfflinePlayer(newClan.getChunkOwnerMap().get(toChunk)).getName();
String msg = String.format(
L4M4.get("claim.territory"),
newClan.getName(),
ownerName
);
player.sendActionBar(MiniMessage.miniMessage().deserialize(msg));
}
}
}

View file

@ -1,6 +1,7 @@
package me.freezy.plugins.papermc.blazesmp.listener;
import com.destroystokyo.paper.event.server.AsyncTabCompleteEvent;
import me.freezy.plugins.papermc.blazesmp.module.manager.L4M4;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -203,11 +204,10 @@ public class PlayerCommandBlockerListener implements Listener {
String message = event.getMessage();
if (isBlocked(message)) {
event.setCancelled(true);
// Zeige den blockierten Befehl als Hinweis (hier der erste Teil der Nachricht)
String blockedPart = message.split(" ")[0];
player.sendMessage(MiniMessage.miniMessage().deserialize(
"<red>Unknown or incomplete command, see below for error\n<u>" + blockedPart + "</u><i> <--[HERE]</i>"
));
// Nutze den zentralen Nachrichtentext aus messages.json
String msg = String.format(L4M4.get("command.blocked"), blockedPart);
player.sendMessage(MiniMessage.miniMessage().deserialize(msg));
}
}
@ -218,8 +218,6 @@ public class PlayerCommandBlockerListener implements Listener {
String buffer = event.getBuffer();
if (isBlocked(buffer)) {
// Alle Tab-Vorschläge entfernen und das Event abbrechen,
// wenn der eingegebene Befehl blockiert ist.
event.getCompletions().clear();
event.setCancelled(true);
}

View file

@ -1,6 +1,7 @@
package me.freezy.plugins.papermc.blazesmp.listener;
import me.freezy.plugins.papermc.blazesmp.manager.PlayerManager;
import me.freezy.plugins.papermc.blazesmp.module.manager.L4M4;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -13,6 +14,8 @@ public class PlayerJoinListener implements Listener {
Player player = event.getPlayer();
new PlayerManager().setPlayerTeam(player);
event.joinMessage(MiniMessage.miniMessage().deserialize("<gray>[<green>+</green>]</gray> <reset>").append(player.teamDisplayName()));
// Verwende den zentral konfigurierten Join-Text aus der JSON-Datei
event.joinMessage(MiniMessage.miniMessage().deserialize(L4M4.get("player.join"))
.append(player.teamDisplayName()));
}
}

View file

@ -1,6 +1,7 @@
package me.freezy.plugins.papermc.blazesmp.listener;
import me.freezy.plugins.papermc.blazesmp.BlazeSMP;
import me.freezy.plugins.papermc.blazesmp.module.manager.L4M4;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.Material;
@ -39,8 +40,9 @@ public class PressurePlateListener implements Listener {
config.getDouble("spawn-location.y", 200),
config.getDouble("spawn-location.z", 0)
);
teleportMessage = config.getString("teleport-message", "§cYou need to wait 5 seconds to be teleported.");
teleportDelay = config.getLong("teleport-delay", 100L); // Default to 5 seconds (100 ticks)
// Verwende die zentrale Nachricht aus der messages.json
teleportMessage = L4M4.get("pressureplate.teleport");
teleportDelay = 5*20L; // Default to 5 seconds (100 ticks)
}
@EventHandler
@ -68,8 +70,9 @@ public class PressurePlateListener implements Listener {
@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
if (event.getBlock().getLocation().equals(pressurePlateLocation) && event.getBlock().getType() == Material.POLISHED_BLACKSTONE_PRESSURE_PLATE) {
if (event.getBlock().getLocation().equals(pressurePlateLocation)
&& event.getBlock().getType() == Material.POLISHED_BLACKSTONE_PRESSURE_PLATE) {
event.setCancelled(true);
}
}
}
}

View file

@ -0,0 +1,100 @@
package me.freezy.plugins.papermc.blazesmp.module.manager;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.Map;
import java.util.logging.Logger;
public class L4M4 {
private static final Logger LOGGER = Logger.getLogger("L4M4");
private static final String MESSAGES_STORAGE_PATH = "plugins/BlazeSMP/storage/messages.json";
// Map zum Speichern der geladenen Nachrichten
private static Map<String, String> messages;
/**
* Initialisiert die messages.json und lädt anschließend die Nachrichten.
* Diese Methode muss vor der Verwendung von get() aufgerufen werden.
*/
public static void init() {
initializeMessages();
loadMessages();
}
/**
* Initialisiert die messages.json.
* Falls die Datei nicht existiert, wird der Standardinhalt aus den Ressourcen geladen und gespeichert.
*/
private static void initializeMessages() {
File messagesFile = new File(MESSAGES_STORAGE_PATH);
if (!messagesFile.exists()) {
// Erstelle die notwendigen Verzeichnisse
if (messagesFile.getParentFile() != null && !messagesFile.getParentFile().exists()) {
if (messagesFile.getParentFile().mkdirs()) {
LOGGER.info("Verzeichnis für messages.json erstellt: " + messagesFile.getParentFile().getAbsolutePath());
} else {
LOGGER.severe("Fehler beim Erstellen des Verzeichnisses für messages.json: " + messagesFile.getParentFile().getAbsolutePath());
return;
}
}
// Lade die Ressource als Stream
try (InputStream in = L4M4.class.getClassLoader().getResourceAsStream("storage/messages.json")) {
if (in == null) {
LOGGER.severe("Resource 'storage/messages.json' nicht gefunden!");
return;
}
// Kopiere den Inhalt der Ressource in die Zieldatei
Files.copy(in, messagesFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
LOGGER.info("Default messages.json wurde kopiert nach: " + MESSAGES_STORAGE_PATH);
} catch (IOException e) {
LOGGER.severe("Fehler beim Kopieren der Default messages.json: " + e.getMessage());
}
} else {
LOGGER.info("messages.json existiert bereits unter: " + MESSAGES_STORAGE_PATH);
}
}
/**
* Lädt die messages.json in ein Map.
*/
private static void loadMessages() {
File messagesFile = new File(MESSAGES_STORAGE_PATH);
if (!messagesFile.exists()) {
LOGGER.severe("messages.json Datei nicht gefunden beim Laden.");
return;
}
try (Reader reader = new FileReader(messagesFile)) {
Gson gson = new Gson();
messages = gson.fromJson(reader, new TypeToken<Map<String, String>>() {}.getType());
LOGGER.info("messages.json wurde erfolgreich geladen.");
} catch (IOException e) {
LOGGER.severe("Fehler beim Laden von messages.json: " + e.getMessage());
}
}
/**
* Gibt den Wert zum gegebenen Schlüssel zurück.
*
* @param key der Schlüssel
* @return der Wert, falls vorhanden, ansonsten null.
*/
public static String get(String key) {
if (messages == null) {
LOGGER.warning("Messages wurden nicht geladen. Bitte init() aufrufen.");
return "404 not found";
}
String value = messages.get(key);
if (value == null) {
LOGGER.warning("Key '" + key + "' nicht in messages.json gefunden.");
}
return value;
}
}

View file

@ -1,6 +1,7 @@
package me.freezy.plugins.papermc.blazesmp.tasks;
import me.freezy.plugins.papermc.blazesmp.BlazeSMP;
import me.freezy.plugins.papermc.blazesmp.module.manager.L4M4;
import net.kyori.adventure.text.minimessage.MiniMessage;
import org.bukkit.Location;
import org.bukkit.Particle;
@ -17,6 +18,7 @@ public class PlayerTeleportHomeTimer extends BukkitRunnable {
// Felder für den Spiraleneffekt
private double angle = 0;
private double yOffset = 0;
public PlayerTeleportHomeTimer(Player player) {
this.player = player;
@ -32,36 +34,45 @@ public class PlayerTeleportHomeTimer extends BukkitRunnable {
if (player.getLocation().getX() != origX ||
player.getLocation().getY() != origY ||
player.getLocation().getZ() != origZ) {
player.sendMessage(MiniMessage.miniMessage().deserialize("<red>Teleporting cancelt you moved!</red>"));
player.sendMessage(MiniMessage.miniMessage().deserialize(L4M4.get("teleport.cancelled")));
cancel();
return;
}
// Berechne, wie viele Ticks bereits vergangen sind
int ticksElapsed = (5 * 20) - ticksRemaining;
// Erzeuge den Spiraleneffekt
Location baseLoc = player.getLocation();
double radius = 1.5;
double offsetX = Math.cos(angle) * radius;
double offsetZ = Math.sin(angle) * radius;
// Inkrementiere den Y-Wert, sodass die Spirale nach oben steigt
double offsetY = 0.2 + ticksElapsed * 0.05;
Location particleLoc = baseLoc.clone().add(offsetX, offsetY, offsetZ);
player.getWorld().spawnParticle(Particle.FLAME, particleLoc, 1, 0, 0, 0, 0);
// Erhöhe den Winkel schneller, sodass sich die Spirale schneller dreht
// Schleife für einen schnelleren Effekt: Mehrere Partikel pro Tick
// Basis-Inkrement des Winkels
double angleIncrement = Math.PI / 4;
angle += angleIncrement;
for (int i = 0; i < 3; i++) {
double currentAngle = angle + (i * angleIncrement);
double offsetX = Math.cos(currentAngle) * radius;
double offsetZ = Math.sin(currentAngle) * radius;
// Verwende yOffset für die vertikale Verschiebung und setze zurück, wenn er über 2 liegt
double currentYOffset = yOffset;
if (currentYOffset > 2) {
currentYOffset = 0;
}
Location particleLoc = baseLoc.clone().add(offsetX, currentYOffset, offsetZ);
player.getWorld().spawnParticle(Particle.FLAME, particleLoc, 1, 0, 0, 0, 0);
}
// Erhöhe den globalen Winkel und yOffset für den nächsten Tick
angle += angleIncrement * 3; // da 3 Partikel pro Tick
yOffset += 0.05 * 3;
if (yOffset > 2) {
yOffset = 0;
}
// Teleport-Countdown und Nachrichten
if (ticksRemaining <= 0) {
player.teleportAsync(BlazeSMP.getInstance().getHomes().getHome(player));
player.sendMessage(MiniMessage.miniMessage().deserialize("<green>Teleported!</green>"));
player.sendMessage(MiniMessage.miniMessage().deserialize(L4M4.get("teleport.success")));
cancel();
} else if (ticksRemaining % 20 == 0) {
int secondsLeft = ticksRemaining / 20;
String message = String.format("<yellow>Teleporting to home in %s seconds!</yellow>", secondsLeft);
String message = String.format(L4M4.get("teleport.countdown"), secondsLeft);
player.sendMessage(MiniMessage.miniMessage().deserialize(message));
}

View file

@ -0,0 +1,119 @@
{
"error.not_a_player": "<red>You must be a player to execute this command!</red>",
"error.already_in_clan": "<red>You are already in a clan!</red>",
"usage.clan_create": "<red>Usage: /clan create <name> <tag></red>",
"success.clan_created": "<green>Clan created successfully!</green>",
"usage.clan_chat": "<red>Usage: /clan chat <message></red>",
"error.not_in_clan_chat": "<red>You are not in a clan!</red>",
"usage.clan_join": "<red>Usage: /clan join <clanName></red>",
"error.clan_not_found": "<red>Clan not found!</red>",
"error.already_requested": "<yellow>You have already requested to join this clan.</yellow>",
"success.join_request_sent": "<green>Join request sent to clan %s!</green>",
"error.player_not_online": "<red>Player %s is not online!</red>",
"error.player_already_in_clan": "<red>%s is already in a clan!</red>",
"success.invite_sent": "<green>Invite sent to %s.</green>",
"notification.invite": "<yellow>Invite from clan %s.</yellow>",
"button.accept": "<green>[Accept]</green>",
"button.deny": "<red>[Deny]</red>",
"usage.clan_invite": "<red>Usage: /clan invite <playerName></red>",
"error.not_authorized_invite": "<red>You are not authorized to invite players to a clan!</red>",
"usage.clan_accept": "<red>Usage: /clan accept <clanName></red>",
"error.invite_not_found": "<red>No invite found from clan %s.</red>",
"success.join_clan": "<green>You have joined the clan %s!</green>",
"success.invite_accepted_notify": "<green>%s has accepted the clan invite.</green>",
"usage.clan_accept_request": "<red>Usage: /clan accept <playerName></red>",
"error.no_join_requests": "<red>No join requests available.</red>",
"error.join_request_not_found": "<red>No join request found from %s.</red>",
"success.join_request_accepted": "<green>You have accepted %s's join request.</green>",
"success.join_request_accepted_notify": "<green>Your join request for clan %s has been accepted.</green>",
"usage.clan_deny_invite": "<red>Usage: /clan deny <clanName></red>",
"error.invite_declined": "<red>You have declined the clan invite from %s.</red>",
"error.invite_declined_notify": "<red>%s has declined the clan invite.</red>",
"usage.clan_deny_request": "<red>Usage: /clan deny <playerName></red>",
"error.join_request_denied": "<red>You have denied %s's join request.</red>",
"error.join_request_denied_notify": "<red>Your join request for clan %s has been denied.</red>",
"error.no_clans": "<red>No clans found!</red>",
"error.not_in_clan_info": "<red>You are not in a clan!</red>",
"error.clan_not_found_info": "<red>Could not find your clan.</red>",
"error.not_authorized_kick": "<red>You are not authorized to kick players.</red>",
"usage.clan_kick": "<red>Usage: /clan kick <playerName></red>",
"error.player_not_found": "<red>No such player found.</red>",
"error.player_not_in_clan": "<red>%s is not in your clan!</red>",
"error.cannot_kick_leader": "<red>You cannot kick the clan leader!</red>",
"success.player_kicked": "<green>You kicked %s from the clan.</green>",
"error.player_kicked_notify": "<red>You have been kicked from the clan %s.</red>",
"error.only_leader_transfer": "<red>Only the clan leader can transfer leadership.</red>",
"usage.clan_transfer": "<red>Usage: /clan transfer <playerName></red>",
"success.leadership_transferred": "<green>You transferred leadership to %s.</green>",
"success.new_leader_notify": "<green>You are now the leader of the clan %s.</green>",
"error.only_leader_promote": "<red>Only the clan leader can promote a member.</red>",
"usage.clan_promote": "<red>Usage: /clan promote <playerName></red>",
"error.already_vice": "<red>%s is already the vice!</red>",
"success.promoted_to_vice": "<green>You promoted %s to vice leader.</green>",
"success.promoted_notify": "<green>You have been promoted to vice leader of clan %s.</green>",
"error.not_authorized_demote": "<red>You are not authorized to demote anyone.</red>",
"usage.clan_demote": "<red>Usage: /clan demote <playerName></red>",
"error.not_vice": "<red>%s is not the vice leader!</red>",
"error.only_self_demote": "<red>You can only demote yourself!</red>",
"success.demoted": "<green>You demoted %s to a normal member.</green>",
"error.demoted_notify": "<red>You have been demoted to a normal member of clan %s.</red>",
"error.only_leader_disband": "<red>Only the clan leader can disband the clan.</red>",
"error.leader_cannot_leave": "<red>You must transfer leadership or disband the clan before leaving.</red>",
"success.clan_disbanded_leave": "<green>You have disbanded your clan (no other members) and left.</green>",
"success.left_clan": "<green>You have left the clan %s.</green>",
"error.only_leader_modify": "<red>Only the clan leader can modify clan settings.</red>",
"usage.clan_modify": "<red>Usage: /clan modify <name|tag> <newValue></red>",
"error.modify_invalid": "<red>You can only modify 'name' or 'tag'.</red>",
"error.unknown_subcommand": "<red>Unknown subcommand. Use /clan for help.</red>",
"error.clan_disbanded_notify": "<red>Your clan %s has been disbanded by the leader.</red>",
"help.leader": "<color:#c70088>=== Clan Commands ===</color>\n<color:#c70088>-</color> <hover:show_text:'Displays clan info'><click:run_command:'/clan info'><color:#10abc7>/clan info</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Invite a player'><click:run_command:'/clan invite'><color:#10abc7>/clan invite</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Kick a player'><click:run_command:'/clan kick'><color:#10abc7>/clan kick</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Transfer leadership'><click:run_command:'/clan transfer'><color:#10abc7>/clan transfer</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Promote a member'><click:run_command:'/clan promote'><color:#10abc7>/clan promote</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Demote the vice leader'><click:run_command:'/clan demote'><color:#10abc7>/clan demote</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Disband your clan'><click:run_command:'/clan disband'><color:#10abc7>/clan disband</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Leave your clan'><click:run_command:'/clan leave'><color:#10abc7>/clan leave</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Accept a join request'><click:run_command:'/clan accept'><color:#10abc7>/clan accept</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Deny a join request'><click:run_command:'/clan deny'><color:#10abc7>/clan deny</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Modify clan name or tag'><click:run_command:'/clan modify'><color:#10abc7>/clan modify</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Show a list of all clans'><click:run_command:'/clan list'><color:#10abc7>/clan list</color></click></hover>\n<color:#c70088>=====================</color>",
"help.vice": "<color:#c70088>=== Clan Commands ===</color>\n<color:#c70088>-</color> <hover:show_text:'Displays clan info'><click:run_command:'/clan info'><color:#10abc7>/clan info</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Invite a player'><click:run_command:'/clan invite'><color:#10abc7>/clan invite</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Kick a player'><click:run_command:'/clan kick'><color:#10abc7>/clan kick</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Demote the vice leader'><click:run_command:'/clan demote'><color:#10abc7>/clan demote</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Leave your clan'><click:run_command:'/clan leave'><color:#10abc7>/clan leave</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Accept a join request'><click:run_command:'/clan accept'><color:#10abc7>/clan accept</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Deny a join request'><click:run_command:'/clan deny'><color:#10abc7>/clan deny</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Show a list of all clans'><click:run_command:'/clan list'><color:#10abc7>/clan list</color></click></hover>\n<color:#c70088>=====================</color>",
"help.member": "<color:#c70088>=== Clan Commands ===</color>\n<color:#c70088>-</color> <hover:show_text:'Displays clan info'><click:run_command:'/clan info'><color:#10abc7>/clan info</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Leave your clan'><click:run_command:'/clan leave'><color:#10abc7>/clan leave</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Show a list of all clans'><click:run_command:'/clan list'><color:#10abc7>/clan list</color></click></hover>\n<color:#c70088>=====================</color>",
"help.none": "<color:#c70088>=== Clan Commands ===</color>\n<color:#c70088>-</color> <hover:show_text:'Create a clan'><click:run_command:'/clan create'><color:#10abc7>/clan create</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Join a clan'><click:run_command:'/clan join'><color:#10abc7>/clan join</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Accept a clan invite'><click:run_command:'/clan accept'><color:#10abc7>/clan accept</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Deny a clan invite'><click:run_command:'/clan deny'><color:#10abc7>/clan deny</color></click></hover>\n<color:#c70088>-</color> <hover:show_text:'Show a list of all clans'><click:run_command:'/clan list'><color:#10abc7>/clan list</color></click></hover>\n<color:#c70088>=====================</color>",
"chat.format": "<color:#10abc7>[Clan] %s:</color> <color:#ff8800>%s</color>",
"info.header": "<color:#c70088>=== Clan info ===</color>\n",
"info.uuid": " <color:#c70088>-</color> <hover:show_text:'Unique identifier'><color:#10abc7>ID:</color></hover> <color:#ff8800>%s</color>\n",
"info.name": " <color:#c70088>-</color> <hover:show_text:'Name'><color:#10abc7>Name:</color></hover> <color:#ff8800>%s</color>\n",
"info.leader": " <color:#c70088>-</color> <hover:show_text:'Leader'><color:#10abc7>Leader:</color></hover> <color:#ff8800>%s</color>\n",
"info.vice": " <color:#c70088>-</color> <hover:show_text:'Vice Leader'><color:#10abc7>Vice Leader:</color></hover> <color:#ff8800>%s</color>\n",
"info.members_count": " <color:#c70088>-</color> <hover:show_text:'Member count'><color:#10abc7>Members:</color></hover> <color:#ff8800>%d</color>\n",
"info.tag": " <color:#c70088>-</color> <hover:show_text:'Clan tag'><color:#10abc7>Tag:</color></hover> <color:#ff8800>%s</color>\n",
"info.members_list_header": "<color:#c70088>Members List:</color>\n",
"info.member_line": " <color:#c70088>-</color> <hover:show_text:'Member'><color:#10abc7>Member:</color></hover> <color:#ff8800>%s</color>\n",
"info.footer": "<color:#c70088>=====================</color>",
"home.error.not_a_player": "<red>You must be a player to use this command!</red>",
"home.sethome.success": "<green>Home set!</green>",
"home.delhome.success": "<red>Home removed!</red>",
"home.teleport.start": "<yellow>Teleporting to home!</yellow>",
"report.error.not_a_player": "<b><i><color:#ff002f>Du darfst das nicht</color></i></b>",
"report.usage": "<i><color:#ff0048>Benutze bitte:</color> <color:#ff00ee>/report</color> <blue><Spieler></blue> <dark_green><Grund></dark_green></i>",
"report.error.invalid_player": "<color:#ff002f>Der Spieler existiert nicht oder war noch nie online!</color>",
"report.success.reported": "<green>Du hast</green> <white><b>%s</b></white> <green>erfolgreich wegen</green> <light_purple><i>%s</i></light_purple> <green>gemeldet</green>",
"report.discord.username": "ReportBot",
"report.discord.title": "Neuer Report",
"report.discord.thumbnail_url_base": "http://209.25.141.65:40018/v1/head/getHead/",
"report.discord.field.reporter": "Reporter",
"report.discord.field.reported": "Gemeldeter Spieler",
"report.discord.field.reason": "Grund",
"chunk.error.no_clan": "<red>You are not in a clan!</red>",
"chunk.title": "<gold>Clan Chunks</gold>",
"chunk.navigation.previous": "<green>Previous Page</green>",
"chunk.navigation.next": "<green>Next Page</green>",
"chunk.clicked": "<yellow>You clicked on Chunk item: %s.</yellow>",
"claim.entered": "<red>You entered the claim of <white>%s</white>!</red>",
"claim.territory": "<red>Territory of <white>%s</white> - <white>%s</white>!</red>",
"command.blocked": "<red>Unknown or incomplete command, see below for error\n<u>%s</u><i> <--[HERE]</i>",
"player.join": "<gray>[<green>+</green>]</gray> <reset>",
"pressureplate.teleport": "<red>You need to wait 5 seconds to be teleported.</red>",
"teleport.cancelled": "<red>Teleporting cancelled, you moved!</red>",
"teleport.success": "<green>Teleported!</green>",
"teleport.countdown": "<yellow>Teleporting to home in %s seconds!</yellow>"
}