diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceRecorder.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceRecorder.java index c976fa14..0c2936ec 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceRecorder.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/TraceRecorder.java @@ -135,6 +135,13 @@ public class TraceRecorder implements Listener { Iterator iter = trackedTNT.getOrDefault(region, Collections.emptyList()).iterator(); while (iter.hasNext()) { TNTPrimed tnt = iter.next(); + if (tnt.isDead()) { + iter.remove(); + tntSpawnRegion.remove(tnt); + historyMap.remove(tnt); + tntSpawnRegion.remove(tnt); + continue; + } if (tnt.getFuseTicks() == 80) continue; TNTPoint record = record(tnt, wrappedTrace, Collections.emptyList()); if (record == null) { diff --git a/CommonCore/SQL/src/de/steamwar/sql/EventFight.kt b/CommonCore/SQL/src/de/steamwar/sql/EventFight.kt index bdbce609..285a01f9 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/EventFight.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/EventFight.kt @@ -237,6 +237,7 @@ class EventFight(id: EntityID) : IntEntity(id), Comparable { override fun delete() = useDb { + EventRelation.deleteRelations(this@EventFight) super.delete() } -} \ No newline at end of file +} diff --git a/CommonCore/SQL/src/de/steamwar/sql/EventGroup.kt b/CommonCore/SQL/src/de/steamwar/sql/EventGroup.kt index 7b20e648..cccbc570 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/EventGroup.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/EventGroup.kt @@ -159,10 +159,13 @@ class EventGroup(id: EntityID) : IntEntity(id) { } override fun delete() = - useDb { super.delete() } + useDb { + EventRelation.deleteRelations(this@EventGroup) + super.delete() + } enum class EventGroupType { GROUP_STAGE, ELIMINATION_STAGE } -} \ No newline at end of file +} diff --git a/CommonCore/SQL/src/de/steamwar/sql/EventRelation.kt b/CommonCore/SQL/src/de/steamwar/sql/EventRelation.kt index 91ccb9db..41e1bb8c 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/EventRelation.kt +++ b/CommonCore/SQL/src/de/steamwar/sql/EventRelation.kt @@ -24,8 +24,10 @@ import org.jetbrains.exposed.v1.core.and import org.jetbrains.exposed.v1.core.dao.id.EntityID import org.jetbrains.exposed.v1.core.dao.id.IntIdTable import org.jetbrains.exposed.v1.core.eq +import org.jetbrains.exposed.v1.core.or import org.jetbrains.exposed.v1.dao.IntEntity import org.jetbrains.exposed.v1.dao.IntEntityClass +import org.jetbrains.exposed.v1.jdbc.deleteWhere import org.jetbrains.exposed.v1.jdbc.select object EventRelationTable : IntIdTable("EventRelation") { @@ -59,6 +61,23 @@ class EventRelation(id: EntityID) : IntEntity(id) { fun getGroupRelations(group: EventGroup) = useDb { find { (EventRelationTable.fromId eq group.id.value) and (EventRelationTable.fromType eq FromType.GROUP) }.toList() } + @JvmStatic + fun deleteRelations(fight: EventFight) = + useDb { + EventRelationTable.deleteWhere { + (EventRelationTable.fightId eq fight.id) or + ((EventRelationTable.fromId eq fight.id.value) and (EventRelationTable.fromType eq FromType.FIGHT)) + } + } + + @JvmStatic + fun deleteRelations(group: EventGroup) = + useDb { + EventRelationTable.deleteWhere { + (EventRelationTable.fromId eq group.id.value) and (EventRelationTable.fromType eq FromType.GROUP) + } + } + @JvmStatic fun create(fight: EventFight, fightTeam: FightTeam, fromType: FromType, fromId: Int, fromPlace: Int) = useDb { @@ -159,4 +178,4 @@ class EventRelation(id: EntityID) : IntEntity(id) { enum class FromType { FIGHT, GROUP } -} \ No newline at end of file +} diff --git a/CommonCore/SQL/src/de/steamwar/sql/GameModeConfig.java b/CommonCore/SQL/src/de/steamwar/sql/GameModeConfig.java index 82ab638b..87c6bdb1 100644 --- a/CommonCore/SQL/src/de/steamwar/sql/GameModeConfig.java +++ b/CommonCore/SQL/src/de/steamwar/sql/GameModeConfig.java @@ -488,6 +488,27 @@ public final class GameModeConfig { */ public final boolean NoFloor; + /** + * Allows Wind Charges to cross the Middle. + * + * @implSpec {@code false} by default + */ + public final boolean WindchargesCanCrossMiddle; + + /** + * Allows Wind Charge interaction with Blocks. + * + * @implSpec {@code true} by default + */ + public final boolean WindchargesInteractWithBlocks; + + /** + * Allows Wind Charge to destroy Water. + * + * @implSpec {@code false} by default + */ + public final boolean WindchargesDestroyWater; + private ArenaConfig(YMLWrapper loader, SchematicConfig.SizeConfig Size, List EnterStages) { loaded = loader.canLoad(); WaterDepth = loader.getInt("WaterDepth", 0); @@ -505,6 +526,9 @@ public final class GameModeConfig { Leaveable = loader.getBoolean("Leaveable", false); AllowMissiles = loader.getBoolean("AllowMissiles", !EnterStages.isEmpty()); NoFloor = loader.getBoolean("NoFloor", false); + WindchargesCanCrossMiddle = loader.getBoolean("WindchargesCanCrossMiddle", false); + WindchargesInteractWithBlocks = loader.getBoolean("WindchargesInteractWithBlocks", true); + WindchargesDestroyWater = loader.getBoolean("WindchargesDestroyWater", false); } @ToString diff --git a/FightSystem/FightSystem_Core/src/config.yml b/FightSystem/FightSystem_Core/src/config.yml index 81620820..185704d5 100644 --- a/FightSystem/FightSystem_Core/src/config.yml +++ b/FightSystem/FightSystem_Core/src/config.yml @@ -64,6 +64,10 @@ Arena: AllowMissiles: false # defaults to true if EnterStages are present otherwise 'false' # Denotes that there is no floor for this GameMode NoFloor: false # defaults to false if missing + # Allows Wind Charges to cross the Middle. + WindchargesCanCrossMiddle: false # defaults to false if missing + # Allows Wind Charge interaction with Blocks. + WindchargesInteractWithBlocks: false # defaults to false if missing Schematic: # The size of the schematics diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/WaterRemover.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/WaterRemover.java index c85da5ce..bded9613 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/WaterRemover.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/WaterRemover.java @@ -72,6 +72,9 @@ public class WaterRemover implements Listener { @EventHandler public void handleEntityExplode(EntityExplodeEvent event) { + if (event.getEntityType() == EntityType.WIND_CHARGE && !Config.GameModeConfig.Arena.WindchargesDestroyWater) { + return; + } event.setYield(0); //No drops (additionally to world config) FightTeam spawn = tnt.remove(event.getEntity().getEntityId()); diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/WindchargeInteractionDisabler.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/WindchargeInteractionDisabler.java new file mode 100644 index 00000000..7c518b2a --- /dev/null +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/WindchargeInteractionDisabler.java @@ -0,0 +1,44 @@ +/* + * 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 . + */ + +package de.steamwar.fightsystem.listener; + +import de.steamwar.fightsystem.Config; +import de.steamwar.fightsystem.states.FightState; +import de.steamwar.fightsystem.states.StateDependentListener; +import de.steamwar.linkage.Linked; +import org.bukkit.entity.EntityType; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityExplodeEvent; + +@Linked +public class WindchargeInteractionDisabler implements Listener { + + public WindchargeInteractionDisabler() { + new StateDependentListener(!Config.GameModeConfig.Arena.WindchargesInteractWithBlocks, FightState.Running, this); + } + + @EventHandler(priority = EventPriority.HIGHEST) + public void handleEntityExplode(EntityExplodeEvent event) { + if (event.getEntityType() != EntityType.WIND_CHARGE) return; + event.blockList().clear(); + } +} diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/WindchargeStopper.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/WindchargeStopper.java index 9abfc92d..a750a1b9 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/WindchargeStopper.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/listener/WindchargeStopper.java @@ -23,14 +23,14 @@ import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.StateDependentTask; import de.steamwar.linkage.Linked; +import net.minecraft.world.entity.projectile.windcharge.WindCharge; import org.bukkit.Location; -import org.bukkit.entity.WindCharge; @Linked public class WindchargeStopper { public WindchargeStopper() { - new StateDependentTask(true, FightState.Running, this::run, 1, 1); + new StateDependentTask(!Config.GameModeConfig.Arena.WindchargesCanCrossMiddle, FightState.Running, this::run, 1, 1); } private static final int middleLine = Config.SpecSpawn.getBlockZ(); @@ -39,13 +39,13 @@ public class WindchargeStopper { private void run() { Recording.iterateOverEntities(windChargeClass::isInstance, entity -> { + Location nextlocation = entity.getLocation().add(entity.getVelocity()); Location location = entity.getLocation(); - Location prevLocation = location.clone().subtract(entity.getVelocity()); - boolean passedMiddle = location.getBlockZ() > middleLine && prevLocation.getBlockZ() > middleLine || - location.getBlockZ() < middleLine && prevLocation.getBlockZ() < middleLine; + boolean passedMiddle = nextlocation.getBlockZ() >= middleLine && location.getBlockZ() <= middleLine || + nextlocation.getBlockZ() <= middleLine && location.getBlockZ() >= middleLine; - if (!passedMiddle) { + if (passedMiddle) { entity.remove(); } }); diff --git a/SchematicSystem/src/de/steamwar/schematicsystem/autocheck/AutoChecker.java b/SchematicSystem/src/de/steamwar/schematicsystem/autocheck/AutoChecker.java index 1d7c0d68..6fa2be03 100644 --- a/SchematicSystem/src/de/steamwar/schematicsystem/autocheck/AutoChecker.java +++ b/SchematicSystem/src/de/steamwar/schematicsystem/autocheck/AutoChecker.java @@ -73,14 +73,19 @@ public class AutoChecker { continue; } - result.getBlockCounts().merge(material, 1, Integer::sum); + BlockPos pos = new BlockPos(x, y, z); if (AutoCheckerItems.impl.getInventoryMaterials().contains(material)) { - checkInventory(result, block, material, new BlockPos(x, y, z), type); + checkInventory(result, block, material, pos, type); + if (result.getDispenserItems().getOrDefault(pos, 0) > 0) { + result.getBlockCounts().merge(material, 1, Integer::sum); + } + } else { + result.getBlockCounts().merge(material, 1, Integer::sum); } if (x == min.x() || x == max.x() || y == max.y() || z == min.z() || z == max.z()) { - result.getDesignBlocks().computeIfAbsent(material, m -> new ArrayList<>()).add(new BlockPos(x, y, z)); + result.getDesignBlocks().computeIfAbsent(material, m -> new ArrayList<>()).add(pos); } } } diff --git a/buildSrc/src/main/kotlin/FightServer.kt b/buildSrc/src/main/kotlin/FightServer.kt index 0788da17..a3b9411a 100644 --- a/buildSrc/src/main/kotlin/FightServer.kt +++ b/buildSrc/src/main/kotlin/FightServer.kt @@ -25,15 +25,15 @@ open class FightServer : DevServer() { @get:Input @get:Optional - var checkSchemID: Int = 0 + var checkSchemID: Int? = 0 @get:Input @get:Optional - var prepareSchemID: Int = 0 + var prepareSchemID: Int? = 0 @get:Input @get:Optional - var replay: Int = 0 + var replay: Int? = 0 @get:Input @get:Optional @@ -42,7 +42,7 @@ open class FightServer : DevServer() { // Property: fightID @get:Input @get:Optional - var eventKampfID: Int = 0 + var eventKampfID: Int? = 0 @get:Input @get:Optional diff --git a/buildSrc/src/main/kotlin/VelocityServer.kt b/buildSrc/src/main/kotlin/VelocityServer.kt index b314981e..b3ca4952 100644 --- a/buildSrc/src/main/kotlin/VelocityServer.kt +++ b/buildSrc/src/main/kotlin/VelocityServer.kt @@ -24,11 +24,11 @@ open class VelocityServer : DevServer() { @get:Input @get:Optional - var packetDecodeLogging: Boolean = false + var packetDecodeLogging: Boolean? = false init { doFirst { - if (packetDecodeLogging) dParams.put("velocity.packet-decode-logging", "true") + if (packetDecodeLogging == true) dParams.put("velocity.packet-decode-logging", "true") } } }