Compare commits
2 Commits
BauSystem/
...
backend-sy
| Author | SHA1 | Date | |
|---|---|---|---|
| eb218c33ca | |||
| 7b01f11b5b |
25
CommonCore/Data/src/de/steamwar/data/SyncCommands.java
Normal file
25
CommonCore/Data/src/de/steamwar/data/SyncCommands.java
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* 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.data;
|
||||||
|
|
||||||
|
public class SyncCommands {
|
||||||
|
public static final String RELOAD_PLAYER = "reload_player";
|
||||||
|
public static final String RELOAD_EVENT = "reload_event";
|
||||||
|
}
|
||||||
97
VelocityCore/src/de/steamwar/velocitycore/BackendSync.java
Normal file
97
VelocityCore/src/de/steamwar/velocitycore/BackendSync.java
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* 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.velocitycore;
|
||||||
|
|
||||||
|
import de.steamwar.data.SyncCommands;
|
||||||
|
import de.steamwar.sql.Event;
|
||||||
|
import de.steamwar.sql.EventFight;
|
||||||
|
import de.steamwar.sql.SteamwarUser;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.*;
|
||||||
|
|
||||||
|
public class BackendSync implements Runnable {
|
||||||
|
private static final Path syncPath = new File("/run/sync").toPath();
|
||||||
|
private final Thread thread;
|
||||||
|
private final WatchService watchService;
|
||||||
|
|
||||||
|
public BackendSync() {
|
||||||
|
try {
|
||||||
|
watchService
|
||||||
|
= FileSystems.getDefault().newWatchService();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new SecurityException("Could not create watch service", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
thread = new Thread(this, "BackendSync");
|
||||||
|
thread.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
try {
|
||||||
|
watchService.close();
|
||||||
|
thread.join();
|
||||||
|
} catch (IOException | InterruptedException e) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleCommand(String name) {
|
||||||
|
try {
|
||||||
|
String[] parts = name.split("\\.");
|
||||||
|
|
||||||
|
switch (parts[0]) {
|
||||||
|
case SyncCommands.RELOAD_EVENT -> EventFight.loadAllComingFights();
|
||||||
|
case SyncCommands.RELOAD_PLAYER -> SteamwarUser.invalidate(Integer.parseInt(parts[1]));
|
||||||
|
default -> VelocityCore.getLogger().warning("Unknown command: " + name);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
VelocityCore.getLogger().throwing(this.getClass().getName(), "handleCommand", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
try {
|
||||||
|
syncPath.register(watchService,
|
||||||
|
java.nio.file.StandardWatchEventKinds.ENTRY_CREATE);
|
||||||
|
|
||||||
|
WatchKey key;
|
||||||
|
while ((key = watchService.take()) != null) {
|
||||||
|
for (WatchEvent<?> event : key.pollEvents()) {
|
||||||
|
String command = event.context().toString();
|
||||||
|
handleCommand(command);
|
||||||
|
|
||||||
|
if (!VelocityCore.get().getConfig().isEventmode()) {
|
||||||
|
Path path = syncPath.resolve((Path) event.context());
|
||||||
|
Files.delete(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
key.reset();
|
||||||
|
}
|
||||||
|
} catch (InterruptedException | ClosedWatchServiceException ignored) {
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
} catch (Exception e) {
|
||||||
|
VelocityCore.getLogger().throwing(this.getClass().getName(), "run", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -95,6 +95,7 @@ public class VelocityCore implements ReloadablePlugin {
|
|||||||
private Config config;
|
private Config config;
|
||||||
private ErrorLogger errorLogger;
|
private ErrorLogger errorLogger;
|
||||||
private TablistManager tablistManager;
|
private TablistManager tablistManager;
|
||||||
|
private BackendSync backendSync;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private TeamCommand teamCommand;
|
private TeamCommand teamCommand;
|
||||||
@ -147,6 +148,8 @@ public class VelocityCore implements ReloadablePlugin {
|
|||||||
new ReplayMod();
|
new ReplayMod();
|
||||||
new FML2();
|
new FML2();
|
||||||
|
|
||||||
|
backendSync = new BackendSync();
|
||||||
|
|
||||||
new ConnectionListener();
|
new ConnectionListener();
|
||||||
new ChatListener();
|
new ChatListener();
|
||||||
new BanListener();
|
new BanListener();
|
||||||
@ -268,6 +271,8 @@ public class VelocityCore implements ReloadablePlugin {
|
|||||||
logger.log(Level.SEVERE, "Could not shutdown discord bot", e);
|
logger.log(Level.SEVERE, "Could not shutdown discord bot", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
backendSync.stop();
|
||||||
|
|
||||||
if(tablistManager != null)
|
if(tablistManager != null)
|
||||||
tablistManager.disable();
|
tablistManager.disable();
|
||||||
errorLogger.unregister();
|
errorLogger.unregister();
|
||||||
|
|||||||
49
WebsiteBackend/src/de/steamwar/data/VelocitySync.kt
Normal file
49
WebsiteBackend/src/de/steamwar/data/VelocitySync.kt
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
* 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.data
|
||||||
|
|
||||||
|
import de.steamwar.sql.SteamwarUser
|
||||||
|
import java.io.File
|
||||||
|
import java.nio.file.Files
|
||||||
|
|
||||||
|
object VelocitySync {
|
||||||
|
private const val SYNC_PATH = "/run/sync"
|
||||||
|
private val SYNC_FILE = File(SYNC_PATH)
|
||||||
|
private val isWindows = System.getProperty("os.name").lowercase().contains("win")
|
||||||
|
private val lastSendMap = mutableMapOf<String, Long>()
|
||||||
|
|
||||||
|
private fun sendCommand(command: String, vararg args: String) {
|
||||||
|
if (isWindows) { return }
|
||||||
|
|
||||||
|
val name = command + if (args.isNotEmpty()) "." + args.joinToString(".") else ""
|
||||||
|
|
||||||
|
if (lastSendMap[name] != null || lastSendMap[name]!! > System.currentTimeMillis() - 1000) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
lastSendMap[name] = System.currentTimeMillis()
|
||||||
|
|
||||||
|
Files.createFile(File(SYNC_FILE, name).toPath())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun reloadEvent() = sendCommand(SyncCommands.RELOAD_EVENT)
|
||||||
|
|
||||||
|
fun reloadPlayer(user: SteamwarUser) = sendCommand(SyncCommands.RELOAD_PLAYER, user.id.toString())
|
||||||
|
}
|
||||||
@ -20,6 +20,7 @@
|
|||||||
package de.steamwar.routes
|
package de.steamwar.routes
|
||||||
|
|
||||||
import de.steamwar.ResponseError
|
import de.steamwar.ResponseError
|
||||||
|
import de.steamwar.data.VelocitySync
|
||||||
import de.steamwar.sql.*
|
import de.steamwar.sql.*
|
||||||
import io.ktor.http.*
|
import io.ktor.http.*
|
||||||
import io.ktor.server.application.*
|
import io.ktor.server.application.*
|
||||||
@ -112,6 +113,7 @@ fun Route.configureEventFightRoutes() {
|
|||||||
if (fight.group != null) {
|
if (fight.group != null) {
|
||||||
eventFight.setGroup(fight.group)
|
eventFight.setGroup(fight.group)
|
||||||
}
|
}
|
||||||
|
VelocitySync.reloadEvent()
|
||||||
call.respond(HttpStatusCode.Created, ResponseEventFight(eventFight))
|
call.respond(HttpStatusCode.Created, ResponseEventFight(eventFight))
|
||||||
}
|
}
|
||||||
route("/{fight}") {
|
route("/{fight}") {
|
||||||
@ -143,11 +145,13 @@ fun Route.configureEventFightRoutes() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fight.update(start, spielmodus, map, teamBlue, teamRed, spectatePort)
|
fight.update(start, spielmodus, map, teamBlue, teamRed, spectatePort)
|
||||||
|
VelocitySync.reloadEvent()
|
||||||
call.respond(HttpStatusCode.OK, ResponseEventFight(fight))
|
call.respond(HttpStatusCode.OK, ResponseEventFight(fight))
|
||||||
}
|
}
|
||||||
delete {
|
delete {
|
||||||
val fight = call.receiveFight() ?: return@delete
|
val fight = call.receiveFight() ?: return@delete
|
||||||
fight.delete()
|
fight.delete()
|
||||||
|
VelocitySync.reloadEvent()
|
||||||
call.respond(HttpStatusCode.OK)
|
call.respond(HttpStatusCode.OK)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package de.steamwar.routes
|
package de.steamwar.routes
|
||||||
|
|
||||||
|
import de.steamwar.data.VelocitySync
|
||||||
import de.steamwar.plugins.SWPermissionCheck
|
import de.steamwar.plugins.SWPermissionCheck
|
||||||
import de.steamwar.plugins.getUser
|
import de.steamwar.plugins.getUser
|
||||||
import de.steamwar.sql.SteamwarUser
|
import de.steamwar.sql.SteamwarUser
|
||||||
@ -86,6 +87,8 @@ fun Route.configureUserPerms() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UserPerm.addPerm(user, UserPerm.entries.find { it == prefix }!!)
|
UserPerm.addPerm(user, UserPerm.entries.find { it == prefix }!!)
|
||||||
|
|
||||||
|
VelocitySync.reloadPlayer(user)
|
||||||
call.respond(HttpStatusCode.Accepted)
|
call.respond(HttpStatusCode.Accepted)
|
||||||
}
|
}
|
||||||
put("/{perm}") {
|
put("/{perm}") {
|
||||||
@ -96,6 +99,8 @@ fun Route.configureUserPerms() {
|
|||||||
call.respond(HttpStatusCode.Accepted)
|
call.respond(HttpStatusCode.Accepted)
|
||||||
return@put
|
return@put
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VelocitySync.reloadPlayer(user)
|
||||||
call.respond(HttpStatusCode.NoContent)
|
call.respond(HttpStatusCode.NoContent)
|
||||||
}
|
}
|
||||||
delete("/{perm}") {
|
delete("/{perm}") {
|
||||||
@ -106,6 +111,8 @@ fun Route.configureUserPerms() {
|
|||||||
call.respond(HttpStatusCode.Accepted)
|
call.respond(HttpStatusCode.Accepted)
|
||||||
return@delete
|
return@delete
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VelocitySync.reloadPlayer(user)
|
||||||
call.respond(HttpStatusCode.NoContent)
|
call.respond(HttpStatusCode.NoContent)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user