Run schematic-file I/O in a task.

Dieser Commit ist enthalten in:
wizjany 2019-05-12 16:01:22 -04:00
Ursprung fab21c3eea
Commit 7b170d8193
4 geänderte Dateien mit 100 neuen und 157 gelöschten Zeilen

Datei anzeigen

@ -21,6 +21,8 @@ package com.sk89q.worldedit;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
import com.sk89q.worldedit.blocks.BaseItem; import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.platform.BlockInteractEvent; import com.sk89q.worldedit.event.platform.BlockInteractEvent;
@ -44,6 +46,7 @@ import com.sk89q.worldedit.scripting.RhinoCraftScriptEngine;
import com.sk89q.worldedit.session.SessionManager; import com.sk89q.worldedit.session.SessionManager;
import com.sk89q.worldedit.util.Direction; import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.Location; import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.concurrency.EvenMoreExecutors;
import com.sk89q.worldedit.util.eventbus.EventBus; import com.sk89q.worldedit.util.eventbus.EventBus;
import com.sk89q.worldedit.util.io.file.FileSelectionAbortedException; import com.sk89q.worldedit.util.io.file.FileSelectionAbortedException;
import com.sk89q.worldedit.util.io.file.FilenameException; import com.sk89q.worldedit.util.io.file.FilenameException;
@ -102,6 +105,7 @@ public final class WorldEdit {
private final PlatformManager platformManager = new PlatformManager(this); private final PlatformManager platformManager = new PlatformManager(this);
private final EditSessionFactory editSessionFactory = new EditSessionFactory.EditSessionFactoryImpl(eventBus); private final EditSessionFactory editSessionFactory = new EditSessionFactory.EditSessionFactoryImpl(eventBus);
private final SessionManager sessions = new SessionManager(this); private final SessionManager sessions = new SessionManager(this);
private final ListeningExecutorService executorService = MoreExecutors.listeningDecorator(EvenMoreExecutors.newBoundedCachedThreadPool(0, 1, 20));;
private final Supervisor supervisor = new SimpleSupervisor(); private final Supervisor supervisor = new SimpleSupervisor();
private final BlockFactory blockFactory = new BlockFactory(this); private final BlockFactory blockFactory = new BlockFactory(this);
@ -152,7 +156,7 @@ public final class WorldEdit {
} }
/** /**
* Get the supervisor. * Get the supervisor. Internal, not for API use.
* *
* @return the supervisor * @return the supervisor
*/ */
@ -160,6 +164,15 @@ public final class WorldEdit {
return supervisor; return supervisor;
} }
/**
* Get the executor service. Internal, not for API use.
*
* @return the executor service
*/
public ListeningExecutorService getExecutorService() {
return executorService;
}
/** /**
* Get the block factory from which new {@link BlockStateHolder}s can be * Get the block factory from which new {@link BlockStateHolder}s can be
* constructed. * constructed.

Datei anzeigen

@ -23,6 +23,7 @@ import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.command.util.AsyncCommandBuilder;
import com.sk89q.worldedit.command.util.CommandPermissions; import com.sk89q.worldedit.command.util.CommandPermissions;
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
@ -60,6 +61,7 @@ import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.concurrent.Callable;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@ -113,20 +115,13 @@ public class SchematicCommands {
return; return;
} }
try (Closer closer = Closer.create()) { SchematicLoadTask task = new SchematicLoadTask(player, f, format);
FileInputStream fis = closer.register(new FileInputStream(f)); AsyncCommandBuilder.wrap(task, player)
BufferedInputStream bis = closer.register(new BufferedInputStream(fis)); .registerWithSupervisor(worldEdit.getSupervisor(), "Loading schematic " + filename)
ClipboardReader reader = closer.register(format.getReader(bis)); .sendMessageAfterDelay("(Please wait... loading schematic.)")
.onSuccess(filename + " loaded. Paste it with //paste", session::setClipboard)
Clipboard clipboard = reader.read(); .onFailure("Failed to load schematic", worldEdit.getPlatformManager().getPlatformCommandManager().getExceptionConverter())
session.setClipboard(new ClipboardHolder(clipboard)); .buildAndExec(worldEdit.getExecutorService());
log.info(player.getName() + " loaded " + f.getCanonicalPath());
player.print(filename + " loaded. Paste it with //paste");
} catch (IOException e) {
player.printError("Schematic could not read or it does not exist: " + e.getMessage());
log.warn("Failed to load schematic: " + e.getMessage());
}
} }
@Command( @Command(
@ -165,42 +160,24 @@ public class SchematicCommands {
} }
} }
ClipboardHolder holder = session.getClipboard();
Clipboard clipboard = holder.getClipboard();
Transform transform = holder.getTransform();
Clipboard target;
// If we have a transform, bake it into the copy
if (!transform.isIdentity()) {
FlattenedClipboardTransform result = FlattenedClipboardTransform.transform(clipboard, transform);
target = new BlockArrayClipboard(result.getTransformedRegion());
target.setOrigin(clipboard.getOrigin());
Operations.completeLegacy(result.copyTo(target));
} else {
target = clipboard;
}
// Create parent directories // Create parent directories
File parent = f.getParentFile(); File parent = f.getParentFile();
if (parent != null && !parent.exists()) { if (parent != null && !parent.exists()) {
if (!parent.mkdirs()) { if (!parent.mkdirs()) {
throw new StopExecutionException(TextComponent.of( throw new StopExecutionException(TextComponent.of(
"Could not create folder for schematics!")); "Could not create folder for schematics!"));
} }
} }
try (Closer closer = Closer.create()) { ClipboardHolder holder = session.getClipboard();
FileOutputStream fos = closer.register(new FileOutputStream(f));
BufferedOutputStream bos = closer.register(new BufferedOutputStream(fos));
ClipboardWriter writer = closer.register(format.getWriter(bos));
writer.write(target);
log.info(player.getName() + " saved " + f.getCanonicalPath() + (overwrite ? " (overwriting previous file)" : "")); SchematicSaveTask task = new SchematicSaveTask(player, f, format, holder, overwrite);
player.print(filename + " saved" + (overwrite ? " (overwriting previous file)." : ".")); AsyncCommandBuilder.wrap(task, player)
} catch (IOException e) { .registerWithSupervisor(worldEdit.getSupervisor(), "Saving schematic " + filename)
player.printError("Schematic could not written: " + e.getMessage()); .sendMessageAfterDelay("(Please wait... saving schematic.)")
log.warn("Failed to write a saved clipboard", e); .onSuccess(filename + " saved" + (overwrite ? " (overwriting previous file)." : "."), null)
} .onFailure("Failed to load schematic", worldEdit.getPlatformManager().getPlatformCommandManager().getExceptionConverter())
.buildAndExec(worldEdit.getExecutorService());
} }
@Command( @Command(
@ -329,4 +306,71 @@ public class SchematicCommands {
return fileList; return fileList;
} }
private static class SchematicLoadTask implements Callable<ClipboardHolder> {
private final Player player;
private final File file;
private final ClipboardFormat format;
SchematicLoadTask(Player player, File file, ClipboardFormat format) {
this.player = player;
this.file = file;
this.format = format;
}
@Override
public ClipboardHolder call() throws Exception {
try (Closer closer = Closer.create()) {
FileInputStream fis = closer.register(new FileInputStream(file));
BufferedInputStream bis = closer.register(new BufferedInputStream(fis));
ClipboardReader reader = closer.register(format.getReader(bis));
Clipboard clipboard = reader.read();
log.info(player.getName() + " loaded " + file.getCanonicalPath());
return new ClipboardHolder(clipboard);
}
}
}
private static class SchematicSaveTask implements Callable<Void> {
private final Player player;
private final File file;
private final ClipboardFormat format;
private final ClipboardHolder holder;
private final boolean overwrite;
SchematicSaveTask(Player player, File file, ClipboardFormat format, ClipboardHolder holder, boolean overwrite) {
this.player = player;
this.file = file;
this.format = format;
this.holder = holder;
this.overwrite = overwrite;
}
@Override
public Void call() 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()) {
FileOutputStream fos = closer.register(new FileOutputStream(file));
BufferedOutputStream bos = closer.register(new BufferedOutputStream(fos));
ClipboardWriter writer = closer.register(format.getWriter(bos));
writer.write(target);
log.info(player.getName() + " saved " + file.getCanonicalPath() + (overwrite ? " (overwriting previous file)" : ""));
}
return null;
}
}
} }

Datei anzeigen

@ -110,7 +110,7 @@ public class WorldEditCommands {
String result = report.toString(); String result = report.toString();
try { try {
File dest = new File(we.getWorkingDirectoryFile(we.getConfiguration().saveDir), "report.txt"); File dest = new File(we.getConfiguration().getWorkingDirectory(), "report.txt");
Files.write(result, dest, Charset.forName("UTF-8")); Files.write(result, dest, Charset.forName("UTF-8"));
actor.print("WorldEdit report written to " + dest.getAbsolutePath()); actor.print("WorldEdit report written to " + dest.getAbsolutePath());
} catch (IOException e) { } catch (IOException e) {

Datei anzeigen

@ -1,114 +0,0 @@
/*
* 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 Lesser 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.command.util;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.util.concurrent.FutureCallback;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.internal.command.exception.ExceptionConverter;
import org.enginehub.piston.exception.CommandException;
import javax.annotation.Nullable;
public class MessageFutureCallback<V> implements FutureCallback<V> {
private final ExceptionConverter exceptionConverter;
private final Actor sender;
@Nullable
private final String success;
@Nullable
private final String failure;
private MessageFutureCallback(ExceptionConverter exceptionConverter, Actor sender, @Nullable String success, @Nullable String failure) {
this.exceptionConverter = exceptionConverter;
this.sender = sender;
this.success = success;
this.failure = failure;
}
@Override
public void onSuccess(@Nullable V v) {
if (success != null) {
sender.print(success);
}
}
@Override
public void onFailure(@Nullable Throwable throwable) {
try {
exceptionConverter.convert(throwable);
} catch (CommandException e) {
String failure = this.failure != null ? this.failure : "An error occurred";
String message = e.getMessage() != null ? e.getMessage() : "An unknown error occurred. Please see the console!";
sender.printError(failure + ": " + message);
}
}
public static class Builder {
private final Actor sender;
@Nullable
private String success;
@Nullable
private String failure;
private ExceptionConverter exceptionConverter;
public Builder(Actor sender) {
checkNotNull(sender);
this.sender = sender;
}
public Builder exceptionConverter(ExceptionConverter exceptionConverter) {
this.exceptionConverter = exceptionConverter;
return this;
}
public Builder onSuccess(@Nullable String message) {
this.success = message;
return this;
}
public Builder onFailure(@Nullable String message) {
this.failure = message;
return this;
}
public <V> MessageFutureCallback<V> build() {
checkNotNull(exceptionConverter);
return new MessageFutureCallback<>(exceptionConverter, sender, success, failure);
}
}
public static <V> MessageFutureCallback<V> createRegionLoadCallback(ExceptionConverter exceptionConverter, Actor sender) {
return new Builder(sender)
.exceptionConverter(exceptionConverter)
.onSuccess("Successfully load the region data.")
.build();
}
public static <V> MessageFutureCallback<V> createRegionSaveCallback(ExceptionConverter exceptionConverter, Actor sender) {
return new Builder(sender)
.exceptionConverter(exceptionConverter)
.onSuccess("Successfully saved the region data.")
.build();
}
}