Merge branch 'main' into exposed

# Conflicts:
#	CommonCore/SQL/src/de/steamwar/sql/GameModeConfig.java
#	CommonCore/SQL/src/de/steamwar/sql/Punishment.java
This commit is contained in:
2025-11-05 16:18:30 +01:00
17 changed files with 138 additions and 35 deletions

View File

@@ -818,7 +818,6 @@ REGION_TNT_HELP_MODE=§8/§etnt §8[§7Mode§8] §8- §7Set TNT behaviour to a g
REGION_TNT_ON=§aTNT-Damage activated
REGION_TNT_OFF=§cTNT-Damage deactivated
REGION_TNT_TB=§aTNT-Damage activated outside the building area
REGION_TNT_BUILD=§aTNT-Damage activated outside the testblok area
REGION_TNT_BUILD_DESTROY=§cAn explosion would have destroyed blocks in the building area
REGION_TNT_TB_DESTROY=§cAn explosion would have destroyed blocks in the testblock area
AFK_KICK_MESSAGE=§cNothing happened on this server for 15 minutes.

View File

@@ -123,10 +123,6 @@ public class TNTCommand extends SWCommand {
return "REGION_TNT_TB";
}
private String getBuildEnableMessage() {
return "REGION_TNT_BUILD";
}
private void tntToggle(Region region, TNTMode requestedMode, String requestedMessage) {
if (requestedMode != null && region.getFlags().get(Flag.TESTBLOCK).isNotWithDefault(TestblockMode.NO_VALUE)) {
region.getFlags().set(Flag.TNT, requestedMode);

View File

@@ -35,19 +35,11 @@ import java.util.stream.Collectors;
public final class GameModeConfig<M, W> {
public static final Function<String, String> ToString = Function.identity();
public static final Function<File, String> ToStaticWarGear = GameModeConfig::constWarGear;
public static final Function<File, String> ToInternalName = GameModeConfig::internalName;
public static final Function<File, String> ToStaticWarGear = __ -> "WarGear";
public static final Function<File, String> ToInternalName = file -> file != null ? file.getName().replace(".yml", "") : "WarGear";
public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("dd.MM.yyyy HH:mm");
private static final Random random = new Random();
private static String constWarGear(File f) {
return "WarGear";
}
private static String internalName(File f) {
return f.getName().replace(".yml", "");
}
private static final Map<String, GameModeConfig<?, String>> byFileName;
private static final Map<String, GameModeConfig<?, String>> byGameName;
private static final Map<SchematicType, GameModeConfig<?, String>> bySchematicType;
@@ -109,6 +101,14 @@ public final class GameModeConfig<M, W> {
*/
public final List<String> CheckQuestions;
/**
* The allowed checkers to check this schematic type denoted by a list of SteamWar ids.
* The people need the {@link UserPerm#CHECK} to be able to check though.
*
* @implSpec {@code []} by default -> denoting every person with {@link UserPerm#CHECK} can check it
*/
public final List<Integer> Checkers;
/**
* Bundle for countdowns during the fight
*/
@@ -202,6 +202,7 @@ public final class GameModeConfig<M, W> {
}
CheckQuestions = loader.getStringList("CheckQuestions");
Checkers = loader.getIntList("Checkers");
Times = new TimesConfig(loader.with("Times"));
// Arena would be here to be in config order but needs Schematic.Size and EnterStages loaded afterwards
Schematic = new SchematicConfig<>(loader.with("Schematic"));

View File

@@ -24,6 +24,7 @@ import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;
import de.steamwar.core.Core;
import de.steamwar.sql.GameModeConfig;
import de.steamwar.sql.SchematicType;
import org.bukkit.Material;
@@ -109,7 +110,7 @@ public class AutoChecker15 implements AutoChecker.IAutoChecker {
if (!itemsInInv.getOrDefault(itemType, EnumSet.noneOf(Material.class)).contains(material)) {
result.getForbiddenItems().computeIfAbsent(pos, blockVector3 -> new HashSet<>()).add(itemType);
} else if(material == Material.DISPENSER && (itemType == Material.ARROW || itemType == Material.FIRE_CHARGE)) {
counter += item.getByte("Count");
counter += Core.getVersion() >= 21 ? item.getInt("count") : item.getByte("Count");
}
if (item.containsKey("tag")) {
result.getForbiddenNbt().computeIfAbsent(pos, blockVector3 -> new HashSet<>()).add(itemType);

View File

@@ -31,6 +31,7 @@ import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import de.steamwar.core.Core;
import de.steamwar.sql.GameModeConfig;
import de.steamwar.schematicsystem.autocheck.AutoCheckerResult;
import de.steamwar.schematicsystem.autocheck.BlockPos;
@@ -38,9 +39,17 @@ import de.steamwar.sql.SchematicType;
import org.bukkit.Material;
import java.util.*;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;
public class SchematicCommand15 implements SchematicCommand.ISchematicCommand {
private static final Function<CompoundTag, Integer> getCount = item -> Core.getVersion() >= 21 ? item.getInt("count") : item.getByte("Count");
private static final BiFunction<CompoundTag, Integer, CompoundTag> setCount = (item, count) -> Core.getVersion() >= 21 ?
item.createBuilder().putInt("count", count).build() :
item.createBuilder().putByte("Count", count.byteValue()).build();
@Override
public Clipboard fixClipboard(Clipboard clipboard, AutoCheckerResult result, GameModeConfig<Material, String> type) throws Exception {
for (BlockPos blockPos : result.getBlockScanResult().getRecords()) {
@@ -87,7 +96,7 @@ public class SchematicCommand15 implements SchematicCommand.ISchematicCommand {
BaseBlock block = clipboard.getFullBlock(vector);
CompoundTag tag = block.getNbtData();
CompoundTagBuilder builder = tag.createBuilder();
List<CompoundTag> items = tag.getList("Items", CompoundTag.class);
List<CompoundTag> items = new ArrayList<>(tag.getList("Items", CompoundTag.class));
Collections.reverse(items); // To let the first item be in the Dispenser
List<CompoundTag> list = new ArrayList<>();
int diff = entry.getValue() - type.Schematic.MaxDispenserItems;
@@ -101,12 +110,12 @@ public class SchematicCommand15 implements SchematicCommand.ISchematicCommand {
continue;
}
if(diff > item.getByte("Count")) {
diff -= item.getByte("Count");
if(diff > getCount.apply(item)) {
diff -= getCount.apply(item);
continue;
}
item = item.createBuilder().putByte("Count", (byte) (item.getByte("Count") - diff)).build();
item = setCount.apply(item, getCount.apply(item) - diff);
diff = 0;
list.add(item);
}

View File

@@ -35,6 +35,7 @@ public class SchematicSystem extends JavaPlugin {
public static GameModeConfig<Material, String> getGameModeConfig(SchematicType type){
GameModeConfig<Material, String> gameModeConfig = GameModeConfig.getBySchematicType(type);
if (gameModeConfig == null) return null;
if (gameModeConfig.CheckQuestions.isEmpty() && gameModeConfig.Schematic.ManualCheck) return null;
return gameModeConfig;
}

View File

@@ -62,7 +62,7 @@ public class ModifyPart extends SWCommand {
SchematicType.values().parallelStream()
.filter(SchematicType::isAssignable)
.filter(type -> finalClipboard == null || SchematicSystem.getGameModeConfig(type) == null || AutoChecker.sizeCheck(finalClipboard, SchematicSystem.getGameModeConfig(type)).fastOk())
.filter(type -> finalClipboard != null && SchematicSystem.getGameModeConfig(type) != null && AutoChecker.sizeCheck(finalClipboard, SchematicSystem.getGameModeConfig(type)).fastOk())
.forEach(type -> {
TextComponent component = new TextComponent(type.name() + " ");
component.setColor(ChatColor.GRAY);

View File

@@ -0,0 +1,42 @@
/*
* 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.core;
import com.destroystokyo.paper.profile.PlayerProfile;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.SkullMeta;
public class FlatteningWrapper21 extends FlatteningWrapper14 implements FlatteningWrapper.IFlatteningWrapper {
@Override
public ItemStack setSkullOwner(String player) {
ItemStack head = new ItemStack(Material.PLAYER_HEAD, 1);
head.editMeta(SkullMeta.class, skullMeta -> {
OfflinePlayer offlinePlayer = Bukkit.getOfflinePlayer(player.startsWith(".") ? player.substring(1) : player);
PlayerProfile playerProfile = offlinePlayer.getPlayerProfile();
if (!playerProfile.isComplete()) playerProfile.complete();
skullMeta.setPlayerProfile(playerProfile);
});
return head;
}
}

View File

@@ -44,7 +44,7 @@ public class SWCommand extends AbstractSWCommand<CommandSender> {
private Command command;
@Setter
private Message message = null;
protected Message message = null;
private List<String> defaultHelpMessages = new ArrayList<>();
protected SWCommand(String command) {

View File

@@ -122,6 +122,7 @@ public class Persistent {
container = proxy.getPluginManager().getPlugin("velocitycore").orElseThrow();
plugin = (ReloadablePlugin) container.getInstance().orElseThrow();
} catch (NoSuchElementException e) {
e.printStackTrace();
logger.log(Level.WARNING, "Could not find loaded VelocityCore, continuing without unloading.");
}
@@ -129,6 +130,7 @@ public class Persistent {
try {
newContainer = prepareLoad();
} catch (Exception e) {
e.printStackTrace();
logger.log(Level.SEVERE, "Could not instantiate new VelocityCore, aborting softreload.", e);
return Command.SINGLE_SUCCESS;
}
@@ -136,13 +138,19 @@ public class Persistent {
broadcast("§eNetwork update is starting§8.");
try {
if(container != null && plugin != null) {
System.out.println("Proxy Shutdown Event");
plugin.onProxyShutdown(new ProxyShutdownEvent());
System.out.println("Unloading of Container");
unload(container, plugin);
}
System.out.println("Loading of new Container");
registerPlugin.invoke((VelocityPluginManager) proxy.getPluginManager(), newContainer);
System.out.println("Proxy Initialization Event");
((ReloadablePlugin) newContainer.getInstance().orElseThrow()).onProxyInitialization(new ProxyInitializeEvent());
System.out.println("Proxy Initialization Event finished");
} catch (Throwable t) {
t.printStackTrace();
logger.log(Level.SEVERE, "Error during softreload", t);
broadcast("§cNetwork update failed§8, §cexpect network restart soon§8.");
return Command.SINGLE_SUCCESS;

View File

@@ -319,6 +319,7 @@ CHECK_LIST_CHECKING_HOVER=§eTo the reviewer
CHECK_SCHEMATIC_ALREADY_CHECKING=§cYou are already reviewing a schematic!
CHECK_SCHEMATIC_OWN=§cYou cannot review your own schematics.
CHECK_SCHEMATIC_OWN_TEAM=§cYou cannot review your team schematics.
CHECK_SCHEMATIC_EVENT=§cYou cannot check the schematic for the event.
CHECK_SCHEMATIC_PREVIOUS=§7{0} from {1}§8: §e{2}
CHECK_INVALID_RANK=§cUnknown schematic rank.
CHECK_ABORT=§aThe test operation was canceled!

View File

@@ -301,6 +301,7 @@ CHECK_LIST_CHECKING_HOVER=§eZum Prüfer
CHECK_SCHEMATIC_ALREADY_CHECKING=§cDu prüfst schon eine Schematic!
CHECK_SCHEMATIC_OWN=§cDu kannst nicht deine eigenen Schematics prüfen.
CHECK_SCHEMATIC_OWN_TEAM=§cDu kannst nicht Schematics deines Teams prüfen.
CHECK_SCHEMATIC_EVENT=§cDu kannst die schematic für das Event nicht prüfen.
CHECK_SCHEMATIC_PREVIOUS=§7{0} von {1}§8: §e{2}
CHECK_INVALID_RANK=§cUnbekannter Schematicrang.
CHECK_ABORT=§aDer Prüfvorgang wurde abgebrochen!

View File

@@ -61,6 +61,8 @@ public class ArenaMode {
}
if (gameModeConfig.Schematic.loaded && gameModeConfig.Schematic.Type != SchematicType.Normal) {
bySchemType.put(gameModeConfig.Schematic.Type, gameModeConfig);
SchematicType checkType = gameModeConfig.Schematic.Type.checkType();
if (checkType != null) bySchemType.put(checkType, gameModeConfig);
}
}
}

View File

@@ -45,6 +45,7 @@ import de.steamwar.velocitycore.commands.ServerSwitchCommand;
import de.steamwar.velocitycore.commands.TeamCommand;
import de.steamwar.velocitycore.discord.DiscordBot;
import de.steamwar.velocitycore.discord.DiscordConfig;
import de.steamwar.velocitycore.listeners.BasicListener;
import de.steamwar.velocitycore.listeners.PollSystem;
import lombok.Getter;
import lombok.NonNull;
@@ -171,6 +172,16 @@ public class VelocityCore implements ReloadablePlugin {
((PacketHandler) any).register();
}
}
@Override
protected void unlinkObject(Object any) {
if (any instanceof PacketHandler) {
((PacketHandler) any).unregister();
}
if (any instanceof BasicListener) {
VelocityCore.getProxy().getEventManager().unregisterListener(instance, any);
}
}
};
try {
linker.link();

View File

@@ -20,8 +20,8 @@
package de.steamwar.velocitycore.commands;
import com.velocitypowered.api.proxy.Player;
import com.velocitypowered.api.proxy.ServerConnection;
import de.steamwar.command.SWCommand;
import de.steamwar.sql.GameModeConfig;
import de.steamwar.linkage.Linked;
import de.steamwar.messages.Chatter;
import de.steamwar.messages.Message;
@@ -100,17 +100,31 @@ public class CheckCommand extends SWCommand {
sender.system("CHECK_LIST_HEADER", schematicList.size());
for (SchematicNode schematic : schematicList) {
GameModeConfig<String, String> gameModeConfig = ArenaMode.getBySchemType(schematic.getSchemtype());
if (gameModeConfig == null) gameModeConfig = GameModeConfig.getDefaults();
CheckSession current = currentSchems.get(schematic.getId());
ClickEvent clickEvent = null;
Message hoverMessage = null;
if (gameModeConfig.Checkers.isEmpty() || gameModeConfig.Checkers.contains(sender.user().getId())) {
if (current == null) {
clickEvent = ClickEvent.runCommand("/check schematic " + schematic.getId());
hoverMessage = new Message("CHECK_LIST_TO_CHECK_HOVER");
} else {
clickEvent = ClickEvent.runCommand("/join " + current.checker.user().getUserName());
hoverMessage = new Message("CHECK_LIST_CHECKING_HOVER");
}
}
if (current == null) {
sender.prefixless("CHECK_LIST_TO_CHECK",
new Message("CHECK_LIST_TO_CHECK_HOVER"),
ClickEvent.runCommand("/check schematic " + schematic.getId()),
hoverMessage,
clickEvent,
getWaitTime(schematic),
schematic.getSchemtype().getKuerzel(), SteamwarUser.byId(schematic.getOwner()).getUserName(), schematic.getName());
} else {
sender.prefixless("CHECK_LIST_CHECKING",
new Message("CHECK_LIST_CHECKING_HOVER"),
ClickEvent.runCommand("/join " + current.checker.user().getUserName()),
hoverMessage,
clickEvent,
getWaitTime(schematic),
schematic.getSchemtype().getKuerzel(), SteamwarUser.byId(schematic.getOwner()).getUserName(), schematic.getName(), current.checker.user().getUserName());
}
@@ -125,6 +139,11 @@ public class CheckCommand extends SWCommand {
}
SchematicNode schem = SchematicNode.getSchematicNode(Integer.parseInt(schemID));
GameModeConfig<String, String> gameModeConfig = ArenaMode.getBySchemType(schem.getSchemtype());
if (!gameModeConfig.Checkers.isEmpty() && !gameModeConfig.Checkers.contains(sender.user().getId())) {
sender.system("CHECK_SCHEMATIC_EVENT");
return;
}
if(!schem.getSchemtype().check()){
VelocityCore.getLogger().log(Level.SEVERE, () -> sender.user().getUserName() + " tried to check an uncheckable schematic!");
return;
@@ -139,6 +158,15 @@ public class CheckCommand extends SWCommand {
sender.system("CHECK_SCHEMATIC_OWN_TEAM");
return;
}
CheckSession checkSession = currentSchems.get(schem.getId());
if (checkSession != null) {
Optional<ServerConnection> serverConnection = checkSession.checker.getPlayer().getCurrentServer();
if (serverConnection.isPresent()) {
sender.getPlayer().createConnectionRequest(serverConnection.get().getServer()).fireAndForget();
return;
}
}
new CheckSession(sender, schem);
}

View File

@@ -21,8 +21,6 @@ package de.steamwar.velocitycore.commands;
import com.google.gson.JsonParser;
import com.velocitypowered.api.proxy.Player;
import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.velocitycore.listeners.IPSanitizer;
import de.steamwar.command.PreviousArguments;
import de.steamwar.command.SWCommand;
import de.steamwar.command.TypeMapper;
@@ -32,6 +30,8 @@ import de.steamwar.sql.BannedUserIPs;
import de.steamwar.sql.Punishment;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserPerm;
import de.steamwar.velocitycore.VelocityCore;
import de.steamwar.velocitycore.listeners.IPSanitizer;
import java.io.IOException;
import java.net.URL;
@@ -97,9 +97,11 @@ public class PunishmentCommand {
bannedUser.punish(Punishment.PunishmentType.Ban, time, banReason, punisher.getId(), perma);
}
}
if (!player.getUsername().startsWith(".")) {
BannedUserIPs.banIP(user.getId(), ip);
}
}
}
public static Message punishmentMessage(SteamwarUser user, Punishment.PunishmentType punishment) {
Punishment currentPunishment = user.getPunishment(punishment);
@@ -179,7 +181,7 @@ public class PunishmentCommand {
private final Punishment.PunishmentType punishmentType;
private PunishCommand(String command, Punishment.PunishmentType punishmentType) {
super(command, UserPerm.TEAM);
super(command, punishmentType.getUserPerm());
this.command = command;
this.punishmentType = punishmentType;
}
@@ -194,7 +196,7 @@ public class PunishmentCommand {
@Register
public void genericCommand(Chatter sender, @Mapper("toPunish") String toPunish, String date, @ErrorMessage(allowEAs = false, value = "PUNISHMENT_USAGE_REASON") String... message) {
SteamwarUser punisher = sender.user();
if (punishmentType.isNeedsAdmin() && !punisher.hasPerm(UserPerm.MODERATION))
if (!punisher.hasPerm(punishmentType.getUserPerm()))
return;
SteamwarUser target = unsafeUser(sender, toPunish);
@@ -244,14 +246,15 @@ public class PunishmentCommand {
private final Punishment.PunishmentType punishmentType;
private UnpunishCommand(String command, Punishment.PunishmentType punishmentType) {
super(command, UserPerm.TEAM);
super(command, punishmentType.getUserPerm());
this.command = command;
this.punishmentType = punishmentType;
}
@Register
public void genericCommand(Chatter sender, @ErrorMessage("UNKNOWN_PLAYER") SteamwarUser target) {
if (punishmentType.isNeedsAdmin() && !sender.user().hasPerm(UserPerm.MODERATION))
SteamwarUser punisher = sender.user();
if (!punisher.hasPerm(punishmentType.getUserPerm()))
return;
if (!target.isPunished(punishmentType)) {

View File

@@ -26,7 +26,7 @@ class SQLWrapperImpl: SQLWrapper<String> {
return File("/configs/GameModes")
}
override fun loadGameModeConfig(file: File): GameModeConfig<String, String> {
override fun loadGameModeConfig(file: File?): GameModeConfig<String, String> {
return GameModeConfig(file, GameModeConfig.ToString, GameModeConfig.ToString, GameModeConfig.ToStaticWarGear, true)
}