Dieser Commit ist enthalten in:
Ursprung
2a91876cb9
Commit
06d3aeb9d1
@ -122,6 +122,7 @@ public class BungeeCore extends Plugin {
|
||||
new Fabric();
|
||||
new SubserverProtocolFixer();
|
||||
new PingListener();
|
||||
new SchematicSearchListener();
|
||||
|
||||
local = new Node.LocalNode();
|
||||
if(MAIN_SERVER) {
|
||||
@ -170,6 +171,7 @@ public class BungeeCore extends Plugin {
|
||||
new CalendarListener();
|
||||
|
||||
new ModCommand();
|
||||
new SchemSearchTestCommand();
|
||||
|
||||
// Punishment Commands:
|
||||
new PunishmentCommand("ban", Punishment.PunishmentType.Ban);
|
||||
|
40
src/de/steamwar/bungeecore/commands/SchemSearchTestCommand.java
Normale Datei
40
src/de/steamwar/bungeecore/commands/SchemSearchTestCommand.java
Normale Datei
@ -0,0 +1,40 @@
|
||||
package de.steamwar.bungeecore.commands;
|
||||
|
||||
import de.steamwar.bungeecore.util.SchematicSearch;
|
||||
import de.steamwar.command.PreviousArguments;
|
||||
import de.steamwar.command.SWCommand;
|
||||
import de.steamwar.command.TypeMapper;
|
||||
import de.steamwar.sql.SchematicNode;
|
||||
import de.steamwar.sql.SteamwarUser;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class SchemSearchTestCommand extends SWCommand {
|
||||
public SchemSearchTestCommand() {
|
||||
super("schemsearch");
|
||||
}
|
||||
|
||||
|
||||
@Register
|
||||
public void genericCommand(ProxiedPlayer player, SchematicNode node) {
|
||||
SchematicSearch.queueSearch(player, node);
|
||||
}
|
||||
|
||||
@ClassMapper(SchematicNode.class)
|
||||
public TypeMapper<SchematicNode> getSchematicNodeMapper() {
|
||||
return new TypeMapper<SchematicNode>() {
|
||||
|
||||
@Override
|
||||
public SchematicNode map(CommandSender commandSender, String[] previousArguments, String s) {
|
||||
return SchematicNode.getNodeFromPath(SteamwarUser.get(commandSender.getName()), s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<String> tabCompletes(CommandSender sender, PreviousArguments previousArguments, String s) {
|
||||
return SchematicNode.getNodeTabcomplete(SteamwarUser.get(sender.getName()), s);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
22
src/de/steamwar/bungeecore/listeners/SchematicSearchListener.java
Normale Datei
22
src/de/steamwar/bungeecore/listeners/SchematicSearchListener.java
Normale Datei
@ -0,0 +1,22 @@
|
||||
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());
|
||||
}
|
||||
}
|
252
src/de/steamwar/bungeecore/util/SchematicSearch.java
Normale Datei
252
src/de/steamwar/bungeecore/util/SchematicSearch.java
Normale Datei
@ -0,0 +1,252 @@
|
||||
package de.steamwar.bungeecore.util;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
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 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.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
public class SchematicSearch {
|
||||
|
||||
private static final Gson gson = new Gson();
|
||||
private static final String searchBinary = "/home/chaoscaot/schemsearch/target/release/schemsearch-cli";
|
||||
private static final List<SchematicSearch> searchQueue = new ArrayList<>();
|
||||
private static SchematicSearch currentSearch;
|
||||
private static ScheduledTask watchdog;
|
||||
|
||||
private static void startQueueWatchdog() {
|
||||
watchdog = BungeeCore.get().getProxy().getScheduler().schedule(BungeeCore.get(), () -> {
|
||||
synchronized (searchQueue) {
|
||||
if(currentSearch == null) {
|
||||
if(!searchQueue.isEmpty()) {
|
||||
currentSearch = searchQueue.remove(0);
|
||||
currentSearch.start();
|
||||
} else {
|
||||
watchdog.cancel();
|
||||
watchdog = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 0, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public static void queueSearch(ProxiedPlayer player, SchematicNode node ) {
|
||||
SteamwarUser user = SteamwarUser.get(player.getUniqueId());
|
||||
synchronized (searchQueue) {
|
||||
if(user.getUserGroup().isAdminGroup()) {
|
||||
searchQueue.add(0, new SchematicSearch(player, node));
|
||||
} else {
|
||||
searchQueue.add(new SchematicSearch(player, node));
|
||||
}
|
||||
}
|
||||
if(watchdog == null) {
|
||||
startQueueWatchdog();
|
||||
} else {
|
||||
Message.send("SCHEMATIC_SEARCH_QUEUED", player);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<String> constructArguments(SteamwarUser user, File pattern) {
|
||||
return Arrays.asList(searchBinary, "-T", "1", "-s", "-u", String.valueOf(user.getId()), "-o", "json:std", "-m", "50", pattern.getAbsolutePath());
|
||||
}
|
||||
|
||||
public static boolean removeFromQueue(ProxiedPlayer player) {
|
||||
boolean removed = false;
|
||||
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 File pattern;
|
||||
private ScheduledTask task;
|
||||
private Process process;
|
||||
|
||||
private SchematicSearch(ProxiedPlayer player, SchematicNode node) {
|
||||
this.player = player;
|
||||
this.node = node;
|
||||
}
|
||||
|
||||
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));
|
||||
process = builder.start();
|
||||
InputStream stdout = process.getInputStream();
|
||||
InputStream stderr = process.getErrorStream();
|
||||
|
||||
while (!process.waitFor(100, TimeUnit.MILLISECONDS)) {
|
||||
String s = readInputStream(stderr);
|
||||
if(s.length() > 0) {
|
||||
if(s.contains("s[")) {
|
||||
s = s.substring(s.lastIndexOf("s[") + 1);
|
||||
}
|
||||
BungeeCore.send(player, ChatMessageType.ACTION_BAR, "§7" + s.replace("█", "§e█§7"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
end();
|
||||
} catch (Exception e) {
|
||||
end();
|
||||
throw new SecurityException(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
private static class Match {
|
||||
int x;
|
||||
int y;
|
||||
int z;
|
||||
float percent;
|
||||
String name;
|
||||
}
|
||||
}
|
@ -680,3 +680,14 @@ 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 in §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 to get more info about {0}.
|
||||
SCHEMATIC_SEARCH_NOT_SUPPORTED=§cThis schematic is not supported by the schematic search.
|
||||
SCHEMATIC_SEARCH_REMOVED_FROM_QUEUE=§cYour search has been removed from the queue because you switched servers.
|
||||
SCHEMATIC_SEARCH_TOO_MANY_RESULTS=§cToo many results found. Please be more specific.
|
In neuem Issue referenzieren
Einen Benutzer sperren