Compare commits
32
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7132bbdfd6 | ||
|
|
397b10c319 | ||
|
|
32569f19d9 | ||
|
|
f19e4158e7 | ||
|
|
6c46b5b2a2 | ||
|
|
58516448d9 | ||
|
|
683236bb59 | ||
|
|
8dc101639d | ||
|
|
792620804a | ||
|
|
4aa7c99a6e | ||
|
|
cce18124f2 | ||
|
|
18ad0ad90c | ||
|
|
a58de898bb | ||
|
|
507b7c2569 | ||
|
|
a18098b8f4 | ||
|
|
97773f292d | ||
|
|
5fdfc03587 | ||
|
|
493e66cc98 | ||
|
|
2be3a136ae | ||
|
|
c62a566447 | ||
|
|
0684765a76 | ||
|
|
c40f29c3c1 | ||
|
|
72dc4eee9e | ||
|
|
c7a949322e | ||
|
|
9d5b7893f1 | ||
|
|
ae898e14c2 | ||
|
|
726f73cc45 | ||
|
|
64e627514d | ||
|
|
3a247de43d
|
||
|
|
bf50b30460 | ||
|
|
6cef6d1f68 | ||
|
|
776b0b1f9f |
+1
-1
@@ -290,7 +290,7 @@ public class KillcheckerVisualizer {
|
||||
}
|
||||
rEntities.get(point).die();
|
||||
}
|
||||
RBlockDisplay entity = new RBlockDisplay(outlinePoints.contains(point) ? outline : inner, point.toLocation(WORLD, 0.5, 0, 0.5));
|
||||
RBlockDisplay entity = new RBlockDisplay(outlinePoints.contains(point) ? outline : inner, point.toLocation(WORLD, 0, 0, 0));
|
||||
entity.setBlock(MATERIALS[Math.min(count - 1, MATERIALS.length) - 1].createBlockData());
|
||||
rEntities.put(point, entity);
|
||||
if (outlinePoints.contains(point)) outlinePointsCache.add(point);
|
||||
|
||||
@@ -165,6 +165,7 @@ public class TPSSystem implements Listener {
|
||||
}
|
||||
|
||||
@Register(value = "default", description = "TPSLIMIT_DEFAULT_HELP")
|
||||
@Register(value = "rate")
|
||||
public void reset(@Validator Player player) {
|
||||
TickManager.impl.setTickRate(20.0F);
|
||||
sendTickRateChange();
|
||||
@@ -187,15 +188,18 @@ public class TPSSystem implements Listener {
|
||||
}
|
||||
|
||||
@Register(value = {"rate", "0"}, description = "TICK_FREEZE_HELP")
|
||||
@Register(value = "freeze", description = "TICK_FREEZE_HELP_2")
|
||||
public void freeze(@Validator Player player) {
|
||||
public void rate(@Validator Player player) {
|
||||
TickManager.impl.setFreeze(true);
|
||||
sendTickRateChange();
|
||||
}
|
||||
|
||||
@Register(value = "unfreeze", description = "TICK_UNFREEZE_HELP")
|
||||
public void unfreeze(@Validator Player player) {
|
||||
TickManager.impl.setTickRate(20.0F);
|
||||
@Register(value = "freeze", description = "TICK_FREEZE_HELP_2")
|
||||
public void freezeToggle(@Validator Player player) {
|
||||
if (TickManager.impl.isFrozen()) {
|
||||
TickManager.impl.setTickRate(20.0F);
|
||||
} else {
|
||||
TickManager.impl.setFreeze(true);
|
||||
}
|
||||
sendTickRateChange();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import de.steamwar.fightsystem.FightSystem;
|
||||
import de.steamwar.fightsystem.states.FightState;
|
||||
import de.steamwar.fightsystem.states.StateDependentListener;
|
||||
import de.steamwar.linkage.Linked;
|
||||
import de.steamwar.sql.GameModeConfig;
|
||||
import de.steamwar.sql.SchematicNode;
|
||||
import de.steamwar.sql.SteamwarUser;
|
||||
import de.steamwar.sql.UserPerm;
|
||||
@@ -44,14 +45,24 @@ public class Check implements Listener {
|
||||
new StateDependentListener(ArenaMode.Check, FightState.All, this);
|
||||
}
|
||||
|
||||
private boolean checkPermission(SteamwarUser user, SchematicNode schematic) {
|
||||
GameModeConfig<Object, String> gameModeConfig = GameModeConfig.getAll().stream()
|
||||
.filter(gmc -> gmc.Schematic.Type != null && gmc.Schematic.Type.equals(schematic.getSchemtype()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (gameModeConfig == null) gameModeConfig = GameModeConfig.getDefaults();
|
||||
if (user.hasPerm(UserPerm.ADMINISTRATION)) return true;
|
||||
if (gameModeConfig.Checkers.isEmpty() && user.hasPerm(UserPerm.CHECK)) return true;
|
||||
return gameModeConfig.Checkers.contains(user.getId());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onJoin(PlayerJoinEvent e) {
|
||||
Player player = e.getPlayer();
|
||||
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
|
||||
|
||||
if (user.hasPerm(UserPerm.CHECK)) return;
|
||||
|
||||
SchematicNode schem = SchematicNode.getSchematicNode(Config.CheckSchemID);
|
||||
if (checkPermission(user, schem)) return;
|
||||
if (user.getId() == schem.getOwner()) return;
|
||||
|
||||
FightSystem.getMessage().send("CHECK_JOIN_DENIED", player);
|
||||
|
||||
@@ -36,6 +36,7 @@ dependencies {
|
||||
compileOnly(libs.paperapi)
|
||||
compileOnly(project(":SpigotCore"))
|
||||
|
||||
implementation(libs.coroutinesCore)
|
||||
implementation(libs.exposedCore)
|
||||
implementation(libs.exposedDao)
|
||||
implementation(libs.exposedJdbc)
|
||||
@@ -47,4 +48,4 @@ val compileKotlin: KotlinCompile by tasks
|
||||
|
||||
compileKotlin.compilerOptions {
|
||||
freeCompilerArgs.set(listOf("-XXLanguage:+ContextParameters"))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* 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.kotlin.ui
|
||||
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
abstract class Observable<T> {
|
||||
internal val listeners = mutableSetOf<ObserverListener>()
|
||||
|
||||
open fun removeListener(render: ObserverListener) {
|
||||
listeners.remove(render)
|
||||
}
|
||||
|
||||
internal fun notifyListeners() {
|
||||
listeners.forEach { it.update() }
|
||||
}
|
||||
|
||||
context(render: ObserverListener)
|
||||
fun listen(): Observable<T> {
|
||||
listeners.add(render)
|
||||
render.observers.add(this)
|
||||
return this
|
||||
}
|
||||
|
||||
fun listen(callback: (T) -> Unit): () -> Unit {
|
||||
val listener = object: ObserverListener() {
|
||||
override fun update() = callback(get())
|
||||
}
|
||||
listeners.add(listener)
|
||||
callback(get())
|
||||
return { removeListener(listener) }
|
||||
}
|
||||
|
||||
abstract fun get(): T
|
||||
|
||||
fun <R> map(mapper: (T) -> R): Observable<R> = Delegate(mapper, this)
|
||||
|
||||
class Delegate<T, R>(val mapper: (T) -> R, val parent: Observable<T>): Observable<R>(), ReadOnlyProperty<Any?, R> {
|
||||
var value: R? = null
|
||||
var unsubParent = parent.listen {
|
||||
val old = value
|
||||
value = mapper(it)
|
||||
if (old != value) {
|
||||
notifyListeners()
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeListener(render: ObserverListener) {
|
||||
super.removeListener(render)
|
||||
if (listeners.isEmpty()) {
|
||||
unsubParent()
|
||||
}
|
||||
}
|
||||
|
||||
override fun get(): R = value!!
|
||||
|
||||
override fun getValue(thisRef: Any?, property: KProperty<*>): R = value!!
|
||||
}
|
||||
}
|
||||
|
||||
class Observer<T>(private var value: T): ReadWriteProperty<Any?, T>, Observable<T>() {
|
||||
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
|
||||
return value
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
|
||||
this.value = value
|
||||
notifyListeners()
|
||||
}
|
||||
|
||||
fun set(value: T) {
|
||||
this.value = value
|
||||
notifyListeners()
|
||||
}
|
||||
|
||||
override fun get() = value
|
||||
|
||||
fun update(update: (T) -> T) {
|
||||
this.value = update(value)
|
||||
notifyListeners()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.kotlin.ui
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.ExperimentalForInheritanceCoroutinesApi
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import kotlinx.coroutines.flow.FlowCollector
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
private val uiStateScope = CoroutineScope(SupervisorJob() + Dispatchers.Unconfined)
|
||||
|
||||
context(render: StateFlowListener)
|
||||
fun <T> StateFlow<T>.listen(): StateFlow<T> {
|
||||
render.track(this) {
|
||||
drop(1).onEach { render.update() }.launchIn(uiStateScope)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
context(render: StateFlowListener)
|
||||
fun <T> MutableStateFlow<T>.listen(): MutableStateFlow<T> {
|
||||
render.track(this) {
|
||||
drop(1).onEach { render.update() }.launchIn(uiStateScope)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
fun <T> StateFlow<T>.listen(callback: (T) -> Unit): () -> Unit {
|
||||
callback(value)
|
||||
val job = drop(1).onEach { callback(it) }.launchIn(uiStateScope)
|
||||
return { job.cancel() }
|
||||
}
|
||||
|
||||
operator fun <T> StateFlow<T>.getValue(thisRef: Any?, property: KProperty<*>): T = value
|
||||
|
||||
operator fun <T> MutableStateFlow<T>.setValue(thisRef: Any?, property: KProperty<*>, value: T) {
|
||||
this.value = value
|
||||
}
|
||||
|
||||
fun <T, R> StateFlow<T>.map(mapper: (T) -> R): StateFlow<R> = MappedStateFlow(this, mapper)
|
||||
|
||||
@OptIn(ExperimentalForInheritanceCoroutinesApi::class)
|
||||
private class MappedStateFlow<T, R>(
|
||||
private val parent: StateFlow<T>,
|
||||
private val mapper: (T) -> R,
|
||||
): StateFlow<R> {
|
||||
override val replayCache: List<R>
|
||||
get() = listOf(value)
|
||||
|
||||
override val value: R
|
||||
get() = mapper(parent.value)
|
||||
|
||||
override suspend fun collect(collector: FlowCollector<R>): Nothing {
|
||||
var initialized = false
|
||||
var previous: Any? = null
|
||||
|
||||
parent.collect {
|
||||
val mapped = mapper(it)
|
||||
if (!initialized || previous != mapped) {
|
||||
initialized = true
|
||||
previous = mapped
|
||||
collector.emit(mapped)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
-5
@@ -19,13 +19,23 @@
|
||||
|
||||
package de.steamwar.kotlin.ui
|
||||
|
||||
abstract class ObserverListener {
|
||||
val observers = mutableSetOf<Observable<*>>()
|
||||
import kotlinx.coroutines.Job
|
||||
|
||||
abstract class StateFlowListener {
|
||||
private val jobs = mutableMapOf<Any, Job>()
|
||||
|
||||
internal fun track(key: Any, createJob: () -> Job) {
|
||||
if (key in jobs) return
|
||||
|
||||
val job = createJob()
|
||||
jobs[key] = job
|
||||
job.invokeOnCompletion { jobs.remove(key) }
|
||||
}
|
||||
|
||||
abstract fun update()
|
||||
|
||||
open fun destroy() {
|
||||
observers.forEach { it.removeListener(this) }
|
||||
observers.clear()
|
||||
jobs.values.toList().forEach { it.cancel() }
|
||||
jobs.clear()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.kotlin.ui
|
||||
|
||||
import de.steamwar.kotlin.ui.components.item
|
||||
import de.steamwar.kotlin.util.count
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
val Counter = MutableStateFlow(0)
|
||||
|
||||
class TestInv(player: Player): UIInventory(player) {
|
||||
override fun view() {
|
||||
inventory(3, "") {
|
||||
item {
|
||||
val amount by Counter.map { it + 1 }.listen()
|
||||
item = ItemStack.of(Material.STONE)
|
||||
.count(amount)
|
||||
x = 0
|
||||
y = 0
|
||||
onClick {
|
||||
Counter.value += 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ import de.steamwar.kotlin.ui.context.WindowContext
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.event.inventory.InventoryType
|
||||
|
||||
abstract class UIInventory(val player: Player): ObserverListener() {
|
||||
abstract class UIInventory(val player: Player): StateFlowListener() {
|
||||
var window: UIWindow? = null
|
||||
|
||||
abstract fun view()
|
||||
@@ -52,4 +52,4 @@ abstract class UIInventory(val player: Player): ObserverListener() {
|
||||
protected fun inventory(type: InventoryType, title: String, init: WindowContext.() -> Unit) {
|
||||
window = UIWindow(type, title, player, init)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
package de.steamwar.kotlin.ui.components
|
||||
|
||||
import de.steamwar.kotlin.ui.ObserverListener
|
||||
import de.steamwar.kotlin.ui.StateFlowListener
|
||||
import de.steamwar.kotlin.ui.RenderMarker
|
||||
import de.steamwar.kotlin.ui.RenderObject
|
||||
import de.steamwar.kotlin.ui.context.GroupContext
|
||||
@@ -29,7 +29,7 @@ import org.bukkit.event.inventory.InventoryClickEvent
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
@RenderMarker
|
||||
class ItemContext(val parent: RenderParent, val renderFunc: ItemContext.() -> Unit): RenderObject, ObserverListener() {
|
||||
class ItemContext(val parent: RenderParent, val renderFunc: ItemContext.() -> Unit): RenderObject, StateFlowListener() {
|
||||
override fun update() {
|
||||
val oldX = x
|
||||
val oldY = y
|
||||
@@ -40,6 +40,7 @@ class ItemContext(val parent: RenderParent, val renderFunc: ItemContext.() -> Un
|
||||
}
|
||||
|
||||
override fun destroy() {
|
||||
super.destroy()
|
||||
parent.resetSlot(x, y)
|
||||
}
|
||||
|
||||
|
||||
@@ -19,14 +19,14 @@
|
||||
|
||||
package de.steamwar.kotlin.ui.context
|
||||
|
||||
import de.steamwar.kotlin.ui.ObserverListener
|
||||
import de.steamwar.kotlin.ui.StateFlowListener
|
||||
import de.steamwar.kotlin.ui.RenderMarker
|
||||
import de.steamwar.kotlin.ui.RenderObject
|
||||
import org.bukkit.event.inventory.InventoryClickEvent
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
@RenderMarker
|
||||
open class GroupContext(val parent: RenderParent?, val init: GroupContext.() -> Unit): ObserverListener(), RenderObject, RenderParent {
|
||||
open class GroupContext(val parent: RenderParent?, val init: GroupContext.() -> Unit): StateFlowListener(), RenderObject, RenderParent {
|
||||
val children = mutableListOf<RenderObject>()
|
||||
val updatedSlots = mutableSetOf<Pair<Int, Int>>()
|
||||
|
||||
@@ -62,4 +62,4 @@ open class GroupContext(val parent: RenderParent?, val init: GroupContext.() ->
|
||||
init(this)
|
||||
(oldUpdatedSlots - updatedSlots).forEach { resetSlot(it.first, it.second) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,7 +271,8 @@ CHALLENGE_ACCEPT_HOVER = §aAccept challenge
|
||||
#EventCommand
|
||||
EVENT_TIME_FORMAT = HH:mm
|
||||
EVENT_DATE_FORMAT = dd.MM.
|
||||
EVENT_USAGE = §8/§7event §8[§eTeam§8] - §7To teleport to a fight
|
||||
EVENT_TEAM_USAGE = §8/§7event team §8[§eTeam§8] - §7To teleport to a fight
|
||||
EVENT_SHOW_FIGHTS_USAGE = §8/§7event showfights §8[§eEvent§8] - §7To show the fights of that Event
|
||||
EVENT_NO_TEAM = §cThis team does not exist
|
||||
EVENT_NO_FIGHT_TEAM = §cThis team has no current fight
|
||||
EVENT_NO_CURRENT = §cThere is no event taking place currently
|
||||
@@ -282,9 +283,13 @@ EVENT_COMING_SCHEM_DEADLINE = §7 Submission deadline§8: §7{0}
|
||||
EVENT_COMING_TEAMS = §7 With§8: {0}
|
||||
EVENT_COMING_TEAM = §{0}{1}
|
||||
EVENT_CURRENT_EVENT = §e§l{0}
|
||||
EVENT_CURRENT_FIGHT = §7{0} §{1}{2}§8 vs §{3}{4}
|
||||
EVENT_CURRENT_FIGHT_1 = §7{0} §{1}{2}
|
||||
EVENT_CURRENT_FIGHT_VS = §8 vs
|
||||
EVENT_CURRENT_FIGHT_2 = §{1}{2}
|
||||
EVENT_CURRENT_FIGHT_WIN = §8: §7Victory §{0}{1}
|
||||
EVENT_CURRENT_FIGHT_DRAW = §8: §7Draw
|
||||
EVENT_TEAM_TABLE = §{0}{1}{2} §8 with §e{3} §7points
|
||||
EVENT_SHOW_TABLE_USAGE = §8/§7event showtable §8[§eEvent§8] - §7To show the table of that Event
|
||||
|
||||
#EventRescheduleCommand
|
||||
EVENTRESCHEDULE_USAGE = §8/§7eventreschedule §8[§eTeam1§8] [§eTeam2§8]
|
||||
@@ -751,3 +756,9 @@ DC_SCHEMUPLOAD_IGNORED = Skipping `{0}`, not a schematic file.
|
||||
DC_SCHEMUPLOAD_INVCHAR = `{0}` has invalid characters in its name.
|
||||
DC_SCHEMUPLOAD_SUCCESS = `{0}` was uploaded successfully.
|
||||
DC_SCHEMUPLOAD_ERROR = An error has occured during the upload of `{0}`. For more information ask a Developer.
|
||||
|
||||
UTIL_LIST_BACK_ARROW = §8««
|
||||
UTIL_LIST_BACK_ARROW_HOVER = §ePrevious page
|
||||
UTIL_LIST_PAGE = §e Page §7({0}/{1})
|
||||
UTIL_LIST_NEXT = §8 »»
|
||||
UTIL_LIST_NEXT_HOVER = §eNext page
|
||||
@@ -253,7 +253,8 @@ CHALLENGE_ACCEPT_HOVER = §aHerausforderung annehmen
|
||||
#EventCommand
|
||||
EVENT_TIME_FORMAT = HH:mm
|
||||
EVENT_DATE_FORMAT = dd.MM.
|
||||
EVENT_USAGE = §8/§7event §8[§eTeam§8] - §7Um dich zum Kampf zu teleportieren
|
||||
EVENT_TEAM_USAGE=§8/§7event team §8[§eTeam§8] - §7Um dich zum Kampf zu teleportieren
|
||||
EVENT_SHOW_FIGHTS_USAGE = §8/§7event showfights §8[§eEvent§8] - §7Um die fights des Events zu zeigen
|
||||
EVENT_NO_TEAM = §cDieses Team gibt es nicht
|
||||
EVENT_NO_FIGHT_TEAM = §cDas Team kämpft derzeit nicht
|
||||
EVENT_NO_CURRENT = §cDerzeit findet kein Event statt
|
||||
@@ -264,9 +265,10 @@ EVENT_COMING_SCHEM_DEADLINE = §7 Einsendeschluss§8: §7{0}
|
||||
EVENT_COMING_TEAMS = §7 Mit§8: {0}
|
||||
EVENT_COMING_TEAM = §{0}{1}
|
||||
EVENT_CURRENT_EVENT = §e§l{0}
|
||||
EVENT_CURRENT_FIGHT = §7{0} §{1}{2}§8 vs §{3}{4}
|
||||
EVENT_CURRENT_FIGHT_WIN = §8: §7Sieg §{0}{1}
|
||||
EVENT_CURRENT_FIGHT_DRAW = §8: §7Unentschieden
|
||||
EVENT_TEAM_TABLE = §{0}{1}{2} §8 mit §e{3} §7Punkten
|
||||
EVENT_SHOW_TABLE_USAGE = §8/§7event showtable §8[§eEvent§8] - §7Um die Tabelle des Events zu zeigen.
|
||||
|
||||
#EventRescheduleCommand
|
||||
EVENTRESCHEDULE_USAGE = §8/§7eventreschedule §8[§eTeam1§8] [§eTeam2§8]
|
||||
|
||||
@@ -55,7 +55,7 @@ public class ServerStarter {
|
||||
public static final String WORLDS_BASE_PATH = WORLDS_FOLDER + "/userworlds";
|
||||
public static final String BUILDER_BASE_PATH = WORLDS_FOLDER + "/builder";
|
||||
|
||||
private static final String WORLDS_STORAGE_BASE_PATH = "/mnt/storage/worlds/userworlds";
|
||||
public static final String WORLDS_STORAGE_BASE_PATH = "/mnt/storage/worlds/userworlds";
|
||||
|
||||
private File directory = null;
|
||||
private String worldDir = null;
|
||||
|
||||
@@ -44,6 +44,7 @@ import de.steamwar.velocitycore.inventory.SWItem;
|
||||
import de.steamwar.velocitycore.network.NetworkSender;
|
||||
import de.steamwar.velocitycore.util.BauLock;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -187,11 +188,35 @@ public class BauCommand extends SWCommand {
|
||||
bauserver.getRegisteredServer().getPlayersConnected().stream().findAny().ifPresent(player -> NetworkSender.send(player, new BaumemberUpdatePacket()));
|
||||
}
|
||||
|
||||
try {
|
||||
deletePlayerData(owner, user);
|
||||
} catch (Exception e) {
|
||||
// Ignore this silently since it does not matter in any way if the data is not deleted properly.
|
||||
}
|
||||
|
||||
member.system("BAU_DELMEMBER_DELETED_TARGET", owner);
|
||||
owner.system("BAU_DELMEMBER_DELETED");
|
||||
});
|
||||
}
|
||||
|
||||
private void deletePlayerData(Chatter owner, SteamwarUser user) {
|
||||
String worldName = String.valueOf(owner.user().getId());
|
||||
String targetDat = user.getUUID().toString().toLowerCase() + ".dat";
|
||||
String targetDatOld = user.getUUID().toString().toLowerCase() + ".dat_old";
|
||||
for (ServerVersion version : ServerVersion.values()) {
|
||||
File playerData = new File(new File(version.getWorldFolder(ServerStarter.WORLDS_BASE_PATH), worldName), "playerdata");
|
||||
if (playerData.exists()) {
|
||||
new File(playerData, targetDat).delete();
|
||||
new File(playerData, targetDatOld).delete();
|
||||
}
|
||||
File playerDataStorage = new File(new File(version.getWorldFolder(ServerStarter.WORLDS_STORAGE_BASE_PATH), worldName), "playerdata");
|
||||
if (playerDataStorage.exists()) {
|
||||
new File(playerDataStorage, targetDat).delete();
|
||||
new File(playerDataStorage, targetDatOld).delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Mapper(value = "addedUsers", local = true)
|
||||
public TypeMapper<SteamwarUser> addedUsers() {
|
||||
return new TypeMapper<SteamwarUser>() {
|
||||
|
||||
@@ -85,7 +85,6 @@ public class CheckCommand extends SWCommand {
|
||||
if (user.perms().contains(UserPerm.CHECK)) return true;
|
||||
return GameModeConfig.getAll()
|
||||
.stream()
|
||||
.filter(GameModeConfig::isActive)
|
||||
.anyMatch(gameMode -> gameMode.Checkers.contains(user.getId()));
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
package de.steamwar.velocitycore.commands;
|
||||
|
||||
import com.google.protobuf.MapEntry;
|
||||
import de.steamwar.command.PreviousArguments;
|
||||
import de.steamwar.command.SWCommand;
|
||||
import de.steamwar.command.TypeMapper;
|
||||
@@ -28,13 +29,18 @@ import de.steamwar.messages.Chatter;
|
||||
import de.steamwar.messages.PlayerChatter;
|
||||
import de.steamwar.persistent.Subserver;
|
||||
import de.steamwar.sql.*;
|
||||
import de.steamwar.sql.Event;
|
||||
import de.steamwar.velocitycore.EventStarter;
|
||||
import de.steamwar.velocitycore.SubserverSystem;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
|
||||
import java.awt.*;
|
||||
import java.sql.Timestamp;
|
||||
import java.time.Instant;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -82,35 +88,84 @@ public class EventCommand extends SWCommand {
|
||||
|
||||
@Register
|
||||
public void eventOverview(@Validator(value = "noEvent", invert = true) Chatter sender) {
|
||||
sender.system("EVENT_USAGE");
|
||||
sender.system("EVENT_TEAM_USAGE");
|
||||
|
||||
Event currentEvent = Event.get();
|
||||
sender.system("EVENT_CURRENT_EVENT", currentEvent.getEventName());
|
||||
eventShowFightsPage(sender, currentEvent, 1);
|
||||
}
|
||||
|
||||
DateTimeFormatter format = DateTimeFormatter.ofPattern(sender.parseToPlain("EVENT_TIME_FORMAT"));
|
||||
for (EventFight fight : EventFight.getEvent(currentEvent.getEventID())) {
|
||||
Team blue = Team.byId(fight.getTeamBlue());
|
||||
Team red = Team.byId(fight.getTeamRed());
|
||||
StringBuilder fline = new StringBuilder(sender.parseToLegacy("EVENT_CURRENT_FIGHT", fight.getStartTime().toLocalDateTime().format(format), blue.getTeamColor(), blue.getTeamKuerzel(), red.getTeamColor(), red.getTeamKuerzel()));
|
||||
@Register(value = "showtable", description = "EVENT_SHOW_TABLE_USAGE")
|
||||
public void eventtable(Chatter sender, Event event) {
|
||||
if (!Instant.now().isBefore(event.getEnd().toInstant())) return;
|
||||
|
||||
if (fight.hasFinished()) {
|
||||
switch (fight.getErgebnis()) {
|
||||
Map<Integer, Integer> Teampoints = new HashMap<>();
|
||||
|
||||
EventFight.getEvent(event.getEventID()).forEach(eventFight -> {
|
||||
if (eventFight.hasFinished() && eventFight.getGroup().isPresent()) {
|
||||
switch (eventFight.getErgebnis()) {
|
||||
case 1:
|
||||
fline.append(sender.parseToLegacy("EVENT_CURRENT_FIGHT_WIN", blue.getTeamColor(), blue.getTeamKuerzel()));
|
||||
//win blue
|
||||
Teampoints.put(eventFight.getTeamBlue(), Teampoints.getOrDefault(eventFight.getTeamBlue(), 0) + eventFight.getGroup().get().getPointsPerWin());
|
||||
Teampoints.put(eventFight.getTeamRed(), Teampoints.getOrDefault(eventFight.getTeamRed(),0) + eventFight.getGroup().get().getPointsPerLoss());
|
||||
break;
|
||||
case 2:
|
||||
fline.append(sender.parseToLegacy("EVENT_CURRENT_FIGHT_WIN", red.getTeamColor(), red.getTeamKuerzel()));
|
||||
//win red
|
||||
Teampoints.put(eventFight.getTeamBlue(), Teampoints.getOrDefault(eventFight.getTeamBlue(),0) + eventFight.getGroup().get().getPointsPerLoss());
|
||||
Teampoints.put(eventFight.getTeamRed(), Teampoints.getOrDefault(eventFight.getTeamRed(),0) + eventFight.getGroup().get().getPointsPerWin());
|
||||
break;
|
||||
default:
|
||||
fline.append(sender.parseToLegacy("EVENT_CURRENT_FIGHT_DRAW"));
|
||||
//draw
|
||||
Teampoints.put(eventFight.getTeamBlue(), Teampoints.getOrDefault(eventFight.getTeamBlue(),0) + eventFight.getGroup().get().getPointsPerDraw());
|
||||
Teampoints.put(eventFight.getTeamRed(), Teampoints.getOrDefault(eventFight.getTeamRed(),0) + eventFight.getGroup().get().getPointsPerDraw());
|
||||
}
|
||||
}
|
||||
});
|
||||
Map<Integer, Integer> Teampointssortet = Teampoints.entrySet()
|
||||
.stream()
|
||||
.sorted(Map.Entry.comparingByValue())
|
||||
.collect(Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
Map.Entry::getValue,
|
||||
(a , b) -> a,
|
||||
LinkedHashMap::new
|
||||
));
|
||||
|
||||
sender.prefixless("PLAIN_STRING", fline.toString());
|
||||
for (Map.Entry<Integer, Integer> entry : Teampointssortet.entrySet()) {
|
||||
Component finalmessage = sender.parse("EVENT_TEAM_TABLE",Team.byId(entry.getKey()).getTeamColor(), Team.byId(entry.getKey()).getTeamKuerzel(), Team.byId(entry.getKey()).getTeamName(), entry.getValue());
|
||||
finalmessage = finalmessage.clickEvent(ClickEvent.runCommand("/team info " + Team.byId(entry.getKey()).getTeamName()));
|
||||
sender.sendMessage(finalmessage);
|
||||
}
|
||||
}
|
||||
|
||||
@Register
|
||||
@Register(value = "showfights", description = "EVENT_SHOW_FIGHTS_USAGE")
|
||||
public void eventShowFightsPage(Chatter sender, Event event, @AllowNull @OptionalValue("1") int page) {
|
||||
if (!Instant.now().isBefore(event.getEnd().toInstant())) return;
|
||||
int pagecount = sendEventPage(sender, event, page);
|
||||
|
||||
Integer nextpage = page + 1;
|
||||
Integer prevpage = page - 1;
|
||||
|
||||
Component finalmessage;
|
||||
|
||||
Component pagenumber = sender.parse("UTIL_LIST_PAGE", page, pagecount);
|
||||
|
||||
if (pagecount != 0 && page != 1) {
|
||||
finalmessage = sender.parse("UTIL_LIST_BACK_ARROW");
|
||||
finalmessage = finalmessage.clickEvent(ClickEvent.runCommand("/event showfights " + event.getEventName() + " " + prevpage));
|
||||
finalmessage = finalmessage.append(pagenumber);
|
||||
} else {
|
||||
finalmessage = pagenumber;
|
||||
}
|
||||
|
||||
if (pagecount != 0 && pagecount > page) {
|
||||
Component nextbutton = sender.parse("UTIL_LIST_NEXT");
|
||||
nextbutton = nextbutton.clickEvent(ClickEvent.runCommand("/event showfights " + event.getEventName() + " " + nextpage));
|
||||
finalmessage = finalmessage.append(nextbutton);
|
||||
}
|
||||
sender.sendMessage(finalmessage);
|
||||
}
|
||||
|
||||
@Register(value = "team", description = "EVENT_TEAM_USAGE")
|
||||
public void eventWithTeam(@Validator(value = "noEvent", invert = true) PlayerChatter sender, @ErrorMessage("EVENT_NO_TEAM") Team team) {
|
||||
Subserver eventArena = EventStarter.getEventServer().get(team.getTeamId());
|
||||
if (eventArena == null || !Subserver.getServerList().contains(eventArena)) {
|
||||
@@ -122,6 +177,69 @@ public class EventCommand extends SWCommand {
|
||||
}
|
||||
}
|
||||
|
||||
private int sendEventPage(Chatter sender, Event event, int page) {
|
||||
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(sender.parseToPlain("EVENT_DATE_FORMAT"));
|
||||
Map<String, List<EventFight>> dates = EventFight.getEvent(event.getEventID()).stream().collect(Collectors.groupingBy(p -> p.getStartTime().toLocalDateTime().format(dateTimeFormatter)));
|
||||
if (dates.size() >= page) {
|
||||
sender.system("EVENT_CURRENT_EVENT", event.getEventName());
|
||||
DateTimeFormatter format = DateTimeFormatter.ofPattern(sender.parseToPlain("EVENT_TIME_FORMAT"));
|
||||
for (EventFight eventFight : dates.get(dates.keySet().toArray()[page - 1])) {
|
||||
Team blue = Team.byId(eventFight.getTeamBlue());
|
||||
Team red = Team.byId(eventFight.getTeamRed());
|
||||
Component finalfightline = sender.parse("EVENT_CURRENT_FIGHT_1", eventFight.getStartTime().toLocalDateTime().format(format), blue.getTeamColor(), blue.getTeamKuerzel());
|
||||
finalfightline = finalfightline.clickEvent(ClickEvent.runCommand("/team info " + blue.getTeamName()));
|
||||
Component vs = sender.parse("EVENT_CURRENT_FIGHT_VS");
|
||||
finalfightline = finalfightline.append(vs);
|
||||
Component redteam = sender.parse("EVENT_CURRENT_FIGHT_2", red.getTeamColor(), red.getTeamKuerzel());
|
||||
redteam = redteam.clickEvent(ClickEvent.runCommand("/team info " + red.getTeamName()));
|
||||
finalfightline = finalfightline.append(redteam);
|
||||
|
||||
if (eventFight.hasFinished()) {
|
||||
Component ergebnis;
|
||||
switch (eventFight.getErgebnis()) {
|
||||
case 1:
|
||||
ergebnis = sender.parse("EVENT_CURRENT_FIGHT_WIN", blue.getTeamColor(), blue.getTeamKuerzel());
|
||||
break;
|
||||
case 2:
|
||||
ergebnis = sender.parse("EVENT_CURRENT_FIGHT_WIN", red.getTeamColor(), red.getTeamKuerzel());
|
||||
break;
|
||||
default:
|
||||
ergebnis = sender.parse("EVENT_CURRENT_FIGHT_DRAW");
|
||||
}
|
||||
finalfightline = finalfightline.append(ergebnis);
|
||||
}
|
||||
sender.sendMessage(finalfightline);
|
||||
}
|
||||
}
|
||||
return dates.size();
|
||||
}
|
||||
|
||||
protected static TypeMapper<Event> eventTypeMapper() {
|
||||
return new TypeMapper<>() {
|
||||
@Override
|
||||
public Event map(Chatter sender, PreviousArguments previousArguments, String s) {
|
||||
return Event.get(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> tabCompletes(Chatter sender, PreviousArguments previousArguments, String s) {
|
||||
Set<String> events = new HashSet<>();
|
||||
List<Event> allevents = Event.getAll();
|
||||
for (Event event : allevents) {
|
||||
if (!Instant.now().isAfter(event.getEnd().toInstant())) {
|
||||
events.add(event.getEventName());
|
||||
}
|
||||
}
|
||||
return events;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ClassMapper(value = Event.class, local = true)
|
||||
public TypeMapper<Event> eventMapper() {
|
||||
return eventTypeMapper();
|
||||
}
|
||||
|
||||
protected static TypeMapper<Team> eventTeam(Function<EventFight, List<Integer>> teamMapper) {
|
||||
return new TypeMapper<>() {
|
||||
@Override
|
||||
|
||||
@@ -39,22 +39,28 @@ public class TexturePackSystem extends BasicListener {
|
||||
|
||||
private static final File PACKS_DIR = new File("/var/www/packs");
|
||||
private static final String BASE_ULR = "https://packs.steamwar.de/";
|
||||
private TreeMap<Integer, Integer> protocolVersionToPackVersion = new TreeMap<>();
|
||||
private TreeMap<Integer, String> protocolVersionToPackVersion = new TreeMap<>();
|
||||
|
||||
public TexturePackSystem() {
|
||||
// https://minecraft.wiki/w/Pack_format#List_of_resource_pack_formats
|
||||
// https://minecraft.wiki/w/Minecraft_Wiki:Projects/wiki.vg_merge/Protocol_version_numbers
|
||||
protocolVersionToPackVersion.put(759, 9);
|
||||
protocolVersionToPackVersion.put(761, 12);
|
||||
protocolVersionToPackVersion.put(762, 13);
|
||||
protocolVersionToPackVersion.put(763, 15);
|
||||
protocolVersionToPackVersion.put(764, 18);
|
||||
protocolVersionToPackVersion.put(765, 22);
|
||||
protocolVersionToPackVersion.put(766, 32);
|
||||
protocolVersionToPackVersion.put(767, 34);
|
||||
protocolVersionToPackVersion.put(768, 42);
|
||||
protocolVersionToPackVersion.put(769, 46);
|
||||
protocolVersionToPackVersion.put(770, 55);
|
||||
protocolVersionToPackVersion.put(759, "9");
|
||||
protocolVersionToPackVersion.put(761, "12");
|
||||
protocolVersionToPackVersion.put(762, "13");
|
||||
protocolVersionToPackVersion.put(763, "15");
|
||||
protocolVersionToPackVersion.put(764, "18");
|
||||
protocolVersionToPackVersion.put(765, "22");
|
||||
protocolVersionToPackVersion.put(766, "32");
|
||||
protocolVersionToPackVersion.put(767, "34");
|
||||
protocolVersionToPackVersion.put(768, "42");
|
||||
protocolVersionToPackVersion.put(769, "46");
|
||||
protocolVersionToPackVersion.put(770, "55");
|
||||
protocolVersionToPackVersion.put(771, "63");
|
||||
protocolVersionToPackVersion.put(772, "64");
|
||||
protocolVersionToPackVersion.put(773, "69.0");
|
||||
protocolVersionToPackVersion.put(774, "75.0");
|
||||
protocolVersionToPackVersion.put(775, "84.0");
|
||||
protocolVersionToPackVersion.put(776, "88.0");
|
||||
}
|
||||
|
||||
@Subscribe
|
||||
@@ -63,20 +69,19 @@ public class TexturePackSystem extends BasicListener {
|
||||
return;
|
||||
}
|
||||
VelocityCore.schedule(() -> {
|
||||
TreeMap<Integer, File> fileTreeMap = new TreeMap<>();
|
||||
TreeMap<String, File> fileTreeMap = new TreeMap<>();
|
||||
for (File fileEntry : PACKS_DIR.listFiles()) {
|
||||
try {
|
||||
int packVersion = Integer.parseInt(fileEntry.getName().split("_")[0]);
|
||||
fileTreeMap.put(packVersion, fileEntry);
|
||||
fileTreeMap.put(fileEntry.getName().split("_")[0], fileEntry);
|
||||
} catch (NumberFormatException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
|
||||
int playerVersion = event.getPlayer().getProtocolVersion().getProtocol();
|
||||
Map.Entry<Integer, Integer> packVersionEntry = protocolVersionToPackVersion.floorEntry(playerVersion);
|
||||
Map.Entry<Integer, String> packVersionEntry = protocolVersionToPackVersion.floorEntry(playerVersion);
|
||||
if (packVersionEntry == null) return;
|
||||
Map.Entry<Integer, File> selectedPackEntry = fileTreeMap.floorEntry(packVersionEntry.getValue());
|
||||
Map.Entry<String, File> selectedPackEntry = fileTreeMap.floorEntry(packVersionEntry.getValue());
|
||||
if (selectedPackEntry == null) return;
|
||||
File selectedPack = selectedPackEntry.getValue();
|
||||
|
||||
|
||||
@@ -128,6 +128,7 @@ dependencyResolutionManagement {
|
||||
library("msgpack", "org.msgpack:msgpack-core:0.9.8")
|
||||
|
||||
library("logback", "ch.qos.logback:logback-classic:1.5.6")
|
||||
library("coroutinesCore", "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2")
|
||||
|
||||
val ktorVersion = "2.3.12"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user