1
0

Commits vergleichen

...

14 Commits

Autor SHA1 Nachricht Datum
3b0e4aa5aa Fix SchematicSearch 2023-05-01 16:12:45 +02:00
d9ad5bd14a Merge branch 'master' into schemsearch 2023-05-01 13:53:46 +02:00
1c54b1c60f Add Copyright 2023-04-13 19:02:48 +02:00
ec0c06227f Remove TestCommand 2023-04-12 02:08:59 +02:00
3bd18531f5 Update CC 2023-04-12 02:08:09 +02:00
afece3008c Merge branch 'master' into schemsearch 2023-04-12 02:05:58 +02:00
a6dbf41feb Finish it up 2023-04-12 02:05:23 +02:00
e728483e5f Merge branch 'master' into schemsearch 2023-04-09 13:39:16 +02:00
b7d42a767a idk 2023-04-06 20:42:05 +02:00
badb5e5e1e Stop the dog 2023-04-06 17:30:18 +02:00
f624d2893d Add catch for IOException 2023-04-06 17:22:20 +02:00
edb108b7b3 Add Softreload cancel 2023-04-06 17:11:17 +02:00
81dbcc691a Add Softreload cancel 2023-04-06 17:07:16 +02:00
06d3aeb9d1 Basic SchemSearch 2023-04-06 14:23:26 +02:00
8 geänderte Dateien mit 428 neuen und 1 gelöschten Zeilen

Datei anzeigen

@ -28,6 +28,7 @@ import de.steamwar.bungeecore.listeners.ping.PingListener;
import de.steamwar.bungeecore.network.BungeeNetworkHandler;
import de.steamwar.bungeecore.network.NetworkReceiver;
import de.steamwar.bungeecore.network.SWScriptSyntaxForwarder;
import de.steamwar.bungeecore.util.SchematicSearch;
import de.steamwar.sql.Punishment;
import de.steamwar.sql.SteamwarUser;
import de.steamwar.sql.UserElo;
@ -122,6 +123,7 @@ public class BungeeCore extends Plugin {
new Fabric();
new SubserverProtocolFixer();
new PingListener();
new SchematicSearchListener();
local = new Node.LocalNode();
if(MAIN_SERVER) {
@ -233,6 +235,7 @@ public class BungeeCore extends Plugin {
tablistManager.disable();
errorLogger.unregister();
Statement.closeAll();
SchematicSearch.abortAll();
}
public static BungeeCore get() {

Datei anzeigen

@ -21,6 +21,7 @@ package de.steamwar.bungeecore.commands;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.Node;
import de.steamwar.bungeecore.util.SchematicSearch;
import de.steamwar.command.SWCommand;
import net.md_5.bungee.api.CommandSender;
@ -37,6 +38,7 @@ public class StatCommand extends SWCommand {
@Register
public void genericCommand(CommandSender sender) {
Message.send("STAT_SEARCH_QUEUE", sender, SchematicSearch.getQueueSize());
Map<String, Integer> serverCount = new HashMap<>();
try {
Process process = new ProcessBuilder("ps", "x").start();

Datei anzeigen

@ -0,0 +1,41 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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.bungeecore.listeners;
import de.steamwar.bungeecore.Message;
import de.steamwar.bungeecore.util.SchematicSearch;
import net.md_5.bungee.api.event.PlayerDisconnectEvent;
import net.md_5.bungee.api.event.ServerSwitchEvent;
import net.md_5.bungee.event.EventHandler;
public class SchematicSearchListener extends BasicListener {
@EventHandler
public void onServerSwitch(ServerSwitchEvent event) {
if(SchematicSearch.removeFromQueue(event.getPlayer())) {
Message.send("SCHEMATIC_SEARCH_REMOVED_FROM_QUEUE", event.getPlayer());
}
}
@EventHandler
public void onQuit(PlayerDisconnectEvent event) {
SchematicSearch.removeFromQueue(event.getPlayer());
}
}

Datei anzeigen

@ -31,5 +31,6 @@ public class BungeeNetworkHandler {
new ImALobbyHandler().register();
new InventoryCallbackHandler().register();
new PrepareSchemHandler().register();
new SchematicSearchRequestHandler().register();
}
}

Datei anzeigen

@ -0,0 +1,47 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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.bungeecore.network.handlers;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.util.SchematicSearch;
import de.steamwar.network.packets.PacketHandler;
import de.steamwar.network.packets.client.RequestSchematicSearchPacket;
import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser;
import net.md_5.bungee.api.connection.ProxiedPlayer;
public class SchematicSearchRequestHandler extends PacketHandler {
@Handler
public void handle(RequestSchematicSearchPacket packet) {
SteamwarUser user = SteamwarUser.get(packet.getPlayerId());
SchematicNode node = SchematicNode.getSchematicNode(packet.getSchematicId());
ProxiedPlayer proxiedPlayer = BungeeCore.get().getProxy().getPlayer(user.getUUID());
if(proxiedPlayer == null) {
return;
}
SchematicSearch.SchematicSearchBehavior behavior = SchematicSearch.SchematicSearchBehavior.builder()
.airAsAny(packet.isAirAsAny())
.ignoreAir(packet.isIgnoreAir())
.ignoreBlockData(packet.isIgnoreBlockData())
.build();
SchematicSearch.queueSearch(proxiedPlayer, node, behavior);
}
}

Datei anzeigen

@ -0,0 +1,307 @@
/*
* This file is a part of the SteamWar software.
*
* Copyright (C) 2023 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.bungeecore.util;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import de.steamwar.bungeecore.BungeeCore;
import de.steamwar.bungeecore.Message;
import de.steamwar.sql.NodeData;
import de.steamwar.sql.SchematicNode;
import de.steamwar.sql.SteamwarUser;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.connection.ProxiedPlayer;
import net.md_5.bungee.api.scheduler.ScheduledTask;
import org.apache.commons.lang3.time.DurationFormatUtils;
import java.io.*;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import java.util.zip.GZIPOutputStream;
public class SchematicSearch {
private static final String SEARCH_BINARY = "/home/chaoscaot/schemsearch/target/release/schemsearch-cli";
private static final LinkedBlockingQueue<SchematicSearch> searchQueue = new LinkedBlockingQueue<>();
private static SchematicSearch currentSearch;
private static void startNext() {
if(currentSearch != null) {
return;
}
synchronized (searchQueue) {
if(searchQueue.isEmpty()) {
return;
}
currentSearch = searchQueue.poll();
currentSearch.start();
}
}
public static void queueSearch(ProxiedPlayer player, SchematicNode node, SchematicSearchBehavior behavior) {
synchronized (searchQueue) {
searchQueue.add(new SchematicSearch(player, node, behavior));
startNext();
if (!searchQueue.isEmpty()) {
Message.send("SCHEMATIC_SEARCH_QUEUED", player);
}
}
}
public static void abortAll() {
synchronized (searchQueue) {
searchQueue.stream().map(schematicSearch -> schematicSearch.player).collect(Collectors.toSet()).forEach(player -> {
Message.send("SCHEMATIC_SEARCH_REMOVED_FROM_QUEUE_SOFTRELOAD", player);
});
searchQueue.clear();
}
if(currentSearch != null) {
Message.send("SCHEMATIC_SEARCH_CANCELED_SOFTRELOAD", currentSearch.player);
currentSearch.end();
}
}
public static int getQueueSize() {
synchronized (searchQueue) {
return searchQueue.size();
}
}
private static List<String> constructArguments(SteamwarUser user, File pattern, SchematicSearchBehavior behavior) {
List<String> args = new ArrayList<>(Arrays.asList(SEARCH_BINARY, "-T", "2", "-s", "-u", String.valueOf(user.getId()), "-o", "json:std", "-m", "50"));
if(behavior.isAirAsAny()) {
args.add("-A");
}
if(behavior.isIgnoreAir()) {
args.add("-a");
}
if(behavior.isIgnoreBlockData()) {
args.add("-d");
}
args.add(pattern.getAbsolutePath());
return args;
}
public static boolean removeFromQueue(ProxiedPlayer player) {
boolean removed;
synchronized (searchQueue) {
removed = searchQueue.removeIf(search -> search.player.equals(player));
}
if (currentSearch != null && currentSearch.player.equals(player)) {
currentSearch.end();
removed = true;
}
return removed;
}
private static File schematicNodeToTempFile(NodeData node) {
try {
File f = File.createTempFile("schemsearch", ".schem");
f.deleteOnExit();
OutputStream os = new GZIPOutputStream(Files.newOutputStream(f.toPath()));
InputStream is = node.schemData();
byte[] buffer = new byte[1024];
int read;
while((read = is.read(buffer)) != -1) {
os.write(buffer, 0, read);
}
os.close();
is.close();
return f;
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private final ProxiedPlayer player;
private final SchematicNode node;
private final SchematicSearchBehavior behavior;
private File pattern;
private ScheduledTask task;
private Process process;
private SchematicSearch(ProxiedPlayer player, SchematicNode node, SchematicSearchBehavior behavior) {
this.player = player;
this.node = node;
this.behavior = behavior;
}
private static String readInputStream(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();
byte[] buffer = new byte[1024];
long total = 0;
while (is.available() > 0) {
int read = is.read(buffer);
total += read;
if (read > 0) {
sb.append(new String(buffer, 0, read));
}
if (total > 1024 * 128) {
break;
}
}
return sb.toString();
}
private void start() {
task = BungeeCore.get().getProxy().getScheduler().runAsync(BungeeCore.get(), () -> {
try {
NodeData data = NodeData.get(node);
if (!data.getNodeFormat()) {
Message.send("SCHEMATIC_SEARCH_NOT_SUPPORTED", player);
end();
return;
}
Message.send("SCHEMATIC_SEARCH_STARTED", player, node.getName());
pattern = schematicNodeToTempFile(data);
ProcessBuilder builder = new ProcessBuilder(constructArguments(SteamwarUser.get(player.getUniqueId()), pattern, behavior));
process = builder.start();
InputStream stdout = process.getInputStream();
InputStream stderr = process.getErrorStream();
String bar = "";
while (!process.waitFor(200, TimeUnit.MILLISECONDS)) {
String s = readInputStream(stderr);
if (s.length() > 0) {
if (s.contains("s[")) {
s = s.substring(s.lastIndexOf("s[") + 1);
}
s = s.replace("", "§e█§7");
bar = s;
}
BungeeCore.send(player, ChatMessageType.ACTION_BAR, "§7" + bar);
}
String s = readInputStream(stderr);
if (s.contains("s[")) {
s = s.substring(s.lastIndexOf("s[") + 1);
}
BungeeCore.send(player, ChatMessageType.ACTION_BAR, "§7" + s.replace("", "§e█§7"));
s = readInputStream(stdout);
String[] outputs = s.split("\n");
List<JsonObject> elements = Arrays.stream(outputs).map(JsonParser::parseString).map(JsonElement::getAsJsonObject).collect(Collectors.toList());
int searchCount = 0;
long searchTime = 0;
List<Match> matches = new ArrayList<>();
for (JsonObject element : elements) {
switch (element.get("event").getAsString()) {
case "Init":
searchCount = element.get("total").getAsInt();
break;
case "Found":
matches.add(new Match(element.get("x").getAsInt(), element.get("y").getAsInt(), element.get("z").getAsInt(), element.get("percent").getAsFloat() * 100, element.get("name").getAsString()));
break;
case "End":
searchTime = element.get("end_time").getAsLong();
break;
default:
break;
}
}
Message.send("SCHEMATIC_SEARCH_RESULT_HEADER", player, searchCount, DurationFormatUtils.formatDuration(searchTime, "' 'm'm 's's 'S'ms'")
.replace(" 0ms", "")
.replace(" 0s", "")
.replace(" 0m", ""));
if (matches.size() <= 1) {
Message.send("SCHEMATIC_SEARCH_NO_RESULTS", player);
end();
return;
}
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
for (Match match : matches) {
String[] nameSplit = match.name.split(" ");
String name = nameSplit[0];
int id = Integer.parseInt(nameSplit[1].substring(1, nameSplit[1].length() - 1));
if (id == node.getId()) continue;
Message.sendPrefixless("SCHEMATIC_SEARCH_RESULT", player, Message.parse("SCHEMATIC_SEARCH_RESULT_HOVER", player, name),
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/schem info " + SchematicNode.byIdAndUser(user, id).generateBreadcrumbs()),
name, match.percent, match.x + 1, match.y + 1, match.z + 1);
}
if (matches.size() >= 49) {
Message.send("SCHEMATIC_SEARCH_TOO_MANY_RESULTS", player);
}
} catch (Exception e) {
throw new SecurityException(e);
} finally {
end();
}
});
}
public void end() {
if(process != null && process.isAlive()) {
process.destroy();
}
if(pattern != null) {
pattern.delete();
}
if(task != null) {
task.cancel();
}
synchronized (searchQueue) {
if(currentSearch == this) {
currentSearch = null;
}
}
startNext();
}
@AllArgsConstructor
private static class Match {
int x;
int y;
int z;
float percent;
String name;
}
@Builder
@Getter
public static class SchematicSearchBehavior {
@Builder.Default
boolean airAsAny = false;
@Builder.Default
boolean ignoreAir = false;
@Builder.Default
boolean ignoreBlockData = false;
}
}

Datei anzeigen

@ -121,6 +121,7 @@ MOD_USE_MODSENDER=§cPlease use the §c§lFabricModSender§c (https://steamwar.d
#Various commands
ALERT=§f{0}
STAT_SERVER=§7Server §e{0}§8: §7Below limit §e{1} §7Server count §e{2}
STAT_SEARCH_QUEUE=§7Schematic search queue: §e{0}
#Ban&Mute-Command
PUNISHMENT_USAGE=§8/§7{0} §8[§eplayer§8] [§edd§8.§emm§8.§eyyyy §7or §edd§8.§emm§8.§eyyyy§8_§ehh§8:§emm §7or §enumber§8[§eh§7our|§ed§7ay|§ew§7eek|§em§7onth|§ey§7ear§8] §7or §eperma§8] [§ereason§8]
@ -690,3 +691,16 @@ MOD_FORBIDDEN=§eForbidden
MOD_AUTOBAN=§cAutoban
MOD_YT=§5YT Only
MOD_ITEM_BACK=§7Back
#Schematic Search
SCHEMATIC_SEARCH_QUEUED=§7Your search has been queued and will be executed shortly.
SCHEMATIC_SEARCH_STARTED=§7Your search for "§e{0}§7" has started.
SCHEMATIC_SEARCH_NO_RESULTS=§cNo results found.
SCHEMATIC_SEARCH_RESULT_HEADER=§7Searched §e{0} §7schematics in§e{1}.
SCHEMATIC_SEARCH_RESULT=§7{0}: §e{1}§7% §8(§e{2}§7,§e{3},§e{4}§8)
SCHEMATIC_SEARCH_RESULT_HOVER=§7Click for more info about {0}.
SCHEMATIC_SEARCH_NOT_SUPPORTED=§cThis schematic is not supported because it is on an old format.
SCHEMATIC_SEARCH_REMOVED_FROM_QUEUE=§cYour search has been removed from the queue because you switched servers.
SCHEMATIC_SEARCH_REMOVED_FROM_QUEUE_SOFTRELOAD=§cYour search has been removed from the queue because of a software update.
SCHEMATIC_SEARCH_CANCELED_SOFTRELOAD=§cYour search has been cancelled because of a software update.
SCHEMATIC_SEARCH_TOO_MANY_RESULTS=§cToo many results found. Please be more specific.

Datei anzeigen

@ -647,4 +647,16 @@ ADVENT_CALENDAR_TITLE=§eAdventskalender
ADVENT_CALENDAR_DAY=§7Tag§8: §e{0}
ADVENT_CALENDAR_MESSAGE=§eHast du heute schon dein Geschenk geholt?
ADVENT_CALENDAR_MESSAGE_HOVER=§eKlicken zum öffnen!
ADVENT_CALENDAR_OPEN=§7Du hast §e{0}§7 aus dem Adventskalender erhalten!
ADVENT_CALENDAR_OPEN=§7Du hast §e{0}§7 aus dem Adventskalender erhalten!
#Schematic Search
SCHEMATIC_SEARCH_QUEUED=§7Deine Suche wurde in die Warteschlange eingereiht.
SCHEMATIC_SEARCH_STARTED=§7Deine Suche nach §e{0} §7wurde gestartet.
SCHEMATIC_SEARCH_NO_RESULTS=§cEs wurden keine Ergebnisse gefunden.
SCHEMATIC_SEARCH_RESULT_HEADER=§e{0} §7Schematics in §e{1} §7durchsucht
SCHEMATIC_SEARCH_RESULT_HOVER=§7Klicke für mehr Informationen
SCHEMATIC_SEARCH_NOT_SUPPORTED=§cDiese Schematic ist in einem alten Format und kann nicht genutzt werden.
SCHEMATIC_SEARCH_REMOVED_FROM_QUEUE=§cDeine Suche wurde aus der Warteschlange entfernt, weil du den Server gewechselt hast.
SCHEMATIC_SEARCH_REMOVED_FROM_QUEUE_SOFTRELOAD=§cWegen eines Software Updates wurde deine Suche aus der Warteschlange entfernt.
SCHEMATIC_SEARCH_CANCELED_SOFTRELOAD=§cDeine Suche wurde wegen eines Software Updates abgebrochen.
SCHEMATIC_SEARCH_TOO_MANY_RESULTS=§cEs wurden zu viele Ergebnisse gefunden. Bitte spezifiziere deine Suche.