mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-22 17:27:38 +00:00
Move the pasting system over to WorldEdit, and add a /we report command. Currently only reports system status and the config. Need to add a platform reporter system.
This commit is contained in:
parent
8f236afae9
commit
5eb9b779d7
@ -14,6 +14,7 @@
|
|||||||
<allow pkg="gnu.trove"/>
|
<allow pkg="gnu.trove"/>
|
||||||
<allow pkg="com.google.gson"/>
|
<allow pkg="com.google.gson"/>
|
||||||
<allow pkg="net.royawesome.jlibnoise"/>
|
<allow pkg="net.royawesome.jlibnoise"/>
|
||||||
|
<allow pkg="org.json.simple" />
|
||||||
|
|
||||||
<subpackage name="util.yaml">
|
<subpackage name="util.yaml">
|
||||||
<allow pkg="org.yaml.snakeyaml"/>
|
<allow pkg="org.yaml.snakeyaml"/>
|
||||||
|
@ -21,6 +21,7 @@ package com.sk89q.worldedit.bukkit;
|
|||||||
|
|
||||||
import com.sk89q.util.yaml.YAMLProcessor;
|
import com.sk89q.util.yaml.YAMLProcessor;
|
||||||
import com.sk89q.worldedit.util.YAMLConfiguration;
|
import com.sk89q.worldedit.util.YAMLConfiguration;
|
||||||
|
import com.sk89q.worldedit.util.report.Unreported;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
@ -30,7 +31,7 @@ import java.io.File;
|
|||||||
public class BukkitConfiguration extends YAMLConfiguration {
|
public class BukkitConfiguration extends YAMLConfiguration {
|
||||||
|
|
||||||
public boolean noOpPermissions = false;
|
public boolean noOpPermissions = false;
|
||||||
private final WorldEditPlugin plugin;
|
@Unreported private final WorldEditPlugin plugin;
|
||||||
|
|
||||||
public BukkitConfiguration(YAMLProcessor config, WorldEditPlugin plugin) {
|
public BukkitConfiguration(YAMLProcessor config, WorldEditPlugin plugin) {
|
||||||
super(config, plugin.getLogger());
|
super(config, plugin.getLogger());
|
||||||
|
@ -11,6 +11,7 @@ dependencies {
|
|||||||
compile 'com.thoughtworks.paranamer:paranamer:2.6'
|
compile 'com.thoughtworks.paranamer:paranamer:2.6'
|
||||||
compile 'com.google.code.gson:gson:2.8.0'
|
compile 'com.google.code.gson:gson:2.8.0'
|
||||||
compile 'com.sk89q.lib:jlibnoise:1.0.0'
|
compile 'com.sk89q.lib:jlibnoise:1.0.0'
|
||||||
|
compile 'com.googlecode.json-simple:json-simple:1.1.1'
|
||||||
//compile 'net.sf.trove4j:trove4j:3.0.3'
|
//compile 'net.sf.trove4j:trove4j:3.0.3'
|
||||||
testCompile 'org.mockito:mockito-core:1.9.0-rc1'
|
testCompile 'org.mockito:mockito-core:1.9.0-rc1'
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,8 @@ import com.sk89q.worldedit.util.io.file.FilenameException;
|
|||||||
import com.sk89q.worldedit.util.io.file.FilenameResolutionException;
|
import com.sk89q.worldedit.util.io.file.FilenameResolutionException;
|
||||||
import com.sk89q.worldedit.util.io.file.InvalidFilenameException;
|
import com.sk89q.worldedit.util.io.file.InvalidFilenameException;
|
||||||
import com.sk89q.worldedit.util.logging.WorldEditPrefixHandler;
|
import com.sk89q.worldedit.util.logging.WorldEditPrefixHandler;
|
||||||
|
import com.sk89q.worldedit.util.task.SimpleSupervisor;
|
||||||
|
import com.sk89q.worldedit.util.task.Supervisor;
|
||||||
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
import com.sk89q.worldedit.world.block.BlockStateHolder;
|
||||||
import com.sk89q.worldedit.world.block.BlockType;
|
import com.sk89q.worldedit.world.block.BlockType;
|
||||||
import com.sk89q.worldedit.world.registry.BundledBlockData;
|
import com.sk89q.worldedit.world.registry.BundledBlockData;
|
||||||
@ -99,6 +101,7 @@ public 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 Supervisor supervisor = new SimpleSupervisor();
|
||||||
|
|
||||||
private final BlockFactory blockFactory = new BlockFactory(this);
|
private final BlockFactory blockFactory = new BlockFactory(this);
|
||||||
private final ItemFactory itemFactory = new ItemFactory(this);
|
private final ItemFactory itemFactory = new ItemFactory(this);
|
||||||
@ -148,6 +151,15 @@ public class WorldEdit {
|
|||||||
return eventBus;
|
return eventBus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the supervisor.
|
||||||
|
*
|
||||||
|
* @return the supervisor
|
||||||
|
*/
|
||||||
|
public Supervisor getSupervisor() {
|
||||||
|
return supervisor;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.command;
|
package com.sk89q.worldedit.command;
|
||||||
|
|
||||||
|
import com.google.common.io.Files;
|
||||||
import com.sk89q.minecraft.util.commands.Command;
|
import com.sk89q.minecraft.util.commands.Command;
|
||||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||||
@ -32,7 +33,14 @@ import com.sk89q.worldedit.extension.platform.Actor;
|
|||||||
import com.sk89q.worldedit.extension.platform.Capability;
|
import com.sk89q.worldedit.extension.platform.Capability;
|
||||||
import com.sk89q.worldedit.extension.platform.Platform;
|
import com.sk89q.worldedit.extension.platform.Platform;
|
||||||
import com.sk89q.worldedit.extension.platform.PlatformManager;
|
import com.sk89q.worldedit.extension.platform.PlatformManager;
|
||||||
|
import com.sk89q.worldedit.util.paste.ActorCallbackPaste;
|
||||||
|
import com.sk89q.worldedit.util.report.ConfigReport;
|
||||||
|
import com.sk89q.worldedit.util.report.ReportList;
|
||||||
|
import com.sk89q.worldedit.util.report.SystemInfoReport;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
@ -86,6 +94,28 @@ public class WorldEditCommands {
|
|||||||
actor.print("Configuration reloaded!");
|
actor.print("Configuration reloaded!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Command(aliases = {"report"}, desc = "Writes a report on WorldEdit", flags = "p", max = 0)
|
||||||
|
@CommandPermissions({"worldedit.report"})
|
||||||
|
public void report(Actor actor, CommandContext args) throws WorldEditException {
|
||||||
|
ReportList report = new ReportList("Report");
|
||||||
|
report.add(new SystemInfoReport());
|
||||||
|
report.add(new ConfigReport());
|
||||||
|
String result = report.toString();
|
||||||
|
|
||||||
|
try {
|
||||||
|
File dest = new File(we.getWorkingDirectoryFile(we.getConfiguration().saveDir), "report.txt");
|
||||||
|
Files.write(result, dest, Charset.forName("UTF-8"));
|
||||||
|
actor.print("WorldEdit report written to " + dest.getAbsolutePath());
|
||||||
|
} catch (IOException e) {
|
||||||
|
actor.printError("Failed to write report: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.hasFlag('p')) {
|
||||||
|
actor.checkPermission("worldedit.report.pastebin");
|
||||||
|
ActorCallbackPaste.pastebin(we.getSupervisor(), actor, result, "WorldEdit report: %s.report");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
aliases = { "cui" },
|
aliases = { "cui" },
|
||||||
usage = "",
|
usage = "",
|
||||||
|
@ -0,0 +1,135 @@
|
|||||||
|
/*
|
||||||
|
* 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.Futures;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
|
import com.sk89q.worldedit.util.task.FutureForwardingTask;
|
||||||
|
import com.sk89q.worldedit.util.task.Supervisor;
|
||||||
|
import com.sk89q.worldedit.world.World;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public class AsyncCommandHelper {
|
||||||
|
|
||||||
|
private final ListenableFuture<?> future;
|
||||||
|
private final Supervisor supervisor;
|
||||||
|
private final Actor sender;
|
||||||
|
@Nullable
|
||||||
|
private Object[] formatArgs;
|
||||||
|
|
||||||
|
private AsyncCommandHelper(ListenableFuture<?> future, Supervisor supervisor, Actor sender) {
|
||||||
|
checkNotNull(future);
|
||||||
|
checkNotNull(supervisor);
|
||||||
|
checkNotNull(sender);
|
||||||
|
|
||||||
|
this.future = future;
|
||||||
|
this.supervisor = supervisor;
|
||||||
|
this.sender = sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncCommandHelper formatUsing(Object... args) {
|
||||||
|
this.formatArgs = args;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String format(String message) {
|
||||||
|
if (formatArgs != null) {
|
||||||
|
return String.format(message, formatArgs);
|
||||||
|
} else {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncCommandHelper registerWithSupervisor(String description) {
|
||||||
|
supervisor.monitor(
|
||||||
|
FutureForwardingTask.create(
|
||||||
|
future, format(description), sender));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncCommandHelper sendMessageAfterDelay(String message) {
|
||||||
|
FutureProgressListener.addProgressListener(future, sender, format(message));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncCommandHelper thenRespondWith(String success, String failure) {
|
||||||
|
// Send a response message
|
||||||
|
Futures.addCallback(
|
||||||
|
future,
|
||||||
|
new MessageFutureCallback.Builder(sender)
|
||||||
|
.onSuccess(format(success))
|
||||||
|
.onFailure(format(failure))
|
||||||
|
.build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncCommandHelper thenTellErrorsOnly(String failure) {
|
||||||
|
// Send a response message
|
||||||
|
Futures.addCallback(
|
||||||
|
future,
|
||||||
|
new MessageFutureCallback.Builder(sender)
|
||||||
|
.onFailure(format(failure))
|
||||||
|
.build());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncCommandHelper forRegionDataLoad(World world, boolean silent) {
|
||||||
|
checkNotNull(world);
|
||||||
|
|
||||||
|
formatUsing(world.getName());
|
||||||
|
registerWithSupervisor("Loading region data for '%s'");
|
||||||
|
if (silent) {
|
||||||
|
thenTellErrorsOnly("Failed to load regions '%s'");
|
||||||
|
} else {
|
||||||
|
sendMessageAfterDelay("(Please wait... loading the region data for '%s')");
|
||||||
|
thenRespondWith(
|
||||||
|
"Loaded region data for '%s'",
|
||||||
|
"Failed to load regions '%s'");
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AsyncCommandHelper forRegionDataSave(World world, boolean silent) {
|
||||||
|
checkNotNull(world);
|
||||||
|
|
||||||
|
formatUsing(world.getName());
|
||||||
|
registerWithSupervisor("Saving region data for '%s'");
|
||||||
|
if (silent) {
|
||||||
|
thenTellErrorsOnly("Failed to save regions '%s'");
|
||||||
|
} else {
|
||||||
|
sendMessageAfterDelay("(Please wait... saving the region data for '%s')");
|
||||||
|
thenRespondWith(
|
||||||
|
"Saved region data for '%s'",
|
||||||
|
"Failed to load regions '%s'");
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AsyncCommandHelper wrap(ListenableFuture<?> future, Supervisor supervisor, Actor sender) {
|
||||||
|
return new AsyncCommandHelper(future, supervisor, sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* 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.ListenableFuture;
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
|
|
||||||
|
import java.util.Timer;
|
||||||
|
|
||||||
|
public class FutureProgressListener implements Runnable {
|
||||||
|
|
||||||
|
private static final Timer timer = new Timer();
|
||||||
|
private static final int MESSAGE_DELAY = 1000;
|
||||||
|
|
||||||
|
private final MessageTimerTask task;
|
||||||
|
|
||||||
|
public FutureProgressListener(Actor sender, String message) {
|
||||||
|
checkNotNull(sender);
|
||||||
|
checkNotNull(message);
|
||||||
|
|
||||||
|
task = new MessageTimerTask(sender, message);
|
||||||
|
timer.schedule(task, MESSAGE_DELAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
task.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addProgressListener(ListenableFuture<?> future, Actor sender, String message) {
|
||||||
|
future.addListener(new FutureProgressListener(sender, message), MoreExecutors.directExecutor());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
/*
|
||||||
|
* 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.minecraft.util.commands.CommandException;
|
||||||
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
|
import com.sk89q.worldedit.util.command.parametric.ExceptionConverter;
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* 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.sk89q.worldedit.extension.platform.Actor;
|
||||||
|
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
public class MessageTimerTask extends TimerTask {
|
||||||
|
|
||||||
|
private final Actor sender;
|
||||||
|
private final String message;
|
||||||
|
|
||||||
|
MessageTimerTask(Actor sender, String message) {
|
||||||
|
checkNotNull(sender);
|
||||||
|
checkNotNull(message);
|
||||||
|
|
||||||
|
this.sender = sender;
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
sender.printDebug(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,280 +1,281 @@
|
|||||||
/*
|
/*
|
||||||
* WorldEdit, a Minecraft world manipulation toolkit
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
* Copyright (C) WorldEdit team and contributors
|
* Copyright (C) WorldEdit team and contributors
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* 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
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or
|
* Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
* for more details.
|
* for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// $Id$
|
// $Id$
|
||||||
|
|
||||||
package com.sk89q.worldedit.util;
|
package com.sk89q.worldedit.util;
|
||||||
|
|
||||||
import com.sk89q.util.StringUtil;
|
import com.sk89q.util.StringUtil;
|
||||||
import com.sk89q.worldedit.LocalConfiguration;
|
import com.sk89q.worldedit.LocalConfiguration;
|
||||||
import com.sk89q.worldedit.LocalSession;
|
import com.sk89q.worldedit.LocalSession;
|
||||||
import com.sk89q.worldedit.world.registry.LegacyMapper;
|
import com.sk89q.worldedit.util.report.Unreported;
|
||||||
import com.sk89q.worldedit.world.snapshot.SnapshotRepository;
|
import com.sk89q.worldedit.world.registry.LegacyMapper;
|
||||||
|
import com.sk89q.worldedit.world.snapshot.SnapshotRepository;
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.FileOutputStream;
|
||||||
import java.io.InputStream;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Arrays;
|
import java.io.OutputStream;
|
||||||
import java.util.HashSet;
|
import java.util.Arrays;
|
||||||
import java.util.Properties;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Properties;
|
||||||
import java.util.logging.Level;
|
import java.util.Set;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
/**
|
|
||||||
* Simple LocalConfiguration that loads settings using
|
/**
|
||||||
* {@code java.util.Properties}.
|
* Simple LocalConfiguration that loads settings using
|
||||||
*/
|
* {@code java.util.Properties}.
|
||||||
public class PropertiesConfiguration extends LocalConfiguration {
|
*/
|
||||||
|
public class PropertiesConfiguration extends LocalConfiguration {
|
||||||
private static final Logger log = Logger.getLogger(PropertiesConfiguration.class.getCanonicalName());
|
|
||||||
|
@Unreported private static final Logger log = Logger.getLogger(PropertiesConfiguration.class.getCanonicalName());
|
||||||
protected Properties properties;
|
|
||||||
protected File path;
|
@Unreported protected Properties properties;
|
||||||
|
@Unreported protected File path;
|
||||||
/**
|
|
||||||
* Construct the object. The configuration isn't loaded yet.
|
/**
|
||||||
*
|
* Construct the object. The configuration isn't loaded yet.
|
||||||
* @param path the path tot he configuration
|
*
|
||||||
*/
|
* @param path the path tot he configuration
|
||||||
public PropertiesConfiguration(File path) {
|
*/
|
||||||
this.path = path;
|
public PropertiesConfiguration(File path) {
|
||||||
|
this.path = path;
|
||||||
properties = new Properties();
|
|
||||||
}
|
properties = new Properties();
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public void load() {
|
@Override
|
||||||
try (InputStream stream = new FileInputStream(path)) {
|
public void load() {
|
||||||
properties.load(stream);
|
try (InputStream stream = new FileInputStream(path)) {
|
||||||
} catch (FileNotFoundException ignored) {
|
properties.load(stream);
|
||||||
} catch (IOException e) {
|
} catch (FileNotFoundException ignored) {
|
||||||
log.log(Level.WARNING, "Failed to read configuration", e);
|
} catch (IOException e) {
|
||||||
}
|
log.log(Level.WARNING, "Failed to read configuration", e);
|
||||||
|
}
|
||||||
loadExtra();
|
|
||||||
|
loadExtra();
|
||||||
profile = getBool("profile", profile);
|
|
||||||
traceUnflushedSessions = getBool("trace-unflushed-sessions", traceUnflushedSessions);
|
profile = getBool("profile", profile);
|
||||||
disallowedBlocks = getStringSet("disallowed-blocks", defaultDisallowedBlocks);
|
traceUnflushedSessions = getBool("trace-unflushed-sessions", traceUnflushedSessions);
|
||||||
defaultChangeLimit = getInt("default-max-changed-blocks", defaultChangeLimit);
|
disallowedBlocks = getStringSet("disallowed-blocks", defaultDisallowedBlocks);
|
||||||
maxChangeLimit = getInt("max-changed-blocks", maxChangeLimit);
|
defaultChangeLimit = getInt("default-max-changed-blocks", defaultChangeLimit);
|
||||||
defaultMaxPolygonalPoints = getInt("default-max-polygon-points", defaultMaxPolygonalPoints);
|
maxChangeLimit = getInt("max-changed-blocks", maxChangeLimit);
|
||||||
maxPolygonalPoints = getInt("max-polygon-points", maxPolygonalPoints);
|
defaultMaxPolygonalPoints = getInt("default-max-polygon-points", defaultMaxPolygonalPoints);
|
||||||
defaultMaxPolyhedronPoints = getInt("default-max-polyhedron-points", defaultMaxPolyhedronPoints);
|
maxPolygonalPoints = getInt("max-polygon-points", maxPolygonalPoints);
|
||||||
maxPolyhedronPoints = getInt("max-polyhedron-points", maxPolyhedronPoints);
|
defaultMaxPolyhedronPoints = getInt("default-max-polyhedron-points", defaultMaxPolyhedronPoints);
|
||||||
shellSaveType = getString("shell-save-type", shellSaveType);
|
maxPolyhedronPoints = getInt("max-polyhedron-points", maxPolyhedronPoints);
|
||||||
maxRadius = getInt("max-radius", maxRadius);
|
shellSaveType = getString("shell-save-type", shellSaveType);
|
||||||
maxSuperPickaxeSize = getInt("max-super-pickaxe-size", maxSuperPickaxeSize);
|
maxRadius = getInt("max-radius", maxRadius);
|
||||||
maxBrushRadius = getInt("max-brush-radius", maxBrushRadius);
|
maxSuperPickaxeSize = getInt("max-super-pickaxe-size", maxSuperPickaxeSize);
|
||||||
logCommands = getBool("log-commands", logCommands);
|
maxBrushRadius = getInt("max-brush-radius", maxBrushRadius);
|
||||||
logFile = getString("log-file", logFile);
|
logCommands = getBool("log-commands", logCommands);
|
||||||
logFormat = getString("log-format", logFormat);
|
logFile = getString("log-file", logFile);
|
||||||
registerHelp = getBool("register-help", registerHelp);
|
logFormat = getString("log-format", logFormat);
|
||||||
wandItem = getString("wand-item", wandItem);
|
registerHelp = getBool("register-help", registerHelp);
|
||||||
try {
|
wandItem = getString("wand-item", wandItem);
|
||||||
wandItem = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(wandItem)).getId();
|
try {
|
||||||
} catch (Throwable e) {
|
wandItem = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(wandItem)).getId();
|
||||||
}
|
} catch (Throwable e) {
|
||||||
superPickaxeDrop = getBool("super-pickaxe-drop-items", superPickaxeDrop);
|
}
|
||||||
superPickaxeManyDrop = getBool("super-pickaxe-many-drop-items", superPickaxeManyDrop);
|
superPickaxeDrop = getBool("super-pickaxe-drop-items", superPickaxeDrop);
|
||||||
noDoubleSlash = getBool("no-double-slash", noDoubleSlash);
|
superPickaxeManyDrop = getBool("super-pickaxe-many-drop-items", superPickaxeManyDrop);
|
||||||
useInventory = getBool("use-inventory", useInventory);
|
noDoubleSlash = getBool("no-double-slash", noDoubleSlash);
|
||||||
useInventoryOverride = getBool("use-inventory-override", useInventoryOverride);
|
useInventory = getBool("use-inventory", useInventory);
|
||||||
useInventoryCreativeOverride = getBool("use-inventory-creative-override", useInventoryCreativeOverride);
|
useInventoryOverride = getBool("use-inventory-override", useInventoryOverride);
|
||||||
navigationWand = getString("nav-wand-item", navigationWand);
|
useInventoryCreativeOverride = getBool("use-inventory-creative-override", useInventoryCreativeOverride);
|
||||||
try {
|
navigationWand = getString("nav-wand-item", navigationWand);
|
||||||
navigationWand = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(navigationWand)).getId();
|
try {
|
||||||
} catch (Throwable e) {
|
navigationWand = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(navigationWand)).getId();
|
||||||
}
|
} catch (Throwable e) {
|
||||||
navigationWandMaxDistance = getInt("nav-wand-distance", navigationWandMaxDistance);
|
}
|
||||||
navigationUseGlass = getBool("nav-use-glass", navigationUseGlass);
|
navigationWandMaxDistance = getInt("nav-wand-distance", navigationWandMaxDistance);
|
||||||
scriptTimeout = getInt("scripting-timeout", scriptTimeout);
|
navigationUseGlass = getBool("nav-use-glass", navigationUseGlass);
|
||||||
calculationTimeout = getInt("calculation-timeout", calculationTimeout);
|
scriptTimeout = getInt("scripting-timeout", scriptTimeout);
|
||||||
saveDir = getString("schematic-save-dir", saveDir);
|
calculationTimeout = getInt("calculation-timeout", calculationTimeout);
|
||||||
scriptsDir = getString("craftscript-dir", scriptsDir);
|
saveDir = getString("schematic-save-dir", saveDir);
|
||||||
butcherDefaultRadius = getInt("butcher-default-radius", butcherDefaultRadius);
|
scriptsDir = getString("craftscript-dir", scriptsDir);
|
||||||
butcherMaxRadius = getInt("butcher-max-radius", butcherMaxRadius);
|
butcherDefaultRadius = getInt("butcher-default-radius", butcherDefaultRadius);
|
||||||
allowSymlinks = getBool("allow-symbolic-links", allowSymlinks);
|
butcherMaxRadius = getInt("butcher-max-radius", butcherMaxRadius);
|
||||||
serverSideCUI = getBool("server-side-cui", serverSideCUI);
|
allowSymlinks = getBool("allow-symbolic-links", allowSymlinks);
|
||||||
|
serverSideCUI = getBool("server-side-cui", serverSideCUI);
|
||||||
LocalSession.MAX_HISTORY_SIZE = Math.max(15, getInt("history-size", 15));
|
|
||||||
|
LocalSession.MAX_HISTORY_SIZE = Math.max(15, getInt("history-size", 15));
|
||||||
String snapshotsDir = getString("snapshots-dir", "");
|
|
||||||
if (!snapshotsDir.isEmpty()) {
|
String snapshotsDir = getString("snapshots-dir", "");
|
||||||
snapshotRepo = new SnapshotRepository(snapshotsDir);
|
if (!snapshotsDir.isEmpty()) {
|
||||||
}
|
snapshotRepo = new SnapshotRepository(snapshotsDir);
|
||||||
|
}
|
||||||
path.getParentFile().mkdirs();
|
|
||||||
try (OutputStream output = new FileOutputStream(path)) {
|
path.getParentFile().mkdirs();
|
||||||
properties.store(output, "Don't put comments; they get removed");
|
try (OutputStream output = new FileOutputStream(path)) {
|
||||||
} catch (IOException e) {
|
properties.store(output, "Don't put comments; they get removed");
|
||||||
log.log(Level.WARNING, "Failed to write configuration", e);
|
} catch (IOException e) {
|
||||||
}
|
log.log(Level.WARNING, "Failed to write configuration", e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Called to load extra configuration.
|
/**
|
||||||
*/
|
* Called to load extra configuration.
|
||||||
protected void loadExtra() {
|
*/
|
||||||
}
|
protected void loadExtra() {
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Get a string value.
|
/**
|
||||||
*
|
* Get a string value.
|
||||||
* @param key the key
|
*
|
||||||
* @param def the default value
|
* @param key the key
|
||||||
* @return the value
|
* @param def the default value
|
||||||
*/
|
* @return the value
|
||||||
protected String getString(String key, String def) {
|
*/
|
||||||
if (def == null) {
|
protected String getString(String key, String def) {
|
||||||
def = "";
|
if (def == null) {
|
||||||
}
|
def = "";
|
||||||
String val = properties.getProperty(key);
|
}
|
||||||
if (val == null) {
|
String val = properties.getProperty(key);
|
||||||
properties.setProperty(key, def);
|
if (val == null) {
|
||||||
return def;
|
properties.setProperty(key, def);
|
||||||
} else {
|
return def;
|
||||||
return val;
|
} else {
|
||||||
}
|
return val;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Get a boolean value.
|
/**
|
||||||
*
|
* Get a boolean value.
|
||||||
* @param key the key
|
*
|
||||||
* @param def the default value
|
* @param key the key
|
||||||
* @return the value
|
* @param def the default value
|
||||||
*/
|
* @return the value
|
||||||
protected boolean getBool(String key, boolean def) {
|
*/
|
||||||
String val = properties.getProperty(key);
|
protected boolean getBool(String key, boolean def) {
|
||||||
if (val == null) {
|
String val = properties.getProperty(key);
|
||||||
properties.setProperty(key, def ? "true" : "false");
|
if (val == null) {
|
||||||
return def;
|
properties.setProperty(key, def ? "true" : "false");
|
||||||
} else {
|
return def;
|
||||||
return val.equalsIgnoreCase("true")
|
} else {
|
||||||
|| val.equals("1");
|
return val.equalsIgnoreCase("true")
|
||||||
}
|
|| val.equals("1");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Get an integer value.
|
/**
|
||||||
*
|
* Get an integer value.
|
||||||
* @param key the key
|
*
|
||||||
* @param def the default value
|
* @param key the key
|
||||||
* @return the value
|
* @param def the default value
|
||||||
*/
|
* @return the value
|
||||||
protected int getInt(String key, int def) {
|
*/
|
||||||
String val = properties.getProperty(key);
|
protected int getInt(String key, int def) {
|
||||||
if (val == null) {
|
String val = properties.getProperty(key);
|
||||||
properties.setProperty(key, String.valueOf(def));
|
if (val == null) {
|
||||||
return def;
|
properties.setProperty(key, String.valueOf(def));
|
||||||
} else {
|
return def;
|
||||||
try {
|
} else {
|
||||||
return Integer.parseInt(val);
|
try {
|
||||||
} catch (NumberFormatException e) {
|
return Integer.parseInt(val);
|
||||||
properties.setProperty(key, String.valueOf(def));
|
} catch (NumberFormatException e) {
|
||||||
return def;
|
properties.setProperty(key, String.valueOf(def));
|
||||||
}
|
return def;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Get a double value.
|
/**
|
||||||
*
|
* Get a double value.
|
||||||
* @param key the key
|
*
|
||||||
* @param def the default value
|
* @param key the key
|
||||||
* @return the value
|
* @param def the default value
|
||||||
*/
|
* @return the value
|
||||||
protected double getDouble(String key, double def) {
|
*/
|
||||||
String val = properties.getProperty(key);
|
protected double getDouble(String key, double def) {
|
||||||
if (val == null) {
|
String val = properties.getProperty(key);
|
||||||
properties.setProperty(key, String.valueOf(def));
|
if (val == null) {
|
||||||
return def;
|
properties.setProperty(key, String.valueOf(def));
|
||||||
} else {
|
return def;
|
||||||
try {
|
} else {
|
||||||
return Double.parseDouble(val);
|
try {
|
||||||
} catch (NumberFormatException e) {
|
return Double.parseDouble(val);
|
||||||
properties.setProperty(key, String.valueOf(def));
|
} catch (NumberFormatException e) {
|
||||||
return def;
|
properties.setProperty(key, String.valueOf(def));
|
||||||
}
|
return def;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Get a double value.
|
/**
|
||||||
*
|
* Get a double value.
|
||||||
* @param key the key
|
*
|
||||||
* @param def the default value
|
* @param key the key
|
||||||
* @return the value
|
* @param def the default value
|
||||||
*/
|
* @return the value
|
||||||
protected Set<Integer> getIntSet(String key, int[] def) {
|
*/
|
||||||
String val = properties.getProperty(key);
|
protected Set<Integer> getIntSet(String key, int[] def) {
|
||||||
if (val == null) {
|
String val = properties.getProperty(key);
|
||||||
properties.setProperty(key, StringUtil.joinString(def, ",", 0));
|
if (val == null) {
|
||||||
Set<Integer> set = new HashSet<>();
|
properties.setProperty(key, StringUtil.joinString(def, ",", 0));
|
||||||
for (int i : def) {
|
Set<Integer> set = new HashSet<>();
|
||||||
set.add(i);
|
for (int i : def) {
|
||||||
}
|
set.add(i);
|
||||||
return set;
|
}
|
||||||
} else {
|
return set;
|
||||||
Set<Integer> set = new HashSet<>();
|
} else {
|
||||||
String[] parts = val.split(",");
|
Set<Integer> set = new HashSet<>();
|
||||||
for (String part : parts) {
|
String[] parts = val.split(",");
|
||||||
try {
|
for (String part : parts) {
|
||||||
int v = Integer.parseInt(part.trim());
|
try {
|
||||||
set.add(v);
|
int v = Integer.parseInt(part.trim());
|
||||||
} catch (NumberFormatException ignored) {
|
set.add(v);
|
||||||
}
|
} catch (NumberFormatException ignored) {
|
||||||
}
|
}
|
||||||
return set;
|
}
|
||||||
}
|
return set;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Get a String set.
|
/**
|
||||||
*
|
* Get a String set.
|
||||||
* @param key the key
|
*
|
||||||
* @param def the default value
|
* @param key the key
|
||||||
* @return the value
|
* @param def the default value
|
||||||
*/
|
* @return the value
|
||||||
protected Set<String> getStringSet(String key, String[] def) {
|
*/
|
||||||
String val = properties.getProperty(key);
|
protected Set<String> getStringSet(String key, String[] def) {
|
||||||
if (val == null) {
|
String val = properties.getProperty(key);
|
||||||
properties.setProperty(key, StringUtil.joinString(def, ",", 0));
|
if (val == null) {
|
||||||
return new HashSet<>(Arrays.asList(def));
|
properties.setProperty(key, StringUtil.joinString(def, ",", 0));
|
||||||
} else {
|
return new HashSet<>(Arrays.asList(def));
|
||||||
Set<String> set = new HashSet<>();
|
} else {
|
||||||
String[] parts = val.split(",");
|
Set<String> set = new HashSet<>();
|
||||||
for (String part : parts) {
|
String[] parts = val.split(",");
|
||||||
try {
|
for (String part : parts) {
|
||||||
String v = part.trim();
|
try {
|
||||||
set.add(v);
|
String v = part.trim();
|
||||||
} catch (NumberFormatException ignored) {
|
set.add(v);
|
||||||
}
|
} catch (NumberFormatException ignored) {
|
||||||
}
|
}
|
||||||
return set;
|
}
|
||||||
}
|
return set;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
|
@ -1,133 +1,134 @@
|
|||||||
/*
|
/*
|
||||||
* WorldEdit, a Minecraft world manipulation toolkit
|
* WorldEdit, a Minecraft world manipulation toolkit
|
||||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||||
* Copyright (C) WorldEdit team and contributors
|
* Copyright (C) WorldEdit team and contributors
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
* 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
|
* under the terms of the GNU Lesser General Public License as published by the
|
||||||
* Free Software Foundation, either version 3 of the License, or
|
* Free Software Foundation, either version 3 of the License, or
|
||||||
* (at your option) any later version.
|
* (at your option) any later version.
|
||||||
*
|
*
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||||
* for more details.
|
* for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
* 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/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.sk89q.worldedit.util;
|
package com.sk89q.worldedit.util;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.sk89q.util.yaml.YAMLProcessor;
|
import com.sk89q.util.yaml.YAMLProcessor;
|
||||||
import com.sk89q.worldedit.LocalConfiguration;
|
import com.sk89q.worldedit.LocalConfiguration;
|
||||||
import com.sk89q.worldedit.LocalSession;
|
import com.sk89q.worldedit.LocalSession;
|
||||||
import com.sk89q.worldedit.session.SessionManager;
|
import com.sk89q.worldedit.session.SessionManager;
|
||||||
import com.sk89q.worldedit.world.snapshot.SnapshotRepository;
|
import com.sk89q.worldedit.util.report.Unreported;
|
||||||
|
import com.sk89q.worldedit.world.snapshot.SnapshotRepository;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.HashSet;
|
import java.io.IOException;
|
||||||
import java.util.logging.Level;
|
import java.util.HashSet;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
/**
|
|
||||||
* A less simple implementation of {@link LocalConfiguration}
|
/**
|
||||||
* using YAML configuration files.
|
* A less simple implementation of {@link LocalConfiguration}
|
||||||
*/
|
* using YAML configuration files.
|
||||||
public class YAMLConfiguration extends LocalConfiguration {
|
*/
|
||||||
|
public class YAMLConfiguration extends LocalConfiguration {
|
||||||
protected final YAMLProcessor config;
|
|
||||||
protected final Logger logger;
|
@Unreported protected final YAMLProcessor config;
|
||||||
|
@Unreported protected final Logger logger;
|
||||||
public YAMLConfiguration(YAMLProcessor config, Logger logger) {
|
|
||||||
this.config = config;
|
public YAMLConfiguration(YAMLProcessor config, Logger logger) {
|
||||||
this.logger = logger;
|
this.config = config;
|
||||||
}
|
this.logger = logger;
|
||||||
|
}
|
||||||
@Override
|
|
||||||
public void load() {
|
@Override
|
||||||
try {
|
public void load() {
|
||||||
config.load();
|
try {
|
||||||
} catch (IOException e) {
|
config.load();
|
||||||
logger.log(Level.WARNING, "Error loading WorldEdit configuration", e);
|
} catch (IOException e) {
|
||||||
}
|
logger.log(Level.WARNING, "Error loading WorldEdit configuration", e);
|
||||||
|
}
|
||||||
profile = config.getBoolean("debug", profile);
|
|
||||||
traceUnflushedSessions = config.getBoolean("debugging.trace-unflushed-sessions", traceUnflushedSessions);
|
profile = config.getBoolean("debug", profile);
|
||||||
wandItem = convertLegacyItem(config.getString("wand-item", wandItem));
|
traceUnflushedSessions = config.getBoolean("debugging.trace-unflushed-sessions", traceUnflushedSessions);
|
||||||
|
wandItem = convertLegacyItem(config.getString("wand-item", wandItem));
|
||||||
defaultChangeLimit = Math.max(-1, config.getInt(
|
|
||||||
"limits.max-blocks-changed.default", defaultChangeLimit));
|
defaultChangeLimit = Math.max(-1, config.getInt(
|
||||||
maxChangeLimit = Math.max(-1,
|
"limits.max-blocks-changed.default", defaultChangeLimit));
|
||||||
config.getInt("limits.max-blocks-changed.maximum", maxChangeLimit));
|
maxChangeLimit = Math.max(-1,
|
||||||
|
config.getInt("limits.max-blocks-changed.maximum", maxChangeLimit));
|
||||||
defaultMaxPolygonalPoints = Math.max(-1,
|
|
||||||
config.getInt("limits.max-polygonal-points.default", defaultMaxPolygonalPoints));
|
defaultMaxPolygonalPoints = Math.max(-1,
|
||||||
maxPolygonalPoints = Math.max(-1,
|
config.getInt("limits.max-polygonal-points.default", defaultMaxPolygonalPoints));
|
||||||
config.getInt("limits.max-polygonal-points.maximum", maxPolygonalPoints));
|
maxPolygonalPoints = Math.max(-1,
|
||||||
|
config.getInt("limits.max-polygonal-points.maximum", maxPolygonalPoints));
|
||||||
defaultMaxPolyhedronPoints = Math.max(-1, config.getInt("limits.max-polyhedron-points.default", defaultMaxPolyhedronPoints));
|
|
||||||
maxPolyhedronPoints = Math.max(-1, config.getInt("limits.max-polyhedron-points.maximum", maxPolyhedronPoints));
|
defaultMaxPolyhedronPoints = Math.max(-1, config.getInt("limits.max-polyhedron-points.default", defaultMaxPolyhedronPoints));
|
||||||
|
maxPolyhedronPoints = Math.max(-1, config.getInt("limits.max-polyhedron-points.maximum", maxPolyhedronPoints));
|
||||||
maxRadius = Math.max(-1, config.getInt("limits.max-radius", maxRadius));
|
|
||||||
maxBrushRadius = config.getInt("limits.max-brush-radius", maxBrushRadius);
|
maxRadius = Math.max(-1, config.getInt("limits.max-radius", maxRadius));
|
||||||
maxSuperPickaxeSize = Math.max(1, config.getInt(
|
maxBrushRadius = config.getInt("limits.max-brush-radius", maxBrushRadius);
|
||||||
"limits.max-super-pickaxe-size", maxSuperPickaxeSize));
|
maxSuperPickaxeSize = Math.max(1, config.getInt(
|
||||||
|
"limits.max-super-pickaxe-size", maxSuperPickaxeSize));
|
||||||
butcherDefaultRadius = Math.max(-1, config.getInt("limits.butcher-radius.default", butcherDefaultRadius));
|
|
||||||
butcherMaxRadius = Math.max(-1, config.getInt("limits.butcher-radius.maximum", butcherMaxRadius));
|
butcherDefaultRadius = Math.max(-1, config.getInt("limits.butcher-radius.default", butcherDefaultRadius));
|
||||||
|
butcherMaxRadius = Math.max(-1, config.getInt("limits.butcher-radius.maximum", butcherMaxRadius));
|
||||||
disallowedBlocks = new HashSet<>(config.getStringList("limits.disallowed-blocks", Lists.newArrayList(defaultDisallowedBlocks)));
|
|
||||||
allowedDataCycleBlocks = new HashSet<>(config.getStringList("limits.allowed-data-cycle-blocks", null));
|
disallowedBlocks = new HashSet<>(config.getStringList("limits.disallowed-blocks", Lists.newArrayList(defaultDisallowedBlocks)));
|
||||||
|
allowedDataCycleBlocks = new HashSet<>(config.getStringList("limits.allowed-data-cycle-blocks", null));
|
||||||
registerHelp = config.getBoolean("register-help", true);
|
|
||||||
logCommands = config.getBoolean("logging.log-commands", logCommands);
|
registerHelp = config.getBoolean("register-help", true);
|
||||||
logFile = config.getString("logging.file", logFile);
|
logCommands = config.getBoolean("logging.log-commands", logCommands);
|
||||||
logFormat = config.getString("logging.format", logFormat);
|
logFile = config.getString("logging.file", logFile);
|
||||||
|
logFormat = config.getString("logging.format", logFormat);
|
||||||
superPickaxeDrop = config.getBoolean("super-pickaxe.drop-items",
|
|
||||||
superPickaxeDrop);
|
superPickaxeDrop = config.getBoolean("super-pickaxe.drop-items",
|
||||||
superPickaxeManyDrop = config.getBoolean(
|
superPickaxeDrop);
|
||||||
"super-pickaxe.many-drop-items", superPickaxeManyDrop);
|
superPickaxeManyDrop = config.getBoolean(
|
||||||
|
"super-pickaxe.many-drop-items", superPickaxeManyDrop);
|
||||||
noDoubleSlash = config.getBoolean("no-double-slash", noDoubleSlash);
|
|
||||||
|
noDoubleSlash = config.getBoolean("no-double-slash", noDoubleSlash);
|
||||||
useInventory = config.getBoolean("use-inventory.enable", useInventory);
|
|
||||||
useInventoryOverride = config.getBoolean("use-inventory.allow-override",
|
useInventory = config.getBoolean("use-inventory.enable", useInventory);
|
||||||
useInventoryOverride);
|
useInventoryOverride = config.getBoolean("use-inventory.allow-override",
|
||||||
useInventoryCreativeOverride = config.getBoolean("use-inventory.creative-mode-overrides",
|
useInventoryOverride);
|
||||||
useInventoryCreativeOverride);
|
useInventoryCreativeOverride = config.getBoolean("use-inventory.creative-mode-overrides",
|
||||||
|
useInventoryCreativeOverride);
|
||||||
navigationWand = convertLegacyItem(config.getString("navigation-wand.item", navigationWand));
|
|
||||||
navigationWandMaxDistance = config.getInt("navigation-wand.max-distance", navigationWandMaxDistance);
|
navigationWand = convertLegacyItem(config.getString("navigation-wand.item", navigationWand));
|
||||||
navigationUseGlass = config.getBoolean("navigation.use-glass", navigationUseGlass);
|
navigationWandMaxDistance = config.getInt("navigation-wand.max-distance", navigationWandMaxDistance);
|
||||||
|
navigationUseGlass = config.getBoolean("navigation.use-glass", navigationUseGlass);
|
||||||
scriptTimeout = config.getInt("scripting.timeout", scriptTimeout);
|
|
||||||
scriptsDir = config.getString("scripting.dir", scriptsDir);
|
scriptTimeout = config.getInt("scripting.timeout", scriptTimeout);
|
||||||
|
scriptsDir = config.getString("scripting.dir", scriptsDir);
|
||||||
calculationTimeout = config.getInt("calculation.timeout", calculationTimeout);
|
|
||||||
|
calculationTimeout = config.getInt("calculation.timeout", calculationTimeout);
|
||||||
saveDir = config.getString("saving.dir", saveDir);
|
|
||||||
|
saveDir = config.getString("saving.dir", saveDir);
|
||||||
allowSymlinks = config.getBoolean("files.allow-symbolic-links", false);
|
|
||||||
LocalSession.MAX_HISTORY_SIZE = Math.max(0, config.getInt("history.size", 15));
|
allowSymlinks = config.getBoolean("files.allow-symbolic-links", false);
|
||||||
SessionManager.EXPIRATION_GRACE = config.getInt("history.expiration", 10) * 60 * 1000;
|
LocalSession.MAX_HISTORY_SIZE = Math.max(0, config.getInt("history.size", 15));
|
||||||
|
SessionManager.EXPIRATION_GRACE = config.getInt("history.expiration", 10) * 60 * 1000;
|
||||||
showHelpInfo = config.getBoolean("show-help-on-first-use", true);
|
|
||||||
serverSideCUI = config.getBoolean("server-side-cui", true);
|
showHelpInfo = config.getBoolean("show-help-on-first-use", true);
|
||||||
|
serverSideCUI = config.getBoolean("server-side-cui", true);
|
||||||
String snapshotsDir = config.getString("snapshots.directory", "");
|
|
||||||
if (!snapshotsDir.isEmpty()) {
|
String snapshotsDir = config.getString("snapshots.directory", "");
|
||||||
snapshotRepo = new SnapshotRepository(snapshotsDir);
|
if (!snapshotsDir.isEmpty()) {
|
||||||
}
|
snapshotRepo = new SnapshotRepository(snapshotsDir);
|
||||||
|
}
|
||||||
String type = config.getString("shell-save-type", "").trim();
|
|
||||||
shellSaveType = type.isEmpty() ? null : type;
|
String type = config.getString("shell-save-type", "").trim();
|
||||||
|
shellSaveType = type.isEmpty() ? null : type;
|
||||||
}
|
|
||||||
|
}
|
||||||
public void unload() {
|
|
||||||
}
|
public void unload() {
|
||||||
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
|
@ -0,0 +1,490 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.net;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.util.io.Closer;
|
||||||
|
|
||||||
|
import java.io.BufferedInputStream;
|
||||||
|
import java.io.BufferedOutputStream;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.Closeable;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class HttpRequest implements Closeable {
|
||||||
|
|
||||||
|
private static final int CONNECT_TIMEOUT = 1000 * 5;
|
||||||
|
private static final int READ_TIMEOUT = 1000 * 5;
|
||||||
|
private static final int READ_BUFFER_SIZE = 1024 * 8;
|
||||||
|
|
||||||
|
private final Map<String, String> headers = new HashMap<>();
|
||||||
|
private final String method;
|
||||||
|
private final URL url;
|
||||||
|
private String contentType;
|
||||||
|
private byte[] body;
|
||||||
|
private HttpURLConnection conn;
|
||||||
|
private InputStream inputStream;
|
||||||
|
|
||||||
|
private long contentLength = -1;
|
||||||
|
private long readBytes = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new HTTP request.
|
||||||
|
*
|
||||||
|
* @param method the method
|
||||||
|
* @param url the URL
|
||||||
|
*/
|
||||||
|
private HttpRequest(String method, URL url) {
|
||||||
|
this.method = method;
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit data.
|
||||||
|
*
|
||||||
|
* @return this object
|
||||||
|
*/
|
||||||
|
public HttpRequest body(String data) {
|
||||||
|
body = data.getBytes();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Submit form data.
|
||||||
|
*
|
||||||
|
* @param form the form
|
||||||
|
* @return this object
|
||||||
|
*/
|
||||||
|
public HttpRequest bodyForm(Form form) {
|
||||||
|
contentType = "application/x-www-form-urlencoded";
|
||||||
|
body = form.toString().getBytes();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a header.
|
||||||
|
*
|
||||||
|
* @param key the header key
|
||||||
|
* @param value the header value
|
||||||
|
* @return this object
|
||||||
|
*/
|
||||||
|
public HttpRequest header(String key, String value) {
|
||||||
|
if (key.equalsIgnoreCase("Content-Type")) {
|
||||||
|
contentType = value;
|
||||||
|
} else {
|
||||||
|
headers.put(key, value);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the request.
|
||||||
|
* <p/>
|
||||||
|
* After execution, {@link #close()} should be called.
|
||||||
|
*
|
||||||
|
* @return this object
|
||||||
|
* @throws java.io.IOException on I/O error
|
||||||
|
*/
|
||||||
|
public HttpRequest execute() throws IOException {
|
||||||
|
boolean successful = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (conn != null) {
|
||||||
|
throw new IllegalArgumentException("Connection already executed");
|
||||||
|
}
|
||||||
|
|
||||||
|
conn = (HttpURLConnection) reformat(url).openConnection();
|
||||||
|
conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Java)");
|
||||||
|
|
||||||
|
if (body != null) {
|
||||||
|
conn.setRequestProperty("Content-Type", contentType);
|
||||||
|
conn.setRequestProperty("Content-Length", Integer.toString(body.length));
|
||||||
|
conn.setDoInput(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Map.Entry<String, String> entry : headers.entrySet()) {
|
||||||
|
conn.setRequestProperty(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.setRequestMethod(method);
|
||||||
|
conn.setUseCaches(false);
|
||||||
|
conn.setDoOutput(true);
|
||||||
|
conn.setConnectTimeout(CONNECT_TIMEOUT);
|
||||||
|
conn.setReadTimeout(READ_TIMEOUT);
|
||||||
|
|
||||||
|
conn.connect();
|
||||||
|
|
||||||
|
if (body != null) {
|
||||||
|
DataOutputStream out = new DataOutputStream(conn.getOutputStream());
|
||||||
|
out.write(body);
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
inputStream = conn.getResponseCode() == HttpURLConnection.HTTP_OK ?
|
||||||
|
conn.getInputStream() : conn.getErrorStream();
|
||||||
|
|
||||||
|
successful = true;
|
||||||
|
} finally {
|
||||||
|
if (!successful) {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Require that the response code is one of the given response codes.
|
||||||
|
*
|
||||||
|
* @param codes a list of codes
|
||||||
|
* @return this object
|
||||||
|
* @throws java.io.IOException if there is an I/O error or the response code is not expected
|
||||||
|
*/
|
||||||
|
public HttpRequest expectResponseCode(int... codes) throws IOException {
|
||||||
|
int responseCode = getResponseCode();
|
||||||
|
|
||||||
|
for (int code : codes) {
|
||||||
|
if (code == responseCode) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close();
|
||||||
|
throw new IOException("Did not get expected response code, got " + responseCode + " for " + url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the response code.
|
||||||
|
*
|
||||||
|
* @return the response code
|
||||||
|
* @throws java.io.IOException on I/O error
|
||||||
|
*/
|
||||||
|
public int getResponseCode() throws IOException {
|
||||||
|
if (conn == null) {
|
||||||
|
throw new IllegalArgumentException("No connection has been made");
|
||||||
|
}
|
||||||
|
|
||||||
|
return conn.getResponseCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the input stream.
|
||||||
|
*
|
||||||
|
* @return the input stream
|
||||||
|
*/
|
||||||
|
public InputStream getInputStream() {
|
||||||
|
return inputStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Buffer the returned response.
|
||||||
|
*
|
||||||
|
* @return the buffered response
|
||||||
|
* @throws java.io.IOException on I/O error
|
||||||
|
* @throws InterruptedException on interruption
|
||||||
|
*/
|
||||||
|
public BufferedResponse returnContent() throws IOException, InterruptedException {
|
||||||
|
if (inputStream == null) {
|
||||||
|
throw new IllegalArgumentException("No input stream available");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
int b = 0;
|
||||||
|
while ((b = inputStream.read()) != -1) {
|
||||||
|
bos.write(b);
|
||||||
|
}
|
||||||
|
return new BufferedResponse(bos.toByteArray());
|
||||||
|
} finally {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the result to a file.
|
||||||
|
*
|
||||||
|
* @param file the file
|
||||||
|
* @return this object
|
||||||
|
* @throws java.io.IOException on I/O error
|
||||||
|
* @throws InterruptedException on interruption
|
||||||
|
*/
|
||||||
|
public HttpRequest saveContent(File file) throws IOException, InterruptedException {
|
||||||
|
Closer closer = Closer.create();
|
||||||
|
|
||||||
|
try {
|
||||||
|
FileOutputStream fos = closer.register(new FileOutputStream(file));
|
||||||
|
BufferedOutputStream bos = closer.register(new BufferedOutputStream(fos));
|
||||||
|
|
||||||
|
saveContent(bos);
|
||||||
|
} finally {
|
||||||
|
closer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the result to an output stream.
|
||||||
|
*
|
||||||
|
* @param out the output stream
|
||||||
|
* @return this object
|
||||||
|
* @throws java.io.IOException on I/O error
|
||||||
|
* @throws InterruptedException on interruption
|
||||||
|
*/
|
||||||
|
public HttpRequest saveContent(OutputStream out) throws IOException, InterruptedException {
|
||||||
|
BufferedInputStream bis;
|
||||||
|
|
||||||
|
try {
|
||||||
|
String field = conn.getHeaderField("Content-Length");
|
||||||
|
if (field != null) {
|
||||||
|
long len = Long.parseLong(field);
|
||||||
|
if (len >= 0) { // Let's just not deal with really big numbers
|
||||||
|
contentLength = len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (NumberFormatException ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
bis = new BufferedInputStream(inputStream);
|
||||||
|
|
||||||
|
byte[] data = new byte[READ_BUFFER_SIZE];
|
||||||
|
int len = 0;
|
||||||
|
while ((len = bis.read(data, 0, READ_BUFFER_SIZE)) >= 0) {
|
||||||
|
out.write(data, 0, len);
|
||||||
|
readBytes += len;
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
if (conn != null) conn.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a GET request.
|
||||||
|
*
|
||||||
|
* @param url the URL
|
||||||
|
* @return a new request object
|
||||||
|
*/
|
||||||
|
public static HttpRequest get(URL url) {
|
||||||
|
return request("GET", url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a POST request.
|
||||||
|
*
|
||||||
|
* @param url the URL
|
||||||
|
* @return a new request object
|
||||||
|
*/
|
||||||
|
public static HttpRequest post(URL url) {
|
||||||
|
return request("POST", url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a request.
|
||||||
|
*
|
||||||
|
* @param method the method
|
||||||
|
* @param url the URL
|
||||||
|
* @return a new request object
|
||||||
|
*/
|
||||||
|
public static HttpRequest request(String method, URL url) {
|
||||||
|
return new HttpRequest(method, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@link java.net.URL} and throw a {@link RuntimeException} if the URL
|
||||||
|
* is not valid.
|
||||||
|
*
|
||||||
|
* @param url the url
|
||||||
|
* @return a URL object
|
||||||
|
* @throws RuntimeException if the URL is invalid
|
||||||
|
*/
|
||||||
|
public static URL url(String url) {
|
||||||
|
try {
|
||||||
|
return new URL(url);
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL may contain spaces and other nasties that will cause a failure.
|
||||||
|
*
|
||||||
|
* @param existing the existing URL to transform
|
||||||
|
* @return the new URL, or old one if there was a failure
|
||||||
|
*/
|
||||||
|
private static URL reformat(URL existing) {
|
||||||
|
try {
|
||||||
|
URL url = new URL(existing.toString());
|
||||||
|
URI uri = new URI(
|
||||||
|
url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(),
|
||||||
|
url.getPath(), url.getQuery(), url.getRef());
|
||||||
|
url = uri.toURL();
|
||||||
|
return url;
|
||||||
|
} catch (MalformedURLException e) {
|
||||||
|
return existing;
|
||||||
|
} catch (URISyntaxException e) {
|
||||||
|
return existing;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used with {@link #bodyForm(Form)}.
|
||||||
|
*/
|
||||||
|
public final static class Form {
|
||||||
|
public final List<String> elements = new ArrayList<>();
|
||||||
|
|
||||||
|
private Form() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a key/value to the form.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param value the value
|
||||||
|
* @return this object
|
||||||
|
*/
|
||||||
|
public Form add(String key, String value) {
|
||||||
|
try {
|
||||||
|
elements.add(URLEncoder.encode(key, "UTF-8") +
|
||||||
|
"=" + URLEncoder.encode(value, "UTF-8"));
|
||||||
|
return this;
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
boolean first = true;
|
||||||
|
for (String element : elements) {
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
builder.append("&");
|
||||||
|
}
|
||||||
|
builder.append(element);
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new form.
|
||||||
|
*
|
||||||
|
* @return a new form
|
||||||
|
*/
|
||||||
|
public static Form create() {
|
||||||
|
return new Form();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to buffer the response in memory.
|
||||||
|
*/
|
||||||
|
public class BufferedResponse {
|
||||||
|
private final byte[] data;
|
||||||
|
|
||||||
|
private BufferedResponse(byte[] data) {
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the result as bytes.
|
||||||
|
*
|
||||||
|
* @return the data
|
||||||
|
*/
|
||||||
|
public byte[] asBytes() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the result as a string.
|
||||||
|
*
|
||||||
|
* @param encoding the encoding
|
||||||
|
* @return the string
|
||||||
|
* @throws java.io.IOException on I/O error
|
||||||
|
*/
|
||||||
|
public String asString(String encoding) throws IOException {
|
||||||
|
return new String(data, encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the result to a file.
|
||||||
|
*
|
||||||
|
* @param file the file
|
||||||
|
* @return this object
|
||||||
|
* @throws java.io.IOException on I/O error
|
||||||
|
* @throws InterruptedException on interruption
|
||||||
|
*/
|
||||||
|
public BufferedResponse saveContent(File file) throws IOException, InterruptedException {
|
||||||
|
Closer closer = Closer.create();
|
||||||
|
file.getParentFile().mkdirs();
|
||||||
|
|
||||||
|
try {
|
||||||
|
FileOutputStream fos = closer.register(new FileOutputStream(file));
|
||||||
|
BufferedOutputStream bos = closer.register(new BufferedOutputStream(fos));
|
||||||
|
|
||||||
|
saveContent(bos);
|
||||||
|
} finally {
|
||||||
|
closer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save the result to an output stream.
|
||||||
|
*
|
||||||
|
* @param out the output stream
|
||||||
|
* @return this object
|
||||||
|
* @throws java.io.IOException on I/O error
|
||||||
|
* @throws InterruptedException on interruption
|
||||||
|
*/
|
||||||
|
public BufferedResponse saveContent(OutputStream out) throws IOException, InterruptedException {
|
||||||
|
out.write(data);
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.paste;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.FutureCallback;
|
||||||
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.sk89q.worldedit.command.util.AsyncCommandHelper;
|
||||||
|
import com.sk89q.worldedit.extension.platform.Actor;
|
||||||
|
import com.sk89q.worldedit.util.task.Supervisor;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class ActorCallbackPaste {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = Logger.getLogger(ActorCallbackPaste.class.getSimpleName());
|
||||||
|
|
||||||
|
private ActorCallbackPaste() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 successMessage The message, formatted with {@link String#format(String, Object...)} on success
|
||||||
|
*/
|
||||||
|
public static void pastebin(Supervisor supervisor, final Actor sender, String content, final String successMessage) {
|
||||||
|
ListenableFuture<URL> future = new EngineHubPaste().paste(content);
|
||||||
|
|
||||||
|
AsyncCommandHelper.wrap(future, supervisor, sender)
|
||||||
|
.registerWithSupervisor("Submitting content to a pastebin service...")
|
||||||
|
.sendMessageAfterDelay("(Please wait... sending output to pastebin...)");
|
||||||
|
|
||||||
|
Futures.addCallback(future, new FutureCallback<URL>() {
|
||||||
|
@Override
|
||||||
|
public void onSuccess(URL url) {
|
||||||
|
sender.print(String.format(successMessage, url));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Throwable throwable) {
|
||||||
|
LOGGER.log(Level.WARNING, "Failed to submit pastebin", throwable);
|
||||||
|
sender.printError("Failed to submit to a pastebin. Please see console for the error.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.paste;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.sk89q.worldedit.util.net.HttpRequest;
|
||||||
|
import org.json.simple.JSONValue;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class EngineHubPaste implements Paster {
|
||||||
|
|
||||||
|
private static final Pattern URL_PATTERN = Pattern.compile("https?://.+$");
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<URL> paste(String content) {
|
||||||
|
return Pasters.getExecutor().submit(new PasteTask(content));
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class PasteTask implements Callable<URL> {
|
||||||
|
private final String content;
|
||||||
|
|
||||||
|
private PasteTask(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URL call() throws IOException, InterruptedException {
|
||||||
|
HttpRequest.Form form = HttpRequest.Form.create();
|
||||||
|
form.add("content", content);
|
||||||
|
form.add("from", "worldguard");
|
||||||
|
|
||||||
|
URL url = HttpRequest.url("http://paste.enginehub.org/paste");
|
||||||
|
String result = HttpRequest.post(url)
|
||||||
|
.bodyForm(form)
|
||||||
|
.execute()
|
||||||
|
.expectResponseCode(200)
|
||||||
|
.returnContent()
|
||||||
|
.asString("UTF-8").trim();
|
||||||
|
|
||||||
|
Object object = JSONValue.parse(result);
|
||||||
|
if (object instanceof Map) {
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
String urlString = String.valueOf(((Map<Object, Object>) object).get("url"));
|
||||||
|
Matcher m = URL_PATTERN.matcher(urlString);
|
||||||
|
|
||||||
|
if (m.matches()) {
|
||||||
|
return new URL(urlString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IOException("Failed to save paste; instead, got: " + result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.paste;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.sk89q.worldedit.util.net.HttpRequest;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class Pastebin implements Paster {
|
||||||
|
|
||||||
|
private static final Pattern URL_PATTERN = Pattern.compile("https?://pastebin.com/([^/]+)$");
|
||||||
|
|
||||||
|
private boolean mungingLinks = true;
|
||||||
|
|
||||||
|
public boolean isMungingLinks() {
|
||||||
|
return mungingLinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMungingLinks(boolean mungingLinks) {
|
||||||
|
this.mungingLinks = mungingLinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ListenableFuture<URL> paste(String content) {
|
||||||
|
if (mungingLinks) {
|
||||||
|
content = content.replaceAll("http://", "http_//");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Pasters.getExecutor().submit(new PasteTask(content));
|
||||||
|
}
|
||||||
|
|
||||||
|
private final class PasteTask implements Callable<URL> {
|
||||||
|
private final String content;
|
||||||
|
|
||||||
|
private PasteTask(String content) {
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public URL call() throws IOException, InterruptedException {
|
||||||
|
HttpRequest.Form form = HttpRequest.Form.create();
|
||||||
|
form.add("api_option", "paste");
|
||||||
|
form.add("api_dev_key", "4867eae74c6990dbdef07c543cf8f805");
|
||||||
|
form.add("api_paste_code", content);
|
||||||
|
form.add("api_paste_private", "0");
|
||||||
|
form.add("api_paste_name", "");
|
||||||
|
form.add("api_paste_expire_date", "1W");
|
||||||
|
form.add("api_paste_format", "text");
|
||||||
|
form.add("api_user_key", "");
|
||||||
|
|
||||||
|
URL url = HttpRequest.url("http://pastebin.com/api/api_post.php");
|
||||||
|
String result = HttpRequest.post(url)
|
||||||
|
.bodyForm(form)
|
||||||
|
.execute()
|
||||||
|
.expectResponseCode(200)
|
||||||
|
.returnContent()
|
||||||
|
.asString("UTF-8").trim();
|
||||||
|
|
||||||
|
Matcher m = URL_PATTERN.matcher(result);
|
||||||
|
|
||||||
|
if (m.matches()) {
|
||||||
|
return new URL("http://pastebin.com/raw.php?i=" + m.group(1));
|
||||||
|
} else if (result.matches("^https?://.+")) {
|
||||||
|
return new URL(result);
|
||||||
|
} else {
|
||||||
|
throw new IOException("Failed to save paste; instead, got: " + result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.paste;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
public interface Paster {
|
||||||
|
|
||||||
|
ListenableFuture<URL> paste(String content);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.paste;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
|
||||||
|
import java.util.concurrent.SynchronousQueue;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
final class Pasters {
|
||||||
|
|
||||||
|
private static final ListeningExecutorService executor =
|
||||||
|
MoreExecutors.listeningDecorator(
|
||||||
|
new ThreadPoolExecutor(0, Integer.MAX_VALUE,
|
||||||
|
2L, TimeUnit.SECONDS,
|
||||||
|
new SynchronousQueue<>()));
|
||||||
|
|
||||||
|
private Pasters() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static ListeningExecutorService getExecutor() {
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.report;
|
||||||
|
|
||||||
|
import com.sk89q.worldedit.WorldEdit;
|
||||||
|
|
||||||
|
public class ConfigReport extends DataReport {
|
||||||
|
|
||||||
|
public ConfigReport() {
|
||||||
|
super("WorldEdit Configuration");
|
||||||
|
|
||||||
|
append("Configuration", new HierarchyObjectReport("Configuration", WorldEdit.getInstance().getConfiguration()));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.report;
|
||||||
|
|
||||||
|
public class HierarchyObjectReport extends ShallowObjectReport {
|
||||||
|
|
||||||
|
public HierarchyObjectReport(String title, Object object) {
|
||||||
|
super(title, object);
|
||||||
|
|
||||||
|
Class<?> type = object.getClass();
|
||||||
|
while ((type = type.getSuperclass()) != null) {
|
||||||
|
scanClass(object, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -34,8 +34,10 @@ public class ShallowObjectReport extends DataReport {
|
|||||||
super(title);
|
super(title);
|
||||||
checkNotNull(object, "object");
|
checkNotNull(object, "object");
|
||||||
|
|
||||||
Class<?> type = object.getClass();
|
scanClass(object, object.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
void scanClass(Object object, Class<?> type) {
|
||||||
for (Field field : type.getDeclaredFields()) {
|
for (Field field : type.getDeclaredFields()) {
|
||||||
if (Modifier.isStatic(field.getModifiers())) {
|
if (Modifier.isStatic(field.getModifiers())) {
|
||||||
continue;
|
continue;
|
||||||
@ -54,5 +56,4 @@ public class ShallowObjectReport extends DataReport {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.task;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.AbstractFuture;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An abstract task that stores a name and owner.
|
||||||
|
*
|
||||||
|
* @param <V> the type returned
|
||||||
|
*/
|
||||||
|
public abstract class AbstractTask<V> extends AbstractFuture<V> implements Task<V> {
|
||||||
|
|
||||||
|
private final UUID uniqueId = UUID.randomUUID();
|
||||||
|
private final String name;
|
||||||
|
private final Object owner;
|
||||||
|
private final Date creationDate = new Date();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance.
|
||||||
|
*
|
||||||
|
* @param name the name
|
||||||
|
* @param owner the owner
|
||||||
|
*/
|
||||||
|
protected AbstractTask(String name, @Nullable Object owner) {
|
||||||
|
checkNotNull(name);
|
||||||
|
this.name = name;
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UUID getUniqueId() {
|
||||||
|
return uniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public Object getOwner() {
|
||||||
|
return owner;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getCreationDate() {
|
||||||
|
return creationDate;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.task;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.sk89q.worldedit.util.task.progress.Progress;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A task that wraps a {@code ListenableFuture}.
|
||||||
|
*
|
||||||
|
* <p>{@link Task.State#SCHEDULED} is never returned because it is not possible
|
||||||
|
* to test whether the future has "started," so {@link Task.State#RUNNING} is
|
||||||
|
* returned in its place.</p>
|
||||||
|
*
|
||||||
|
* <p>Use {@link #create(ListenableFuture, String, Object)} to create a new
|
||||||
|
* instance.</p>
|
||||||
|
*
|
||||||
|
* @param <V> the type returned
|
||||||
|
*/
|
||||||
|
public class FutureForwardingTask<V> extends AbstractTask<V> {
|
||||||
|
|
||||||
|
private final ListenableFuture<V> future;
|
||||||
|
|
||||||
|
private FutureForwardingTask(ListenableFuture<V> future, String name, @Nullable Object owner) {
|
||||||
|
super(name, owner);
|
||||||
|
checkNotNull(future);
|
||||||
|
this.future = future;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addListener(Runnable listener, Executor executor) {
|
||||||
|
future.addListener(listener, executor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||||
|
return future.cancel(mayInterruptIfRunning);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return future.isCancelled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDone() {
|
||||||
|
return future.isDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V get() throws InterruptedException, ExecutionException {
|
||||||
|
return future.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
|
||||||
|
return future.get(timeout, unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public State getState() {
|
||||||
|
if (isCancelled()) {
|
||||||
|
return State.CANCELLED;
|
||||||
|
} else if (isDone()) {
|
||||||
|
try {
|
||||||
|
get();
|
||||||
|
return State.SUCCEEDED;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return State.CANCELLED;
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
return State.FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return State.RUNNING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Progress getProgress() {
|
||||||
|
return Progress.indeterminate();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance.
|
||||||
|
*
|
||||||
|
* @param future the future
|
||||||
|
* @param name the name of the task
|
||||||
|
* @param owner the owner of the task, or {@code null}
|
||||||
|
* @param <V> the type returned by the future
|
||||||
|
* @return a new instance
|
||||||
|
*/
|
||||||
|
public static <V> FutureForwardingTask<V> create(ListenableFuture<V> future, String name, @Nullable Object owner) {
|
||||||
|
return new FutureForwardingTask<>(future, name, owner);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.task;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implementation of a {@code Supervisor}.
|
||||||
|
*/
|
||||||
|
public class SimpleSupervisor implements Supervisor {
|
||||||
|
|
||||||
|
private final List<Task<?>> monitored = new ArrayList<>();
|
||||||
|
private final Object lock = new Object();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Task<?>> getTasks() {
|
||||||
|
synchronized (lock) {
|
||||||
|
return new ArrayList<>(monitored);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void monitor(final Task<?> task) {
|
||||||
|
checkNotNull(task);
|
||||||
|
|
||||||
|
synchronized (lock) {
|
||||||
|
monitored.add(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
task.addListener(() -> {
|
||||||
|
synchronized (lock) {
|
||||||
|
monitored.remove(task);
|
||||||
|
}
|
||||||
|
}, MoreExecutors.directExecutor());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.task;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages running tasks and informs users of their progress, but does not
|
||||||
|
* execute the task.
|
||||||
|
*/
|
||||||
|
public interface Supervisor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a list of running or queued tasks.
|
||||||
|
*
|
||||||
|
* @return a list of tasks
|
||||||
|
*/
|
||||||
|
List<Task<?>> getTasks();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Monitor the given task.
|
||||||
|
*
|
||||||
|
* @param task the task
|
||||||
|
*/
|
||||||
|
void monitor(Task<?> task);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.task;
|
||||||
|
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.sk89q.worldedit.util.task.progress.ProgressObservable;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A task is a job that can be scheduled, run, or cancelled. Tasks can report
|
||||||
|
* on their own status. Tasks have owners.
|
||||||
|
*/
|
||||||
|
public interface Task<V> extends ListenableFuture<V>, ProgressObservable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the unique ID of this task.
|
||||||
|
*
|
||||||
|
* @return this task's unique ID
|
||||||
|
*/
|
||||||
|
UUID getUniqueId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the task so it can be printed to the user.
|
||||||
|
*
|
||||||
|
* @return the name of the task
|
||||||
|
*/
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the owner of the task.
|
||||||
|
*
|
||||||
|
* @return an owner object, if one is known or valid, otherwise {@code null}
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
Object getOwner();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the state of the task.
|
||||||
|
*
|
||||||
|
* @return the state of the task
|
||||||
|
*/
|
||||||
|
State getState();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the time at which the task was created.
|
||||||
|
*
|
||||||
|
* @return a date
|
||||||
|
*/
|
||||||
|
Date getCreationDate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the state of a task.
|
||||||
|
*/
|
||||||
|
enum State {
|
||||||
|
/**
|
||||||
|
* The task has been scheduled to run but is not running yet.
|
||||||
|
*/
|
||||||
|
SCHEDULED,
|
||||||
|
/**
|
||||||
|
* The task has been cancelled and may be stopped or will stop.
|
||||||
|
*/
|
||||||
|
CANCELLED,
|
||||||
|
/**
|
||||||
|
* The task is currently running.
|
||||||
|
*/
|
||||||
|
RUNNING,
|
||||||
|
/**
|
||||||
|
* The task has failed.
|
||||||
|
*/
|
||||||
|
FAILED,
|
||||||
|
/**
|
||||||
|
* The task has succeeded.
|
||||||
|
*/
|
||||||
|
SUCCEEDED
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.task;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares task states according to the order of the {@link Task.State}
|
||||||
|
* enumeration.
|
||||||
|
*/
|
||||||
|
public class TaskStateComparator implements Comparator<Task<?>> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compare(com.sk89q.worldedit.util.task.Task<?> o1, Task<?> o2) {
|
||||||
|
int ordinal1 = o1.getState().ordinal();
|
||||||
|
int ordinal2 = o2.getState().ordinal();
|
||||||
|
if (ordinal1 < ordinal2) {
|
||||||
|
return -1;
|
||||||
|
} else if (ordinal1 > ordinal2) {
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,183 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.task.progress;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A progress object describes the progress of an operation, specifying
|
||||||
|
* either a percentage of completion or a status of indeterminacy.
|
||||||
|
*
|
||||||
|
* <p>Progress objects are immutable.</p>
|
||||||
|
*
|
||||||
|
* <p>To create a new instance, use one of the static constructors
|
||||||
|
* on this class.</p>
|
||||||
|
*/
|
||||||
|
public abstract class Progress {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance.
|
||||||
|
*/
|
||||||
|
private Progress() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return whether the current progress is indeterminate.
|
||||||
|
*
|
||||||
|
* @return true if indeterminate
|
||||||
|
*/
|
||||||
|
public abstract boolean isIndeterminate();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the progress percentage.
|
||||||
|
*
|
||||||
|
* <p>If {@link #isIndeterminate()} returns {@code true}, the behavior
|
||||||
|
* of this method is undefined.</p>
|
||||||
|
*
|
||||||
|
* @return a number in the range [0, 1]
|
||||||
|
*/
|
||||||
|
public abstract double getProgress();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a static progress object that is indeterminate.
|
||||||
|
*
|
||||||
|
* @return a progress object
|
||||||
|
*/
|
||||||
|
public static Progress indeterminate() {
|
||||||
|
return INDETERMINATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a static progress object that is complete.
|
||||||
|
*
|
||||||
|
* @return a progress object
|
||||||
|
*/
|
||||||
|
public static Progress completed() {
|
||||||
|
return COMPLETED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new progress object with the given percentage.
|
||||||
|
*
|
||||||
|
* @param value the percentage, which will be clamped to [0, 1]
|
||||||
|
* @return a progress object
|
||||||
|
*/
|
||||||
|
public static Progress of(double value) {
|
||||||
|
if (value < 0) {
|
||||||
|
value = 0;
|
||||||
|
} else if (value > 1) {
|
||||||
|
value = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
final double finalValue = value;
|
||||||
|
return new Progress() {
|
||||||
|
@Override
|
||||||
|
public boolean isIndeterminate() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getProgress() {
|
||||||
|
return finalValue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new progress object with progress split equally between the
|
||||||
|
* given progress objects.
|
||||||
|
*
|
||||||
|
* @param objects an array of progress objects
|
||||||
|
* @return a new progress value
|
||||||
|
*/
|
||||||
|
public static Progress split(Progress... objects) {
|
||||||
|
return split(Arrays.asList(objects));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new progress object with progress split equally between the
|
||||||
|
* given progress objects.
|
||||||
|
*
|
||||||
|
* @param progress a collection of progress objects
|
||||||
|
* @return a new progress value
|
||||||
|
*/
|
||||||
|
public static Progress split(Collection<Progress> progress) {
|
||||||
|
int count = 0;
|
||||||
|
double total = 0;
|
||||||
|
|
||||||
|
for (Progress p : progress) {
|
||||||
|
if (p.isIndeterminate()) {
|
||||||
|
return indeterminate();
|
||||||
|
}
|
||||||
|
total += p.getProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
return of(total / count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new progress object with progress split equally between the
|
||||||
|
* given {@link ProgressObservable}s.
|
||||||
|
*
|
||||||
|
* @param observables an array of observables
|
||||||
|
* @return a new progress value
|
||||||
|
*/
|
||||||
|
public static Progress splitObservables(ProgressObservable... observables) {
|
||||||
|
return splitObservables(Arrays.asList(observables));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new progress object with progress split equally between the
|
||||||
|
* given {@link ProgressObservable}s.
|
||||||
|
*
|
||||||
|
* @param observables a collection of observables
|
||||||
|
* @return a new progress value
|
||||||
|
*/
|
||||||
|
public static Progress splitObservables(Collection<? extends ProgressObservable> observables) {
|
||||||
|
int count = 0;
|
||||||
|
double total = 0;
|
||||||
|
|
||||||
|
for (ProgressObservable observable : observables) {
|
||||||
|
Progress p = observable.getProgress();
|
||||||
|
if (p.isIndeterminate()) {
|
||||||
|
return indeterminate();
|
||||||
|
}
|
||||||
|
total += p.getProgress();
|
||||||
|
}
|
||||||
|
|
||||||
|
return of(total / count);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final Progress COMPLETED = of(1);
|
||||||
|
|
||||||
|
private static final Progress INDETERMINATE = new Progress() {
|
||||||
|
@Override
|
||||||
|
public boolean isIndeterminate() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getProgress() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.task.progress;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An iterator that keeps track of how many entries have been visited and
|
||||||
|
* calculates a "percent completed" using a provided total count.
|
||||||
|
*
|
||||||
|
* <p>The returned progress percentage will always be between 0 or 1
|
||||||
|
* (inclusive). If the iterator returns more entries than the total count,
|
||||||
|
* then 100% will be returned for the progress.</p>
|
||||||
|
*
|
||||||
|
* @param <V> the type
|
||||||
|
*/
|
||||||
|
public class ProgressIterator<V> implements Iterator<V>, ProgressObservable {
|
||||||
|
|
||||||
|
private final Iterator<V> iterator;
|
||||||
|
private final int count;
|
||||||
|
private int visited = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance.
|
||||||
|
*
|
||||||
|
* @param iterator the iterator
|
||||||
|
* @param count the count
|
||||||
|
*/
|
||||||
|
private ProgressIterator(Iterator<V> iterator, int count) {
|
||||||
|
checkNotNull(iterator);
|
||||||
|
this.iterator = iterator;
|
||||||
|
this.count = count;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return iterator.hasNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public V next() {
|
||||||
|
V value = iterator.next();
|
||||||
|
visited++;
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
iterator.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Progress getProgress() {
|
||||||
|
return Progress.of(count > 0 ? Math.min(1, Math.max(0, (visited / (double) count))) : 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance.
|
||||||
|
*
|
||||||
|
* @param iterator the iterator
|
||||||
|
* @param count the number of objects
|
||||||
|
* @param <V> the type
|
||||||
|
* @return an instance
|
||||||
|
*/
|
||||||
|
public static <V> ProgressIterator<V> create(Iterator<V> iterator, int count) {
|
||||||
|
return new ProgressIterator<V>(iterator, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance from a list.
|
||||||
|
*
|
||||||
|
* @param list a list
|
||||||
|
* @param <V> the type
|
||||||
|
* @return an instance
|
||||||
|
*/
|
||||||
|
public static <V> ProgressIterator<V> create(List<V> list) {
|
||||||
|
return create(list.iterator(), list.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* 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.util.task.progress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An object that is able to report on its progress.
|
||||||
|
*/
|
||||||
|
public interface ProgressObservable {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the current percentage of completion.
|
||||||
|
*
|
||||||
|
* @return a progress object
|
||||||
|
*/
|
||||||
|
Progress getProgress();
|
||||||
|
|
||||||
|
}
|
@ -23,6 +23,7 @@ import com.google.common.reflect.TypeToken;
|
|||||||
import com.sk89q.worldedit.LocalConfiguration;
|
import com.sk89q.worldedit.LocalConfiguration;
|
||||||
import com.sk89q.worldedit.LocalSession;
|
import com.sk89q.worldedit.LocalSession;
|
||||||
import com.sk89q.worldedit.session.SessionManager;
|
import com.sk89q.worldedit.session.SessionManager;
|
||||||
|
import com.sk89q.worldedit.util.report.Unreported;
|
||||||
import com.sk89q.worldedit.world.registry.LegacyMapper;
|
import com.sk89q.worldedit.world.registry.LegacyMapper;
|
||||||
import com.sk89q.worldedit.world.snapshot.SnapshotRepository;
|
import com.sk89q.worldedit.world.snapshot.SnapshotRepository;
|
||||||
import ninja.leaping.configurate.ConfigurationOptions;
|
import ninja.leaping.configurate.ConfigurationOptions;
|
||||||
@ -36,10 +37,10 @@ import java.util.HashSet;
|
|||||||
|
|
||||||
public class ConfigurateConfiguration extends LocalConfiguration {
|
public class ConfigurateConfiguration extends LocalConfiguration {
|
||||||
|
|
||||||
protected final ConfigurationLoader<CommentedConfigurationNode> config;
|
@Unreported protected final ConfigurationLoader<CommentedConfigurationNode> config;
|
||||||
protected final Logger logger;
|
@Unreported protected final Logger logger;
|
||||||
|
|
||||||
protected CommentedConfigurationNode node;
|
@Unreported protected CommentedConfigurationNode node;
|
||||||
|
|
||||||
public ConfigurateConfiguration(ConfigurationLoader<CommentedConfigurationNode> config, Logger logger) {
|
public ConfigurateConfiguration(ConfigurationLoader<CommentedConfigurationNode> config, Logger logger) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
Loading…
Reference in New Issue
Block a user