mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-22 17:27:38 +00:00
Integrate WE Schematic Share system (#2619)
* Integrate WE Schematic Share system (cherry picked from commit 303f5a76b2df70d63480f2126c9ef4b228eb3c59) * disable feature for now --------- Co-authored-by: Madeline Miller <mnmiller1@me.com>
This commit is contained in:
parent
991d93d8ce
commit
9bc09c6a4c
@ -26,6 +26,7 @@ import com.fastasyncworldedit.core.extent.clipboard.MultiClipboardHolder;
|
|||||||
import com.fastasyncworldedit.core.extent.clipboard.URIClipboardHolder;
|
import com.fastasyncworldedit.core.extent.clipboard.URIClipboardHolder;
|
||||||
import com.fastasyncworldedit.core.extent.clipboard.io.schematic.MinecraftStructure;
|
import com.fastasyncworldedit.core.extent.clipboard.io.schematic.MinecraftStructure;
|
||||||
import com.fastasyncworldedit.core.util.MainUtil;
|
import com.fastasyncworldedit.core.util.MainUtil;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import com.sk89q.worldedit.LocalConfiguration;
|
import com.sk89q.worldedit.LocalConfiguration;
|
||||||
import com.sk89q.worldedit.LocalSession;
|
import com.sk89q.worldedit.LocalSession;
|
||||||
@ -60,15 +61,19 @@ import com.sk89q.worldedit.util.formatting.text.format.TextColor;
|
|||||||
import com.sk89q.worldedit.util.io.Closer;
|
import com.sk89q.worldedit.util.io.Closer;
|
||||||
import com.sk89q.worldedit.util.io.file.FilenameException;
|
import com.sk89q.worldedit.util.io.file.FilenameException;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import com.sk89q.worldedit.util.paste.EngineHubPaste;
|
||||||
|
import com.sk89q.worldedit.util.paste.PasteMetadata;
|
||||||
import org.enginehub.piston.annotation.Command;
|
import org.enginehub.piston.annotation.Command;
|
||||||
import org.enginehub.piston.annotation.CommandContainer;
|
import org.enginehub.piston.annotation.CommandContainer;
|
||||||
import org.enginehub.piston.annotation.param.Arg;
|
import org.enginehub.piston.annotation.param.Arg;
|
||||||
import org.enginehub.piston.annotation.param.ArgFlag;
|
import org.enginehub.piston.annotation.param.ArgFlag;
|
||||||
import org.enginehub.piston.annotation.param.Switch;
|
import org.enginehub.piston.annotation.param.Switch;
|
||||||
|
import org.enginehub.piston.exception.CommandException;
|
||||||
import org.enginehub.piston.exception.StopExecutionException;
|
import org.enginehub.piston.exception.StopExecutionException;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.BufferedInputStream;
|
||||||
import java.io.BufferedOutputStream;
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
@ -79,9 +84,12 @@ import java.net.URISyntaxException;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.channels.Channels;
|
import java.nio.channels.Channels;
|
||||||
import java.nio.channels.ReadableByteChannel;
|
import java.nio.channels.ReadableByteChannel;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Base64;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@ -536,6 +544,42 @@ public class SchematicCommands {
|
|||||||
.buildAndExec(worldEdit.getExecutorService());
|
.buildAndExec(worldEdit.getExecutorService());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Command(
|
||||||
|
name = "share",
|
||||||
|
desc = "Share your clipboard as a schematic online"
|
||||||
|
)
|
||||||
|
@CommandPermissions({ "worldedit.clipboard.share", "worldedit.schematic.share" })
|
||||||
|
public void share(Actor actor, LocalSession session,
|
||||||
|
@Arg(desc = "Schematic name. Defaults to name-millis", def = "")
|
||||||
|
String schematicName,
|
||||||
|
@Arg(desc = "Format name.", def = "sponge")
|
||||||
|
String formatName) throws WorldEditException {
|
||||||
|
if (true) {
|
||||||
|
throw new UnsupportedOperationException("This feature is currently not implemented");
|
||||||
|
}
|
||||||
|
if (worldEdit.getPlatformManager().queryCapability(Capability.GAME_HOOKS).getDataVersion() == -1) {
|
||||||
|
actor.printError(TranslatableComponent.of("worldedit.schematic.unsupported-minecraft-version"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClipboardFormat format = ClipboardFormats.findByAlias(formatName);
|
||||||
|
if (format == null) {
|
||||||
|
actor.printError(TranslatableComponent.of("worldedit.schematic.unknown-format", TextComponent.of(formatName)));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClipboardHolder holder = session.getClipboard();
|
||||||
|
|
||||||
|
SchematicShareTask task = new SchematicShareTask(actor, format, holder, schematicName);
|
||||||
|
AsyncCommandBuilder.wrap(task, actor)
|
||||||
|
.registerWithSupervisor(worldEdit.getSupervisor(), "Sharing schematic")
|
||||||
|
.setDelayMessage(TranslatableComponent.of("worldedit.schematic.save.saving"))
|
||||||
|
.setWorkingMessage(TranslatableComponent.of("worldedit.schematic.save.still-saving"))
|
||||||
|
.onSuccess("Shared", (url -> actor.printInfo(TextComponent.of(url.toExternalForm() + ".schem").clickEvent(ClickEvent.openUrl(url.toExternalForm() + ".schem")))))
|
||||||
|
.onFailure("Failed to share schematic", worldEdit.getPlatformManager().getPlatformCommandManager().getExceptionConverter())
|
||||||
|
.buildAndExec(worldEdit.getExecutorService());
|
||||||
|
}
|
||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
name = "formats",
|
name = "formats",
|
||||||
aliases = {"listformats", "f"},
|
aliases = {"listformats", "f"},
|
||||||
@ -804,14 +848,48 @@ public class SchematicCommands {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SchematicSaveTask implements Callable<Void> {
|
private abstract static class SchematicOutputTask<T> implements Callable<T> {
|
||||||
|
protected final Actor actor;
|
||||||
|
protected final ClipboardFormat format;
|
||||||
|
protected final ClipboardHolder holder;
|
||||||
|
|
||||||
private final Actor actor;
|
SchematicOutputTask(
|
||||||
private final ClipboardFormat format;
|
Actor actor,
|
||||||
private final ClipboardHolder holder;
|
ClipboardFormat format,
|
||||||
|
ClipboardHolder holder
|
||||||
|
) {
|
||||||
|
this.actor = actor;
|
||||||
|
this.format = format;
|
||||||
|
this.holder = holder;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void writeToOutputStream(OutputStream outputStream) throws Exception {
|
||||||
|
Clipboard clipboard = holder.getClipboard();
|
||||||
|
Transform transform = holder.getTransform();
|
||||||
|
Clipboard target;
|
||||||
|
// If we have a transform, bake it into the copy
|
||||||
|
if (transform.isIdentity()) {
|
||||||
|
target = clipboard;
|
||||||
|
} else {
|
||||||
|
FlattenedClipboardTransform result = FlattenedClipboardTransform.transform(clipboard, transform);
|
||||||
|
target = new BlockArrayClipboard(result.getTransformedRegion());
|
||||||
|
target.setOrigin(clipboard.getOrigin());
|
||||||
|
Operations.completeLegacy(result.copyTo(target));
|
||||||
|
}
|
||||||
|
|
||||||
|
try (Closer closer = Closer.create()) {
|
||||||
|
OutputStream stream = closer.register(outputStream);
|
||||||
|
BufferedOutputStream bos = closer.register(new BufferedOutputStream(stream));
|
||||||
|
ClipboardWriter writer = closer.register(format.getWriter(bos));
|
||||||
|
writer.write(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SchematicSaveTask extends SchematicOutputTask<Void> {
|
||||||
|
private File file;
|
||||||
private final boolean overwrite;
|
private final boolean overwrite;
|
||||||
private final File rootDir;
|
private final File rootDir;
|
||||||
private File file;
|
|
||||||
|
|
||||||
SchematicSaveTask(
|
SchematicSaveTask(
|
||||||
Actor actor,
|
Actor actor,
|
||||||
@ -821,11 +899,9 @@ public class SchematicCommands {
|
|||||||
ClipboardHolder holder,
|
ClipboardHolder holder,
|
||||||
boolean overwrite
|
boolean overwrite
|
||||||
) {
|
) {
|
||||||
this.actor = actor;
|
super(actor, format, holder);
|
||||||
this.file = file;
|
this.file = file;
|
||||||
this.rootDir = rootDir;
|
this.rootDir = rootDir;
|
||||||
this.format = format;
|
|
||||||
this.holder = holder;
|
|
||||||
this.overwrite = overwrite;
|
this.overwrite = overwrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -984,7 +1060,32 @@ public class SchematicCommands {
|
|||||||
//FAWE end
|
//FAWE end
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class SchematicShareTask extends SchematicOutputTask<URL> {
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
SchematicShareTask(Actor actor, ClipboardFormat format, ClipboardHolder holder, String name) {
|
||||||
|
super(actor, format, holder);
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URL call() throws Exception {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
try {
|
||||||
|
writeToOutputStream(baos);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new CommandException(TextComponent.of(e.getMessage()), e, ImmutableList.of());
|
||||||
|
}
|
||||||
|
|
||||||
|
EngineHubPaste pasteService = new EngineHubPaste();
|
||||||
|
PasteMetadata metadata = new PasteMetadata();
|
||||||
|
metadata.author = this.actor.getName();
|
||||||
|
metadata.extension = "schem";
|
||||||
|
metadata.name = name == null ? actor.getName() + "-" + System.currentTimeMillis() : name;
|
||||||
|
return pasteService.paste(new String(Base64.getEncoder().encode(baos.toByteArray()), StandardCharsets.UTF_8), metadata).call();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class SchematicListTask implements Callable<Component> {
|
private static class SchematicListTask implements Callable<Component> {
|
||||||
|
@ -83,4 +83,26 @@ public final class ActorCallbackPaste {
|
|||||||
.buildAndExec(Pasters.getExecutor());
|
.buildAndExec(Pasters.getExecutor());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit data to a pastebin service and inform the sender of
|
||||||
|
* success or failure.
|
||||||
|
*
|
||||||
|
* @param supervisor The supervisor instance
|
||||||
|
* @param sender The sender
|
||||||
|
* @param content The content
|
||||||
|
* @param pasteMetadata The paste metadata
|
||||||
|
* @param successMessage The message builder, given the URL as an arg
|
||||||
|
*/
|
||||||
|
public static void pastebin(Supervisor supervisor, final Actor sender, String content, PasteMetadata pasteMetadata, final TranslatableComponent.Builder successMessage) {
|
||||||
|
Callable<URL> task = paster.paste(content, pasteMetadata);
|
||||||
|
|
||||||
|
AsyncCommandBuilder.wrap(task, sender)
|
||||||
|
.registerWithSupervisor(supervisor, "Submitting content to a pastebin service.")
|
||||||
|
.setDelayMessage(TranslatableComponent.of("worldedit.pastebin.uploading"))
|
||||||
|
.onSuccess((String) null, url -> sender.printInfo(successMessage.args(TextComponent.of(url.toString())).build()))
|
||||||
|
.onFailure("Failed to submit paste", null)
|
||||||
|
.buildAndExec(Pasters.getExecutor());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,23 +33,38 @@ public class EngineHubPaste implements Paster {
|
|||||||
private static final Gson GSON = new Gson();
|
private static final Gson GSON = new Gson();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Callable<URL> paste(String content) {
|
public Callable<URL> paste(String content, PasteMetadata metadata) {
|
||||||
return new PasteTask(content);
|
return new PasteTask(content, metadata);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class PasteTask implements Callable<URL> {
|
private static final class PasteTask implements Callable<URL> {
|
||||||
|
|
||||||
private final String content;
|
private final String content;
|
||||||
|
private final PasteMetadata metadata;
|
||||||
|
|
||||||
private PasteTask(String content) {
|
private PasteTask(String content, PasteMetadata metadata) {
|
||||||
this.content = content;
|
this.content = content;
|
||||||
|
this.metadata = metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public URL call() throws IOException, InterruptedException {
|
public URL call() throws IOException, InterruptedException {
|
||||||
URL initialUrl = HttpRequest.url("https://paste.enginehub.org/signed_paste");
|
URL initialUrl = HttpRequest.url("https://paste.enginehub.org/signed_paste");
|
||||||
|
|
||||||
SignedPasteResponse response = GSON.fromJson(HttpRequest.get(initialUrl)
|
HttpRequest requestBuilder = HttpRequest.get(initialUrl);
|
||||||
|
|
||||||
|
requestBuilder.header("x-paste-meta-from", "EngineHub");
|
||||||
|
if (metadata.name != null) {
|
||||||
|
requestBuilder.header("x-paste-meta-name", metadata.name);
|
||||||
|
}
|
||||||
|
if (metadata.author != null) {
|
||||||
|
requestBuilder.header("x-paste-meta-author", metadata.author);
|
||||||
|
}
|
||||||
|
if (metadata.extension != null) {
|
||||||
|
requestBuilder.header("x-paste-meta-extension", metadata.extension);
|
||||||
|
}
|
||||||
|
|
||||||
|
SignedPasteResponse response = GSON.fromJson(requestBuilder
|
||||||
.execute()
|
.execute()
|
||||||
.expectResponseCode(200)
|
.expectResponseCode(200)
|
||||||
.returnContent()
|
.returnContent()
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
|
* Copyright (C) WorldEdit team and contributors
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.sk89q.worldedit.util.paste;
|
||||||
|
|
||||||
|
public class PasteMetadata {
|
||||||
|
public String name;
|
||||||
|
public String extension;
|
||||||
|
public String author;
|
||||||
|
}
|
@ -24,6 +24,10 @@ import java.util.concurrent.Callable;
|
|||||||
|
|
||||||
public interface Paster {
|
public interface Paster {
|
||||||
|
|
||||||
Callable<URL> paste(String content);
|
default Callable<URL> paste(String content) {
|
||||||
|
return paste(content, new PasteMetadata());
|
||||||
|
}
|
||||||
|
|
||||||
|
Callable<URL> paste(String content, PasteMetadata metadata);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user