Compare commits

...

2 Commits

Author SHA1 Message Date
59de3e81ae Merge branch 'main' into modular-fight-system
Some checks failed
SteamWarCI Build failed
2026-05-09 20:16:30 +02:00
a37321d3b8 Add modular fight system components and configurations
Signed-off-by: Chaoscaot <max@maxsp.de>
2026-03-17 18:30:53 +01:00
19 changed files with 638 additions and 3 deletions

View File

@@ -67,9 +67,10 @@ tasks.register<FightServer>("WarGear21") {
description = "Run a WarGear 1.21 Fight Server"
dependsOn(":SpigotCore:shadowJar")
dependsOn(":FightSystem:shadowJar")
dependsOn(":KotlinCore:shadowJar")
template = "WarGear21"
worldName = "arenas/Pentraki"
config = "WarGear20.yml"
worldName = "arenas/Colosso"
config = "WarGear21.yml"
jar = "/jars/paper-1.21.6.jar"
}

View File

@@ -0,0 +1,32 @@
/*
* 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/>.
*/
plugins {
steamwar.kotlin
alias(libs.plugins.shadow)
}
java {
targetCompatibility = JavaVersion.VERSION_21
sourceCompatibility = JavaVersion.VERSION_21
}
dependencies {
implementation(project(":ModularFightSystem:GameCore"))
}

View File

@@ -0,0 +1,29 @@
/*
* 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
import de.steamwar.fightsystem.state.FightState
class FightSystem {
}
fun test() {
FightState.register()
}

View File

@@ -0,0 +1,54 @@
/*
* 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.state
import de.steamwar.modularfightsystem.complement
import de.steamwar.modularfightsystem.enumSetAll
import de.steamwar.modularfightsystem.enumSetOf
import de.steamwar.modularfightsystem.state.FightStateMachine
enum class FightState {
PRE_LEADER_SETUP,
PRE_SCHEM_SETUP,
POST_SCHEM_SETUP,
PRE_RUNNING,
RUNNING,
SPECTATE;
companion object : FightStateMachine<FightState>(PRE_LEADER_SETUP) {
val All = enumSetAll<FightState>()
val PreLeaderSetup = enumSetOf(PRE_LEADER_SETUP)
val PreSchemSetup = enumSetOf(PRE_SCHEM_SETUP)
val PostSchemSetup = enumSetOf(POST_SCHEM_SETUP)
val PreRunning = enumSetOf(PRE_RUNNING)
val Running = enumSetOf(RUNNING)
val Spectate = enumSetOf(SPECTATE)
val Setup = enumSetOf(PRE_LEADER_SETUP, PRE_SCHEM_SETUP, POST_SCHEM_SETUP)
val Ingame = enumSetOf(PRE_RUNNING, RUNNING)
val TeamFix = enumSetOf(PRE_RUNNING, RUNNING, SPECTATE)
val Schem = enumSetOf(PRE_LEADER_SETUP, PRE_SCHEM_SETUP).complement()
val Recording = enumSetOf(PRE_LEADER_SETUP, PRE_SCHEM_SETUP, SPECTATE).complement()
val AntiRunning = enumSetOf(RUNNING).complement()
val AntiIngame = enumSetOf(PRE_RUNNING, RUNNING).complement()
val AntiSpectate = enumSetOf(SPECTATE).complement()
}
}

View File

@@ -0,0 +1,33 @@
/*
* 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/>.
*/
plugins {
steamwar.kotlin
}
java {
targetCompatibility = JavaVersion.VERSION_21
sourceCompatibility = JavaVersion.VERSION_21
}
dependencies {
compileOnly(libs.paperapi21)
compileOnly(libs.nms21)
compileOnly(project(":SpigotCore", "default"))
}

View File

@@ -0,0 +1,54 @@
/*
* 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.modularfightsystem
enum class ArenaMode {
NORMAL,
EVENT,
TEST,
CHECK,
PREPARE,
REPLAY;
companion object {
val All = enumSetAll<ArenaMode>()
val Normal = enumSetOf(NORMAL)
val Event = enumSetOf(EVENT)
val Test = enumSetOf(TEST)
val Check = enumSetOf(CHECK)
val Prepare = enumSetOf(PREPARE)
val Replay = enumSetOf(REPLAY)
val AntiReplay = Replay.complement()
val AntiTest = Test.complement()
val AntiEvent = Event.complement()
val AntiTestCheckPrepare = enumSetOf(TEST, CHECK, PREPARE).complement()
val AntiPrepare = Prepare.complement()
val VariableTeams = enumSetOf(EVENT, REPLAY, CHECK).complement()
val ManualTeams = enumSetOf(EVENT, REPLAY).complement()
val RankedEvent = enumSetOf(EVENT, REPLAY)
val Restartable = enumSetOf(NORMAL, TEST)
val NotRestartable = enumSetOf(EVENT, REPLAY)
val SoloLeader = enumSetOf(TEST, CHECK, PREPARE)
val NotOnBau = enumSetOf(TEST, CHECK, PREPARE, REPLAY).complement()
val SeriousFight = enumSetOf(TEST, CHECK, REPLAY).complement()
}
}

View File

@@ -0,0 +1,29 @@
/*
* 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.modularfightsystem
import de.steamwar.message.Message
import org.bukkit.plugin.Plugin
object Config {
lateinit var plugin: Plugin
val mode = ArenaMode.TEST
}

View File

@@ -0,0 +1,33 @@
/*
* 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.modularfightsystem
import java.util.Collections
import java.util.EnumSet
typealias KEnumSet<T> = Set<T>
inline fun <reified T> enumSetOf(): KEnumSet<T> where T : Enum<T> = Collections.unmodifiableSet(EnumSet.noneOf(T::class.java))
inline fun <reified T> enumSetAll(): KEnumSet<T> where T : Enum<T> = Collections.unmodifiableSet(EnumSet.allOf(T::class.java))
inline fun <reified T> enumSetOf(vararg elements: T): KEnumSet<T> where T : Enum<T> = Collections.unmodifiableSet(EnumSet.copyOf(elements.toSet()))
fun <T> KEnumSet<T>.complement(): KEnumSet<T> where T: Enum<T> = Collections.unmodifiableSet(EnumSet.complementOf(EnumSet.copyOf(this)))

View File

@@ -0,0 +1,96 @@
/*
* 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.modularfightsystem.countdown
import de.steamwar.modularfightsystem.Config
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.ComponentLike
import org.bukkit.Bukkit
import org.bukkit.Sound
import org.bukkit.entity.Player
import org.bukkit.scheduler.BukkitTask
abstract class Countdown(val totalTime: Int, val appendix: ComponentLike, val sound: Sound?, val level: Boolean) {
var time = totalTime
private var task: BukkitTask? = null
abstract fun countdownFinished()
fun enable() {
time = totalTime
task = Bukkit.getScheduler().runTaskTimer(Config.plugin, this::count, 0, 20)
countdowns.add(this)
show()
}
fun disable() {
if (task != null) {
task!!.cancel()
countdowns.remove(this)
task = null
}
}
private fun show() {
when(time) {
900, 600, 300, 180, 120 -> broadcast("COUNTDOWN_MINUTES", 60)
60, 30, 20, 15, 10, 5, 4, 3, 2 -> broadcast("COUNTDOWN_SECONDS", 1)
1 -> broadcast("COUNTDOWN_SECOND", 1)
0 -> {
playSound()
disable()
countdownFinished()
}
}
if (level) {
Bukkit.getOnlinePlayers().forEach { it.level = time }
}
}
private fun count() {
time--
show()
}
protected fun broadcast(message: String, divisor: Int) {
playSound()
Bukkit.getOnlinePlayers().forEach { sendCountdownMessage(it, message, totalTime / divisor, appendix) }
}
fun playSound() = sound?.let { Bukkit.getOnlinePlayers().forEach { it.playSound(it.location, sound, 100f, 1f) } }
fun sendCountdownMessage(p: Player, message: String, displayTime: Int, appendix: ComponentLike) =
p.sendMessage(Component.translatable(message, Component.text(displayTime), appendix))
companion object {
private val countdowns = mutableListOf<Countdown>()
fun skip() {
if (countdowns.isEmpty()) return
val smallestTime = countdowns.minOf { it.time }
countdowns.forEach { it.also { it.time -= smallestTime }.show() }
}
}
}

View File

@@ -0,0 +1,23 @@
/*
* 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.modularfightsystem.fight
class FightPlayer {
}

View File

@@ -0,0 +1,22 @@
/*
* 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.modularfightsystem.fight
class FightTeam()

View File

@@ -0,0 +1,46 @@
/*
* 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.modularfightsystem.state
abstract class FightStateMachine<T: Enum<*>>(initialState: T) {
init {
instance = this
}
var state: T = initialState
set(value) {
field = value
stateDependents.forEach { dependent -> dependent.enabled = value in dependent.states }
}
private val stateDependents = mutableListOf<StateDependent>()
fun register(stateDependent: StateDependent) {
if (stateDependent.states.isEmpty() or !stateDependent.active) return
stateDependents.add(stateDependent)
stateDependent.enabled = state in stateDependent.states
}
companion object {
lateinit var instance: FightStateMachine<*>
private set
}
}

View File

@@ -0,0 +1,35 @@
/*
* 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.modularfightsystem.state
import de.steamwar.modularfightsystem.ArenaMode
import de.steamwar.modularfightsystem.Config
import de.steamwar.modularfightsystem.KEnumSet
class OneShotStateDependent(active: Boolean, states: KEnumSet<*>, val runnable: () -> Unit): StateDependent(active, states) {
constructor(modes: KEnumSet<ArenaMode>, states: KEnumSet<*>, runnable: () -> Unit) : this(Config.mode in modes, states, runnable)
init {
register()
}
override fun enable() = runnable()
override fun disable() = Unit
}

View File

@@ -0,0 +1,41 @@
/*
* 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.modularfightsystem.state
import de.steamwar.modularfightsystem.ArenaMode
import de.steamwar.modularfightsystem.Config
import de.steamwar.modularfightsystem.KEnumSet
abstract class StateDependent(val active: Boolean, val states: KEnumSet<*>) {
constructor(modes: KEnumSet<ArenaMode>, states: KEnumSet<*>) : this(Config.mode in modes, states)
var enabled = false
set(value) {
if (value != field) if (value) enable() else disable()
field = value
}
fun register() {
FightStateMachine.instance.register(this)
}
abstract fun enable()
abstract fun disable()
}

View File

@@ -0,0 +1,33 @@
/*
* 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.modularfightsystem.state
import de.steamwar.command.SWCommand
import de.steamwar.modularfightsystem.ArenaMode
import de.steamwar.modularfightsystem.KEnumSet
class StateDependentCommand(mode: KEnumSet<ArenaMode>, states: KEnumSet<*>, val command: SWCommand): StateDependent(mode, states) {
init {
register()
}
override fun enable() = command.register()
override fun disable() = command.unregister()
}

View File

@@ -0,0 +1,45 @@
/*
* 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.modularfightsystem.state
import de.steamwar.modularfightsystem.ArenaMode
import de.steamwar.modularfightsystem.Config
import de.steamwar.modularfightsystem.KEnumSet
import org.bukkit.Bukkit
import org.bukkit.scheduler.BukkitTask
class StateDependentTask(active: Boolean, states: KEnumSet<*>, val runnable: () -> Unit, val delay: Long, val period: Long): StateDependent(active, states) {
constructor(modes: KEnumSet<ArenaMode>, states: KEnumSet<*>, runnable: () -> Unit, delay: Long, period: Long) : this(
Config.mode in modes, states, runnable, delay, period)
init {
register()
}
var task: BukkitTask? = null
override fun enable() {
task = Bukkit.getScheduler().runTaskTimer(Config.plugin, runnable, delay, period)
}
override fun disable() {
task?.cancel()
}
}

View File

@@ -0,0 +1,22 @@
/*
* 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/>.
*/
plugins {
`java-library`
}

View File

@@ -18,7 +18,7 @@
*/
plugins {
steamwar.java
steamwar.kotlin
}
dependencies {
@@ -29,4 +29,5 @@ dependencies {
compileOnly(libs.nms14)
compileOnly(libs.worldedit15)
compileOnly("org.jetbrains.kotlin:kotlin-stdlib:2.2.21")
}

View File

@@ -257,3 +257,9 @@ include(
include("TNTLeague")
include("WebsiteBackend")
include(
"ModularFightSystem",
"ModularFightSystem:GameCore",
"ModularFightSystem:FightSystem"
)