Dieser Commit ist enthalten in:
Ursprung
2a91876cb9
Commit
06d3aeb9d1
@ -122,6 +122,7 @@ public class BungeeCore extends Plugin {
|
|||||||
new Fabric();
|
new Fabric();
|
||||||
new SubserverProtocolFixer();
|
new SubserverProtocolFixer();
|
||||||
new PingListener();
|
new PingListener();
|
||||||
|
new SchematicSearchListener();
|
||||||
|
|
||||||
local = new Node.LocalNode();
|
local = new Node.LocalNode();
|
||||||
if(MAIN_SERVER) {
|
if(MAIN_SERVER) {
|
||||||
@ -170,6 +171,7 @@ public class BungeeCore extends Plugin {
|
|||||||
new CalendarListener();
|
new CalendarListener();
|
||||||
|
|
||||||
new ModCommand();
|
new ModCommand();
|
||||||
|
new SchemSearchTestCommand();
|
||||||
|
|
||||||
// Punishment Commands:
|
// Punishment Commands:
|
||||||
new PunishmentCommand("ban", Punishment.PunishmentType.Ban);
|
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_AUTOBAN=§cAutoban
|
||||||
MOD_YT=§5YT Only
|
MOD_YT=§5YT Only
|
||||||
MOD_ITEM_BACK=§7Back
|
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