From 1ac19014c1e35996895430ae7dc44029f0d05ca4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= Date: Sat, 13 Dec 2025 13:45:37 +0100 Subject: [PATCH 1/3] introduced `AntiInventoryMove` appliance with related listeners and optimized admin notification logic in `AcInform` --- .../antiBoatFreecam/AntiBoatFreecam.java | 13 ++----- .../antiInventoryMove/AntiInventoryMove.java | 38 +++++++++++++++++++ .../InInventoryMoveListener.java | 21 ++++++++++ .../InventoryTrackerListener.java | 21 ++++++++++ .../appliances/tooling/acInform/AcInform.java | 25 ++++++++++++ 5 files changed, 108 insertions(+), 10 deletions(-) create mode 100644 common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiInventoryMove/AntiInventoryMove.java create mode 100644 common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiInventoryMove/InInventoryMoveListener.java create mode 100644 common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiInventoryMove/InventoryTrackerListener.java diff --git a/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiBoatFreecam/AntiBoatFreecam.java b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiBoatFreecam/AntiBoatFreecam.java index 8313799..3830920 100644 --- a/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiBoatFreecam/AntiBoatFreecam.java +++ b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiBoatFreecam/AntiBoatFreecam.java @@ -5,15 +5,10 @@ import eu.mhsl.craftattack.spawn.core.Main; import eu.mhsl.craftattack.spawn.core.appliance.Appliance; import org.bukkit.Bukkit; import org.bukkit.entity.Boat; -import org.bukkit.entity.Player; - -import java.util.HashMap; -import java.util.Map; @SuppressWarnings("unused") public class AntiBoatFreecam extends Appliance { private static final float MAX_YAW_OFFSET = 106.0f; - private final Map violatedPlayers = new HashMap<>(); public AntiBoatFreecam() { Bukkit.getScheduler().runTaskTimerAsynchronously( @@ -27,14 +22,12 @@ public class AntiBoatFreecam extends Appliance { float yawDelta = wrapDegrees(playerYaw - boatYaw); if(Math.abs(yawDelta) <= MAX_YAW_OFFSET) return; - this.violatedPlayers.merge(player, 1f, Float::sum); - float violationCount = this.violatedPlayers.get(player); - if(violationCount != 1 && violationCount % 100 != 0) return; - Main.instance().getAppliance(AcInform.class).notifyAdmins( + Main.instance().getAppliance(AcInform.class).slowedNotifyAdmins( "internal", player.getName(), "illegalBoatLookYaw", - violationCount + yawDelta, + 3000 ); }), 1L, diff --git a/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiInventoryMove/AntiInventoryMove.java b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiInventoryMove/AntiInventoryMove.java new file mode 100644 index 0000000..2b7a21d --- /dev/null +++ b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiInventoryMove/AntiInventoryMove.java @@ -0,0 +1,38 @@ +package eu.mhsl.craftattack.spawn.common.appliances.security.antiInventoryMove; + +import eu.mhsl.craftattack.spawn.core.appliance.Appliance; +import net.kyori.adventure.util.Ticks; +import org.bukkit.entity.Player; +import org.bukkit.event.Listener; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public class AntiInventoryMove extends Appliance { + private static final long errorTimeMargin = Ticks.SINGLE_TICK_DURATION_MS * 2; + + private final Map invOpen = new ConcurrentHashMap<>(); + + public void setInvOpen(Player player, boolean open) { + if(open) + this.invOpen.put(player.getUniqueId(), System.currentTimeMillis()); + else + this.invOpen.remove(player.getUniqueId()); + } + + public boolean hasInventoryOpen(Player player) { + if(!this.invOpen.containsKey(player.getUniqueId())) return false; + return this.invOpen.get(player.getUniqueId()) < System.currentTimeMillis() - errorTimeMargin; + } + + @Override + protected @NotNull List listeners() { + return List.of( + new InventoryTrackerListener(), + new InInventoryMoveListener() + ); + } +} diff --git a/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiInventoryMove/InInventoryMoveListener.java b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiInventoryMove/InInventoryMoveListener.java new file mode 100644 index 0000000..0fd4b28 --- /dev/null +++ b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiInventoryMove/InInventoryMoveListener.java @@ -0,0 +1,21 @@ +package eu.mhsl.craftattack.spawn.common.appliances.security.antiInventoryMove; + +import eu.mhsl.craftattack.spawn.common.appliances.tooling.acInform.AcInform; +import eu.mhsl.craftattack.spawn.core.Main; +import eu.mhsl.craftattack.spawn.core.appliance.ApplianceListener; +import org.bukkit.event.EventHandler; +import org.bukkit.event.player.PlayerInputEvent; + +class InInventoryMoveListener extends ApplianceListener { + @EventHandler + public void onInput(PlayerInputEvent event) { + if(!this.getAppliance().hasInventoryOpen(event.getPlayer())) return; + Main.instance().getAppliance(AcInform.class).slowedNotifyAdmins( + "internal", + event.getPlayer().getName(), + "inInventoryMove", + -1f, + 3000 + ); + } +} diff --git a/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiInventoryMove/InventoryTrackerListener.java b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiInventoryMove/InventoryTrackerListener.java new file mode 100644 index 0000000..0c5c89f --- /dev/null +++ b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/security/antiInventoryMove/InventoryTrackerListener.java @@ -0,0 +1,21 @@ +package eu.mhsl.craftattack.spawn.common.appliances.security.antiInventoryMove; + +import eu.mhsl.craftattack.spawn.core.appliance.ApplianceListener; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.inventory.InventoryOpenEvent; + +class InventoryTrackerListener extends ApplianceListener { + @EventHandler + public void onOpen(InventoryOpenEvent event) { + if(!(event.getPlayer() instanceof Player player)) return; + this.getAppliance().setInvOpen(player, true); + } + + @EventHandler + public void onClose(InventoryCloseEvent event) { + if(!(event.getPlayer() instanceof Player player)) return; + this.getAppliance().setInvOpen(player, false); + } +} diff --git a/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/acInform/AcInform.java b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/acInform/AcInform.java index efd5c05..a721ad3 100644 --- a/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/acInform/AcInform.java +++ b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/acInform/AcInform.java @@ -11,14 +11,20 @@ import org.bukkit.Bukkit; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public class AcInform extends Appliance { + private final Map> violationSlowdowns = new ConcurrentHashMap<>(); + public void processCommand(@NotNull String[] args) { String anticheatName = null; String playerName = null; String checkName = null; Float violationCount = null; + int notifyEvery = 0; for(int i = 0; i < args.length; i++) { if(!args[i].startsWith("--")) continue; @@ -36,13 +42,32 @@ public class AcInform extends Appliance { case "--playerName" -> playerName = value; case "--check" -> checkName = value; case "--violationCount" -> violationCount = value.isEmpty() ? null : Float.valueOf(value); + case "--notifyEvery" -> notifyEvery = Integer.parseInt(value); } } + if(notifyEvery == 0) { + this.notifyAdmins(anticheatName, playerName, checkName, violationCount); + } else { + this.slowedNotifyAdmins(anticheatName, playerName, checkName, violationCount, notifyEvery); + } + } + + public void slowedNotifyAdmins(@Nullable String anticheatName, @Nullable String playerName, @Nullable String checkName, @Nullable Float violationCount, int notifyEvery) { + this.violationSlowdowns.putIfAbsent(playerName, new HashMap<>()); + + var slowdowns = this.violationSlowdowns.get(playerName); + if(slowdowns.containsKey(checkName)) { + if(slowdowns.get(checkName) > System.currentTimeMillis() - notifyEvery) return; + } + this.notifyAdmins(anticheatName, playerName, checkName, violationCount); } public void notifyAdmins(@Nullable String anticheatName, @Nullable String playerName, @Nullable String checkName, @Nullable Float violationCount) { + this.violationSlowdowns.putIfAbsent(playerName, new HashMap<>()); + this.violationSlowdowns.get(playerName).put(checkName, System.currentTimeMillis()); + ComponentBuilder component = Component.text(); NamedTextColor textColor = NamedTextColor.GRAY; From e015bbb3561e6604313a591f06fd51bc36a866cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= Date: Sat, 13 Dec 2025 15:00:48 +0100 Subject: [PATCH 2/3] added `unsuspectedKick` and `crashKick` features to `Kick` appliance; updated `AcInform` to include related commands --- .../appliances/tooling/acInform/AcInform.java | 22 +++++++++--- .../common/appliances/tooling/kick/Kick.java | 34 ++++++++++++++++++- .../tooling/kick/KickCrashCommand.java | 31 +++++++++++++++++ .../tooling/kick/KickUnsuspectedCommand.java | 31 +++++++++++++++++ .../spawn/core/util/entity/PlayerUtils.java | 32 +++++++++++++++++ 5 files changed, 145 insertions(+), 5 deletions(-) create mode 100644 common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/kick/KickCrashCommand.java create mode 100644 common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/kick/KickUnsuspectedCommand.java diff --git a/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/acInform/AcInform.java b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/acInform/AcInform.java index a721ad3..72f855d 100644 --- a/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/acInform/AcInform.java +++ b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/acInform/AcInform.java @@ -110,28 +110,42 @@ public class AcInform extends Appliance { Component.newline() .append(Component.text("⊥ ", NamedTextColor.GRAY)) .append(Component.text("[", NamedTextColor.GRAY)) - .append(Component.text("Report", NamedTextColor.GOLD)) + .append(Component.text("\uD83D\uDCD6", NamedTextColor.GOLD)) .append(Component.text("]", NamedTextColor.GRAY)) .clickEvent(ClickEvent.suggestCommand(String.format("/report %s anticheat %s flagged %s", playerName, anticheatName, checkName))) ); component.append( Component.text(" [", NamedTextColor.GRAY) - .append(Component.text("Kick", NamedTextColor.GOLD)) + .append(Component.text("\u23F1", NamedTextColor.GOLD)) .append(Component.text("]", NamedTextColor.GRAY)) .clickEvent(ClickEvent.suggestCommand(String.format("/kick %s", playerName))) ); component.append( Component.text(" [", NamedTextColor.GRAY) - .append(Component.text("Panic Ban", NamedTextColor.GOLD)) + .append(Component.text("\uD83E\uDDB6", NamedTextColor.GOLD)) + .append(Component.text("]", NamedTextColor.GRAY)) + .clickEvent(ClickEvent.suggestCommand(String.format("/kickunsuspected %s", playerName))) + ); + + component.append( + Component.text(" [", NamedTextColor.GRAY) + .append(Component.text("\u2623", NamedTextColor.GOLD)) + .append(Component.text("]", NamedTextColor.GRAY)) + .clickEvent(ClickEvent.suggestCommand(String.format("/kickcrash %s", playerName))) + ); + + component.append( + Component.text(" [", NamedTextColor.GRAY) + .append(Component.text("\uD83D\uDD12", NamedTextColor.GOLD)) .append(Component.text("]", NamedTextColor.GRAY)) .clickEvent(ClickEvent.suggestCommand(String.format("/panicban %s", playerName))) ); component.append( Component.text(" [", NamedTextColor.GRAY) - .append(Component.text("Spectate/Teleport", NamedTextColor.GOLD)) + .append(Component.text("\uD83D\uDC41", NamedTextColor.GOLD)) .append(Component.text("]", NamedTextColor.GRAY)) .clickEvent(ClickEvent.suggestCommand(String.format("/grim spectate %s", playerName))) ); diff --git a/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/kick/Kick.java b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/kick/Kick.java index c9b1389..9bc67e9 100644 --- a/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/kick/Kick.java +++ b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/kick/Kick.java @@ -1,9 +1,14 @@ package eu.mhsl.craftattack.spawn.common.appliances.tooling.kick; +import eu.mhsl.craftattack.spawn.core.Main; import eu.mhsl.craftattack.spawn.core.appliance.Appliance; import eu.mhsl.craftattack.spawn.core.appliance.ApplianceCommand; +import eu.mhsl.craftattack.spawn.core.util.entity.PlayerUtils; import eu.mhsl.craftattack.spawn.core.util.text.DisconnectInfo; +import net.kyori.adventure.text.Component; +import net.kyori.adventure.util.Ticks; import org.bukkit.Bukkit; +import org.bukkit.Material; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -25,9 +30,36 @@ public class Kick extends Appliance { ).applyKick(player); } + public void unsuspectedKick(@NotNull String playerName) { + Player player = Bukkit.getPlayer(playerName); + + if(player == null) + throw new ApplianceCommand.Error("Player not found"); + + String material = Material.values()[(int)(Math.random() * Material.values().length)].name(); + player.kick(Component.text("java.lang.IllegalStateException: Failed to create model for minecraft:%s".formatted(material))); + } + + public void crashKick(@NotNull String playerName) { + Player player = Bukkit.getPlayer(playerName); + + if(player == null) + throw new ApplianceCommand.Error("Player not found"); + + Bukkit.getScheduler().runTaskAsynchronously(Main.instance(), () -> { + PlayerUtils.sendCube(player, 100, Material.ENCHANTING_TABLE.createBlockData()); + PlayerUtils.sendCube(player, 5, Material.DIRT.createBlockData()); + }); + Bukkit.getScheduler().runTaskLater(Main.instance(), () -> player.kick(Component.empty()), Ticks.TICKS_PER_SECOND * 15); + } + @Override @NotNull protected List> commands() { - return List.of(new KickCommand()); + return List.of( + new KickCommand(), + new KickUnsuspectedCommand(), + new KickCrashCommand() + ); } } diff --git a/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/kick/KickCrashCommand.java b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/kick/KickCrashCommand.java new file mode 100644 index 0000000..79025f1 --- /dev/null +++ b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/kick/KickCrashCommand.java @@ -0,0 +1,31 @@ +package eu.mhsl.craftattack.spawn.common.appliances.tooling.kick; + +import eu.mhsl.craftattack.spawn.core.appliance.ApplianceCommand; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class KickCrashCommand extends ApplianceCommand { + public KickCrashCommand() { + super("kickCrash"); + } + + @Override + protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception { + if(args.length < 1) throw new Error("Es muss ein Spielername angegeben werden!"); + this.getAppliance().crashKick(args[0]); + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + return super.tabCompleteReducer( + Bukkit.getOnlinePlayers().stream().map(Player::getName).toList(), + args + ); + } +} diff --git a/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/kick/KickUnsuspectedCommand.java b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/kick/KickUnsuspectedCommand.java new file mode 100644 index 0000000..f84fa45 --- /dev/null +++ b/common/src/main/java/eu/mhsl/craftattack/spawn/common/appliances/tooling/kick/KickUnsuspectedCommand.java @@ -0,0 +1,31 @@ +package eu.mhsl.craftattack.spawn.common.appliances.tooling.kick; + +import eu.mhsl.craftattack.spawn.core.appliance.ApplianceCommand; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class KickUnsuspectedCommand extends ApplianceCommand { + public KickUnsuspectedCommand() { + super("kickUnsuspected"); + } + + @Override + protected void execute(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) throws Exception { + if(args.length < 1) throw new Error("Es muss ein Spielername angegeben werden!"); + this.getAppliance().unsuspectedKick(args[0]); + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + return super.tabCompleteReducer( + Bukkit.getOnlinePlayers().stream().map(Player::getName).toList(), + args + ); + } +} diff --git a/core/src/main/java/eu/mhsl/craftattack/spawn/core/util/entity/PlayerUtils.java b/core/src/main/java/eu/mhsl/craftattack/spawn/core/util/entity/PlayerUtils.java index 41c5914..2994461 100644 --- a/core/src/main/java/eu/mhsl/craftattack/spawn/core/util/entity/PlayerUtils.java +++ b/core/src/main/java/eu/mhsl/craftattack/spawn/core/util/entity/PlayerUtils.java @@ -1,10 +1,16 @@ package eu.mhsl.craftattack.spawn.core.util.entity; +import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.Statistic; +import org.bukkit.World; +import org.bukkit.block.data.BlockData; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; +import java.util.HashMap; +import java.util.Map; + public class PlayerUtils { public static void resetStatistics(Player player) { for(Statistic statistic : Statistic.values()) { @@ -30,4 +36,30 @@ public class PlayerUtils { } } } + + public static void sendCube(Player player, int cubeSize, BlockData fakeBlock) { + Location loc = player.getLocation(); + World world = player.getWorld(); + + int half = cubeSize / 2; + int cx = loc.getBlockX(); + int cy = loc.getBlockY(); + int cz = loc.getBlockZ(); + + int minY = world.getMinHeight(); + int maxY = world.getMaxHeight() - 1; + + Map changes = new HashMap<>(); + + for (int x = cx - half; x <= cx + half; x++) { + for (int y = Math.max(cy - half, minY); y <= Math.min(cy + half, maxY); y++) { + for (int z = cz - half; z <= cz + half; z++) { + changes.put(new Location(world, x, y, z), fakeBlock); + } + } + } + + //noinspection UnstableApiUsage + player.sendMultiBlockChange(changes); + } } From 9767896cde43e76bf6a7a4745afbf8e817982738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elias=20M=C3=BCller?= Date: Sat, 20 Dec 2025 11:51:30 +0100 Subject: [PATCH 3/3] updated `OutlawedCommand` and `Outlawed` to rename `vogelfrei` to `PVP`, adjusted related messages accordingly --- .../appliances/gameplay/outlawed/Outlawed.java | 14 +++++++------- .../gameplay/outlawed/OutlawedCommand.java | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/outlawed/Outlawed.java b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/outlawed/Outlawed.java index a322a38..3eddd09 100644 --- a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/outlawed/Outlawed.java +++ b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/outlawed/Outlawed.java @@ -74,11 +74,11 @@ public class Outlawed extends Appliance implements DisplayName.Prefixed { void switchLawStatus(Player player) throws OutlawChangeNotPermitted { if(this.getLawStatus(player).equals(Status.FORCED)) { - throw new OutlawChangeNotPermitted("Dein Vogelfreistatus wurde als Strafe auferlegt und kann daher nicht verändert werden."); + throw new OutlawChangeNotPermitted("Dein PVP-Status wurde als Strafe auferlegt und kann daher nicht verändert werden."); } if(this.isTimeout(player)) { - throw new OutlawChangeNotPermitted("Du kannst deinen Vogelfreistatus nicht so schnell wechseln. Bitte warte einige Stunden bevor du umschaltest!"); + throw new OutlawChangeNotPermitted("Du kannst deinen PVP-Status nicht so schnell wechseln. Bitte warte einige Stunden bevor du umschaltest!"); } this.setLawStatus(player, this.isOutlawed(player) ? Status.DISABLED : Status.VOLUNTARILY); @@ -126,13 +126,13 @@ public class Outlawed extends Appliance implements DisplayName.Prefixed { public Component getStatusDescription(Status status) { return switch(status) { - case DISABLED -> Component.text("Vogelfreistatus inaktiv: ", NamedTextColor.GREEN) + case DISABLED -> Component.text("PVP-Modus inaktiv: ", NamedTextColor.GREEN) .append(Component.text("Es gelten die normalen Regeln!", NamedTextColor.GOLD)); - case VOLUNTARILY, FORCED -> Component.text("Vogelfreistatus aktiv: ", NamedTextColor.RED) + case VOLUNTARILY, FORCED -> Component.text("PVP-Modus aktiv: ", NamedTextColor.RED) .append(Component.text( - "Du darfst von allen anderen vogelfreien Spielern angegriffen und getötet werden!" + - "Wenn du getötet wirst, müssen andere Spieler deine Items nicht zurückerstatten!", + "Du darfst von allen anderen PVP-Spielern angegriffen und getötet werden!\n" + + "Wenn du getötet wirst, müssen andere Spieler deine Items *nicht* zurückerstatten!", NamedTextColor.GOLD )); }; @@ -143,7 +143,7 @@ public class Outlawed extends Appliance implements DisplayName.Prefixed { if(this.isOutlawed(player)) { return Component.text("[☠]", NamedTextColor.RED) .hoverEvent(HoverEvent.showText(Component.text( - "Vogelfreie Spieler dürfen von anderen vogelfreien Spielern ohne Grund angegriffen werden!" + "PVP-Modus Spieler dürfen von anderen vogelfreien Spielern ohne Grund angegriffen werden!" ))); } diff --git a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/outlawed/OutlawedCommand.java b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/outlawed/OutlawedCommand.java index 7af40cd..5c0980c 100644 --- a/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/outlawed/OutlawedCommand.java +++ b/craftattack/src/main/java/eu/mhsl/craftattack/spawn/craftattack/appliances/gameplay/outlawed/OutlawedCommand.java @@ -8,7 +8,7 @@ import org.bukkit.command.CommandSender; import org.jetbrains.annotations.NotNull; class OutlawedCommand extends ApplianceCommand.PlayerChecked { - public static final String commandName = "vogelfrei"; + public static final String commandName = "pvp"; public OutlawedCommand() { super(commandName);