Mirror von
https://github.com/IntellectualSites/FastAsyncWorldEdit.git
synchronisiert 2024-11-05 11:00:05 +01:00
Run schematic-file I/O in a task.
Dieser Commit ist enthalten in:
Ursprung
fab21c3eea
Commit
7b170d8193
@ -21,6 +21,8 @@ package com.sk89q.worldedit;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
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.entity.Player;
|
||||
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.util.Direction;
|
||||
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.io.file.FileSelectionAbortedException;
|
||||
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 EditSessionFactory editSessionFactory = new EditSessionFactory.EditSessionFactoryImpl(eventBus);
|
||||
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 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
|
||||
*/
|
||||
@ -160,6 +164,15 @@ public final class WorldEdit {
|
||||
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
|
||||
* constructed.
|
||||
|
@ -23,6 +23,7 @@ import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
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.CommandPermissionsConditionGenerator;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
@ -60,6 +61,7 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@ -113,20 +115,13 @@ public class SchematicCommands {
|
||||
return;
|
||||
}
|
||||
|
||||
try (Closer closer = Closer.create()) {
|
||||
FileInputStream fis = closer.register(new FileInputStream(f));
|
||||
BufferedInputStream bis = closer.register(new BufferedInputStream(fis));
|
||||
ClipboardReader reader = closer.register(format.getReader(bis));
|
||||
|
||||
Clipboard clipboard = reader.read();
|
||||
session.setClipboard(new ClipboardHolder(clipboard));
|
||||
|
||||
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());
|
||||
}
|
||||
SchematicLoadTask task = new SchematicLoadTask(player, f, format);
|
||||
AsyncCommandBuilder.wrap(task, player)
|
||||
.registerWithSupervisor(worldEdit.getSupervisor(), "Loading schematic " + filename)
|
||||
.sendMessageAfterDelay("(Please wait... loading schematic.)")
|
||||
.onSuccess(filename + " loaded. Paste it with //paste", session::setClipboard)
|
||||
.onFailure("Failed to load schematic", worldEdit.getPlatformManager().getPlatformCommandManager().getExceptionConverter())
|
||||
.buildAndExec(worldEdit.getExecutorService());
|
||||
}
|
||||
|
||||
@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
|
||||
File parent = f.getParentFile();
|
||||
if (parent != null && !parent.exists()) {
|
||||
if (!parent.mkdirs()) {
|
||||
throw new StopExecutionException(TextComponent.of(
|
||||
"Could not create folder for schematics!"));
|
||||
"Could not create folder for schematics!"));
|
||||
}
|
||||
}
|
||||
|
||||
try (Closer closer = Closer.create()) {
|
||||
FileOutputStream fos = closer.register(new FileOutputStream(f));
|
||||
BufferedOutputStream bos = closer.register(new BufferedOutputStream(fos));
|
||||
ClipboardWriter writer = closer.register(format.getWriter(bos));
|
||||
writer.write(target);
|
||||
ClipboardHolder holder = session.getClipboard();
|
||||
|
||||
log.info(player.getName() + " saved " + f.getCanonicalPath() + (overwrite ? " (overwriting previous file)" : ""));
|
||||
player.print(filename + " saved" + (overwrite ? " (overwriting previous file)." : "."));
|
||||
} catch (IOException e) {
|
||||
player.printError("Schematic could not written: " + e.getMessage());
|
||||
log.warn("Failed to write a saved clipboard", e);
|
||||
}
|
||||
SchematicSaveTask task = new SchematicSaveTask(player, f, format, holder, overwrite);
|
||||
AsyncCommandBuilder.wrap(task, player)
|
||||
.registerWithSupervisor(worldEdit.getSupervisor(), "Saving schematic " + filename)
|
||||
.sendMessageAfterDelay("(Please wait... saving schematic.)")
|
||||
.onSuccess(filename + " saved" + (overwrite ? " (overwriting previous file)." : "."), null)
|
||||
.onFailure("Failed to load schematic", worldEdit.getPlatformManager().getPlatformCommandManager().getExceptionConverter())
|
||||
.buildAndExec(worldEdit.getExecutorService());
|
||||
}
|
||||
|
||||
@Command(
|
||||
@ -329,4 +306,71 @@ public class SchematicCommands {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ public class WorldEditCommands {
|
||||
String result = report.toString();
|
||||
|
||||
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"));
|
||||
actor.print("WorldEdit report written to " + dest.getAbsolutePath());
|
||||
} catch (IOException e) {
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren