Compare commits

...
Author SHA1 Message Date
Hut512 9e0314472b Disable FML2 handler 2026-09-08 12:36:04 +02:00
YoyoNow 6209b86149 Fix TeamCommand.info 2026-09-07 14:03:06 +02:00
YoyoNow 6f1403df9c Cleanup SWPlayer 2026-09-05 14:52:59 +02:00
YoyoNow 0113788da2 Fix SteamEditWand 2026-09-05 09:50:47 +02:00
YoyoNow 8a7f65e000 Merge pull request 'Fix CRIU subserver stop' (#485) from Hut512/SteamWar:main into main
Reviewed-on: SteamWar/SteamWar#485
Reviewed-by: YoyoNow <4+yoyonow@noreply.localhost>
2026-09-03 21:39:15 +02:00
Hut512 8401f67b24 Fix CRIU subserver stop 2026-09-03 02:24:49 +02:00
YoyoNow 362468e756 Fix SteamEditWand 2026-09-01 11:14:30 +02:00
YoyoNow ece12df0bc Add SteamEdit 2026-09-01 10:32:56 +02:00
YoyoNow f35c07ab5b Fix EventStarter 2026-08-30 16:12:32 +02:00
YoyoNow 549f7e555c Remove NoTeamServer punishment 2026-08-30 13:04:52 +02:00
YoyoNow 859238d7fa Disable 'showtable' in EventCommand 2026-08-30 12:25:34 +02:00
YoyoNow a79b00f78f Fix EventCommand 2026-08-30 12:23:23 +02:00
YoyoNow 105eda32e6 Update CustomMap 2026-08-30 12:15:22 +02:00
YoyoNow b4487b8079 Update doc comment 2026-08-30 12:00:40 +02:00
YoyoNow ea3aad3bd2 Initial FightSWCommand 2026-08-29 12:52:09 +02:00
54 changed files with 1031 additions and 505 deletions
@@ -32,6 +32,7 @@ import de.steamwar.bausystem.features.tracer.TraceManager;
import de.steamwar.bausystem.features.tracer.TraceRecorder; import de.steamwar.bausystem.features.tracer.TraceRecorder;
import de.steamwar.bausystem.features.world.BauScoreboard; import de.steamwar.bausystem.features.world.BauScoreboard;
import de.steamwar.bausystem.linkage.BauGuiItem; import de.steamwar.bausystem.linkage.BauGuiItem;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.region.RegionSystem; import de.steamwar.bausystem.region.RegionSystem;
import de.steamwar.bausystem.utils.ScoreboardElement; import de.steamwar.bausystem.utils.ScoreboardElement;
import de.steamwar.bausystem.utils.TickManager; import de.steamwar.bausystem.utils.TickManager;
@@ -40,8 +41,9 @@ import de.steamwar.command.AbstractValidator;
import de.steamwar.command.SWCommandUtils; import de.steamwar.command.SWCommandUtils;
import de.steamwar.core.CRIUSleepEvent; import de.steamwar.core.CRIUSleepEvent;
import de.steamwar.core.Core; import de.steamwar.core.Core;
import de.steamwar.core.WorldEditRendererCUIEditor;
import de.steamwar.core.WorldIdentifier; import de.steamwar.core.WorldIdentifier;
import de.steamwar.core.worldedit.SteamEdit;
import de.steamwar.core.worldedit.WorldEditRendererCUIEditor;
import de.steamwar.linkage.AbstractLinker; import de.steamwar.linkage.AbstractLinker;
import de.steamwar.linkage.SpigotLinker; import de.steamwar.linkage.SpigotLinker;
import de.steamwar.message.Message; import de.steamwar.message.Message;
@@ -49,6 +51,7 @@ import de.steamwar.providers.BauServerInfo;
import lombok.Getter; import lombok.Getter;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.GameRule; import org.bukkit.GameRule;
import org.bukkit.Location;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
@@ -129,7 +132,19 @@ public class BauSystem extends JavaPlugin implements Listener {
TraceManager.instance.init(); TraceManager.instance.init();
TraceRecorder.instance.init(); TraceRecorder.instance.init();
new WorldEditRendererCUIEditor(); SteamEdit.init();
SteamEdit.ADJACENT_FILTERS = location -> {
Region region = Region.getRegion(location);
Region.Area area;
if (region.getBuildArea().inRegion(location, true)) {
area = region.getBuildArea();
} else if (region.getTestblockArea().inRegion(location, true)) {
area = region.getTestblockArea();
} else {
return SteamEdit.AdjacentFilter.ALWAYS;
}
return (x, y, z) -> area.inRegion(new Location(null, x, y, z), true);
};
Bukkit.getWorlds().get(0).setGameRule(GameRule.SEND_COMMAND_FEEDBACK, false); Bukkit.getWorlds().get(0).setGameRule(GameRule.SEND_COMMAND_FEEDBACK, false);
@@ -46,7 +46,7 @@ public class ObserverTracerListener implements Listener {
public ObserverTracerListener() { public ObserverTracerListener() {
Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> { Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> {
SWPlayer.allWithSingleComponent(ObserverTracer.class).forEach(pair -> { SWPlayer.allWithSingleComponent(ObserverTracer.class).forEach(pair -> {
if (pair.getPlayer().getGameMode() != GameMode.SPECTATOR) return; if (pair.getSwPlayer().getPlayer().getGameMode() != GameMode.SPECTATOR) return;
pair.getComponent().show(); pair.getComponent().show();
}); });
}, 15L, 15L); }, 15L, 15L);
@@ -53,7 +53,7 @@ public class NoClipCommand extends SWCommand implements Listener {
@Override @Override
public void onUnmount(SWPlayer player) { public void onUnmount(SWPlayer player) {
player.setGameMode(GameMode.CREATIVE); player.getPlayer().setGameMode(GameMode.CREATIVE);
} }
} }
@@ -797,7 +797,7 @@ public final class GameModeConfig<M, W> {
/** /**
* Resolves one {@code Materials} entry to the concrete materials it denotes: {@code storage} * Resolves one {@code Materials} entry to the concrete materials it denotes: {@code storage}
* for {@link SQLWrapper#getStorageMaterials()}, {@code all} for * for {@link SQLWrapper#getStorageMaterials()}, {@code inventory} for
* {@link SQLWrapper#getInventoryMaterials()}, or the material itself otherwise. * {@link SQLWrapper#getInventoryMaterials()}, or the material itself otherwise.
*/ */
private Set<M> expandInventoryGroup(YMLWrapper<M, ?> loader, String name) { private Set<M> expandInventoryGroup(YMLWrapper<M, ?> loader, String name) {
@@ -183,14 +183,6 @@ class Punishment(id: EntityID<Int>) : IntEntity(id) {
"UNNOFIGHTSERVER", "UNNOFIGHTSERVER",
UserPerm.MODERATION UserPerm.MODERATION
), ),
NoTeamServer(
"NOTEAMSERVER_TEAM",
"NOTEAMSERVER_PERMA",
"NOTEAMSERVER_UNTIL",
"UNNOTEAMSERVER_ERROR",
"UNNOTEAMSERVER",
UserPerm.MODERATION
),
Note("NOTE_TEAM", null, null, null, null, UserPerm.PUNISHMENTS, true); Note("NOTE_TEAM", null, null, null, null, UserPerm.PUNISHMENTS, true);
fun isMulti() = fun isMulti() =
@@ -39,6 +39,7 @@ public enum ArenaMode {
public static final Set<ArenaMode> Test = Collections.unmodifiableSet(EnumSet.of(TEST, CHECK)); public static final Set<ArenaMode> Test = Collections.unmodifiableSet(EnumSet.of(TEST, CHECK));
public static final Set<ArenaMode> Prepare = Collections.unmodifiableSet(EnumSet.of(PREPARE)); public static final Set<ArenaMode> Prepare = Collections.unmodifiableSet(EnumSet.of(PREPARE));
public static final Set<ArenaMode> Replay = Collections.unmodifiableSet(EnumSet.of(REPLAY, TEST)); public static final Set<ArenaMode> Replay = Collections.unmodifiableSet(EnumSet.of(REPLAY, TEST));
public static final Set<ArenaMode> TestOrReferee = Collections.unmodifiableSet(EnumSet.of(TEST, CHECK, EVENT));
public static final Set<ArenaMode> AntiReplay = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(REPLAY))); public static final Set<ArenaMode> AntiReplay = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(REPLAY)));
public static final Set<ArenaMode> AntiTest = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(TEST, CHECK))); public static final Set<ArenaMode> AntiTest = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.of(TEST, CHECK)));
@@ -21,8 +21,8 @@ package de.steamwar.fightsystem;
import com.comphenix.tinyprotocol.TinyProtocol; import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.core.Core; import de.steamwar.core.Core;
import de.steamwar.core.WorldEditRendererCUIEditor; import de.steamwar.core.worldedit.SteamEdit;
import de.steamwar.fightsystem.commands.TechareaCommand; import de.steamwar.core.worldedit.WorldEditRendererCUIEditor;
import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.fightsystem.listener.ClickAnalyzer; import de.steamwar.fightsystem.listener.ClickAnalyzer;
@@ -108,7 +108,7 @@ public class FightSystem extends JavaPlugin {
} }
}); });
new OneShotStateDependent(ArenaMode.All, FightState.PreSchemSetup, () -> Fight.playSound(SWSound.BLOCK_NOTE_PLING.getSound(), 100.0f, 2.0f)); new OneShotStateDependent(ArenaMode.All, FightState.PreSchemSetup, () -> Fight.playSound(SWSound.BLOCK_NOTE_PLING.getSound(), 100.0f, 2.0f));
new OneShotStateDependent(ArenaMode.Test, FightState.All, WorldEditRendererCUIEditor::new); new OneShotStateDependent(ArenaMode.Test, FightState.All, SteamEdit::init);
Config.world.setGameRule(GameRule.REDUCED_DEBUG_INFO, ArenaMode.AntiTest.contains(Config.mode)); Config.world.setGameRule(GameRule.REDUCED_DEBUG_INFO, ArenaMode.AntiTest.contains(Config.mode));
hullHider = new HullHider(); hullHider = new HullHider();
@@ -127,8 +127,6 @@ public class FightSystem extends JavaPlugin {
if (checkSchematicNode.isPrepared()) { if (checkSchematicNode.isPrepared()) {
Fight.getRedTeam().setSchem(checkSchematicNode, NodeData.getRevisions(checkSchematicNode) - 1); Fight.getRedTeam().setSchem(checkSchematicNode, NodeData.getRevisions(checkSchematicNode) - 1);
} }
new TechareaCommand();
} else if (Config.mode == ArenaMode.PREPARE) { } else if (Config.mode == ArenaMode.PREPARE) {
Fight.getUnrotated().setSchem(SchematicNode.getSchematicNode(Config.PrepareSchemID)); Fight.getUnrotated().setSchem(SchematicNode.getSchematicNode(Config.PrepareSchemID));
} }
@@ -24,35 +24,25 @@ import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.fight.Kit; import de.steamwar.fightsystem.fight.Kit;
import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentCommand;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm; import de.steamwar.sql.UserPerm;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@Linked @Linked
public class AkCommand implements CommandExecutor { public class AkCommand extends FightSWCommand {
public AkCommand() { public AkCommand() {
new StateDependentCommand(ArenaMode.Test, FightState.All, "ak", this); super(ArenaMode.Test, FightState.All, "ak");
} }
@Override @Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { protected boolean hasPerm(Player player, SteamwarUser user) {
if (!(sender instanceof Player)) { return player.isOp() && user.hasPerm(UserPerm.ADMINISTRATION) && Core.getInstance() != FightSystem.getPlugin();
return false;
}
Player player = (Player) sender;
if (!player.isOp()) return false;
if (!SteamwarUser.get(player.getUniqueId()).hasPerm(UserPerm.ADMINISTRATION) && Core.getInstance() != FightSystem.getPlugin()) {
return false;
} }
Kit.createKit(args[0], player); @Register
return false; public void run(@Validator Player player, String name) {
Kit.createKit(name, player);
} }
} }
@@ -0,0 +1,95 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2026 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.commands;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeValidator;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependent;
import de.steamwar.sql.SteamwarUser;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerCommandSendEvent;
import java.util.Set;
public abstract class FightSWCommand extends SWCommand implements Listener {
private final String command;
private final String[] aliases;
protected FightSWCommand(Set<ArenaMode> mode, Set<FightState> states, String command) {
super(command);
this.command = command;
this.aliases = new String[0];
stateDependant(mode, states);
}
protected FightSWCommand(Set<ArenaMode> mode, Set<FightState> states, String command, String... aliases) {
super(command, aliases);
this.command = command;
this.aliases = aliases;
stateDependant(mode, states);
}
private void stateDependant(Set<ArenaMode> mode, Set<FightState> states) {
FightSWCommand.this.unregister();
new StateDependent(mode, states) {
@Override
public void enable() {
System.out.println("--- Enable: " + command);
FightSWCommand.this.register();
}
@Override
public void disable() {
System.out.println("--- Disable: " + command);
FightSWCommand.this.unregister();
}
}.register();
}
public static void postFightStateChange() {
for (Player player : Bukkit.getOnlinePlayers()) {
player.updateCommands();
}
}
protected boolean hasPerm(Player player, SteamwarUser user) {
return true;
}
@EventHandler(ignoreCancelled = true)
public final void onPlayerCommandSend(PlayerCommandSendEvent event) {
if (hasPerm(event.getPlayer(), SteamwarUser.get(event.getPlayer().getUniqueId()))) return;
event.getCommands().remove(command);
for (String alias : aliases) {
event.getCommands().remove(alias);
}
}
@ClassValidator(value = Player.class, local = true)
public final TypeValidator<Player> permissionCheck() {
return (sender, value, messageSender) -> hasPerm(value, SteamwarUser.get(value.getUniqueId()));
}
}
@@ -19,92 +19,28 @@
package de.steamwar.fightsystem.commands; package de.steamwar.fightsystem.commands;
import com.google.common.collect.ImmutableList; import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.states.FightState;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import net.md_5.bungee.api.ChatMessageType; import de.steamwar.sql.SteamwarUser;
import org.bukkit.Bukkit;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.defaults.BukkitCommand;
import org.bukkit.craftbukkit.CraftServer;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.util.StringUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Linked @Linked
public class GamemodeCommand extends BukkitCommand { public class GamemodeCommand extends FightSWCommand {
private static final List<String> GAMEMODE_NAMES = ImmutableList.of("adventure", "creative", "survival",
"spectator");
public GamemodeCommand() { public GamemodeCommand() {
super("gamemode"); super(ArenaMode.TestOrReferee, FightState.All, "gamemode", "gm");
List<String> aliases = new ArrayList<>();
aliases.add("gm");
this.setAliases(aliases);
Map<String, Command> knownCommands = ((CraftServer) Bukkit.getServer()).getCommandMap().getKnownCommands();
knownCommands.remove("gamemode");
Commands.injectCommand(this);
} }
@Override @Override
public boolean execute(CommandSender sender, String currentAlias, String[] args) { protected boolean hasPerm(Player player, SteamwarUser user) {
if (!(sender instanceof Player)) { return Config.test() || Config.isReferee(player);
return false;
} else if (args.length == 0) {
FightSystem.getMessage().sendPrefixless("GAMEMODE_HELP", sender);
return false;
} }
Player p = (Player) sender; @Register(description = "GAMEMODE_HELP")
public void execute(@Validator Player player, GameMode gameMode) {
if (!(Config.test() || Config.isReferee(p))) { player.setGameMode(gameMode);
FightSystem.getMessage().sendPrefixless("GAMEMODE_NOT_ALLOWED", p, ChatMessageType.ACTION_BAR);
return false;
}
GameMode mode = createMode(args[0]);
if (mode == null) {
FightSystem.getMessage().sendPrefixless("GAMEMODE_UNKNOWN", p, ChatMessageType.ACTION_BAR, args[0]);
return false;
}
p.setGameMode(mode);
return true;
}
@SuppressWarnings("deprecation")
private GameMode createMode(String modeArg) {
try {
return GameMode.getByValue(Integer.parseInt(modeArg));
} catch (NumberFormatException ignored) {
if ((modeArg.equalsIgnoreCase("creative")) || (modeArg.equalsIgnoreCase("c"))) {
return GameMode.CREATIVE;
} else if ((modeArg.equalsIgnoreCase("adventure")) || (modeArg.equalsIgnoreCase("a"))) {
return GameMode.ADVENTURE;
} else if ((modeArg.equalsIgnoreCase("spectator")) || (modeArg.equalsIgnoreCase("sp"))) {
return GameMode.SPECTATOR;
} else if ((modeArg.equalsIgnoreCase("survival")) || (modeArg.equalsIgnoreCase("s"))) {
return GameMode.SURVIVAL;
} }
} }
return null;
}
@Override
public List<String> tabComplete(CommandSender sender, String alias, String[] args) {
if (args.length == 1) {
return StringUtil.copyPartialMatches(args[0], GAMEMODE_NAMES, new ArrayList<>(GAMEMODE_NAMES.size()));
}
return ImmutableList.of();
}
}
@@ -20,34 +20,31 @@
package de.steamwar.fightsystem.commands; package de.steamwar.fightsystem.commands;
import de.steamwar.fightsystem.ArenaMode; import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.fightsystem.listener.Check;
import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentCommand;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@Linked @Linked
public class InfoCommand implements CommandExecutor { public class InfoCommand extends FightSWCommand {
public InfoCommand() { public InfoCommand() {
new StateDependentCommand(ArenaMode.All, FightState.All, "fightinfo", this); super(ArenaMode.All, FightState.All, "fightinfo");
} }
@Override @Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { protected boolean hasPerm(Player player, SteamwarUser user) {
if (!(sender instanceof Player)) return false; return Check.checkPermission(user, Config.GameModeConfig);
}
Player player = (Player) sender;
if (!SteamwarUser.get(player.getUniqueId()).hasPerm(UserPerm.CHECK)) return false;
@Register
public void run(@Validator Player player) {
for (FightTeam team : Fight.teams()) { for (FightTeam team : Fight.teams()) {
if (!team.isLeaderless()) { if (!team.isLeaderless()) {
FightSystem.getMessage().send("INFO_LEADER", player, team.getColoredName(), team.getLeader().getEntity().getName()); FightSystem.getMessage().send("INFO_LEADER", player, team.getColoredName(), team.getLeader().getEntity().getName());
@@ -58,6 +55,5 @@ public class InfoCommand implements CommandExecutor {
FightSystem.getMessage().send("INFO_SCHEMATIC", player, team.getColoredName(), schematic.getName(), SteamwarUser.byId(schematic.getOwner()).getUserName(), schematic.getRank()); FightSystem.getMessage().send("INFO_SCHEMATIC", player, team.getColoredName(), schematic.getName(), SteamwarUser.byId(schematic.getOwner()).getUserName(), schematic.getRank());
} }
} }
return false;
} }
} }
@@ -21,32 +21,23 @@ package de.steamwar.fightsystem.commands;
import de.steamwar.fightsystem.ArenaMode; import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentCommand;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@Linked @Linked
public class KitCommand implements CommandExecutor { public class KitCommand extends FightSWCommand {
public KitCommand() { public KitCommand() {
new StateDependentCommand(ArenaMode.AntiReplay, FightState.Setup, "kit", this); super(ArenaMode.AntiReplay, FightState.Setup, "kit");
} }
@Override @Register
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { public void execute(Player player) {
if (!(sender instanceof Player)) {
return false;
}
Player player = (Player) sender;
if (args.length != 1) {
GUI.kitSelection(player, ""); GUI.kitSelection(player, "");
} else {
Commands.kit(player, args[0]);
} }
return false;
@Register
public void execute(Player player, String query) { // TODO: TabCompletion of Kit Names!
GUI.kitSelection(player, query);
} }
} }
@@ -21,28 +21,18 @@ package de.steamwar.fightsystem.commands;
import de.steamwar.fightsystem.ArenaMode; import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentCommand;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@Linked @Linked
public class LeaveCommand implements CommandExecutor { public class LeaveCommand extends FightSWCommand {
public LeaveCommand() { public LeaveCommand() {
new StateDependentCommand(ArenaMode.AntiReplay, FightState.Setup, "leave", this); super(ArenaMode.AntiReplay, FightState.Setup, "leave");
} }
@Override @Register
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { public void execute(Player player) {
if (!(sender instanceof Player)) {
return false;
}
Player player = (Player) sender;
Commands.leaveTeam(player); Commands.leaveTeam(player);
return false;
} }
} }
@@ -20,52 +20,42 @@
package de.steamwar.fightsystem.commands; package de.steamwar.fightsystem.commands;
import de.steamwar.fightsystem.ArenaMode; import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.fightsystem.listener.Check;
import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentCommand;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import de.steamwar.sql.SchematicNode; import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SchematicType; import de.steamwar.sql.SchematicType;
import de.steamwar.sql.SteamwarUser; import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm;
import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.ChatMessageType;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@Linked @Linked
public class LockschemCommand implements CommandExecutor { public class LockschemCommand extends FightSWCommand {
public LockschemCommand() { public LockschemCommand() {
new StateDependentCommand(ArenaMode.All, FightState.Schem, "lockschem", this); super(ArenaMode.All, FightState.Schem, "lockschem");
} }
@Override @Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { protected boolean hasPerm(Player player, SteamwarUser user) {
if (!(sender instanceof Player)) return false; return Check.checkPermission(user, Config.GameModeConfig);
Player player = (Player) sender;
if (!SteamwarUser.get(player.getUniqueId()).hasPerm(UserPerm.CHECK)) return false;
if (args.length != 1) {
FightSystem.getMessage().sendPrefixless("LOCKSCHEM_HELP", player);
return false;
} }
String teamName = args[0]; @Register(description = "LOCKSCHEM_HELP")
public void execute(@Validator Player player, String teamName) {
FightTeam fightTeam = Fight.getTeamByName(teamName); FightTeam fightTeam = Fight.getTeamByName(teamName);
if (fightTeam == null) { if (fightTeam == null) {
FightSystem.getMessage().sendPrefixless("UNKNOWN_TEAM", player, ChatMessageType.ACTION_BAR); FightSystem.getMessage().sendPrefixless("UNKNOWN_TEAM", player, ChatMessageType.ACTION_BAR);
return false; return;
} }
SchematicNode.getSchematicNode(fightTeam.getSchematic()).setSchemtype(SchematicType.Normal); SchematicNode.getSchematicNode(fightTeam.getSchematic()).setSchemtype(SchematicType.Normal);
FightSystem.getMessage().sendPrefixless("LOCKSCHEM_LOCKED", player, ChatMessageType.ACTION_BAR); FightSystem.getMessage().sendPrefixless("LOCKSCHEM_LOCKED", player, ChatMessageType.ACTION_BAR);
fightTeam.broadcastSystem("LOCKSCHEM_LOCKED_BY", player.getName()); fightTeam.broadcastSystem("LOCKSCHEM_LOCKED_BY", player.getName());
return false;
} }
} }
@@ -21,28 +21,18 @@ package de.steamwar.fightsystem.commands;
import de.steamwar.fightsystem.ArenaMode; import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentCommand;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@Linked @Linked
public class ReadyCommand implements CommandExecutor { public class ReadyCommand extends FightSWCommand {
public ReadyCommand() { public ReadyCommand() {
new StateDependentCommand(ArenaMode.AntiPrepare, FightState.PostSchemSetup, "ready", this); super(ArenaMode.AntiPrepare, FightState.PostSchemSetup, "ready");
} }
@Override @Register
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { public void execute(Player player) {
if (!(sender instanceof Player)) {
return false;
}
Player player = (Player) sender;
Commands.toggleReady(player); Commands.toggleReady(player);
return false;
} }
} }
@@ -20,35 +20,19 @@
package de.steamwar.fightsystem.commands; package de.steamwar.fightsystem.commands;
import de.steamwar.fightsystem.ArenaMode; import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentCommand;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@Linked @Linked
public class RemoveCommand implements CommandExecutor { public class RemoveCommand extends FightSWCommand {
public RemoveCommand() { public RemoveCommand() {
new StateDependentCommand(ArenaMode.VariableTeams, FightState.Setup, "remove", this); super(ArenaMode.VariableTeams, FightState.Setup, "remove");
} }
@Override @Register(description = "REMOVE_HELP")
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { public void execute(Player player, Player teamMember) {
if (!(sender instanceof Player)) { Commands.kick(player, teamMember.getName());
return false;
}
Player player = (Player) sender;
if (args.length != 1) {
FightSystem.getMessage().sendPrefixless("REMOVE_HELP", player);
return false;
}
Commands.kick(player, args[0]);
return false;
} }
} }
@@ -26,37 +26,28 @@ import de.steamwar.fightsystem.fight.FightPlayer;
import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.fightsystem.fight.JoinRequest; import de.steamwar.fightsystem.fight.JoinRequest;
import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentCommand;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
@Linked @Linked
public class RequestsCommand implements CommandExecutor { public class RequestsCommand extends FightSWCommand {
public RequestsCommand() { public RequestsCommand() {
new StateDependentCommand(ArenaMode.VariableTeams, FightState.AntiSpectate, "request", this); super(ArenaMode.VariableTeams, FightState.AntiSpectate, "request", "requests");
new StateDependentCommand(ArenaMode.VariableTeams, FightState.AntiSpectate, "requests", this);
} }
@Override @Register
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { public void execute(Player player) {
if (!(sender instanceof Player)) return false;
Player player = (Player) sender;
FightPlayer fp = Fight.getFightPlayer(player); FightPlayer fp = Fight.getFightPlayer(player);
if (fp == null || !(fp.isLeader() || fp.isLiving())) { if (fp == null || !(fp.isLeader() || fp.isLiving())) {
GUI.joinRequest(player); GUI.joinRequest(player);
return false; return;
} }
if (Commands.checkGetLeader(player) == null) return false; if (Commands.checkGetLeader(player) == null) return;
GUI.chooseJoinRequests(player); GUI.chooseJoinRequests(player);
return false;
} }
public static void onJoinRequest(Player player, JoinRequest request, BiConsumer<JoinRequest, FightTeam> handleJoinRequest) { public static void onJoinRequest(Player player, JoinRequest request, BiConsumer<JoinRequest, FightTeam> handleJoinRequest) {
@@ -24,32 +24,22 @@ import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.record.PacketProcessor; import de.steamwar.fightsystem.record.PacketProcessor;
import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentCommand;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@Linked @Linked
public class SkipCommand implements CommandExecutor { public class SkipCommand extends FightSWCommand {
public SkipCommand() { public SkipCommand() {
new StateDependentCommand(ArenaMode.AntiPrepare, ArenaMode.Replay.contains(Config.mode) ? FightState.All : FightState.TeamFix, "skip", this); super(ArenaMode.AntiPrepare, ArenaMode.Replay.contains(Config.mode) ? FightState.All : FightState.TeamFix, "skip");
} }
@Override @Register
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { public void execute(Player player) {
if (!(sender instanceof Player)) {
return false;
}
Player player = (Player) sender;
if (PacketProcessor.isReplaying() && player.getUniqueId().equals(Fight.getBlueTeam().getDesignatedLeader())) { if (PacketProcessor.isReplaying() && player.getUniqueId().equals(Fight.getBlueTeam().getDesignatedLeader())) {
PacketProcessor.currentReplay().skipToSubtitle(); PacketProcessor.currentReplay().skipToSubtitle();
} else { } else {
Commands.toggleSkip(player); Commands.toggleSkip(player);
} }
return false;
} }
} }
@@ -21,27 +21,18 @@ package de.steamwar.fightsystem.commands;
import de.steamwar.fightsystem.ArenaMode; import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentCommand;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@Linked @Linked
public class StateCommand implements CommandExecutor { public class StateCommand extends FightSWCommand {
public StateCommand() { public StateCommand() {
new StateDependentCommand(ArenaMode.Test, FightState.All, "state", this); super(ArenaMode.Test, FightState.All, "state");
} }
@Override @Register
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { public void execute(Player player) {
if (!(sender instanceof Player)) { GUI.state(player);
return false;
}
GUI.state((Player) sender);
return false;
} }
} }
@@ -22,26 +22,18 @@ package de.steamwar.fightsystem.commands;
import de.steamwar.fightsystem.ArenaMode; import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentCommand;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@Linked @Linked
public class TBCommand implements CommandExecutor { public class TBCommand extends FightSWCommand {
public TBCommand() { public TBCommand() {
new StateDependentCommand(ArenaMode.Check, FightState.All, "resettb", this); super(ArenaMode.Check, FightState.All, "resettb");
} }
@Override @Register
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { public void execute(Player player) {
if (!(sender instanceof Player)) {
return false;
}
Fight.getRedTeam().pasteSchem(); Fight.getRedTeam().pasteSchem();
return false;
} }
} }
@@ -20,34 +20,20 @@ package de.steamwar.fightsystem.commands;
import de.steamwar.fightsystem.ArenaMode; import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentCommand;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import org.bukkit.command.Command; import org.bukkit.entity.Player;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
@Linked @Linked
public class TPSWarpCommand implements CommandExecutor { public class TPSWarpCommand extends FightSWCommand {
public TPSWarpCommand() { public TPSWarpCommand() {
new StateDependentCommand(ArenaMode.Prepare, FightState.PostSchemSetup, "tpswarp", this); super(ArenaMode.Prepare, FightState.PostSchemSetup, "tpswarp", "tpslimit");
new StateDependentCommand(ArenaMode.Prepare, FightState.PostSchemSetup, "tpslimit", this);
}
@Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
float tps;
try {
tps = Float.parseFloat(args[0]);
} catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
FightSystem.getMessage().send("TPSWARP_HELP", sender);
return false;
} }
@Register(description = "TPSWARP_HELP")
public void execute(Player player, float tps) {
MinecraftServer.getServer().tickRateManager().setTickRate(tps); MinecraftServer.getServer().tickRateManager().setTickRate(tps);
FightSystem.getMessage().broadcastActionbar("TPSWARP_SET", tps); FightSystem.getMessage().broadcastActionbar("TPSWARP_SET", tps);
return false;
} }
} }
@@ -19,42 +19,39 @@
package de.steamwar.fightsystem.commands; package de.steamwar.fightsystem.commands;
import de.steamwar.command.SWCommand;
import de.steamwar.entity.CWireframe; import de.steamwar.entity.CWireframe;
import de.steamwar.entity.REntityServer; import de.steamwar.entity.REntityServer;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.states.FightState;
import org.bukkit.Bukkit; import de.steamwar.fightsystem.states.OneShotStateDependent;
import de.steamwar.linkage.Linked;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.HashMap; @Linked
import java.util.Map; public class TechareaCommand extends FightSWCommand {
import java.util.UUID; private REntityServer entityServer = new REntityServer();
public class TechareaCommand extends SWCommand {
private final Map<UUID, REntityServer> servers = new HashMap<>();
public TechareaCommand() { public TechareaCommand() {
super("techarea"); super(ArenaMode.Check, FightState.All, "techarea");
new OneShotStateDependent(ArenaMode.Check, FightState.All, () -> {
Bukkit.getScheduler().runTaskTimer(FightSystem.getPlugin(), () -> servers.forEach((uuid, rEntityServer) -> rEntityServer.tick()), 2, 2); if (!entityServer.getEntities().isEmpty()) return;
}
@Register
public void genericCommand(Player player) {
if (servers.containsKey(player.getUniqueId())) {
servers.get(player.getUniqueId()).close();
} else {
REntityServer server = new REntityServer(); REntityServer server = new REntityServer();
CWireframe wireframe = new CWireframe(server); CWireframe wireframe = new CWireframe(server);
wireframe.setPos1(Config.BlueInsetRegion.getMinLocation(Config.world)); wireframe.setPos1(Config.BlueInsetRegion.getMinLocation(Config.world));
wireframe.setPos2(Config.BlueInsetRegion.getMaxLocation(Config.world).subtract(1, 1, 1)); wireframe.setPos2(Config.BlueInsetRegion.getMaxLocation(Config.world).subtract(1, 1, 1));
wireframe.setBlock(Material.RED_CONCRETE.createBlockData()); wireframe.setBlock(Material.RED_CONCRETE.createBlockData());
});
}
server.addPlayer(player); @Register
servers.put(player.getUniqueId(), server); public void genericCommand(Player player) {
if (entityServer.getPlayers().contains(player)) {
entityServer.removePlayer(player);
} else {
entityServer.addPlayer(player);
} }
} }
} }
@@ -25,27 +25,24 @@ import de.steamwar.fightsystem.Config;
import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentCommand;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import de.steamwar.sql.SWException; import de.steamwar.sql.SWException;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.Command; import org.bukkit.entity.Player;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.Arrays; import java.util.Arrays;
import java.util.logging.Level; import java.util.logging.Level;
@Linked @Linked
public class TechhiderbugCommand implements CommandExecutor { public class TechhiderbugCommand extends FightSWCommand {
public TechhiderbugCommand() { public TechhiderbugCommand() {
new StateDependentCommand(ArenaMode.All, FightState.All, "techhiderbug", this); super(ArenaMode.All, FightState.All, "techhiderbug");
} }
@Override @Register
public boolean onCommand(CommandSender sender, Command cmd, String alias, String[] args) { public void execute(Player player, String... args) {
StringWriter writer = new StringWriter(); StringWriter writer = new StringWriter();
try { try {
@@ -76,7 +73,6 @@ public class TechhiderbugCommand implements CommandExecutor {
Bukkit.getLogger().log(Level.SEVERE, "Error while generating bug report", e); Bukkit.getLogger().log(Level.SEVERE, "Error while generating bug report", e);
} }
SWException.log("Techhider-Bug reported by " + sender.getName() + ": " + Arrays.toString(args), writer.toString()); SWException.log("Techhider-Bug reported by " + player.getName() + ": " + Arrays.toString(args), writer.toString());
return false;
} }
} }
@@ -23,28 +23,20 @@ import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.fight.FightWorld; import de.steamwar.fightsystem.fight.FightWorld;
import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentCommand;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@Linked @Linked
public class WGCommand implements CommandExecutor { public class WGCommand extends FightSWCommand {
public WGCommand() { public WGCommand() {
new StateDependentCommand(ArenaMode.Check, FightState.All, "resetwg", this); super(ArenaMode.Check, FightState.All, "resetwg");
} }
@Override @Register
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { public void execute(Player player) {
if (!(sender instanceof Player)) {
return false;
}
FightWorld.resetWorld(); FightWorld.resetWorld();
Fight.getBlueTeam().pasteSchem(); Fight.getBlueTeam().pasteSchem();
Fight.getRedTeam().pasteSchem(); Fight.getRedTeam().pasteSchem();
return false;
} }
} }
@@ -25,49 +25,34 @@ import de.steamwar.fightsystem.FightSystem;
import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.fight.Fight;
import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.fight.FightTeam;
import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.FightState;
import de.steamwar.fightsystem.states.StateDependentCommand;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import net.md_5.bungee.api.ChatMessageType; import de.steamwar.sql.SteamwarUser;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@Linked @Linked
public class WinCommand implements CommandExecutor { public class WinCommand extends FightSWCommand {
public WinCommand() { public WinCommand() {
new StateDependentCommand(ArenaMode.Event, FightState.Ingame, "win", this); super(ArenaMode.Event, FightState.Ingame, "win");
} }
@Override @Override
public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { protected boolean hasPerm(Player player, SteamwarUser user) {
if (!(sender instanceof Player)) { return Config.isReferee(player);
return false;
}
Player p = (Player) sender;
if (!Config.isReferee(p)) {
FightSystem.getMessage().sendPrefixless("NOT_FIGHTLEADER", p, ChatMessageType.ACTION_BAR);
return false;
} }
if (args.length == 0) { @Register
FightSystem.getMessage().sendPrefixless("WIN_HELP", p); public void execute(@Validator Player player, String teamName) {
return false; if (teamName.equalsIgnoreCase("tie")) {
}
if (args[0].equalsIgnoreCase("tie")) {
FightSystem.setSpectateState(null, "Referee", "WIN_FIGHTLEADER"); FightSystem.setSpectateState(null, "Referee", "WIN_FIGHTLEADER");
return false; return;
} }
for (FightTeam team : Fight.teams()) { for (FightTeam team : Fight.teams()) {
if (args[0].equalsIgnoreCase(team.getName())) { if (teamName.equalsIgnoreCase(team.getName())) {
FightSystem.setSpectateState(team, "Referee", "WIN_FIGHTLEADER"); FightSystem.setSpectateState(team, "Referee", "WIN_FIGHTLEADER");
return false; return;
} }
} }
return false;
} }
} }
@@ -51,6 +51,10 @@ public class Check implements Listener {
.findFirst() .findFirst()
.orElse(null); .orElse(null);
if (gameModeConfig == null) gameModeConfig = GameModeConfig.getDefaults(); if (gameModeConfig == null) gameModeConfig = GameModeConfig.getDefaults();
return checkPermission(user, gameModeConfig);
}
public static boolean checkPermission(SteamwarUser user, GameModeConfig gameModeConfig) {
if (user.hasPerm(UserPerm.ADMINISTRATION)) return true; if (user.hasPerm(UserPerm.ADMINISTRATION)) return true;
if (gameModeConfig.Checkers.isEmpty() && user.hasPerm(UserPerm.CHECK)) return true; if (gameModeConfig.Checkers.isEmpty() && user.hasPerm(UserPerm.CHECK)) return true;
return gameModeConfig.Checkers.contains(user.getId()); return gameModeConfig.Checkers.contains(user.getId());
@@ -20,7 +20,7 @@
package de.steamwar.fightsystem.record; package de.steamwar.fightsystem.record;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import de.steamwar.core.WorldEditWrapper; import de.steamwar.core.worldedit.WorldEditWrapper;
import de.steamwar.entity.REntity; import de.steamwar.entity.REntity;
import de.steamwar.entity.REntityServer; import de.steamwar.entity.REntityServer;
import de.steamwar.entity.RPlayer; import de.steamwar.entity.RPlayer;
@@ -19,6 +19,7 @@
package de.steamwar.fightsystem.states; package de.steamwar.fightsystem.states;
import de.steamwar.fightsystem.commands.FightSWCommand;
import lombok.Getter; import lombok.Getter;
import java.util.*; import java.util.*;
@@ -62,6 +63,7 @@ public enum FightState {
} }
public static void setFightState(FightState state) { public static void setFightState(FightState state) {
if (fightState.equals(state)) return;
fightState = state; fightState = state;
for (Map.Entry<IStateDependent, Boolean> feature : stateDependentFeatures.entrySet()) { for (Map.Entry<IStateDependent, Boolean> feature : stateDependentFeatures.entrySet()) {
@@ -77,6 +79,7 @@ public enum FightState {
feature.setValue(false); feature.setValue(false);
} }
} }
FightSWCommand.postFightStateChange();
} }
public static boolean setup() { public static boolean setup() {
@@ -1,58 +0,0 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2025 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.fightsystem.states;
import de.steamwar.fightsystem.ArenaMode;
import de.steamwar.fightsystem.FightSystem;
import net.md_5.bungee.api.ChatMessageType;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.PluginCommand;
import java.util.Set;
public class StateDependentCommand extends StateDependent {
private static final CommandExecutor unavailable = (sender, cmd, s, strings) -> {
FightSystem.getMessage().sendPrefixless("COMMAND_CURRENTLY_UNAVAILABLE", sender, ChatMessageType.ACTION_BAR);
return false;
};
private final PluginCommand command;
private final CommandExecutor executor;
public StateDependentCommand(Set<ArenaMode> mode, Set<FightState> states, String name, CommandExecutor executor) {
super(mode, states);
this.executor = executor;
this.command = FightSystem.getPlugin().getCommand(name);
assert command != null;
disable();
register();
}
@Override
public void enable() {
command.setExecutor(executor);
}
@Override
public void disable() {
command.setExecutor(unavailable);
}
}
@@ -11,21 +11,3 @@ depend:
api-version: "1.13" api-version: "1.13"
commands: commands:
ak:
request:
requests:
fightinfo:
leave:
ready:
kit:
remove:
lockschem:
state:
skip:
win:
resetwg:
resettb:
tpslimit:
tpswarp:
techhiderbug:
unrank:
+12
View File
@@ -53,3 +53,15 @@ tasks.register<FightServer>("WarGear21") {
config = "WarGear21.yml" config = "WarGear21.yml"
jar = "/jars/paper-1.21.6.jar" jar = "/jars/paper-1.21.6.jar"
} }
tasks.register<FightServer>("WarShip21") {
group = "run"
description = "Run a WarShip 1.21 Fight Server"
dependsOn(":SpigotCore:shadowJar")
dependsOn(":FightSystem:shadowJar")
dependsOn(":KotlinCore:shadowJar")
template = "WarShip21"
worldName = "arenas/Artic"
config = "WarShip21.yml"
jar = "/jars/paper-1.21.6.jar"
}
@@ -80,9 +80,12 @@ public class CustomMap implements Listener {
if (mapFileOrDirectory.isDirectory()) { if (mapFileOrDirectory.isDirectory()) {
AtomicReference<Month> lastMonth = new AtomicReference<>(LocalDateTime.now().getMonth()); AtomicReference<Month> lastMonth = new AtomicReference<>(LocalDateTime.now().getMonth());
AtomicReference<Long> lastModified = new AtomicReference<>(Long.MAX_VALUE);
Bukkit.getScheduler().runTaskTimer(LobbySystem.getInstance(), () -> { Bukkit.getScheduler().runTaskTimer(LobbySystem.getInstance(), () -> {
long modified = mapFileOrDirectory.lastModified();
Month current = LocalDateTime.now().getMonth(); Month current = LocalDateTime.now().getMonth();
if (!current.equals(lastMonth.get()) || update) { if (modified > lastModified.get() || !current.equals(lastMonth.get()) || update) {
lastModified.set(modified);
lastMonth.set(current); lastMonth.set(current);
update = false; update = false;
this.mapFile = new File(mapFileOrDirectory, current.getValue() + ".png"); this.mapFile = new File(mapFileOrDirectory, current.getValue() + ".png");
@@ -108,19 +108,33 @@ UNNOSCHEMSUBMITTING = §e{0} §7may now submit §e§lschematics§7 again§8.
WORLDEDIT_CUI_TITLE = WorldEdit CUI WORLDEDIT_CUI_TITLE = WorldEdit CUI
WORLDEDIT_CUI_TITLE_SUBMENU = WorldEdit CUI - {0} WORLDEDIT_CUI_TITLE_SUBMENU = WorldEdit CUI - {0}
WORLDEDIT_CUI_SELECTION = Own Selection WORLDEDIT_CUI_SELECTION = Selection
WORLDEDIT_CUI_CLIPBOARD = Own Clipboard WORLDEDIT_CUI_CLIPBOARD = Clipboard
WORLDEDIT_CUI_SELECTION_OTHER = Other Selection WORLDEDIT_CUI_CURSOR = Cursor
WORLDEDIT_CUI_CLIPBOARD_OTHER = Other Clipboard
WORLDEDIT_CUI_MATERIAL_NAME = §eWorldEdit {0} WORLDEDIT_CUI_MATERIAL_NAME = §eWorldEdit {0}
WORLDEDIT_CUI_MATERIAL_CLICK = §7Click to edit WORLDEDIT_CUI_MATERIAL_CLICK = §7Click to edit
WORLDEDIT_CUI_WIDTH_NAME = §eWidth {0} WORLDEDIT_CUI_WIDTH_NAME = §eWidth {0}
WORLDEDIT_CUI_WIDTH_NAME_DIST = §eRange {0}
WORLDEDIT_CUI_WIDTH_LORE = §8> §7{0} WORLDEDIT_CUI_WIDTH_LORE = §8> §7{0}
WORLDEDIT_CUI_WIDTH_LORE_SELECTED = §8> §e{0} WORLDEDIT_CUI_WIDTH_LORE_SELECTED = §8> §e{0}
WORLDEDIT_CUI_WIDTH_CLICK = §7Click to change WORLDEDIT_CUI_WIDTH_CLICK = §7Click to change
WORLDEDIT_CUI_WIDTH_HUGE = 1/ 8 Block WORLDEDIT_CUI_WIDTH_HUGE = 1/ 8 Block
WORLDEDIT_CUI_WIDTH_LARGE = 1/16 Block WORLDEDIT_CUI_WIDTH_LARGE = 1/16 Block
WORLDEDIT_CUI_WIDTH_MEDIUM = 1/32 Block WORLDEDIT_CUI_WIDTH_MEDIUM = 1/32 Block
WORLDEDIT_CUI_WIDTH_SLIM = 1/64 Block WORLDEDIT_CUI_WIDTH_SLIM = 1/64 Block
WORLDEDIT_CUI_WIDTH_HUGE_DIST = 40 Blocks
WORLDEDIT_CUI_WIDTH_LARGE_DIST = 30 Blocks
WORLDEDIT_CUI_WIDTH_MEDIUM_DIST = 20 Blocks
WORLDEDIT_CUI_WIDTH_SLIM_DIST = 10 Blocks
WORLDEDIT_CUI_TOOL_SOON = §7Tool cooming soon!
WORLDEDIT_CUI_TOOL_COPY = §eCopy Tool
WORLDEDIT_CUI_TOOL_COPY_LORE = §eClick§8:§7 copy selection
WORLDEDIT_CUI_TOOL_PASTE = §ePaste Tool
WORLDEDIT_CUI_TOOL_PASTE_LORE_1 = §eClick§8:§7 paste clipboard
WORLDEDIT_CUI_TOOL_PASTE_LORE_2 = §eShift §8+§e Click§8:§7 paste clipboard and select
WORLDEDIT_CUI_TOOL_PASTE_LORE_3 = §eDrop§8:§7 paste clipboard at copy origin
@@ -101,13 +101,20 @@ NOSCHEMSUBMITTING_UNTIL = §7Du bist §ebis zum {0} §7vom §e§lEinsenden von S
UNNOSCHEMSUBMITTING_ERROR = §cDer Spieler ist nicht vom Einsenden von Schematics ausgeschlossen. UNNOSCHEMSUBMITTING_ERROR = §cDer Spieler ist nicht vom Einsenden von Schematics ausgeschlossen.
UNNOSCHEMSUBMITTING = §e{0} §7darf nun wieder §e§lSchematis§7 einsenden§8. UNNOSCHEMSUBMITTING = §e{0} §7darf nun wieder §e§lSchematis§7 einsenden§8.
WORLDEDIT_CUI_SELECTION = Eigene Auswahl WORLDEDIT_CUI_SELECTION = Auswahl
WORLDEDIT_CUI_CLIPBOARD = Eigene Kopie WORLDEDIT_CUI_CLIPBOARD = Kopie
WORLDEDIT_CUI_SELECTION_OTHER = Auswahl Anderer
WORLDEDIT_CUI_CLIPBOARD_OTHER = Kopie Anderer
WORLDEDIT_CUI_MATERIAL_NAME = §eWorldEdit {0} WORLDEDIT_CUI_MATERIAL_NAME = §eWorldEdit {0}
WORLDEDIT_CUI_MATERIAL_CLICK = §7Klicke zum Editieren WORLDEDIT_CUI_MATERIAL_CLICK = §7Klicke zum Editieren
WORLDEDIT_CUI_WIDTH_NAME = §eDicke - {0} WORLDEDIT_CUI_WIDTH_NAME = §eKlicke - {0}
WORLDEDIT_CUI_WIDTH_NAME_DIST = Reichweite§e {0}
WORLDEDIT_CUI_WIDTH_CLICK = §7Klicke zum ändern WORLDEDIT_CUI_WIDTH_CLICK = §7Klicke zum ändern
WORLDEDIT_CUI_TOOL_SOON = §7Werkzeug kommt in kürze!
WORLDEDIT_CUI_TOOL_COPY = §eCopy Werkzeug
WORLDEDIT_CUI_TOOL_COPY_LORE = §eKlick§8:§7 Auswahl zu kopieren
WORLDEDIT_CUI_TOOL_PASTE = §ePaste Werkzeug
WORLDEDIT_CUI_TOOL_PASTE_LORE_1 = §eKlick§8:§7 Clipboard einzufügen
WORLDEDIT_CUI_TOOL_PASTE_LORE_2 = §eUmschalt §8+§e Klick§8:§7 Clipboard einzufügen und auszuwählen
WORLDEDIT_CUI_TOOL_PASTE_LORE_3 = §eDrop§8:§7 Clipboard am Kopierpunkt einzufügen
@@ -21,8 +21,8 @@ package de.steamwar.core;
import de.steamwar.message.Message; import de.steamwar.message.Message;
import lombok.Data; import lombok.Data;
import lombok.Getter;
import lombok.NonNull; import lombok.NonNull;
import lombok.experimental.Delegate;
import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.ClickEvent;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@@ -99,11 +99,11 @@ public class SWPlayer {
@Data @Data
public static final class SWPlayerWithComponent<T extends Component> { public static final class SWPlayerWithComponent<T extends Component> {
private final SWPlayer player; private final SWPlayer swPlayer;
private final T component; private final T component;
} }
@Delegate @Getter
private final Player player; private final Player player;
private final Map<Class<? extends Component>, Component> components = new HashMap<>(); private final Map<Class<? extends Component>, Component> components = new HashMap<>();
@@ -0,0 +1,73 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2026 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.core.worldedit;
import de.steamwar.command.SWCommand;
import lombok.experimental.UtilityClass;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Function;
@UtilityClass
public class SteamEdit {
private static final AtomicBoolean INITIALIZED = new AtomicBoolean();
public static void init() {
INITIALIZED.set(true);
new Command();
new SteamEditWand();
new WorldEditRendererCUIEditor();
}
public boolean isInitialized() {
return INITIALIZED.get();
}
public static Function<Location, AdjacentFilter> ADJACENT_FILTERS = location -> AdjacentFilter.ALWAYS;
public interface AdjacentFilter {
AdjacentFilter ALWAYS = (x, y, z) -> true;
boolean contains(int x, int y, int z);
}
private static final class Command extends SWCommand {
public Command() {
super("steamwand", "steamedit", "steameditwand", "swwand", "sweditwand", "swedit");
}
@Register
public void get(Player player) {
if (player.getInventory().contains(SteamEditWand.ITEM)) {
player.getInventory().remove(SteamEditWand.ITEM);
}
ItemStack handItem = player.getInventory().getItemInMainHand();
player.getInventory().setItemInMainHand(SteamEditWand.ITEM);
if (!handItem.isEmpty()) {
player.getInventory().addItem(handItem);
}
}
}
}
@@ -0,0 +1,117 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2026 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.core.worldedit;
import com.sk89q.worldedit.math.BlockVector3;
import de.steamwar.core.Core;
import org.bukkit.Location;
import org.bukkit.block.BlockFace;
import org.bukkit.util.Vector;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.stream.Stream;
public class SteamEditSelectAdjacent {
private static final BlockFace[] FACES = {
BlockFace.NORTH,
BlockFace.SOUTH,
BlockFace.EAST,
BlockFace.WEST,
BlockFace.UP,
BlockFace.DOWN,
};
private Location min;
private Location max;
private SteamEdit.AdjacentFilter filter;
private LinkedHashSet<Location> frontier = new LinkedHashSet<>();
public SteamEditSelectAdjacent(Location origin) {
// TODO: Fix the flood fill algorithm!
min = origin.clone();
max = origin.clone();
frontier.add(origin);
filter = SteamEdit.ADJACENT_FILTERS.apply(origin);
long time = System.currentTimeMillis();
for (int i = 0; i < 500_000 && !frontier.isEmpty(); i++) {
if (System.currentTimeMillis() - time > 1000) break;
expandNext();
}
Core.getInstance().getLogger().finer(System.currentTimeMillis() - time + "ms " + frontier.size() + " " + min + " to " + max);
}
public BlockVector3 pos1() {
return BlockVector3.at(min.getBlockX(), min.getBlockY(), min.getBlockZ());
}
public BlockVector3 pos2() {
return BlockVector3.at(max.getBlockX(), max.getBlockY(), max.getBlockZ());
}
private boolean inside(Location loc, int offset) {
return loc.getBlockX() >= min.getBlockX() + offset && loc.getBlockX() <= max.getBlockX() - offset &&
loc.getBlockY() >= min.getBlockY() + offset && loc.getBlockY() <= max.getBlockY() - offset &&
loc.getBlockZ() >= min.getBlockZ() + offset && loc.getBlockZ() <= max.getBlockZ() - offset;
}
public void expandNext() {
Location location = frontier.removeFirst();
expand(location);
}
private void expand(Location loc) {
for (BlockFace face : FACES) {
Vector direction = face.getDirection();
Location location = loc.clone().add(direction);
if (!filter.contains(location.getBlockX(), location.getBlockY(), location.getBlockZ())) continue;
if (inside(location, 0)) continue;
List<Location> layer = Stream.concat(selectFrontier(direction.getBlockX() == 0 ? null : loc.getBlockX(), direction.getBlockY() == 0 ? null : loc.getBlockY(), direction.getBlockZ() == 0 ? null : loc.getBlockZ())
.map(Location::clone)
.map(l -> l.add(direction)), Stream.of(location))
.filter(l -> !l.getBlock().isEmpty())
.filter(l -> !l.getBlock().isLiquid())
.toList();
if (layer.isEmpty()) continue;
if (direction.getBlockX() < 0 || direction.getBlockY() < 0 || direction.getBlockZ() < 0) {
min.add(direction);
} else {
max.add(direction);
}
layer.stream().filter(l -> !inside(l, 1))
.filter(l -> filter.contains(l.getBlockX(), l.getBlockY(), l.getBlockZ()))
.forEach(frontier::add);
}
}
private Stream<Location> selectFrontier(Integer x, Integer y, Integer z) {
Stream<Location> stream = frontier.stream();
if (x != null) stream = stream.filter(loc -> loc.getBlockX() == x);
if (y != null) stream = stream.filter(loc -> loc.getBlockY() == y);
if (z != null) stream = stream.filter(loc -> loc.getBlockZ() == z);
return stream;
}
}
@@ -0,0 +1,409 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2026 SteamWar.de-Serverteam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package de.steamwar.core.worldedit;
import com.comphenix.tinyprotocol.TinyProtocol;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.limit.PermissiveSelectorLimits;
import com.sk89q.worldedit.world.World;
import de.steamwar.core.Core;
import de.steamwar.core.SWPlayer;
import de.steamwar.entity.CWireframe;
import de.steamwar.entity.REntityServer;
import de.steamwar.inventory.SWItem;
import net.minecraft.core.BlockPos;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.*;
import org.bukkit.Bukkit;
import org.bukkit.FluidCollisionMode;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.scheduler.BukkitTask;
import org.bukkit.util.RayTraceResult;
import java.util.List;
public class SteamEditWand implements Listener {
public static final Material MATERIAL = Material.GOLDEN_AXE;
public static final String NAME = "§eSteam§8Edit §7Wand";
public static final String[] LORE = {
"§eL-Click§8: §7Set Pos1",
"§eR-Click§8: §7Set Pos2",
"§eShift §8+ §eR-Click§8: §7Set Pos2 or Expand Selection",
"§eM-Click§8: §7Select connected",
"§eSwap-Hands§8: §7Open CUI"
};
public static final ItemStack ITEM = new SWItem(MATERIAL, NAME).setLore(LORE).getItemStack();
private boolean noWand(Player player) {
return player.getInventory().getItemInMainHand().getType() != SteamEditWand.MATERIAL;
}
private final WorldEditPlugin we;
SteamEditWand() {
we = WorldEditWrapper.getWorldEditPlugin();
Bukkit.getPluginManager().registerEvents(this, Core.getInstance());
TinyProtocol.instance.addFilter(ServerboundSwingPacket.class, this::leftClick);
TinyProtocol.instance.addFilter(ServerboundInteractPacket.class, (player, packet) -> {
if (packet.isAttack()) {
return leftClick(player, packet);
} else {
return rightClick(player, packet);
}
});
TinyProtocol.instance.addFilter(ServerboundUseItemPacket.class, this::rightClick);
TinyProtocol.instance.addFilter(ServerboundUseItemOnPacket.class, this::rightClick);
TinyProtocol.instance.addFilter(ServerboundPickItemFromBlockPacket.class, this::middleClick);
TinyProtocol.instance.addFilter(ServerboundPlayerActionPacket.class, this::swapHands);
TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.Pos.class, this::movePlayerPacket);
TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.Rot.class, this::movePlayerPacket);
TinyProtocol.instance.addFilter(ServerboundMovePlayerPacket.PosRot.class, this::movePlayerPacket);
Bukkit.getScheduler().runTaskTimer(Core.getInstance(), () -> {
for (Player player : Bukkit.getOnlinePlayers()) {
if (noWand(player)) SWPlayer.of(player).removeComponent(SWEditCursor.class);
}
}, 1, 1);
}
@EventHandler
public void onPlayerInteract(PlayerInteractEvent event) {
if (noWand(event.getPlayer())) return;
event.setCancelled(true);
}
public static class SWEditCursor implements SWPlayer.Component {
private Player player;
private REntityServer entityServer = new REntityServer();
private CWireframe wireframe;
@Override
public void onMount(SWPlayer player) {
this.player = player.getPlayer();
entityServer.addPlayer(player.getPlayer());
wireframe = new CWireframe(entityServer);
}
@Override
public void onUnmount(SWPlayer player) {
entityServer.close();
}
public void setLocation(Location location) {
wireframe.setPos1And2(location, location);
wireframe.setBlock(WorldEditRendererCUIEditor.Type.CURSOR.getMaterial(player).createBlockData());
}
}
private Packet<?> leftClick(Player player, Packet<?> packet) {
if (noWand(player)) return packet;
if (player.getOpenInventory().getType() != InventoryType.CREATIVE) return packet;
double distance = WorldEditRendererCUIEditor.Type.CURSOR.getWidth(player).blocks;
RayTraceResult result = player.rayTraceBlocks(distance, FluidCollisionMode.NEVER);
if (result == null) return packet;
Block block = result.getHitBlock();
if (block == null) return packet;
BlockVector3 pos1 = BlockVector3.at(block.getX(), block.getY(), block.getZ());
setPos1(player, pos1);
return null;
}
private void setPos1(Player player, BlockVector3 pos1) {
LocalSession session = we.getSession(player);
World world = session.getSelectionWorld();
if (world == null) return;
selectPos1(session.getRegionSelector(world), player, session, pos1);
}
private Packet<?> rightClick(Player player, Packet<?> packet) {
if (noWand(player)) return packet;
double distance = WorldEditRendererCUIEditor.Type.CURSOR.getWidth(player).blocks;
RayTraceResult result = player.rayTraceBlocks(distance, FluidCollisionMode.NEVER);
if (result == null) return packet;
Block block = result.getHitBlock();
if (block == null) return packet;
BlockVector3 pos2 = BlockVector3.at(block.getX(), block.getY(), block.getZ());
if (!player.isSneaking()) {
setPos2(player, pos2);
} else {
setPos2OrExpand(player, pos2);
}
return null;
}
private void setPos2(Player player, BlockVector3 pos2) {
LocalSession session = we.getSession(player);
World world = session.getSelectionWorld();
if (world == null) return;
selectPos2(session.getRegionSelector(world), player, session, pos2);
}
private void setPos2OrExpand(Player player, BlockVector3 expand) {
LocalSession session = we.getSession(player);
World world = session.getSelectionWorld();
if (world == null) return;
RegionSelector regionSelector = session.getRegionSelector(world);
// Only primary set for now
if (!regionSelector.isDefined()) {
selectPos2(session.getRegionSelector(world), player, session, expand);
return;
}
List<BlockVector3> vertices = regionSelector.getVertices();
// Probably not a cuboid selection!
if (vertices.size() > 2) {
selectPos2(session.getRegionSelector(world), player, session, expand);
return;
}
BlockVector3 pos1 = vertices.get(0);
BlockVector3 pos2 = vertices.get(1);
BlockVector3 min = pos1.getMinimum(pos2);
BlockVector3 max = pos1.getMaximum(pos2);
if (expand.containedWithin(pos1, pos2)) {
return;
}
Closer x = Closer.UNKNOWN;
Closer y = Closer.UNKNOWN;
Closer z = Closer.UNKNOWN;
boolean insideX = min.x() < expand.x() && max.x() > expand.x();
boolean insideY = min.y() < expand.y() && max.y() > expand.y();
boolean insideZ = min.z() < expand.z() && max.z() > expand.z();
if (insideX) {
// No Change needed
} else if (Math.abs(pos1.x() - expand.x()) > Math.abs(pos2.x() - expand.x())) {
x = Closer.POS2;
} else if (Math.abs(pos1.x() - expand.x()) < Math.abs(pos2.x() - expand.x())) {
x = Closer.POS1;
}
if (insideY) {
// No Change needed
} else if (Math.abs(pos1.y() - expand.y()) > Math.abs(pos2.y() - expand.y())) {
y = Closer.POS2;
} else if (Math.abs(pos1.y() - expand.y()) < Math.abs(pos2.y() - expand.y())) {
y = Closer.POS1;
}
if (insideZ) {
// No Change needed
} else if (Math.abs(pos1.z() - expand.z()) > Math.abs(pos2.z() - expand.z())) {
z = Closer.POS2;
} else if (Math.abs(pos1.z() - expand.z()) < Math.abs(pos2.z() - expand.z())) {
z = Closer.POS1;
}
Closer x1 = Closer.UNKNOWN;
Closer y1 = Closer.UNKNOWN;
Closer z1 = Closer.UNKNOWN;
if (!insideX && pos1.x() != expand.x() && pos2.x() != expand.x() && x == Closer.UNKNOWN) {
x1 = y.and(z).or(Closer.POS1);
}
if (!insideY && pos1.y() != expand.y() && pos2.y() != expand.y() && y == Closer.UNKNOWN) {
y1 = x.and(z).or(Closer.POS1);
}
if (!insideZ && pos1.z() != expand.z() && pos2.z() != expand.z() && z == Closer.UNKNOWN) {
z1 = x.and(y).or(Closer.POS1);
}
if (x1 != Closer.UNKNOWN) x = x1;
if (y1 != Closer.UNKNOWN) y = y1;
if (z1 != Closer.UNKNOWN) z = z1;
boolean p1updated = false;
boolean p2updated = false;
if (x == Closer.POS1) {
pos1 = pos1.withX(expand.x());
p1updated = true;
} else if (x == Closer.POS2) {
pos2 = pos2.withX(expand.x());
p2updated = true;
}
if (y == Closer.POS1) {
pos1 = pos1.withY(expand.y());
p1updated = true;
} else if (y == Closer.POS2) {
pos2 = pos2.withY(expand.y());
p2updated = true;
}
if (z == Closer.POS1) {
pos1 = pos1.withZ(expand.z());
p1updated = true;
} else if (z == Closer.POS2) {
pos2 = pos2.withZ(expand.z());
p2updated = true;
}
if (p1updated) selectPos1(session.getRegionSelector(world), player, session, pos1);
if (p2updated) selectPos2(session.getRegionSelector(world), player, session, pos2);
}
private enum Closer {
POS1,
POS2,
UNKNOWN,
;
public Closer and(Closer closer) {
if (this == closer) {
return this;
} else if (this == UNKNOWN) {
return closer;
} else if (closer == UNKNOWN) {
return this;
} else {
return UNKNOWN;
}
}
public Closer or(Closer closer) {
if (this == UNKNOWN) return closer;
return this;
}
}
private ServerboundPickItemFromBlockPacket middleClick(Player player, ServerboundPickItemFromBlockPacket packet) {
if (noWand(player)) return packet;
LocalSession session = we.getSession(player);
World world = session.getSelectionWorld();
if (world == null) return packet;
RegionSelector regionSelector = session.getRegionSelector(world);
BlockPos pos = packet.pos();
SteamEditSelectAdjacent selector = new SteamEditSelectAdjacent(new Location(player.getWorld(), pos.getX(), pos.getY(), pos.getZ()));
selectPos1(regionSelector, player, session, selector.pos1());
selectPos2(regionSelector, player, session, selector.pos2());
return null;
}
private static class Pos1Message implements SWPlayer.Component {
private BukkitTask task;
public Pos1Message(RegionSelector regionSelector, Player player, LocalSession session, BlockVector3 pos1) {
task = Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> {
regionSelector.explainPrimarySelection(BukkitAdapter.adapt(player), session, pos1);
SWPlayer.of(player).removeComponent(Pos1Message.class);
}, 1);
}
@Override
public void onUnmount(SWPlayer player) {
task.cancel();
}
}
private void selectPos1(RegionSelector regionSelector, Player player, LocalSession session, BlockVector3 pos1) {
try {
if (!pos1.equals(regionSelector.getPrimaryPosition())) {
SWPlayer.of(player).setComponent(new Pos1Message(regionSelector, player, session, pos1));
}
} catch (IncompleteRegionException e) {
SWPlayer.of(player).setComponent(new Pos1Message(regionSelector, player, session, pos1));
}
regionSelector.selectPrimary(pos1, PermissiveSelectorLimits.getInstance());
WorldEditRenderer.renderPlayer(player);
}
private static class Pos2Message implements SWPlayer.Component {
private BukkitTask task;
public Pos2Message(RegionSelector regionSelector, Player player, LocalSession session, BlockVector3 pos2) {
task = Bukkit.getScheduler().runTaskLater(Core.getInstance(), () -> {
regionSelector.explainSecondarySelection(BukkitAdapter.adapt(player), session, pos2);
SWPlayer.of(player).removeComponent(Pos1Message.class);
}, 1);
}
@Override
public void onUnmount(SWPlayer player) {
task.cancel();
}
}
private void selectPos2(RegionSelector regionSelector, Player player, LocalSession session, BlockVector3 pos2) {
try {
if (regionSelector.getVertices().size() == 2 && !pos2.equals(regionSelector.getVertices().get(1))) {
SWPlayer.of(player).setComponent(new Pos2Message(regionSelector, player, session, pos2));
}
} catch (IncompleteRegionException e) {
SWPlayer.of(player).setComponent(new Pos2Message(regionSelector, player, session, pos2));
}
regionSelector.selectSecondary(pos2, PermissiveSelectorLimits.getInstance());
WorldEditRenderer.renderPlayer(player);
}
private ServerboundPlayerActionPacket swapHands(Player player, ServerboundPlayerActionPacket packet) {
if (noWand(player)) return packet;
if (packet.getAction() != ServerboundPlayerActionPacket.Action.SWAP_ITEM_WITH_OFFHAND) return packet;
Bukkit.getScheduler().runTask(Core.getInstance(), () -> {
WorldEditRendererCUIEditor.open(player, true);
});
return null;
}
public ServerboundMovePlayerPacket movePlayerPacket(Player player, ServerboundMovePlayerPacket packet) {
SWPlayer swPlayer = SWPlayer.of(player);
if (noWand(player)) {
swPlayer.removeComponent(SWEditCursor.class);
return packet;
}
double distance = WorldEditRendererCUIEditor.Type.CURSOR.getWidth(player).blocks;
RayTraceResult result = player.rayTraceBlocks(distance, FluidCollisionMode.NEVER);
Block block = result == null ? null : result.getHitBlock();
if (result == null || block == null) {
swPlayer.removeComponent(SWEditCursor.class);
return packet;
}
if (!swPlayer.hasComponent(SWEditCursor.class)) {
swPlayer.setComponent(new SWEditCursor());
}
swPlayer.getComponent(SWEditCursor.class).ifPresent(cursor -> {
cursor.setLocation(block.getLocation());
});
return packet;
}
}
@@ -1,7 +1,7 @@
/* /*
* This file is a part of the SteamWar software. * This file is a part of the SteamWar software.
* *
* Copyright (C) 2025 SteamWar.de-Serverteam * Copyright (C) 2026 SteamWar.de-Serverteam
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by * it under the terms of the GNU Affero General Public License as published by
@@ -17,7 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.steamwar.core; package de.steamwar.core.worldedit;
import com.sk89q.worldedit.EmptyClipboardException; import com.sk89q.worldedit.EmptyClipboardException;
import com.sk89q.worldedit.IncompleteRegionException; import com.sk89q.worldedit.IncompleteRegionException;
@@ -28,6 +28,7 @@ import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.world.World; import com.sk89q.worldedit.world.World;
import de.steamwar.core.Core;
import de.steamwar.linkage.Linked; import de.steamwar.linkage.Linked;
import de.steamwar.linkage.PluginCheck; import de.steamwar.linkage.PluginCheck;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@@ -39,13 +40,15 @@ import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.player.*; import org.bukkit.event.player.*;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import java.util.Set;
@Linked @Linked
@PluginCheck("FastAsyncWorldEdit") @PluginCheck("FastAsyncWorldEdit")
public class WorldEditRenderer implements Listener { public class WorldEditRenderer implements Listener {
private static WorldEditRenderer INSTANCE; private static WorldEditRenderer INSTANCE;
private static final Material WAND = Material.WOODEN_AXE; private static final Set<Material> WANDS = Set.of(Material.WOODEN_AXE, SteamEditWand.MATERIAL);
private final WorldEditPlugin we; private final WorldEditPlugin we;
@@ -102,7 +105,7 @@ public class WorldEditRenderer implements Listener {
private void drawCuboid(Vector min, Vector max, boolean scheduled, boolean clipboard, Player owner) { private void drawCuboid(Vector min, Vector max, boolean scheduled, boolean clipboard, Player owner) {
//noinspection deprecation //noinspection deprecation
if (owner.getItemInHand().getType() != WAND) { if (!WANDS.contains(owner.getItemInHand().getType())) {
WorldEditRendererWrapper.impl.hide(owner, true, true); WorldEditRendererWrapper.impl.hide(owner, true, true);
WorldEditRendererWrapper.impl.hide(owner, false, true); WorldEditRendererWrapper.impl.hide(owner, false, true);
} else { } else {
@@ -114,7 +117,8 @@ public class WorldEditRenderer implements Listener {
@EventHandler @EventHandler
public void onPlayerMove(PlayerMoveEvent event) { public void onPlayerMove(PlayerMoveEvent event) {
if (event.getPlayer().getItemInHand().getType() == WAND) { //noinspection deprecation
if (WANDS.contains(event.getPlayer().getItemInHand().getType())) {
WorldEditRendererWrapper.impl.tick(event.getPlayer()); WorldEditRendererWrapper.impl.tick(event.getPlayer());
} }
renderClipboard(event.getPlayer(), we.getSession(event.getPlayer()), false); renderClipboard(event.getPlayer(), we.getSession(event.getPlayer()), false);
@@ -1,7 +1,7 @@
/* /*
* This file is a part of the SteamWar software. * This file is a part of the SteamWar software.
* *
* Copyright (C) 2025 SteamWar.de-Serverteam * Copyright (C) 2026 SteamWar.de-Serverteam
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by * it under the terms of the GNU Affero General Public License as published by
@@ -17,9 +17,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.steamwar.core; package de.steamwar.core.worldedit;
import de.steamwar.command.SWCommand; import de.steamwar.command.SWCommand;
import de.steamwar.core.CRIUSleepEvent;
import de.steamwar.core.Core;
import de.steamwar.inventory.SWInventory; import de.steamwar.inventory.SWInventory;
import de.steamwar.inventory.SWItem; import de.steamwar.inventory.SWItem;
import de.steamwar.sql.UserConfig; import de.steamwar.sql.UserConfig;
@@ -30,6 +32,7 @@ import org.bukkit.block.data.type.Light;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.meta.BlockDataMeta; import org.bukkit.inventory.meta.BlockDataMeta;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
@@ -59,6 +62,7 @@ public class WorldEditRendererCUIEditor implements Listener {
public enum Type { public enum Type {
SELECTION("cui_selection_material", "cui_selection_width", Material.PURPLE_CONCRETE, Width.MEDIUM), SELECTION("cui_selection_material", "cui_selection_width", Material.PURPLE_CONCRETE, Width.MEDIUM),
CLIPBOARD("cui_clipboard_material", "cui_clipboard_width", Material.LIME_CONCRETE, Width.SLIM), CLIPBOARD("cui_clipboard_material", "cui_clipboard_width", Material.LIME_CONCRETE, Width.SLIM),
CURSOR("cui_cursor_material", "cui_cursor_range", Material.RED_CONCRETE, Width.SLIM),
; ;
private final Map<Player, Material> materialCache = new HashMap<>(); private final Map<Player, Material> materialCache = new HashMap<>();
@@ -104,19 +108,27 @@ public class WorldEditRendererCUIEditor implements Listener {
@AllArgsConstructor @AllArgsConstructor
public enum Width { public enum Width {
HUGE(15, "WORLDEDIT_CUI_WIDTH_HUGE", 2 / 16f), HUGE(15, "WORLDEDIT_CUI_WIDTH_HUGE", 1 / 8f, 40),
LARGE(8, "WORLDEDIT_CUI_WIDTH_LARGE", 1 / 16f), LARGE(8, "WORLDEDIT_CUI_WIDTH_LARGE", 1 / 16f, 30),
MEDIUM(4, "WORLDEDIT_CUI_WIDTH_MEDIUM", 1 / 32f), MEDIUM(4, "WORLDEDIT_CUI_WIDTH_MEDIUM", 1 / 32f, 20),
SLIM(0, "WORLDEDIT_CUI_WIDTH_SLIM", 1 / 64f); SLIM(0, "WORLDEDIT_CUI_WIDTH_SLIM", 1 / 64f, 10);
public final int lightLevel; public final int lightLevel;
public final String name; public final String name;
public final float value; public final float width;
public final int blocks;
} }
private static Command command = null;
public WorldEditRendererCUIEditor() { public WorldEditRendererCUIEditor() {
Bukkit.getPluginManager().registerEvents(this, Core.getInstance()); Bukkit.getPluginManager().registerEvents(this, Core.getInstance());
new Command(); command = new Command();
}
public static void open(Player player, boolean steamEditWand) {
if (command == null) return;
command.cuiEditor(player, steamEditWand);
} }
private static class Command extends SWCommand { private static class Command extends SWCommand {
@@ -127,18 +139,44 @@ public class WorldEditRendererCUIEditor implements Listener {
@Register @Register
public void cuiEditor(Player player) { public void cuiEditor(Player player) {
cuiEditor(player, false);
}
public void cuiEditor(Player player, boolean steamEditWand) {
SWInventory inv = new SWInventory(player, 9 * 2, Core.MESSAGE.parse("WORLDEDIT_CUI_TITLE", player)); SWInventory inv = new SWInventory(player, 9 * 2, Core.MESSAGE.parse("WORLDEDIT_CUI_TITLE", player));
setElement(inv, player, 3, "WORLDEDIT_CUI_SELECTION", Type.SELECTION); if (SteamEdit.isInitialized() && steamEditWand) {
setElement(inv, player, 5, "WORLDEDIT_CUI_CLIPBOARD", Type.CLIPBOARD); setElement(inv, player, true, 1, "WORLDEDIT_CUI_SELECTION", Type.SELECTION);
setElement(inv, player, true, 2, "WORLDEDIT_CUI_CLIPBOARD", Type.CLIPBOARD);
setCursor(inv, player, 3, "WORLDEDIT_CUI_CURSOR");
inv.setItem(5, new SWItem(Material.PAPER, "WORLDEDIT_CUI_TOOL_COPY").setLore("WORLDEDIT_CUI_TOOL_COPY_LORE").translate(player, Core.MESSAGE).getItemStack(), click -> {
player.performCommand("/copy");
});
inv.setItem(6, new SWItem(Material.STRUCTURE_VOID, "WORLDEDIT_CUI_TOOL_SOON").translate(player, Core.MESSAGE).getItemStack(), click -> {});
inv.setItem(7, new SWItem(Material.GRASS_BLOCK, "WORLDEDIT_CUI_TOOL_PASTE").setLore("WORLDEDIT_CUI_TOOL_PASTE_LORE_1", "WORLDEDIT_CUI_TOOL_PASTE_LORE_2", "WORLDEDIT_CUI_TOOL_PASTE_LORE_3").translate(player, Core.MESSAGE).getItemStack(), click -> {
if (click == ClickType.DROP) {
player.performCommand("/paste -o");
} else if (click == ClickType.SHIFT_LEFT || click == ClickType.SHIFT_RIGHT) {
player.performCommand("/paste -s");
} else if (click == ClickType.LEFT || click == ClickType.RIGHT) {
player.performCommand("/paste");
}
});
inv.setItem(14, new SWItem(Material.STRUCTURE_VOID, "WORLDEDIT_CUI_TOOL_SOON").translate(player, Core.MESSAGE).getItemStack(), click -> {});
inv.setItem(15, new SWItem(Material.STRUCTURE_VOID, "WORLDEDIT_CUI_TOOL_SOON").translate(player, Core.MESSAGE).getItemStack(), click -> {});
inv.setItem(16, new SWItem(Material.STRUCTURE_VOID, "WORLDEDIT_CUI_TOOL_SOON").translate(player, Core.MESSAGE).getItemStack(), click -> {});
} else {
setElement(inv, player, false, 3, "WORLDEDIT_CUI_SELECTION", Type.SELECTION);
setElement(inv, player, false, 5, "WORLDEDIT_CUI_CLIPBOARD", Type.CLIPBOARD);
}
inv.open(); inv.open();
} }
private void setElement(SWInventory inv, Player player, int index, String uiName, Type type) { private void setElement(SWInventory inv, Player player, boolean steamEditWand, int index, String uiName, Type type) {
Material material = type.getMaterial(player); Material material = type.getMaterial(player);
Width width = type.getWidth(player); Width width = type.getWidth(player);
inv.setItem(index, new SWItem(material, Core.MESSAGE.parse("WORLDEDIT_CUI_MATERIAL_NAME", player, Core.MESSAGE.parse(uiName, player)), Arrays.asList(Core.MESSAGE.parse("WORLDEDIT_CUI_MATERIAL_CLICK", player)), false, click -> { inv.setItem(index, new SWItem(material, Core.MESSAGE.parse("WORLDEDIT_CUI_MATERIAL_NAME", player, Core.MESSAGE.parse(uiName, player)), Arrays.asList(Core.MESSAGE.parse("WORLDEDIT_CUI_MATERIAL_CLICK", player)), false, click -> {
cuiMaterial(player, uiName, type, material); cuiMaterial(player, steamEditWand, uiName, type, material);
})); }));
List<String> lore = new ArrayList<>(); List<String> lore = new ArrayList<>();
@@ -153,7 +191,7 @@ public class WorldEditRendererCUIEditor implements Listener {
} }
SWItem lightItem = new SWItem(Material.LIGHT, Core.MESSAGE.parse("WORLDEDIT_CUI_WIDTH_NAME", player, Core.MESSAGE.parse(uiName, player)), lore, false, click -> { SWItem lightItem = new SWItem(Material.LIGHT, Core.MESSAGE.parse("WORLDEDIT_CUI_WIDTH_NAME", player, Core.MESSAGE.parse(uiName, player)), lore, false, click -> {
type.setWidth(player, Width.values()[(width.ordinal() + 1) % Width.values().length]); type.setWidth(player, Width.values()[(width.ordinal() + 1) % Width.values().length]);
setElement(inv, player, index, uiName, type); setElement(inv, player, steamEditWand, index, uiName, type);
}); });
ItemMeta itemMeta = lightItem.getItemMeta(); ItemMeta itemMeta = lightItem.getItemMeta();
Light light = (Light) Material.LIGHT.createBlockData(); Light light = (Light) Material.LIGHT.createBlockData();
@@ -163,16 +201,41 @@ public class WorldEditRendererCUIEditor implements Listener {
inv.setItem(index + 9, lightItem); inv.setItem(index + 9, lightItem);
} }
private void setCursor(SWInventory inv, Player player, int index, String uiName) {
Material material = Type.CURSOR.getMaterial(player);
Width width = Type.CURSOR.getWidth(player);
inv.setItem(index, new SWItem(material, Core.MESSAGE.parse("WORLDEDIT_CUI_MATERIAL_NAME", player, Core.MESSAGE.parse(uiName, player)), Arrays.asList(Core.MESSAGE.parse("WORLDEDIT_CUI_MATERIAL_CLICK", player)), false, click -> {
cuiMaterial(player, true, uiName, Type.CURSOR, material);
}));
List<String> lore = new ArrayList<>();
lore.add(Core.MESSAGE.parse("WORLDEDIT_CUI_WIDTH_CLICK", player));
lore.add("");
for (Width value : Width.values()) {
if (value == width) {
lore.add(Core.MESSAGE.parse("WORLDEDIT_CUI_WIDTH_LORE_SELECTED", player, Core.MESSAGE.parse(value.name + "_DIST", player)));
} else {
lore.add(Core.MESSAGE.parse("WORLDEDIT_CUI_WIDTH_LORE", player, Core.MESSAGE.parse(value.name + "_DIST", player)));
}
}
SWItem stickItem = new SWItem(Material.STICK, Core.MESSAGE.parse("WORLDEDIT_CUI_WIDTH_NAME_DIST", player, Core.MESSAGE.parse(uiName, player)), lore, false, click -> {
Type.CURSOR.setWidth(player, Width.values()[(width.ordinal() + 1) % Width.values().length]);
setCursor(inv, player, index, uiName);
}).setCustomModelData(1);
inv.setItem(index + 9, stickItem);
}
private final Material[] materials = {Material.WHITE_CONCRETE, Material.LIGHT_GRAY_CONCRETE, Material.GRAY_CONCRETE, Material.BLACK_CONCRETE, Material.BROWN_CONCRETE, Material.RED_CONCRETE, Material.ORANGE_CONCRETE, Material.YELLOW_CONCRETE, Material.LIME_CONCRETE, Material.GREEN_CONCRETE, Material.CYAN_CONCRETE, Material.LIGHT_BLUE_CONCRETE, Material.BLUE_CONCRETE, Material.PURPLE_CONCRETE, Material.MAGENTA_CONCRETE, Material.PINK_CONCRETE, null, Material.BARRIER}; private final Material[] materials = {Material.WHITE_CONCRETE, Material.LIGHT_GRAY_CONCRETE, Material.GRAY_CONCRETE, Material.BLACK_CONCRETE, Material.BROWN_CONCRETE, Material.RED_CONCRETE, Material.ORANGE_CONCRETE, Material.YELLOW_CONCRETE, Material.LIME_CONCRETE, Material.GREEN_CONCRETE, Material.CYAN_CONCRETE, Material.LIGHT_BLUE_CONCRETE, Material.BLUE_CONCRETE, Material.PURPLE_CONCRETE, Material.MAGENTA_CONCRETE, Material.PINK_CONCRETE, null, Material.BARRIER};
private void cuiMaterial(Player player, String subMenu, Type type, Material currentSelection) { private void cuiMaterial(Player player, boolean steamEditWand, String subMenu, Type type, Material currentSelection) {
SWInventory inv = new SWInventory(player, 9 * 2, Core.MESSAGE.parse("WORLDEDIT_CUI_TITLE_SUBMENU", player, Core.MESSAGE.parse(subMenu, player))); SWInventory inv = new SWInventory(player, 9 * 2, Core.MESSAGE.parse("WORLDEDIT_CUI_TITLE_SUBMENU", player, Core.MESSAGE.parse(subMenu, player)));
for (int i = 0; i < materials.length; i++) { for (int i = 0; i < materials.length; i++) {
Material material = materials[i]; Material material = materials[i];
if (material == null) continue; if (material == null) continue;
inv.setItem(i, new SWItem(material, "", Collections.emptyList(), material == currentSelection, click -> { inv.setItem(i, new SWItem(material, "", Collections.emptyList(), material == currentSelection, click -> {
type.setMaterial(player, material); type.setMaterial(player, material);
cuiEditor(player); cuiEditor(player, steamEditWand);
})); }));
} }
inv.open(); inv.open();
@@ -17,7 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.steamwar.core; package de.steamwar.core.worldedit;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Particle; import org.bukkit.Particle;
@@ -1,7 +1,7 @@
/* /*
* This file is a part of the SteamWar software. * This file is a part of the SteamWar software.
* *
* Copyright (C) 2025 SteamWar.de-Serverteam * Copyright (C) 2026 SteamWar.de-Serverteam
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by * it under the terms of the GNU Affero General Public License as published by
@@ -17,8 +17,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.steamwar.core; package de.steamwar.core.worldedit;
import de.steamwar.core.PlayerVersion;
import de.steamwar.entity.CWireframe; import de.steamwar.entity.CWireframe;
import de.steamwar.entity.REntityServer; import de.steamwar.entity.REntityServer;
import org.bukkit.Material; import org.bukkit.Material;
@@ -82,7 +83,7 @@ public class WorldEditRendererWrapper {
}); });
WorldEditRendererCUIEditor.Type type = clipboard ? WorldEditRendererCUIEditor.Type.CLIPBOARD : WorldEditRendererCUIEditor.Type.SELECTION; WorldEditRendererCUIEditor.Type type = clipboard ? WorldEditRendererCUIEditor.Type.CLIPBOARD : WorldEditRendererCUIEditor.Type.SELECTION;
float width = type.getWidth(player).value; float width = type.getWidth(player).width;
Material material = type.getMaterial(player); Material material = type.getMaterial(player);
if (material == Material.BARRIER) { if (material == Material.BARRIER) {
hide(player, clipboard, true); hide(player, clipboard, true);
@@ -1,7 +1,7 @@
/* /*
* This file is a part of the SteamWar software. * This file is a part of the SteamWar software.
* *
* Copyright (C) 2025 SteamWar.de-Serverteam * Copyright (C) 2026 SteamWar.de-Serverteam
* *
* This program is free software: you can redistribute it and/or modify * This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by * it under the terms of the GNU Affero General Public License as published by
@@ -17,7 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package de.steamwar.core; package de.steamwar.core.worldedit;
import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReaderV2; import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReaderV2;
import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReaderV3; import com.fastasyncworldedit.core.extent.clipboard.io.FastSchematicReaderV3;
@@ -34,6 +34,7 @@ import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.session.ClipboardHolder; import com.sk89q.worldedit.session.ClipboardHolder;
import de.steamwar.core.Core;
import de.steamwar.sql.NoClipboardException; import de.steamwar.sql.NoClipboardException;
import de.steamwar.sql.NodeData; import de.steamwar.sql.NodeData;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@@ -22,10 +22,12 @@ package de.steamwar.inventory;
import com.destroystokyo.paper.profile.PlayerProfile; import com.destroystokyo.paper.profile.PlayerProfile;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import de.steamwar.message.Message;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.enchantments.Enchantment; import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemFlag; import org.bukkit.inventory.ItemFlag;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.ItemMeta;
@@ -225,4 +227,14 @@ public class SWItem {
itemStack.setAmount(count); itemStack.setAmount(count);
return this; return this;
} }
public SWItem translate(Player player, Message message) {
setName(message.parse(itemMeta.getDisplayName(), player));
if (itemMeta.hasLore()) {
setLore(itemMeta.getLore().stream()
.map(s -> message.parse(s, player))
.toList());
}
return this;
}
} }
@@ -20,7 +20,7 @@
package de.steamwar.sql; package de.steamwar.sql;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import de.steamwar.core.WorldEditWrapper; import de.steamwar.core.worldedit.WorldEditWrapper;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@@ -19,7 +19,8 @@
package de.steamwar.teamserver; package de.steamwar.teamserver;
import de.steamwar.core.WorldEditRendererCUIEditor; import de.steamwar.core.worldedit.SteamEdit;
import de.steamwar.core.worldedit.WorldEditRendererCUIEditor;
import de.steamwar.linkage.AbstractLinker; import de.steamwar.linkage.AbstractLinker;
import de.steamwar.linkage.SpigotLinker; import de.steamwar.linkage.SpigotLinker;
import de.steamwar.message.Message; import de.steamwar.message.Message;
@@ -51,7 +52,7 @@ public final class Builder extends JavaPlugin {
} }
Bukkit.getWorlds().get(0).setGameRule(GameRule.REDUCED_DEBUG_INFO, false); Bukkit.getWorlds().get(0).setGameRule(GameRule.REDUCED_DEBUG_INFO, false);
new WorldEditRendererCUIEditor(); SteamEdit.init();
} }
@Override @Override
@@ -138,14 +138,16 @@ public class Subserver {
writer.println(command); writer.println(command);
} }
public void sleep() { private ProcessHandle serverProcess() {
try {
long pid = process.pid();
if (checkpoint) { if (checkpoint) {
pid = process.children().findAny().map(ProcessHandle::pid).orElse(pid); return process.children().findAny().orElseGet(process::toHandle);
}
return process.toHandle();
} }
Runtime.getRuntime().exec(new String[]{"kill", "-SIGUSR1", Long.toString(pid)}); public void sleep() {
try {
Runtime.getRuntime().exec(new String[]{"kill", "-SIGUSR1", Long.toString(serverProcess().pid())});
} catch (IOException e) { } catch (IOException e) {
logger.log(Level.SEVERE, "Failed to send SIGUSR1 to subserver.", e); logger.log(Level.SEVERE, "Failed to send SIGUSR1 to subserver.", e);
} }
@@ -162,7 +164,7 @@ public class Subserver {
public void stop() { public void stop() {
try { try {
process.destroy(); serverProcess().destroy();
if (!process.waitFor(1, TimeUnit.MINUTES)) { if (!process.waitFor(1, TimeUnit.MINUTES)) {
forceStop(); forceStop();
} else if (thread.isAlive()) { } else if (thread.isAlive()) {
@@ -177,6 +179,7 @@ public class Subserver {
public void forceStop() { public void forceStop() {
try { try {
logger.log(Level.SEVERE, () -> serverName + " did not stop correctly, forcibly stopping!"); logger.log(Level.SEVERE, () -> serverName + " did not stop correctly, forcibly stopping!");
serverProcess().destroyForcibly();
process.destroyForcibly(); process.destroyForcibly();
if (thread.isAlive()) thread.join(); if (thread.isAlive()) thread.join();
@@ -202,12 +202,6 @@ NOFIGHTSERVER_UNTIL = §7You are excluded from §e§lfighting§7 §euntil {0}§8
UNNOFIGHTSERVER_ERROR = §cThe player is not excluded from fighting. UNNOFIGHTSERVER_ERROR = §cThe player is not excluded from fighting.
UNNOFIGHTSERVER = §e{0} §7may now join §e§lfights§7 again§8. UNNOFIGHTSERVER = §e{0} §7may now join §e§lfights§7 again§8.
NOTEAMSERVER_TEAM = §e{0} §7was excluded from §e{1} {2} §7from §e§lteam servers§8: §f{3}
NOTEAMSERVER_PERMA = §7You are §epermanently§7 excluded from §e§lteam servers§8: §e{0}
NOTEAMSERVER_UNTIL = §7You are excluded from §e§lteam servers§7 §euntil {0}§8: §e{1}
UNNOTEAMSERVER_ERROR = §cThe player is not excluded from team servers.
UNNOTEAMSERVER = §e{0} §7may now set §e§lteam servers§7 again§8.
NOTE_TEAM = §e{0} §7received a §e§lnote§7 from §e{1} {2}: §f{3} NOTE_TEAM = §e{0} §7received a §e§lnote§7 from §e{1} {2}: §f{3}
#BugCommand #BugCommand
@@ -284,8 +278,8 @@ EVENT_COMING_TEAMS = §7 With§8: {0}
EVENT_COMING_TEAM = §{0}{1} EVENT_COMING_TEAM = §{0}{1}
EVENT_CURRENT_EVENT = §e§l{0} EVENT_CURRENT_EVENT = §e§l{0}
EVENT_CURRENT_FIGHT_1 = §7{0} §{1}{2} EVENT_CURRENT_FIGHT_1 = §7{0} §{1}{2}
EVENT_CURRENT_FIGHT_VS = §8 vs EVENT_CURRENT_FIGHT_VS = '§8 vs '
EVENT_CURRENT_FIGHT_2 = §{1}{2} EVENT_CURRENT_FIGHT_2 = §{0}{1}
EVENT_CURRENT_FIGHT_WIN = §8: §7Victory §{0}{1} EVENT_CURRENT_FIGHT_WIN = §8: §7Victory §{0}{1}
EVENT_CURRENT_FIGHT_DRAW = §8: §7Draw EVENT_CURRENT_FIGHT_DRAW = §8: §7Draw
EVENT_TEAM_TABLE = §{0}{1}{2} §8 with §e{3} §7points EVENT_TEAM_TABLE = §{0}{1}{2} §8 with §e{3} §7points
@@ -184,12 +184,6 @@ NOFIGHTSERVER_UNTIL = §7Du bist §ebis zum {0} §7vom §e§lKämpfen§7 ausgesc
UNNOFIGHTSERVER_ERROR = §cDer Spieler ist nicht vom Kämpfen ausgeschlossen. UNNOFIGHTSERVER_ERROR = §cDer Spieler ist nicht vom Kämpfen ausgeschlossen.
UNNOFIGHTSERVER = §e{0} §7darf nun wieder §e§lKämpfen§7 beitreten§8. UNNOFIGHTSERVER = §e{0} §7darf nun wieder §e§lKämpfen§7 beitreten§8.
NOTEAMSERVER_TEAM = §e{0} §7wurde von §e{1} {2} §7vom §e§lTeamserver§7 setzen ausgeschlossen§8: §f{3}
NOTEAMSERVER_PERMA = §7Du bist §epermanent §7vom §e§lTeamserver§7 setzen ausgeschlossen§8: §e{0}
NOTEAMSERVER_UNTIL = §7Du bist §ebis zum {0} §7vom §e§lTeamserver§7 setzen ausgeschlossen§8: §e{1}
UNNOTEAMSERVER_ERROR = §cDer Spieler ist nicht vom Teamserver setzten ausgeschlossen.
UNNOTEAMSERVER = §e{0} §7darf nun wieder §e§lTeamserver§7 setzen§8.
NOTE_TEAM = §e{0} §7erhielt von §e{1} {2} §7die §e§lNotiz§7§8: §f{3} NOTE_TEAM = §e{0} §7erhielt von §e{1} {2} §7die §e§lNotiz§7§8: §f{3}
#BugCommand #BugCommand
@@ -86,7 +86,7 @@ public class EventStarter {
} }
}).start(); }).start();
command = "/event " + blue.getTeamKuerzel(); command = "/event team " + blue.getTeamKuerzel();
} else { } else {
command = "/" + spectatePorts.get(next.getSpectatePort()); command = "/" + spectatePorts.get(next.getSpectatePort());
} }
@@ -149,7 +149,6 @@ public class VelocityCore implements ReloadablePlugin {
new PunishmentCommand("noschemsubmitting", Punishment.PunishmentType.NoSchemSubmitting); new PunishmentCommand("noschemsubmitting", Punishment.PunishmentType.NoSchemSubmitting);
new PunishmentCommand("nodev", Punishment.PunishmentType.NoDevServer); new PunishmentCommand("nodev", Punishment.PunishmentType.NoDevServer);
new PunishmentCommand("nofight", Punishment.PunishmentType.NoFightServer); new PunishmentCommand("nofight", Punishment.PunishmentType.NoFightServer);
new PunishmentCommand("noteamserver", Punishment.PunishmentType.NoTeamServer);
new PunishmentCommand("note", Punishment.PunishmentType.Note); new PunishmentCommand("note", Punishment.PunishmentType.Note);
linker = new AbstractLinker<>(this) { linker = new AbstractLinker<>(this) {
@@ -19,7 +19,6 @@
package de.steamwar.velocitycore.commands; package de.steamwar.velocitycore.commands;
import com.google.protobuf.MapEntry;
import de.steamwar.command.PreviousArguments; import de.steamwar.command.PreviousArguments;
import de.steamwar.command.SWCommand; import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeMapper; import de.steamwar.command.TypeMapper;
@@ -29,18 +28,15 @@ import de.steamwar.messages.Chatter;
import de.steamwar.messages.PlayerChatter; import de.steamwar.messages.PlayerChatter;
import de.steamwar.persistent.Subserver; import de.steamwar.persistent.Subserver;
import de.steamwar.sql.*; import de.steamwar.sql.*;
import de.steamwar.sql.Event;
import de.steamwar.velocitycore.EventStarter; import de.steamwar.velocitycore.EventStarter;
import de.steamwar.velocitycore.SubserverSystem; import de.steamwar.velocitycore.SubserverSystem;
import net.kyori.adventure.text.Component; import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent; import net.kyori.adventure.text.event.ClickEvent;
import java.awt.*;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.Instant; import java.time.Instant;
import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatter;
import java.util.*; import java.util.*;
import java.util.List;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -94,7 +90,7 @@ public class EventCommand extends SWCommand {
eventShowFightsPage(sender, currentEvent, 1); eventShowFightsPage(sender, currentEvent, 1);
} }
@Register(value = "showtable", description = "EVENT_SHOW_TABLE_USAGE") // @Register(value = "showtable", description = "EVENT_SHOW_TABLE_USAGE")
public void eventtable(Chatter sender, Event event) { public void eventtable(Chatter sender, Event event) {
if (!Instant.now().isBefore(event.getEnd().toInstant())) return; if (!Instant.now().isBefore(event.getEnd().toInstant())) return;
@@ -287,6 +287,10 @@ public class TeamCommand extends SWCommand {
@Register(value = "info", description = "TEAM_INFO_USAGE") @Register(value = "info", description = "TEAM_INFO_USAGE")
public void info(Chatter sender, @ErrorMessage("UNKNOWN_TEAM") Team team) { public void info(Chatter sender, @ErrorMessage("UNKNOWN_TEAM") Team team) {
if (team.getMembers().isEmpty()) {
sender.system("UNKNOWN_TEAM");
return;
}
List<SteamwarUser> users = team.getMembers().stream().map(SteamwarUser::byId).toList(); List<SteamwarUser> users = team.getMembers().stream().map(SteamwarUser::byId).toList();
sender.system("TEAM_INFO_TEAM", team.getTeamName(), team.getTeamColor(), team.getTeamKuerzel()); sender.system("TEAM_INFO_TEAM", team.getTeamName(), team.getTeamColor(), team.getTeamKuerzel());
@@ -38,7 +38,7 @@ import net.kyori.adventure.text.Component;
import java.util.*; import java.util.*;
import java.util.logging.Level; import java.util.logging.Level;
@Linked //@Linked
public class FML2 extends BasicListener { public class FML2 extends BasicListener {
// FML2: https://wiki.vg/Minecraft_Forge_Handshake#FML2_protocol_.281.13_-_Current.29 // FML2: https://wiki.vg/Minecraft_Forge_Handshake#FML2_protocol_.281.13_-_Current.29
// FML3: https://github.com/adde0109/Ambassador/tree/non-api/src/main/java/org/adde0109/ambassador/forge // FML3: https://github.com/adde0109/Ambassador/tree/non-api/src/main/java/org/adde0109/ambassador/forge