diff --git a/BauSystem/BauSystem_Main/build.gradle.kts b/BauSystem/BauSystem_Main/build.gradle.kts
index f51b33cd..e29ce456 100644
--- a/BauSystem/BauSystem_Main/build.gradle.kts
+++ b/BauSystem/BauSystem_Main/build.gradle.kts
@@ -19,6 +19,7 @@
plugins {
steamwar.java
+ kotlin("jvm") version "2.4.0"
}
tasks.compileJava {
@@ -26,8 +27,6 @@ tasks.compileJava {
}
java {
- sourceCompatibility = JavaVersion.VERSION_21
- targetCompatibility = JavaVersion.VERSION_21
}
dependencies {
@@ -46,4 +45,11 @@ dependencies {
implementation(libs.luaj)
implementation(files("$projectDir/../libs/YAPION-SNAPSHOT.jar"))
+ implementation(kotlin("stdlib-jdk8"))
}
+repositories {
+ mavenCentral()
+}
+kotlin {
+ jvmToolchain(21)
+}
\ No newline at end of file
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/CannonCore.kt b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/CannonCore.kt
new file mode 100644
index 00000000..5dc34e7d
--- /dev/null
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/CannonCore.kt
@@ -0,0 +1,30 @@
+/*
+ * 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.bausystem.features.cannonCore
+
+import org.bukkit.Location
+
+class CannonCore(val location: Location) {
+
+ companion object Manager {
+ var activeCores: Observable> = Observable(ArrayList())
+ }
+}
+
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/CannonCoreCommand.kt b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/CannonCoreCommand.kt
new file mode 100644
index 00000000..e03bc7d2
--- /dev/null
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/CannonCoreCommand.kt
@@ -0,0 +1,36 @@
+/*
+ * 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.bausystem.features.cannonCore
+
+import de.steamwar.bausystem.SWUtils
+import de.steamwar.command.SWCommand
+import de.steamwar.linkage.Linked
+import org.bukkit.entity.Player
+
+@Linked
+object CannonCoreCommand : SWCommand("cannoncore") {
+
+ @Register
+ fun giveCannonCoreWand(player: Player) {
+ val wandItem = CannonCoreWand.getWandItem()
+
+ SWUtils.giveItemToPlayer(player, wandItem)
+ }
+}
\ No newline at end of file
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/CannonCoreEntity.kt b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/CannonCoreEntity.kt
new file mode 100644
index 00000000..80238791
--- /dev/null
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/CannonCoreEntity.kt
@@ -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 .
+ */
+
+package de.steamwar.bausystem.features.cannonCore
+
+import de.steamwar.entity.RBlockDisplay
+import de.steamwar.entity.REntityAction
+import de.steamwar.entity.REntityServer
+import de.steamwar.entity.RInteraction
+import org.bukkit.Location
+import org.bukkit.Material
+import org.bukkit.entity.Player
+
+class CannonCoreEntity: RBlockDisplay {
+ val entityMaterial = Material.COMMAND_BLOCK
+
+ val hitbox: RInteraction
+
+ constructor(server: REntityServer, location: Location, onClick: (player: Player, clickAction: REntityAction) -> Unit) : super(server, location) {
+ setBlock(entityMaterial.createBlockData())
+
+ hitbox = RInteraction(server, location)
+ hitbox.setCallback(onClick)
+ }
+
+ override fun die() {
+ this.die()
+ hitbox.die()
+ }
+}
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/CannonCoreWand.kt b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/CannonCoreWand.kt
new file mode 100644
index 00000000..c59a6c13
--- /dev/null
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/CannonCoreWand.kt
@@ -0,0 +1,68 @@
+/*
+ * 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.bausystem.features.cannonCore
+
+import de.steamwar.bausystem.utils.ItemUtils
+import de.steamwar.core.SWPlayer
+import de.steamwar.inventory.SWItem
+import de.steamwar.linkage.Linked
+import org.bukkit.Material
+import org.bukkit.event.EventHandler
+import org.bukkit.event.Listener
+import org.bukkit.event.player.PlayerItemHeldEvent
+import org.bukkit.inventory.ItemStack
+
+@Linked
+object CannonCoreWand: Listener {
+ val wandId = "CANNON_CORE_WAND"
+ val wandMaterial = Material.BREEZE_ROD
+
+
+ fun getWandItem(): ItemStack {
+ val title = "Cannon Core Wand"
+ val lore = listOf(
+ "§eRight Click §8- §7Create a new cannon core"
+ )
+
+ val wand = SWItem(wandMaterial, title, lore, false, null)
+ val item = wand.itemStack
+ return ItemUtils.setItem(item, wandId)
+ }
+
+ fun isWandItem(itemStack: ItemStack): Boolean {
+ return ItemUtils.isItem(itemStack, wandId)
+ }
+
+ @EventHandler
+ fun onPlayerEquip(event: PlayerItemHeldEvent) {
+ val player = event.player
+ val swPlayer = SWPlayer.of(event.player)
+ val item = swPlayer.inventory.itemInMainHand
+
+ if(!isWandItem(item)) {
+ swPlayer.removeComponent(EmptyCannonCoreWandDisplay::class.java)
+ }
+ else {
+ // TODO add handling for bound wand
+ val newCursor = EmptyCannonCoreWandDisplay(player)
+ swPlayer.setComponent(newCursor)
+ }
+ }
+}
\ No newline at end of file
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/CannonCoresDisplay.kt b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/CannonCoresDisplay.kt
new file mode 100644
index 00000000..aeae49c8
--- /dev/null
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/CannonCoresDisplay.kt
@@ -0,0 +1,42 @@
+/*
+ * 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.bausystem.features.cannonCore
+
+import de.steamwar.core.SWPlayer
+import de.steamwar.entity.REntityServer
+import org.bukkit.entity.Player
+
+class CannonCoresDisplay: SWPlayer.Component {
+ val displayServer = REntityServer()
+ val unlisten: () -> Unit
+
+ constructor(owner: Player) {
+ displayServer.addPlayer(owner)
+ unlisten = CannonCore.activeCores.observe( { cores ->
+ displayServer.entities.forEach { it.die() }
+ cores.forEach { CannonCoreEntity(displayServer, it.location) { _, _ -> println("Handler clicked at ${it.location}") } }
+ })
+ }
+
+ override fun onUnmount(player: SWPlayer?) {
+ super.onUnmount(player)
+ unlisten()
+ }
+}
\ No newline at end of file
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/EmptyCannonCoreWandDisplay.kt b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/EmptyCannonCoreWandDisplay.kt
new file mode 100644
index 00000000..6f5c745e
--- /dev/null
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/EmptyCannonCoreWandDisplay.kt
@@ -0,0 +1,47 @@
+/*
+ * 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.bausystem.features.cannonCore
+
+import de.steamwar.core.SWPlayer
+import de.steamwar.cursor.Cursor
+import de.steamwar.entity.REntity
+import org.bukkit.Location
+import org.bukkit.Material
+import org.bukkit.entity.Player
+import org.bukkit.event.block.Action
+import java.util.Optional
+
+class EmptyCannonCoreWandDisplay : SWPlayer.Component {
+ val coresDisplay: CannonCoresDisplay
+ val cursor: Cursor
+
+ constructor(owner: Player) {
+ coresDisplay = CannonCoresDisplay(owner)
+
+ cursor = Cursor(
+ coresDisplay.displayServer, owner, Material.GLASS, Material.COMMAND_BLOCK,
+ listOf(
+ Cursor.CursorMode.BLOCK_ALIGNED
+ ),
+ ) { location, hitEntity, action ->
+ print("Hello")
+ }
+ }
+}
\ No newline at end of file
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/Observable.kt b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/Observable.kt
new file mode 100644
index 00000000..9db619c9
--- /dev/null
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/cannonCore/Observable.kt
@@ -0,0 +1,47 @@
+/*
+ * 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.bausystem.features.cannonCore
+
+typealias Observer = (currentValue: T) -> Unit
+
+class Observable(var value: T) {
+ private val observers = ArrayList>()
+
+ fun set(value: T) {
+ val oldValue = this.value
+ this.value = value
+
+ observers.forEach { it.invoke(value) }
+ }
+
+ fun get(): T {
+ return value
+ }
+
+ fun observe(observer: Observer): () -> Unit {
+ observers.add(observer)
+ observer(value)
+ return {removeObserver(observer)}
+ }
+
+ fun removeObserver(observer: Observer) {
+ observers.remove(observer)
+ }
+}
\ No newline at end of file
diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/utils/ItemUtils.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/utils/ItemUtils.java
index 64bd9197..f4958db0 100644
--- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/utils/ItemUtils.java
+++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/utils/ItemUtils.java
@@ -37,8 +37,9 @@ public class ItemUtils {
return value != null && value.equals(tag);
}
- public void setItem(ItemStack itemStack, String tag) {
+ public ItemStack setItem(ItemStack itemStack, String tag) {
setTag(itemStack, ITEM_KEY, tag);
+ return itemStack;
}
public String getTag(ItemStack itemStack, NamespacedKey key) {
diff --git a/settings.gradle.kts b/settings.gradle.kts
index b84535d4..5644decf 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -21,6 +21,10 @@ import org.apache.tools.ant.taskdefs.condition.Os
import java.net.URI
import java.util.*
+plugins {
+ id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0"
+}
+
rootProject.name = "SteamWar"
private val isInCi by lazy { Os.isFamily(Os.FAMILY_UNIX) && ProcessBuilder("hostname").start().inputStream.bufferedReader().readText().startsWith("steamwar.de") }