Feature/propagate diff and object cleanup (#1190)

* Feature/main/propagate diff annotations (#1187)

* 25% done

* More work

* More work

* 50%

* More work

* 75%

* 100% & cleanup

* Update adapters

* Squish squash, applesauce

commit 275ba9bd84
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Sat Jul 17 01:10:20 2021 +0200

    Update dependency com.comphenix.protocol:ProtocolLib to v4.7.0 (#1173)

    Co-authored-by: Renovate Bot <bot@renovateapp.com>

commit 9fd8984804
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Date:   Sat Jul 17 01:09:29 2021 +0200

    Update dependency org.checkerframework:checker-qual to v3.16.0 (#1184)

    Co-authored-by: Renovate Bot <bot@renovateapp.com>

commit 861fb45e5c
Author: dordsor21 <dordsor21@gmail.com>
Date:   Fri Jul 16 19:07:02 2021 +0100

    Fix #1075

commit 420c45a29a
Author: dordsor21 <dordsor21@gmail.com>
Date:   Fri Jul 16 18:48:21 2021 +0100

    Entity removal should be on the main thread as we're just passing through rather than doing chunk operations
     - Fixes #1164
     - Not working: butcher/remove history

commit 4d4db7dcd0
Author: SirYwell <hannesgreule@outlook.de>
Date:   Fri Jul 16 17:52:44 2021 +0200

    Make sure leaves category is loaded for heightmaps (fixes #1176)

commit c98f6e4f37
Author: dordsor21 <dordsor21@gmail.com>
Date:   Fri Jul 16 10:44:52 2021 +0100

    Do not allow generation commands to generate outside selection

commit 2485f5eccc
Author: dordsor21 <dordsor21@gmail.com>
Date:   Fri Jul 16 10:43:15 2021 +0100

    EditSession needs to override some Extent methods to ensure block changes are correctly set through the various extents
    Fixes #1152

commit d9418ec8ae
Author: dordsor21 <dordsor21@gmail.com>
Date:   Fri Jul 16 09:52:44 2021 +0100

    Undo part of 41073bb1a0
    Fixes #1178

* Update Upstream

fb1fb84 Fixed typo and grammar

* We don't support custom heights yet

* Casing inconsistency

* Address a few comments

* Address comments

* Don't refactor to AP classpath

* Document annotation style

* Refactoring & shade cleanup

* Address a few comments

* More work

* Resolve comments not being resolved yet

* Feature/main/propagate diff annotations (#1187) (#1194)

* Remove beta package, fix history packages, move classes out of object package

* Resolve comments not being resolved yet

* Remove beta package, fix history packages, move classes out of object package

Co-authored-by: NotMyFault <mc.cache@web.de>

* brushes should be under brush

* More refactoring
 - Filters/processors should be in the same place and are related to extents
 - Transforms are in `extent.transform` in upstream

* Move history classes under history

* Update adapters

Co-authored-by: dordsor21 <dordsor21@gmail.com>
This commit is contained in:
NotMyFault
2021-07-23 17:48:51 +02:00
committed by GitHub
parent ad102ab7a9
commit 50ab8ad5c7
799 changed files with 4916 additions and 10589 deletions

View File

@ -34,7 +34,7 @@ import com.sk89q.worldedit.command.util.PermissionCondition;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.function.Contextual;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.factory.Apply;
import com.sk89q.worldedit.function.factory.ApplyRegion;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.internal.annotation.Direction;
import com.sk89q.worldedit.internal.command.CommandRegistrationHandler;
@ -97,7 +97,7 @@ public class ApplyBrushCommands {
double radius = requireNonNull(RADIUS.value(parameters).asSingle(double.class));
RegionFactory regionFactory = REGION_FACTORY.value(parameters).asSingle(RegionFactory.class);
BrushCommands.setOperationBasedBrush(player, localSession, Expression.compile(Double.toString(radius)),
new Apply(generatorFactory), regionFactory, "worldedit.brush.apply");
new ApplyRegion(generatorFactory), regionFactory, "worldedit.brush.apply");
}
@Command(

View File

@ -27,6 +27,7 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.command.util.CommandPermissions;
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
import com.sk89q.worldedit.command.util.Logging;
import com.sk89q.worldedit.command.util.WorldEditAsyncCommandBuilder;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.internal.anvil.ChunkDeleter;
@ -38,6 +39,7 @@ import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.formatting.component.PaginationBox;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldedit.world.World;
@ -100,6 +102,12 @@ public class ChunkCommands {
@ArgFlag(name = 'p', desc = "Page number.", def = "1") int page) throws WorldEditException {
final Region region = session.getSelection(world);
WorldEditAsyncCommandBuilder.createAndSendMessage(actor,
() -> new ChunkListPaginationBox(region).create(page),
TranslatableComponent.of(
"worldedit.listchunks.listfor",
TextComponent.of(actor.getName())
));
actor.print(new ChunkListPaginationBox(region).create(page));
actor.print(Caption.of("worldedit.listchunks.listfor", TextComponent.of(actor.getName())));
}
@ -178,6 +186,10 @@ public class ChunkCommands {
ChunkListPaginationBox(Region region) {
super("Selected Chunks", "/listchunks -p %page%");
// TODO make efficient/streamable/calculable implementations of this
// for most region types, so we can just store the region and random-access get one page of chunks
// (this is non-trivial for some types of selections...)
//this.region = region.clone();
this.chunks = new ArrayList<>(region.getChunks());
}

View File

@ -24,13 +24,13 @@ import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.object.FaweLimit;
import com.fastasyncworldedit.core.object.RunnableVal;
import com.fastasyncworldedit.core.object.clipboard.DiskOptimizedClipboard;
import com.fastasyncworldedit.core.object.clipboard.MultiClipboardHolder;
import com.fastasyncworldedit.core.object.clipboard.ReadOnlyClipboard;
import com.fastasyncworldedit.core.object.clipboard.URIClipboardHolder;
import com.fastasyncworldedit.core.object.exception.FaweException;
import com.fastasyncworldedit.core.object.io.FastByteArrayOutputStream;
import com.fastasyncworldedit.core.util.task.RunnableVal;
import com.fastasyncworldedit.core.extent.clipboard.DiskOptimizedClipboard;
import com.fastasyncworldedit.core.extent.clipboard.MultiClipboardHolder;
import com.fastasyncworldedit.core.extent.clipboard.ReadOnlyClipboard;
import com.fastasyncworldedit.core.extent.clipboard.URIClipboardHolder;
import com.fastasyncworldedit.core.internal.exception.FaweException;
import com.fastasyncworldedit.core.internal.io.FastByteArrayOutputStream;
import com.fastasyncworldedit.core.util.ImgurUtility;
import com.fastasyncworldedit.core.util.MainUtil;
import com.fastasyncworldedit.core.util.MaskTraverser;
@ -45,7 +45,7 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
import com.sk89q.worldedit.command.util.Logging;
import com.sk89q.worldedit.command.util.annotation.Confirm;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.extent.PasteEvent;
import com.fastasyncworldedit.core.event.extent.PasteEvent;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
@ -119,6 +119,7 @@ public class ClipboardCommands {
boolean copyEntities,
@Switch(name = 'b', desc = "Also copy biomes")
boolean copyBiomes,
//FAWE start
@Switch(name = 'c', desc = "Set the origin of the clipboard to the center of the copied region")
boolean centerClipboard,
@ArgFlag(name = 'm', desc = "Set the include mask, non-matching blocks become air", def = "")
@ -165,8 +166,10 @@ public class ClipboardCommands {
session.setClipboard(new ClipboardHolder(clipboard));
copy.getStatusMessages().forEach(actor::print);
//FAWE end
}
//FAWE start
@Command(
name = "/lazycopy",
desc = "Lazily copy the selection to the clipboard"
@ -223,6 +226,7 @@ public class ClipboardCommands {
session.setClipboard(new ClipboardHolder(lazyClipboard));
actor.print(Caption.of("fawe.worldedit.cut.command.cut.lazy", region.getArea()));
}*/
//FAWE end
@Command(
name = "/cut",
@ -243,6 +247,7 @@ public class ClipboardCommands {
boolean copyBiomes,
@ArgFlag(name = 'm', desc = "Set the exclude mask, non-matching blocks become air")
Mask mask) throws WorldEditException {
//FAWE start - Inject limits & respect source mask
BlockVector3 min = region.getMinimumPoint();
BlockVector3 max = region.getMaximumPoint();
@ -289,8 +294,10 @@ public class ClipboardCommands {
actor.print(Caption.of("fawe.tips.tip.lazycut"));
}
copy.getStatusMessages().forEach(actor::print);
//FAWE end
}
//FAWE start
@Command(
name = "download",
aliases = { "/download" },
@ -329,7 +336,7 @@ public class ClipboardCommands {
final LocalConfiguration config = WorldEdit.getInstance().getConfiguration();
final File working = WorldEdit.getInstance().getWorkingDirectoryFile(config.saveDir).getAbsoluteFile();
url = MainUtil.upload(null, null, "zip", new RunnableVal<OutputStream>() {
url = MainUtil.upload(null, null, "zip", new RunnableVal<>() {
@Override
public void run(OutputStream out) {
try (ZipOutputStream zos = new ZipOutputStream(out)) {
@ -388,6 +395,61 @@ public class ClipboardCommands {
}
}
@Command(
name = "/place",
desc = "Place the clipboard's contents without applying transformations (e.g. rotate)"
)
@CommandPermissions("worldedit.clipboard.place")
@Logging(PLACEMENT)
public void place(Actor actor, World world, LocalSession session, final EditSession editSession,
@Switch(name = 'a', desc = "Skip air blocks")
boolean ignoreAirBlocks,
@Switch(name = 'o', desc = "Paste at the original position")
boolean atOrigin,
@Switch(name = 's', desc = "Select the region after pasting")
boolean selectPasted,
@Switch(name = 'e', desc = "Paste entities if available")
boolean pasteEntities,
@Switch(name = 'b', desc = "Paste biomes if available")
boolean pasteBiomes) throws WorldEditException {
ClipboardHolder holder = session.getClipboard();
final Clipboard clipboard = holder.getClipboard();
final BlockVector3 origin = clipboard.getOrigin();
final BlockVector3 to = atOrigin ? origin : session.getPlacementPosition(actor);
checkPaste(actor, editSession, to, holder, clipboard);
clipboard.paste(editSession, to, !ignoreAirBlocks, pasteEntities, pasteBiomes);
Region region = clipboard.getRegion().clone();
if (selectPasted) {
BlockVector3 clipboardOffset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin());
BlockVector3 realTo = to.add(holder.getTransform().apply(clipboardOffset.toVector3()).toBlockPoint());
BlockVector3 max = realTo.add(holder.getTransform().apply(region.getMaximumPoint().subtract(region.getMinimumPoint()).toVector3()).toBlockPoint());
RegionSelector selector = new CuboidRegionSelector(world, realTo, max);
session.setRegionSelector(world, selector);
selector.learnChanges();
selector.explainRegionAdjust(actor, session);
}
actor.print(Caption.of("fawe.worldedit.paste.command.paste", to));
if (!actor.hasPermission("fawe.tips")) {
actor.print(Caption.of("fawe.tips.tip.copypaste"));
}
}
private void saveDiskClipboard(Clipboard clipboard) {
DiskOptimizedClipboard c;
if (clipboard instanceof DiskOptimizedClipboard)
c = (DiskOptimizedClipboard) clipboard;
else if (clipboard instanceof BlockArrayClipboard
&& ((BlockArrayClipboard) clipboard).getParent() instanceof DiskOptimizedClipboard)
c = (DiskOptimizedClipboard) ((BlockArrayClipboard) clipboard).getParent();
else
return;
c.flush();
}
//FAWE end
@Command(
name = "/paste",
aliases = {"/p", "/pa"},
@ -414,8 +476,10 @@ public class ClipboardCommands {
ClipboardHolder holder = session.getClipboard();
if (holder.getTransform().isIdentity() && editSession.getSourceMask() == null) {
//FAWE start - use place
place(actor, world, session, editSession, ignoreAirBlocks, atOrigin, selectPasted,
pasteEntities, pasteBiomes);
//FAWE end
return;
}
Clipboard clipboard = holder.getClipboard();
@ -423,7 +487,9 @@ public class ClipboardCommands {
List<Component> messages = Lists.newArrayList();
BlockVector3 to = atOrigin ? clipboard.getOrigin() : session.getPlacementPosition(actor);
//FAWE start
checkPaste(actor, editSession, to, holder, clipboard);
//FAWE end
if (!onlySelect) {
Operation operation = holder
@ -456,6 +522,7 @@ public class ClipboardCommands {
messages.forEach(actor::print);
}
//FAWE start
private void checkPaste(Actor player, EditSession editSession, BlockVector3 to, ClipboardHolder holder, Clipboard clipboard) {
URI uri = null;
if (holder instanceof URIClipboardHolder) {
@ -467,48 +534,7 @@ public class ClipboardCommands {
throw new FaweException(Caption.of("fawe.cancel.worldedit.cancel.reason.manual"));
}
}
@Command(
name = "/place",
desc = "Place the clipboard's contents without applying transformations (e.g. rotate)"
)
@CommandPermissions("worldedit.clipboard.place")
@Logging(PLACEMENT)
public void place(Actor actor, World world, LocalSession session, final EditSession editSession,
@Switch(name = 'a', desc = "Skip air blocks")
boolean ignoreAirBlocks,
@Switch(name = 'o', desc = "Paste at the original position")
boolean atOrigin,
@Switch(name = 's', desc = "Select the region after pasting")
boolean selectPasted,
@Switch(name = 'e', desc = "Paste entities if available")
boolean pasteEntities,
@Switch(name = 'b', desc = "Paste biomes if available")
boolean pasteBiomes) throws WorldEditException {
ClipboardHolder holder = session.getClipboard();
final Clipboard clipboard = holder.getClipboard();
final BlockVector3 origin = clipboard.getOrigin();
final BlockVector3 to = atOrigin ? origin : session.getPlacementPosition(actor);
checkPaste(actor, editSession, to, holder, clipboard);
clipboard.paste(editSession, to, !ignoreAirBlocks, pasteEntities, pasteBiomes);
Region region = clipboard.getRegion().clone();
if (selectPasted) {
BlockVector3 clipboardOffset = clipboard.getRegion().getMinimumPoint().subtract(clipboard.getOrigin());
BlockVector3 realTo = to.add(holder.getTransform().apply(clipboardOffset.toVector3()).toBlockPoint());
BlockVector3 max = realTo.add(holder.getTransform().apply(region.getMaximumPoint().subtract(region.getMinimumPoint()).toVector3()).toBlockPoint());
RegionSelector selector = new CuboidRegionSelector(world, realTo, max);
session.setRegionSelector(world, selector);
selector.learnChanges();
selector.explainRegionAdjust(actor, session);
}
actor.print(Caption.of("fawe.worldedit.paste.command.paste", to));
if (!actor.hasPermission("fawe.tips")) {
actor.print(Caption.of("fawe.tips.tip.copypaste"));
}
}
//FAWE end
@Command(
name = "/rotate",
@ -559,16 +585,4 @@ public class ClipboardCommands {
session.setClipboard(null);
actor.print(Caption.of("worldedit.clearclipboard.cleared"));
}
private void saveDiskClipboard(Clipboard clipboard) {
DiskOptimizedClipboard c;
if (clipboard instanceof DiskOptimizedClipboard)
c = (DiskOptimizedClipboard) clipboard;
else if (clipboard instanceof BlockArrayClipboard
&& ((BlockArrayClipboard) clipboard).getParent() instanceof DiskOptimizedClipboard)
c = (DiskOptimizedClipboard) ((BlockArrayClipboard) clipboard).getParent();
else
return;
c.flush();
}
}

View File

@ -83,7 +83,8 @@ public class FlattenedClipboardTransform {
minimum.withZ(maximum.getZ()),
maximum.withX(minimum.getX()),
maximum.withY(minimum.getY()),
maximum.withZ(minimum.getZ()) };
maximum.withZ(minimum.getZ())
};
for (int i = 0; i < corners.length; i++) {
corners[i] = transformAround.apply(corners[i]);
@ -112,10 +113,12 @@ public class FlattenedClipboardTransform {
* @return the operation
*/
public Operation copyTo(Extent target) {
//FAWE start
Extent extent = original;
if (transform != null && !transform.isIdentity()) {
extent = new BlockTransformExtent(original, transform);
}
//FAWE end
ForwardExtentCopy copy = new ForwardExtentCopy(extent, original.getRegion(), original.getOrigin(), target, original.getOrigin());
copy.setTransform(transform);
if (original.hasBiomes()) {

View File

@ -21,7 +21,7 @@ package com.sk89q.worldedit.command;
import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.object.extent.ResettableExtent;
import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.fastasyncworldedit.core.util.CachedTextureUtil;
import com.fastasyncworldedit.core.util.CleanTextureUtil;
import com.fastasyncworldedit.core.util.MathMan;
@ -48,6 +48,7 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.internal.command.CommandRegistrationHandler;
import com.sk89q.worldedit.internal.command.CommandUtil;
import com.sk89q.worldedit.internal.cui.ServerCUIHandler;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.SideEffectSet;
import com.sk89q.worldedit.util.auth.AuthorizationException;
@ -102,7 +103,7 @@ public class GeneralCommands {
Set<org.enginehub.piston.Command> commands = collect.getAllCommands()
.collect(Collectors.toSet());
for (org.enginehub.piston.Command command : commands) {
/*if in FAWE, //fast will remain for now
/*FAWE start - if in FAWE, //fast will remain for now
(command.getName().equals("/fast")) {
// deprecate to `//perf`
@ -211,30 +212,6 @@ public class GeneralCommands {
actor.print(component);
}
@Command(
name = "/fast",
desc = "Toggle fast mode"
)
@CommandPermissions("worldedit.fast")
@Deprecated
void fast(Actor actor, LocalSession session,
@Arg(desc = "The new fast mode state", def = "")
Boolean fastMode) {
boolean hasFastMode = session.hasFastMode();
if (fastMode != null && fastMode == hasFastMode) {
actor.print(Caption.of(fastMode ? "worldedit.fast.enabled.already" : "worldedit.fast.disabled.already"));
return;
}
if (hasFastMode) {
session.setFastMode(false);
actor.print(Caption.of("worldedit.fast.disabled"));
} else {
session.setFastMode(true);
actor.print(Caption.of("worldedit.fast.enabled"));
}
}
@Command(
name = "/perf",
desc = "Toggle side effects for performance",
@ -338,7 +315,8 @@ public class GeneralCommands {
} else {
session.setUseServerCUI(true);
session.updateServerCUI(player);
player.print(Caption.of("worldedit.drawsel.enabled"));
int maxSize = ServerCUIHandler.getMaxServerCuiSize();
player.print(Caption.of("worldedit.drawsel.enabled", TextComponent.of(maxSize), TextComponent.of(maxSize), TextComponent.of(maxSize)));
}
}
@ -487,6 +465,7 @@ public class GeneralCommands {
}
}
//FAWE start
@Command(
name = "/gtexture",
aliases = {"gtexture"},
@ -601,4 +580,29 @@ public class GeneralCommands {
player.print(Caption.of("fawe.info.worldedit.toggle.tips.off"));
}
}
@Command(
name = "/fast",
desc = "Toggle fast mode"
)
@CommandPermissions("worldedit.fast")
@Deprecated
void fast(Actor actor, LocalSession session,
@Arg(desc = "The new fast mode state", def = "")
Boolean fastMode) {
boolean hasFastMode = session.hasFastMode();
if (fastMode != null && fastMode == hasFastMode) {
actor.print(Caption.of(fastMode ? "worldedit.fast.enabled.already" : "worldedit.fast.disabled.already"));
return;
}
if (hasFastMode) {
session.setFastMode(false);
actor.print(Caption.of("worldedit.fast.disabled"));
} else {
session.setFastMode(true);
actor.print(Caption.of("worldedit.fast.enabled"));
}
}
//FAWE end
}

View File

@ -34,7 +34,7 @@ import com.sk89q.worldedit.command.util.Logging;
import com.sk89q.worldedit.command.util.annotation.Confirm;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.function.generator.CavesGen;
import com.fastasyncworldedit.core.function.generator.CavesGen;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern;
@ -87,111 +87,6 @@ public class GenerationCommands {
this.worldEdit = worldEdit;
}
@Command(
name = "/caves",
desc = "Generates a cave network"
)
@CommandPermissions("worldedit.generation.caves")
@Logging(PLACEMENT)
@Confirm(Confirm.Processor.REGION)
public void caves(Actor actor, LocalSession session, EditSession editSession, @Selection Region region,
@Arg(name = "size", desc = "TODO", def = "8") int sizeOpt,
@Arg(name = "frequency", desc = "TODO", def = "40") int frequencyOpt,
@Arg(name = "rarity", desc = "TODO", def = "7") int rarityOpt,
@Arg(name = "minY", desc = "TODO", def = "8") int minYOpt,
@Arg(name = "maxY", desc = "TODO", def = "127") int maxYOpt,
@Arg(name = "systemFrequency", desc = "TODO", def = "1") int systemFrequencyOpt,
@Arg(name = "individualRarity", desc = "TODO", def = "25") int individualRarityOpt,
@Arg(name = "pocketChance", desc = "TODO", def = "0") int pocketChanceOpt,
@Arg(name = "pocketMin", desc = "TODO", def = "0") int pocketMinOpt,
@Arg(name = "pocketMax", desc = "TODO", def = "3") int pocketMaxOpt) throws WorldEditException {
CavesGen gen = new CavesGen(sizeOpt, frequencyOpt, rarityOpt, minYOpt, maxYOpt, systemFrequencyOpt, individualRarityOpt, pocketChanceOpt, pocketMinOpt, pocketMaxOpt);
editSession.generate(region, gen);
actor.print(Caption.of("fawe.worldedit.visitor.visitor.block", editSession.getBlockChangeCount()));
}
@Command(
name = "/ores",
desc = "Generates ores"
)
@CommandPermissions("worldedit.generation.ore")
@Logging(PLACEMENT)
@Confirm(Confirm.Processor.REGION)
public void ores(Actor actor, LocalSession session, EditSession editSession, @Selection Region region, @Arg(desc = "Mask") Mask mask) throws WorldEditException {
editSession.addOres(region, mask);
actor.print(Caption.of("fawe.worldedit.visitor.visitor.block", editSession.getBlockChangeCount()));
}
@Command(
name = "/img",
aliases = { "/image", "image" },
desc = "Generate an image"
)
@CommandPermissions("worldedit.generation.image")
@Logging(PLACEMENT)
public void image(Actor actor,
LocalSession session,
EditSession editSession,
@Arg(desc = "Image URL (imgur only)") String imageURL,
@Arg(desc = "boolean", def = "true") boolean randomize,
@Arg(desc = "TODO", def = "100") int threshold,
@Arg(desc = "BlockVector2", def = "") BlockVector2 dimensions) throws WorldEditException, IOException {
TextureUtil tu = Fawe.get().getCachedTextureUtil(randomize, 0, threshold);
URL url = new URL(imageURL);
if (!url.getHost().equalsIgnoreCase("i.imgur.com")) {
throw new IOException("Only i.imgur.com links are allowed!");
}
BufferedImage image = MainUtil.readImage(url);
if (dimensions != null) {
image = ImageUtil.getScaledInstance(image, dimensions.getBlockX(), dimensions.getBlockZ(),
RenderingHints.VALUE_INTERPOLATION_BILINEAR, false);
}
BlockVector3 pos1 = session.getPlacementPosition(actor);
BlockVector3 pos2 = pos1.add(image.getWidth() - 1, 0, image.getHeight() - 1);
CuboidRegion region = new CuboidRegion(pos1, pos2);
int[] count = new int[1];
final BufferedImage finalImage = image;
RegionVisitor visitor = new RegionVisitor(region, pos -> {
try {
int x = pos.getBlockX() - pos1.getBlockX();
int z = pos.getBlockZ() - pos1.getBlockZ();
int color = finalImage.getRGB(x, z);
BlockType block = tu.getNearestBlock(color);
count[0]++;
if (block != null) {
return editSession.setBlock(pos, block.getDefaultState());
}
return false;
} catch (Throwable e) {
e.printStackTrace();
}
return false;
});
Operations.completeBlindly(visitor);
actor.print(Caption.of("fawe.worldedit.visitor.visitor.block", editSession.getBlockChangeCount()));
}
@Command(name = "/ore", desc = "Generates ores")
@CommandPermissions("worldedit.generation.ore")
@Logging(PLACEMENT)
@Confirm(Confirm.Processor.REGION)
public void ore(Actor actor,
LocalSession session,
EditSession editSession,
@Selection Region region,
@Arg(desc = "Mask") Mask mask,
@Arg(desc = "Pattern") Pattern material,
@Arg(desc = "Ore vein size") @Range(from = 0, to = Integer.MAX_VALUE) int size,
@Arg(desc = "Ore vein frequency (number of times to attempt to place ore)", def = "10") @Range(from = 0, to = Integer.MAX_VALUE) int freq,
@Arg(desc = "Ore vein rarity (% chance each attempt is placed)", def = "100") @Range(from = 0, to = 100) int rarity,
@Arg(desc = "Ore vein min y", def = "0") @Range(from = 0, to = 255) int minY,
@Arg(desc = "Ore vein max y", def = "63") @Range(from = 0, to = 255) int maxY) throws WorldEditException {
editSession.addOre(region, mask, material, size, freq, rarity, minY, maxY);
actor.print(Caption.of("fawe.worldedit.visitor.visitor.block", editSession.getBlockChangeCount()));
}
@Command(
name = "/hcyl",
desc = "Generates a hollow cylinder."
@ -539,4 +434,111 @@ public class GenerationCommands {
}
}
//FAWE start
@Command(
name = "/caves",
desc = "Generates a cave network"
)
@CommandPermissions("worldedit.generation.caves")
@Logging(PLACEMENT)
@Confirm(Confirm.Processor.REGION)
public void caves(Actor actor, LocalSession session, EditSession editSession, @Selection Region region,
@Arg(name = "size", desc = "TODO", def = "8") int sizeOpt,
@Arg(name = "frequency", desc = "TODO", def = "40") int frequencyOpt,
@Arg(name = "rarity", desc = "TODO", def = "7") int rarityOpt,
@Arg(name = "minY", desc = "TODO", def = "8") int minYOpt,
@Arg(name = "maxY", desc = "TODO", def = "127") int maxYOpt,
@Arg(name = "systemFrequency", desc = "TODO", def = "1") int systemFrequencyOpt,
@Arg(name = "individualRarity", desc = "TODO", def = "25") int individualRarityOpt,
@Arg(name = "pocketChance", desc = "TODO", def = "0") int pocketChanceOpt,
@Arg(name = "pocketMin", desc = "TODO", def = "0") int pocketMinOpt,
@Arg(name = "pocketMax", desc = "TODO", def = "3") int pocketMaxOpt) throws WorldEditException {
CavesGen gen = new CavesGen(sizeOpt, frequencyOpt, rarityOpt, minYOpt, maxYOpt, systemFrequencyOpt, individualRarityOpt, pocketChanceOpt, pocketMinOpt, pocketMaxOpt);
editSession.generate(region, gen);
actor.print(Caption.of("fawe.worldedit.visitor.visitor.block", editSession.getBlockChangeCount()));
}
@Command(
name = "/ores",
desc = "Generates ores"
)
@CommandPermissions("worldedit.generation.ore")
@Logging(PLACEMENT)
@Confirm(Confirm.Processor.REGION)
public void ores(Actor actor, LocalSession session, EditSession editSession, @Selection Region region, @Arg(desc = "Mask") Mask mask) throws WorldEditException {
editSession.addOres(region, mask);
actor.print(Caption.of("fawe.worldedit.visitor.visitor.block", editSession.getBlockChangeCount()));
}
@Command(
name = "/img",
aliases = { "/image", "image" },
desc = "Generate an image"
)
@CommandPermissions("worldedit.generation.image")
@Logging(PLACEMENT)
public void image(Actor actor,
LocalSession session,
EditSession editSession,
@Arg(desc = "Image URL (imgur only)") String imageURL,
@Arg(desc = "boolean", def = "true") boolean randomize,
@Arg(desc = "TODO", def = "100") int threshold,
@Arg(desc = "BlockVector2", def = "") BlockVector2 dimensions) throws WorldEditException, IOException {
TextureUtil tu = Fawe.get().getCachedTextureUtil(randomize, 0, threshold);
URL url = new URL(imageURL);
if (!url.getHost().equalsIgnoreCase("i.imgur.com")) {
throw new IOException("Only i.imgur.com links are allowed!");
}
BufferedImage image = MainUtil.readImage(url);
if (dimensions != null) {
image = ImageUtil.getScaledInstance(image, dimensions.getBlockX(), dimensions.getBlockZ(),
RenderingHints.VALUE_INTERPOLATION_BILINEAR, false);
}
BlockVector3 pos1 = session.getPlacementPosition(actor);
BlockVector3 pos2 = pos1.add(image.getWidth() - 1, 0, image.getHeight() - 1);
CuboidRegion region = new CuboidRegion(pos1, pos2);
int[] count = new int[1];
final BufferedImage finalImage = image;
RegionVisitor visitor = new RegionVisitor(region, pos -> {
try {
int x = pos.getBlockX() - pos1.getBlockX();
int z = pos.getBlockZ() - pos1.getBlockZ();
int color = finalImage.getRGB(x, z);
BlockType block = tu.getNearestBlock(color);
count[0]++;
if (block != null) {
return editSession.setBlock(pos, block.getDefaultState());
}
return false;
} catch (Throwable e) {
e.printStackTrace();
}
return false;
});
Operations.completeBlindly(visitor);
actor.print(Caption.of("fawe.worldedit.visitor.visitor.block", editSession.getBlockChangeCount()));
}
@Command(name = "/ore", desc = "Generates ores")
@CommandPermissions("worldedit.generation.ore")
@Logging(PLACEMENT)
@Confirm(Confirm.Processor.REGION)
public void ore(Actor actor,
LocalSession session,
EditSession editSession,
@Selection Region region,
@Arg(desc = "Mask") Mask mask,
@Arg(desc = "Pattern") Pattern material,
@Arg(desc = "Ore vein size") @Range(from = 0, to = Integer.MAX_VALUE) int size,
@Arg(desc = "Ore vein frequency (number of times to attempt to place ore)", def = "10") @Range(from = 0, to = Integer.MAX_VALUE) int freq,
@Arg(desc = "Ore vein rarity (% chance each attempt is placed)", def = "100") @Range(from = 0, to = 100) int rarity,
@Arg(desc = "Ore vein min y", def = "0") @Range(from = 0, to = 255) int minY,
@Arg(desc = "Ore vein max y", def = "63") @Range(from = 0, to = 255) int maxY) throws WorldEditException {
editSession.addOre(region, mask, material, size, freq, rarity, minY, maxY);
actor.print(Caption.of("fawe.worldedit.visitor.visitor.block", editSession.getBlockChangeCount()));
}
//FAWE end
}

View File

@ -68,10 +68,12 @@ public class HistoryCommands {
String playerName) throws WorldEditException {
times = Math.max(1, times);
LocalSession undoSession = session;
//FAWE start - Add fastmode check
if (session.hasFastMode()) {
actor.print(Caption.of("fawe.worldedit.history.command.undo.disabled"));
return;
}
//FAWE end
if (playerName != null) {
actor.checkPermission("worldedit.history.undo.other");
undoSession = worldEdit.getSessionManager().findByName(playerName);

View File

@ -6,9 +6,9 @@ import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.database.DBHandler;
import com.fastasyncworldedit.core.database.RollbackDatabase;
import com.fastasyncworldedit.core.logging.RollbackOptimizedHistory;
import com.fastasyncworldedit.core.object.RegionWrapper;
import com.fastasyncworldedit.core.object.changeset.SimpleChangeSetSummary;
import com.fastasyncworldedit.core.history.RollbackOptimizedHistory;
import com.fastasyncworldedit.core.regions.RegionWrapper;
import com.fastasyncworldedit.core.history.changeset.SimpleChangeSetSummary;
import com.fastasyncworldedit.core.util.MainUtil;
import com.fastasyncworldedit.core.util.StringMan;
import com.google.common.base.Function;
@ -22,8 +22,8 @@ import com.sk89q.worldedit.command.util.annotation.Confirm;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.history.changeset.ChangeSet;
import com.sk89q.worldedit.internal.annotation.AllowedRegion;
import com.sk89q.worldedit.internal.annotation.Time;
import com.sk89q.worldedit.command.util.annotation.AllowedRegion;
import com.sk89q.worldedit.command.util.annotation.Time;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
@ -76,7 +76,7 @@ public class HistorySubCommands {
+ " - The time uses s, m, h, d, y.\n"
+ " - Import from disk: /history import"
)
@CommandPermissions("worldedit.history.redo")
@CommandPermissions("worldedit.history.restore")
@Confirm
public synchronized void rerun(Player player, World world, RollbackDatabase database,
@AllowedRegion Region[] allowedRegions,
@ -96,7 +96,7 @@ public class HistorySubCommands {
desc = "Undo a specific edit. "
+ " - The time uses s, m, h, d, y."
)
@CommandPermissions("worldedit.history.undo")
@CommandPermissions("worldedit.history.rollback")
@Confirm
public synchronized void rollback(Player player, World world, RollbackDatabase database,
@AllowedRegion Region[] allowedRegions,

View File

@ -1,132 +0,0 @@
package com.sk89q.worldedit.command;
import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.util.StringMan;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import org.enginehub.piston.annotation.Command;
import org.enginehub.piston.exception.StopExecutionException;
import java.io.File;
import java.util.Locale;
import java.util.UUID;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
//TODO This class breaks compilation
//@CommandContainer
public class ListFilters {
public class Filter {
public boolean listPrivate() {
return true;
}
public boolean listPublic() {
return false;
}
public File getPath(File root) {
return null;
}
public boolean applies(File file) {
return true;
}
}
@Command(
name = "all",
desc = "List both public and private schematics"
)
public Filter all() {
return new Filter() {
@Override
public boolean listPublic() {
return true;
}
};
}
@Command(
name = "local",
aliases = {"me", "mine", "private"},
desc = "List your personal schematics"
)
public Filter local() {
return new Filter();
}
@Command(
name = "global",
aliases = {"public"},
desc = "List public schematics"
)
public Filter global() {
return new Filter() {
@Override
public boolean listPrivate() {
return false;
}
@Override
public boolean listPublic() {
return true;
}
};
}
@Command(
name = "*", //TODO NOT IMPLEMENTED originally this was left blank but doing so causes a major compilation error
desc = "wildcard"
)
public Filter wildcard(Actor actor, File root, String arg) {
arg = arg.replace("/", File.separator);
String argLower = arg.toLowerCase(Locale.ROOT);
if (arg.endsWith(File.separator)) {
String finalArg = arg;
return new Filter() {
@Override
public File getPath(File root) {
File newRoot = new File(root, finalArg);
if (newRoot.exists()) {
return newRoot;
}
String firstArg = finalArg.substring(0, finalArg.length() - File.separator.length());
if (firstArg.length() > 3 && firstArg.length() <= 16) {
UUID fromName = Fawe.imp().getUUID(finalArg);
if (fromName != null) {
newRoot = new File(root, finalArg);
if (newRoot.exists()) {
return newRoot;
}
}
}
throw new StopExecutionException(TextComponent.of("Cannot find path: " + finalArg));
}
};
} else {
if (StringMan.containsAny(arg, "\\^$.|?+(){}<>~$!%^&*+-/")) {
Pattern pattern;
try {
pattern = Pattern.compile(argLower);
} catch (PatternSyntaxException ignored) {
pattern = Pattern.compile(Pattern.quote(argLower));
}
Pattern finalPattern = pattern;
return new Filter() {
@Override
public boolean applies(File file) {
String path = file.getPath().toLowerCase(Locale.ROOT);
return finalPattern.matcher(path).find();
}
};
}
return new Filter() {
@Override
public boolean applies(File file) {
return StringMan.containsIgnoreCase(file.getPath(), argLower);
}
};
}
}
}

View File

@ -1,132 +0,0 @@
// TODO: Ping @MattBDev to reimplement (or remove because this class is stupid) 2020-02-04
//package com.sk89q.worldedit.command;
//
//import com.boydti.fawe.object.mask.AdjacentAnyMask;
//import com.boydti.fawe.object.mask.AdjacentMask;
//import com.boydti.fawe.object.mask.AngleMask;
//import com.boydti.fawe.object.mask.BiomeMask;
//import com.boydti.fawe.object.mask.BlockLightMask;
//import com.boydti.fawe.object.mask.BrightnessMask;
//import com.boydti.fawe.object.mask.ExtremaMask;
//import com.boydti.fawe.object.mask.LightMask;
//import com.boydti.fawe.object.mask.OpacityMask;
//import com.boydti.fawe.object.mask.ROCAngleMask;
//import com.boydti.fawe.object.mask.RadiusMask;
//import com.boydti.fawe.object.mask.RandomMask;
//import com.boydti.fawe.object.mask.SimplexMask;
//import com.boydti.fawe.object.mask.SkyLightMask;
//import com.boydti.fawe.object.mask.SurfaceMask;
//import com.boydti.fawe.object.mask.WallMask;
//import com.boydti.fawe.function.mask.XAxisMask;
//import com.boydti.fawe.function.mask.YAxisMask;
//import com.boydti.fawe.function.mask.ZAxisMask;
//import com.sk89q.worldedit.IncompleteRegionException;
//import com.sk89q.worldedit.LocalSession;
//import com.sk89q.worldedit.WorldEdit;
//import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
//import com.sk89q.worldedit.entity.Player;
//import com.sk89q.worldedit.extent.Extent;
//import com.sk89q.worldedit.function.mask.BlockMaskBuilder;
//import com.sk89q.worldedit.function.mask.ExistingBlockMask;
//import com.sk89q.worldedit.function.mask.ExpressionMask;
//import com.sk89q.worldedit.function.mask.Mask;
//import com.sk89q.worldedit.function.mask.MaskIntersection;
//import com.sk89q.worldedit.function.mask.MaskUnion;
//import com.sk89q.worldedit.function.mask.Masks;
//import com.sk89q.worldedit.function.mask.OffsetMask;
//import com.sk89q.worldedit.function.mask.RegionMask;
//import com.sk89q.worldedit.function.mask.SolidBlockMask;
//import com.sk89q.worldedit.internal.expression.Expression;
//import com.sk89q.worldedit.internal.expression.ExpressionEnvironment;
//import com.sk89q.worldedit.internal.expression.ExpressionException;
//import com.sk89q.worldedit.math.BlockVector3;
//import com.sk89q.worldedit.math.Vector3;
//import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
//import com.sk89q.worldedit.session.request.RequestSelection;
//import com.sk89q.worldedit.world.biome.BiomeType;
//import org.enginehub.piston.annotation.Command;
//import org.enginehub.piston.annotation.CommandContainer;
//import org.enginehub.piston.annotation.param.Arg;
//import org.enginehub.piston.annotation.param.Switch;
//
////@Command(aliases = {"masks"},
//// desc = "Help for the various masks. [More Info](https://git.io/v9r4K)",
//// descFooter = "Masks determine if a block can be placed\n" +
//// " - Use [brackets] for arguments\n" +
//// " - Use , to OR multiple\n" +
//// " - Use & to AND multiple\n" +
//// "e.g. >[stone,dirt],#light[0][5],$jungle\n" +
//// "More Info: https://git.io/v9r4K"
////)
//@CommandContainer//(superTypes = CommandPermissionsConditionGenerator.Registration.class)
//public class MaskCommands {
// private final WorldEdit worldEdit;
//
// public MaskCommands(WorldEdit worldEdit) {
// this.worldEdit = worldEdit;
// }
// @Command(
// name = "#light",
// desc = "Restrict to specific light levels"
// )
// public Mask light(Extent extent, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) {
// return new LightMask(extent, (int) minInt, (int) maxInt);
// }
//
// @Command(
// name = "#skylight",
// desc = "Restrict to specific sky light levels"
// )
// public Mask skylight(Extent extent, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) {
// return new SkyLightMask(extent, (int) minInt, (int) maxInt);
// }
//
// @Command(
// name = "#blocklight",
// aliases = {"#emittedlight"},
// desc = "Restrict to specific block light levels"
// )
// public Mask blocklight(Extent extent, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) {
// return new BlockLightMask(extent, (int) minInt, (int) maxInt);
// }
//
// @Command(
// name = "#opacity",
// desc = "Restrict to specific opacity levels"
// )
// public Mask opacity(Extent extent, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) {
// return new OpacityMask(extent, (int) minInt, (int) maxInt);
// }
//
// @Command(
// name = "#brightness",
// desc = "Restrict to specific block brightness"
// )
// public Mask brightness(Extent extent, @Arg(name="mine", desc = "min light") double minInt, @Arg(name="mine", desc = "max light") double maxInt) {
// return new BrightnessMask(extent, (int) minInt, (int) maxInt);
// }
//
// @Command(
// name = "#haslight",
// desc = "Restricts to blocks with light (sky or emitted)"
// )
// public Mask haslight(Extent extent) {
// return new LightMask(extent, 1, Integer.MAX_VALUE);
// }
//
// @Command(
// name = "#nolight",
// desc = "Restrict to blocks without light (sky or emitted)"
// )
// public Mask nolight(Extent extent) {
// return new LightMask(extent, 0, 0);
// }
// @Command(
// name = "#iddata",
// desc = "Restrict to initial block id and data"
// )
// public Mask iddata(Extent extent) {
// return new IdDataMask(extent);
// }
//}

View File

@ -1,19 +0,0 @@
package com.sk89q.worldedit.command;
import com.sk89q.worldedit.command.argument.Arguments;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.enginehub.piston.inject.Key;
import java.util.Optional;
public class MethodCommands {
public static String getArguments(InjectedValueAccess context) {
if (context == null) {
return null;
}
Optional<Arguments> arguments = context.injectedValue(Key.of(Arguments.class));
return arguments.map(Arguments::get).orElse(null);
}
}

View File

@ -151,20 +151,22 @@ public class NavigationCommands {
}
@Command(
name = "jumpto",
aliases = { "j", "/jumpto", "/j" },
desc = "Teleport to a location"
name = "jumpto",
aliases = { "j", "/jumpto", "/j" },
desc = "Teleport to a location"
)
@CommandPermissions("worldedit.navigation.jumpto.command")
public void jumpTo(Player player,
@Arg(desc = "Location to jump to", def = "")
Location pos,
@Switch(name = 'f', desc = "force teleport")
boolean force) throws WorldEditException {
@Arg(desc = "Location to jump to", def = "")
Location pos,
//FAWE start
@Switch(name = 'f', desc = "force teleport")
boolean force) throws WorldEditException {
if (pos == null) {
pos = player.getSolidBlockTrace(300);
}
//FAWE end
if (pos != null) {
player.findFreePosition(pos);
player.print(Caption.of("worldedit.jumpto.moved"));

View File

@ -1,356 +0,0 @@
// TODO: Ping @MattBDev to reimplement 2020-02-04
//package com.sk89q.worldedit.command;
//
//import com.boydti.fawe.object.DataAnglePattern;
//import com.boydti.fawe.object.clipboard.MultiClipboardHolder;
//import com.boydti.fawe.object.collection.RandomCollection;
//import com.boydti.fawe.object.pattern.AngleColorPattern;
//import com.boydti.fawe.object.pattern.AverageColorPattern;
//import com.boydti.fawe.object.pattern.BiomePattern;
//import com.boydti.fawe.object.pattern.BufferedPattern;
//import com.boydti.fawe.object.pattern.BufferedPattern2D;
//import com.boydti.fawe.object.pattern.DataPattern;
//import com.boydti.fawe.object.pattern.DesaturatePattern;
//import com.boydti.fawe.object.pattern.ExistingPattern;
//import com.boydti.fawe.object.pattern.ExpressionPattern;
//import com.boydti.fawe.object.pattern.FullClipboardPattern;
//import com.boydti.fawe.object.pattern.IdDataMaskPattern;
//import com.boydti.fawe.object.pattern.IdPattern;
//import com.boydti.fawe.object.pattern.Linear2DBlockPattern;
//import com.boydti.fawe.object.pattern.Linear3DBlockPattern;
//import com.boydti.fawe.object.pattern.LinearBlockPattern;
//import com.boydti.fawe.object.pattern.MaskedPattern;
//import com.boydti.fawe.object.pattern.NoXPattern;
//import com.boydti.fawe.object.pattern.NoYPattern;
//import com.boydti.fawe.object.pattern.NoZPattern;
//import com.boydti.fawe.object.pattern.OffsetPattern;
//import com.boydti.fawe.object.pattern.PropertyPattern;
//import com.boydti.fawe.object.pattern.RandomFullClipboardPattern;
//import com.boydti.fawe.object.pattern.RandomOffsetPattern;
//import com.boydti.fawe.object.pattern.RelativePattern;
//import com.boydti.fawe.object.pattern.SaturatePattern;
//import com.boydti.fawe.object.pattern.ShadePattern;
//import com.boydti.fawe.object.pattern.SolidRandomOffsetPattern;
//import com.boydti.fawe.object.pattern.SurfaceRandomOffsetPattern;
//import com.boydti.fawe.object.random.SimplexRandom;
//import com.boydti.fawe.util.ColorUtil;
//import com.boydti.fawe.util.TextureUtil;
//import com.sk89q.worldedit.EmptyClipboardException;
//import com.sk89q.worldedit.LocalSession;
//import com.sk89q.worldedit.entity.Player;
//import com.sk89q.worldedit.extension.input.InputParseException;
//import com.sk89q.worldedit.extension.platform.Actor;
//import com.sk89q.worldedit.extent.Extent;
//import com.sk89q.worldedit.extent.clipboard.Clipboard;
//import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
//import com.sk89q.worldedit.function.mask.Mask;
//import com.sk89q.worldedit.function.pattern.ClipboardPattern;
//import com.sk89q.worldedit.function.pattern.Pattern;
//import com.sk89q.worldedit.function.pattern.RandomPattern;
//import com.sk89q.worldedit.internal.expression.Expression;
//import com.sk89q.worldedit.internal.expression.ExpressionException;
//import com.sk89q.worldedit.math.Vector3;
//import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
//import com.sk89q.worldedit.session.ClipboardHolder;
//import com.sk89q.worldedit.world.biome.BiomeType;
//import java.awt.Color;
//import java.io.IOException;
//import java.util.Collections;
//import java.util.List;
//import java.util.Set;
//import org.enginehub.piston.annotation.Command;
//import org.enginehub.piston.annotation.CommandContainer;
//import org.enginehub.piston.annotation.param.Arg;
//import org.jetbrains.annotations.Range;
//
////@Command(aliases = {"patterns"},
//// desc = "Help for the various patterns. [More Info](https://git.io/vSPmA)",
//// descFooter = "Patterns determine what blocks are placed\n" +
//// " - Use [brackets] for arguments\n" +
//// " - Use , to OR multiple\n" +
//// "e.g., #surfacespread[10][#existing],andesite\n" +
//// "More Info: https://git.io/vSPmA"
////)
//@CommandContainer//(superTypes = CommandPermissionsConditionGenerator.Registration.class)
//public class PatternCommands {
//
//
// @Command(
// name = "#simplex",
// desc = "Use simplex noise to randomize blocks. Tutorial: https://imgur.com/a/rwVAE"
//)
// public Pattern simplex(@Arg(desc = "scale factor") double scale, @Arg(desc = "Pattern") Pattern other) {
// if (other instanceof RandomPattern) {
// scale = (1d / Math.max(1, scale));
// RandomCollection<Pattern> collection = ((RandomPattern) other).getCollection();
// collection.setRandom(new SimplexRandom(scale));
// }
// return other;
// }
//
// @Command(
// name = "#color",
// desc = "Use the block closest to a specific color"
//)
// public Pattern color(TextureUtil textureUtil, @Arg(desc = "String color") String color) {
// Color colorObj = ColorUtil.parseColor(color);
// return textureUtil.getNearestBlock(colorObj.getRGB()).getDefaultState();
// }
//
// @Command(
// name = "#anglecolor",
// desc = "A darker block based on the existing terrain angle"
//)
// public Pattern anglecolor(Extent extent, LocalSession session, @Arg(desc = "int", def = "1") int distance) {
// return new AngleColorPattern(extent, session, distance);
// }
//
// @Command(
// name = "#angledata",
// desc = "Block data based on the existing terrain angle"
// )
// public Pattern angledata(Extent extent, @Arg(desc = "int", def = "1") int distance) {
// return new DataAnglePattern(extent, distance);
// }
//
// @Command(
// name = "#saturate",
// desc = "Saturate the existing block with a color"
//)
// public Pattern saturate(Extent extent, LocalSession session, @Arg(desc = "Color code") String colorStr) {
// Color color = ColorUtil.parseColor(colorStr);
// return new SaturatePattern(extent, color.getRGB(), session);
// }
//
// @Command(
// name = "#averagecolor",
// desc = "Average between the existing block and a color"
//)
// public Pattern averagecolor(Extent extent, LocalSession session, @Arg(desc = "Color code") String colorStr) {
// Color color = ColorUtil.parseColor(colorStr);
// return new AverageColorPattern(extent, color.getRGB(), session);
// }
//
// @Command(
// name = "#desaturate",
// desc = "Desaturated color of the existing block"
//)
// public Pattern desaturate(Extent extent, LocalSession session, @Arg(desc = "double", def = "100") double percent) {
// return new DesaturatePattern(extent, percent / 100d, session);
// }
//
// @Command(
// name = "#lighten",
// desc = "Lighten the existing block"
//)
// public Pattern lighten(Extent extent, TextureUtil util) {
// return new ShadePattern(extent, false, util);
// }
//
// @Command(
// name = "#darken",
// desc = "Darken the existing block"
//)
// public Pattern darken(Extent extent, TextureUtil util) {
// return new ShadePattern(extent, true, util);
// }
//
// @Command(
// name = "#buffer",
// desc = "Only place a block once while a pattern is in use",
// descFooter = "Only place a block once while a pattern is in use\n" +
// "Use with a brush when you don't want to apply to the same spot twice"
//)
// public Pattern buffer(Actor actor, @Arg(desc = "Pattern")Pattern pattern) {
// return new BufferedPattern(actor, pattern);
// }
//
// @Command(
// name = "#buffer2d",
// desc = "Only place a block once in a column while a pattern is in use"
//)
// public Pattern buffer2d(Actor actor, @Arg(desc = "Pattern")Pattern pattern) {
// return new BufferedPattern2D(actor, pattern);
// }
//
// @Command(
// name = "#iddatamask",
// desc = "Use the pattern's id and the existing blocks data with the provided mask",
// descFooter = "Use the pattern's id and the existing blocks data with the provided mask\n" +
// " - Use to replace slabs or where the data values needs to be shifted instead of set"
//)
// public Pattern iddatamask(Extent extent, @Range(from = 0, to = 15) @Arg(desc = "bit mask") int bitmask, @Arg(desc = "Pattern")Pattern pattern) {
//
// return new IdDataMaskPattern(extent, pattern, bitmask);
// }
//
// @Command(
// name = "#id",
// desc = "Only change the block id"
//)
// public Pattern id(Extent extent, @Arg(desc = "Pattern")Pattern pattern) {
//
// return new IdPattern(extent, pattern);
// }
//
// @Command(
// name = "#data",
// desc = "Only change the block data"
//)
// public Pattern data(Extent extent, @Arg(desc = "Pattern")Pattern pattern) {
//
// return new DataPattern(extent, pattern);
// }
//
// @Command(
// name = "#biome",
// aliases = {"$"},
// desc = "Set the biome"
//)
// public Pattern biome(Extent extent, @Arg(desc = "Biome type") BiomeType biome) {
//
// return new BiomePattern(extent, biome);
// }
//
// @Command(
// name = "#relative",
// aliases = {"#~", "#r", "#rel"},
// desc = "Offset the pattern to where you click"
//)
// public Pattern relative(@Arg(desc = "Pattern")Pattern pattern) {
//
// return new RelativePattern(pattern);
// }
//
// @Command(
// name = "#!x",
// aliases = {"#nx", "#nox"},
// desc = "The pattern will not be provided the x axis info",
// descFooter = "The pattern will not be provided the z axis info.\n" +
// "Example: #!x[#!z[#~[#l3d[pattern]]]]"
//)
// public Pattern nox(@Arg(desc = "Pattern")Pattern pattern) {
//
// return new NoXPattern(pattern);
// }
//
// @Command(
// name = "#!y",
// aliases = {"#ny", "#noy"},
// desc = "The pattern will not be provided the y axis info"
//)
// public Pattern noy(@Arg(desc = "Pattern")Pattern pattern) {
//
// return new NoYPattern(pattern);
// }
//
// @Command(
// name = "#!z",
// aliases = {"#nz", "#noz"},
// desc = "The pattern will not be provided the z axis info"
//)
// public Pattern noz(@Arg(desc = "Pattern")Pattern pattern) {
//
// return new NoZPattern(pattern);
// }
//
// @Command(
// name = "#mask",
// desc = "Apply a pattern depending on a mask"
//)
// public Pattern mask(@Arg(desc = "Mask") Mask mask, @Arg(desc = "Pattern")Pattern pass, @Arg(desc = "Pattern")Pattern fail) {
// return new MaskedPattern(mask, pass, fail);
// }
//
// @Command(
// name = "#offset",
// desc = "Offset a pattern"
//)
// public Pattern offset(@Arg(desc = "x offset") double x, @Arg(desc = "y offset") double y, @Arg(desc = "z offset") double z, @Arg(desc = "Pattern")Pattern pattern) {
//
// return new OffsetPattern(pattern, (int) x, (int) y, (int) z);
// }
//
// @Command(
// name = "#surfacespread",
// desc = "Applies to only blocks on a surface. Selects a block from provided pattern with a given randomized offset `[0, <distance>)`. e.g., Use `#existing` to randomly offset blocks in the world, or `#copy` to offset blocks in your clipboard"
//)
// public Pattern surfacespread(@Arg(desc = "spread distance (blocks)") double distance, @Arg(desc = "Pattern")Pattern pattern) {
//
// return new SurfaceRandomOffsetPattern(pattern, (int) distance);
// }
//
// @Command(
// name = "#solidspread",
// desc = "Randomly spread solid blocks"
//)
// public Pattern solidspread(@Arg(desc = "x offset") double x, @Arg(desc = "y offset") double y, @Arg(desc = "z offset") double z, @Arg(desc = "Pattern")Pattern pattern) {
//
// return new SolidRandomOffsetPattern(pattern, (int) x, (int) y, (int) z);
// }
//
// @Command(
// name = "#spread",
// aliases = {"#randomoffset"},
// desc = "Randomly spread blocks"
//)
// public Pattern spread(@Arg(desc = "x offset") double x, @Arg(desc = "y offset") double y, @Arg(desc = "z offset") double z, @Arg(desc = "Pattern")Pattern pattern) {
//
// return new RandomOffsetPattern(pattern, (int) x, (int) y, (int) z);
// }
//
// @Command(
// name = "#linear",
// aliases = {"#l"},
// desc = "Sequentially set blocks from a list of patterns"
//)
// public Pattern linear(@Arg(desc = "Pattern") Pattern other) {
//
// if (other instanceof RandomPattern) {
// Set<Pattern> patterns = ((RandomPattern) other).getPatterns();
// return new LinearBlockPattern(patterns.toArray(new Pattern[patterns.size()]));
// }
// return other;
// }
//
// @Command(
// name = "#linear3d",
// aliases = {"#l3d"},
// desc = "Use the x,y,z coordinate to pick a block from the list"
//)
// public Pattern linear3d(@Arg(desc = "Pattern") Pattern other) {
//
// if (other instanceof RandomPattern) {
// Set<Pattern> patterns = ((RandomPattern) other).getPatterns();
// return new Linear3DBlockPattern(patterns.toArray(new Pattern[patterns.size()]));
// }
// return other;
// }
//
// @Command(
// name = "#linear2d",
// aliases = {"#l2d"},
// desc = "Use the x,z coordinate to pick a block from the list"
//)
// public Pattern linear2d(@Arg(desc = "Pattern") Pattern other) {
//
// if (other instanceof RandomPattern) {
// Set<Pattern> patterns = ((RandomPattern) other).getPatterns();
// return new Linear2DBlockPattern(patterns.toArray(new Pattern[patterns.size()]));
// }
// return other;
// }
//
// @Command(
// name = "=",
// aliases = {"#=", "#expression"},
// desc = "Expression pattern: http://wiki.sk89q.com/wiki/WorldEdit/Expression_syntax"
//)
// public Pattern expression(Extent extent, @Arg(desc = "Expression") String input) throws ExpressionException {
//
// Expression exp = Expression.compile(input, "x", "y", "z");
// WorldEditExpressionEnvironment env = new WorldEditExpressionEnvironment(extent, Vector3.ONE, Vector3.ZERO);
// exp.setEnvironment(env);
// return new ExpressionPattern(exp);
// }
//}

View File

@ -23,7 +23,7 @@ import com.fastasyncworldedit.core.FaweAPI;
import com.fastasyncworldedit.core.FaweCache;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.object.FaweLimit;
import com.fastasyncworldedit.core.object.RelightMode;
import com.fastasyncworldedit.core.extent.processor.lighting.RelightMode;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;

View File

@ -21,9 +21,9 @@ package com.sk89q.worldedit.command;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.object.clipboard.MultiClipboardHolder;
import com.fastasyncworldedit.core.object.clipboard.URIClipboardHolder;
import com.fastasyncworldedit.core.object.schematic.MinecraftStructure;
import com.fastasyncworldedit.core.extent.clipboard.MultiClipboardHolder;
import com.fastasyncworldedit.core.extent.clipboard.URIClipboardHolder;
import com.fastasyncworldedit.core.extent.clipboard.io.schematic.MinecraftStructure;
import com.fastasyncworldedit.core.util.MainUtil;
import com.google.common.base.Function;
import com.google.common.collect.Multimap;
@ -36,7 +36,7 @@ import com.sk89q.worldedit.command.util.AsyncCommandBuilder;
import com.sk89q.worldedit.command.util.CommandPermissions;
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.extent.ActorSaveClipboardEvent;
import com.fastasyncworldedit.core.event.extent.ActorSaveClipboardEvent;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
@ -115,6 +115,7 @@ public class SchematicCommands {
this.worldEdit = worldEdit;
}
//FAWE start
//TODO filtering for directories, global, and private scheamtics needs to be reimplemented here
private static List<File> getFiles(File root, String filter, ClipboardFormat format) {
File[] files = root.listFiles();
@ -215,6 +216,76 @@ public class SchematicCommands {
player.print(Caption.of("fawe.worldedit.clipboard.clipboard.uri.not.found", fileName));
}
//FAWE start
@Command(
name = "move",
aliases = {"m"},
desc = "Move your loaded schematic"
)
@CommandPermissions({"worldedit.schematic.move", "worldedit.schematic.move.other"})
public void move(Player player, LocalSession session, String directory) throws WorldEditException, IOException {
LocalConfiguration config = worldEdit.getConfiguration();
File working = worldEdit.getWorkingDirectoryPath(config.saveDir).toFile();
File dir = Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS ? new File(working, player.getUniqueId().toString()) : working;
File destDir = new File(dir, directory);
if (!MainUtil.isInSubDirectory(working, destDir)) {
player.print(Caption.of("worldedit.schematic.directory-does-not-exist", TextComponent.of(String.valueOf(destDir))));
return;
}
if (Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS && !MainUtil.isInSubDirectory(dir, destDir) && !player.hasPermission("worldedit.schematic.move.other")) {
player.print(Caption.of("fawe.error.no-perm", "worldedit.schematic.move.other"));
return;
}
ClipboardHolder clipboard = session.getClipboard();
List<File> sources = getFiles(clipboard);
if (sources.isEmpty()) {
player.print(Caption.of("fawe.worldedit.schematic.schematic.none"));
return;
}
if (!destDir.exists() && !destDir.mkdirs()) {
player.print(Caption.of("worldedit.schematic.file-perm-fail", TextComponent.of(String.valueOf(destDir))));
return;
}
for (File source : sources) {
File destFile = new File(destDir, source.getName());
if (destFile.exists()) {
player.print(Caption.of("fawe.worldedit.schematic.schematic.move.exists", destFile));
continue;
}
if (Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS && (!MainUtil.isInSubDirectory(dir, destFile) || !MainUtil.isInSubDirectory(dir, source)) && !player.hasPermission("worldedit.schematic.delete.other")) {
player.print(Caption.of("fawe.worldedit.schematic.schematic.move.failed", destFile,
Caption.of("fawe.error.no-perm", ("worldedit.schematic.move.other"))));
continue;
}
try {
File cached = new File(source.getParentFile(), "." + source.getName() + ".cached");
Files.move(source.toPath(), destFile.toPath());
if (cached.exists()) {
Files.move(cached.toPath(), destFile.toPath());
}
player.print(Caption.of("fawe.worldedit.schematic.schematic.move.success", source, destFile));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
private List<File> getFiles(ClipboardHolder clipboard) {
Collection<URI> uris = Collections.emptyList();
if (clipboard instanceof URIClipboardHolder) {
uris = ((URIClipboardHolder) clipboard).getURIs();
}
List<File> files = new ArrayList<>();
for (URI uri : uris) {
File file = new File(uri);
if (file.exists()) {
files.add(file);
}
}
return files;
}
//FAWE end
@Command(
name = "load",
desc = "Load a schematic into your clipboard"
@ -227,6 +298,7 @@ public class SchematicCommands {
String formatName) throws FilenameException {
LocalConfiguration config = worldEdit.getConfiguration();
//FAWE start
ClipboardFormat format = null;
InputStream in = null;
try {
@ -313,6 +385,7 @@ public class SchematicCommands {
}
}
}
//FAWE end
}
@Command(
@ -327,8 +400,10 @@ public class SchematicCommands {
String formatName,
@Switch(name = 'f', desc = "Overwrite an existing file.")
boolean allowOverwrite,
//FAWE start
@Switch(name = 'g', desc = "Bypasses per-player-schematic folders")
boolean global) throws WorldEditException {
//FAWE end
if (worldEdit.getPlatformManager().queryCapability(Capability.GAME_HOOKS).getDataVersion() == -1) {
actor.printError(TranslatableComponent.of("worldedit.schematic.unsupported-minecraft-version"));
return;
@ -338,6 +413,7 @@ public class SchematicCommands {
File dir = worldEdit.getWorkingDirectoryPath(config.saveDir).toFile();
//FAWE start
if (!global && Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS) {
dir = new File(dir, actor.getUniqueId().toString());
}
@ -361,6 +437,7 @@ public class SchematicCommands {
}
}
//FAWE end
File f = worldEdit.getSafeSaveFile(actor, dir, filename, format.getPrimaryFileExtension());
boolean overwrite = f.exists();
@ -394,80 +471,12 @@ public class SchematicCommands {
SchematicSaveTask task = new SchematicSaveTask(actor, f, dir, format, holder, overwrite);
AsyncCommandBuilder.wrap(task, actor)
.registerWithSupervisor(worldEdit.getSupervisor(), "Saving schematic " + filename)
.sendMessageAfterDelay(Caption.of("worldedit.schematic.save.saving"))
.setDelayMessage(Caption.of("worldedit.schematic.save.saving"))
.onSuccess(filename + " saved" + (overwrite ? " (overwriting previous file)." : "."), null)
.onFailure(Caption.of("worldedit.schematic.failed-to-save"), worldEdit.getPlatformManager().getPlatformCommandManager().getExceptionConverter())
.buildAndExec(worldEdit.getExecutorService());
}
@Command(
name = "move",
aliases = {"m"},
desc = "Move your loaded schematic"
)
@CommandPermissions({"worldedit.schematic.move", "worldedit.schematic.move.other"})
public void move(Player player, LocalSession session, String directory) throws WorldEditException, IOException {
LocalConfiguration config = worldEdit.getConfiguration();
File working = worldEdit.getWorkingDirectoryPath(config.saveDir).toFile();
File dir = Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS ? new File(working, player.getUniqueId().toString()) : working;
File destDir = new File(dir, directory);
if (!MainUtil.isInSubDirectory(working, destDir)) {
player.print(Caption.of("worldedit.schematic.directory-does-not-exist", TextComponent.of(String.valueOf(destDir))));
return;
}
if (Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS && !MainUtil.isInSubDirectory(dir, destDir) && !player.hasPermission("worldedit.schematic.move.other")) {
player.print(Caption.of("fawe.error.no-perm", "worldedit.schematic.move.other"));
return;
}
ClipboardHolder clipboard = session.getClipboard();
List<File> sources = getFiles(clipboard);
if (sources.isEmpty()) {
player.print(Caption.of("fawe.worldedit.schematic.schematic.none"));
return;
}
if (!destDir.exists() && !destDir.mkdirs()) {
player.print(Caption.of("worldedit.schematic.file-perm-fail", TextComponent.of(String.valueOf(destDir))));
return;
}
for (File source : sources) {
File destFile = new File(destDir, source.getName());
if (destFile.exists()) {
player.print(Caption.of("fawe.worldedit.schematic.schematic.move.exists", destFile));
continue;
}
if (Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS && (!MainUtil.isInSubDirectory(dir, destFile) || !MainUtil.isInSubDirectory(dir, source)) && !player.hasPermission("worldedit.schematic.delete.other")) {
player.print(Caption.of("fawe.worldedit.schematic.schematic.move.failed", destFile,
Caption.of("fawe.error.no-perm", ("worldedit.schematic.move.other"))));
continue;
}
try {
File cached = new File(source.getParentFile(), "." + source.getName() + ".cached");
Files.move(source.toPath(), destFile.toPath());
if (cached.exists()) {
Files.move(cached.toPath(), destFile.toPath());
}
player.print(Caption.of("fawe.worldedit.schematic.schematic.move.success", source, destFile));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
private List<File> getFiles(ClipboardHolder clipboard) {
Collection<URI> uris = Collections.emptyList();
if (clipboard instanceof URIClipboardHolder) {
uris = ((URIClipboardHolder) clipboard).getURIs();
}
List<File> files = new ArrayList<>();
for (URI uri : uris) {
File file = new File(uri);
if (file.exists()) {
files.add(file);
}
}
return files;
}
@Command(
name = "formats",
aliases = {"listformats", "f"},
@ -514,6 +523,7 @@ public class SchematicCommands {
if (oldFirst && newFirst) {
throw new StopExecutionException(Caption.of("worldedit.schematic.sorting-old-new"));
}
//FAWE start
String pageCommand = "/" + arguments.get();
LocalConfiguration config = worldEdit.getConfiguration();
File dir = worldEdit.getWorkingDirectoryPath(config.saveDir).toFile();
@ -621,6 +631,7 @@ public class SchematicCommands {
PaginationBox paginationBox = PaginationBox.fromComponents(fullHeader, pageCommand, components);
actor.print(paginationBox.create(page));
}
//FAWE end
}
@ -635,6 +646,7 @@ public class SchematicCommands {
String filename) throws WorldEditException, IOException {
LocalConfiguration config = worldEdit.getConfiguration();
File working = worldEdit.getWorkingDirectoryPath(config.saveDir).toFile();
//FAWE start
File dir = Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS ? new File(working, actor.getUniqueId().toString()) : working;
List<File> files = new ArrayList<>();
@ -664,8 +676,10 @@ public class SchematicCommands {
}
actor.print(Caption.of("worldedit.schematic.delete.deleted", filename));
}
//FAWE end
}
//FAWE start
private boolean deleteFile(File file) {
if (file.delete()) {
new File(file.getParentFile(), "." + file.getName() + ".cached").delete();
@ -673,6 +687,7 @@ public class SchematicCommands {
}
return false;
}
//FAWE end
private static class SchematicLoadTask implements Callable<ClipboardHolder> {
private final Actor actor;
@ -722,6 +737,7 @@ public class SchematicCommands {
Transform transform = holder.getTransform();
Clipboard target;
//FAWE start
boolean checkFilesize = false;
if (Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS
@ -782,6 +798,7 @@ public class SchematicCommands {
};
}
}
//FAWE end
// If we have a transform, bake it into the copy
if (transform.isIdentity()) {
@ -797,6 +814,7 @@ public class SchematicCommands {
FileOutputStream fos = closer.register(new FileOutputStream(file));
BufferedOutputStream bos = closer.register(new BufferedOutputStream(fos));
ClipboardWriter writer = closer.register(format.getWriter(bos));
//FAWE start
URI uri = null;
if (holder instanceof URIClipboardHolder) {
uri = ((URIClipboardHolder) holder).getURI(clipboard);
@ -857,6 +875,7 @@ public class SchematicCommands {
actor.print(Caption.of("fawe.cancel.worldedit.cancel.reason.manual"));
}
}
//FAWE end
return null;
}
}
@ -890,6 +909,7 @@ public class SchematicCommands {
return ErrorFormat.wrap("No schematics found.");
}
//FAWE start
File[] files = new File[fileList.size()];
fileList.toArray(files);
// cleanup file list
@ -912,12 +932,14 @@ public class SchematicCommands {
return res;
});
//FAWE end
PaginationBox paginationBox = new SchematicPaginationBox(prefix, files, pageCommand);
return paginationBox.create(page);
}
}
private static class SchematicPaginationBox extends PaginationBox {
//FAWE start - Expand to per player schematics
private final String prefix;
private final File[] files;
@ -925,11 +947,13 @@ public class SchematicCommands {
super("worldedit.schematic.available", pageCommand);
this.prefix = rootDir == null ? "" : rootDir;
this.files = files;
//FAWE end
}
@Override
public Component getComponent(int number) {
checkArgument(number < files.length && number >= 0);
//FAWE start - Per player schematic support & translatable things
File file = files[number];
Multimap<String, ClipboardFormat> exts = ClipboardFormats.getFileExtensionMap();
String format = exts.get(com.google.common.io.Files.getFileExtension(file.getName()))
@ -948,6 +972,7 @@ public class SchematicCommands {
.append(TextComponent.of(path)
.hoverEvent(HoverEvent.of(HoverEvent.Action.SHOW_TEXT, TextComponent.of(format))))
.build();
//FAWE end
}
@Override

View File

@ -20,10 +20,10 @@
package com.sk89q.worldedit.command;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.object.clipboard.URIClipboardHolder;
import com.fastasyncworldedit.core.object.mask.IdMask;
import com.fastasyncworldedit.core.object.regions.selector.FuzzyRegionSelector;
import com.fastasyncworldedit.core.object.regions.selector.PolyhedralRegionSelector;
import com.fastasyncworldedit.core.extent.clipboard.URIClipboardHolder;
import com.fastasyncworldedit.core.function.mask.IdMask;
import com.fastasyncworldedit.core.regions.selector.FuzzyRegionSelector;
import com.fastasyncworldedit.core.regions.selector.PolyhedralRegionSelector;
import com.google.common.base.Strings;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
@ -47,7 +47,6 @@ import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.visitor.RegionVisitor;
import com.sk89q.worldedit.internal.annotation.Direction;
import com.sk89q.worldedit.internal.annotation.MultiDirection;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException;
@ -94,6 +93,8 @@ import java.util.stream.Stream;
import static com.sk89q.worldedit.command.util.Logging.LogMode.POSITION;
import static com.sk89q.worldedit.command.util.Logging.LogMode.REGION;
import static com.sk89q.worldedit.world.storage.ChunkStore.CHUNK_SHIFTS;
import static com.sk89q.worldedit.world.storage.ChunkStore.CHUNK_SHIFTS_Y;
/**
* Selection commands.
@ -118,10 +119,12 @@ public class SelectionCommands {
@Arg(desc = "Coordinates to set position 1 to", def = "")
BlockVector3 coordinates) throws WorldEditException {
Location pos;
//FAWE start - clamp
if (coordinates != null) {
pos = new Location(world, coordinates.toVector3().clampY(0, world.getMaxY()));
} else if (actor instanceof Locatable) {
pos = ((Locatable) actor).getBlockLocation().clampY(0, world.getMaxY());
//FAWE end
} else {
actor.print(Caption.of("worldedit.pos.console-require-coords"));
return;
@ -148,9 +151,11 @@ public class SelectionCommands {
BlockVector3 coordinates) throws WorldEditException {
Location pos;
if (coordinates != null) {
//FAWE start - clamp
pos = new Location(world, coordinates.toVector3().clampY(0, world.getMaxY()));
} else if (actor instanceof Locatable) {
pos = ((Locatable) actor).getBlockLocation().clampY(0, world.getMaxY());
//Fawe end
} else {
actor.print(Caption.of("worldedit.pos.console-require-coords"));
return;
@ -218,7 +223,7 @@ public class SelectionCommands {
@CommandPermissions("worldedit.selection.chunk")
public void chunk(Actor actor, World world, LocalSession session,
@Arg(desc = "The chunk to select", def = "")
BlockVector2 coordinates,
BlockVector3 coordinates,
@Switch(name = 's', desc = "Expand your selection to encompass all chunks that are part of it")
boolean expandSelection,
@Switch(name = 'c', desc = "Use chunk coordinates instead of block coordinates")
@ -228,40 +233,49 @@ public class SelectionCommands {
if (expandSelection) {
Region region = session.getSelection(world);
final BlockVector2 min2D = ChunkStore.toChunk(region.getMinimumPoint());
final BlockVector2 max2D = ChunkStore.toChunk(region.getMaximumPoint());
int minChunkY = world.getMinY() >> CHUNK_SHIFTS_Y;
int maxChunkY = world.getMaxY() >> CHUNK_SHIFTS_Y;
min = BlockVector3.at(min2D.getBlockX() * 16, 0, min2D.getBlockZ() * 16);
max = BlockVector3.at(max2D.getBlockX() * 16 + 15, world.getMaxY(), max2D.getBlockZ() * 16 + 15);
BlockVector3 minChunk = ChunkStore.toChunk3d(region.getMinimumPoint())
.clampY(minChunkY, maxChunkY);
BlockVector3 maxChunk = ChunkStore.toChunk3d(region.getMaximumPoint())
.clampY(minChunkY, maxChunkY);
min = minChunk.shl(CHUNK_SHIFTS, CHUNK_SHIFTS_Y, CHUNK_SHIFTS);
max = maxChunk.shl(CHUNK_SHIFTS, CHUNK_SHIFTS_Y, CHUNK_SHIFTS).add(15, world.getMaxY(), 15);
actor.print(Caption.of(
"worldedit.chunk.selected-multiple",
TextComponent.of(min2D.getBlockX()),
TextComponent.of(min2D.getBlockZ()),
TextComponent.of(max2D.getBlockX()),
TextComponent.of(max2D.getBlockZ())
TextComponent.of(minChunk.getBlockX()),
TextComponent.of(minChunk.getBlockY()),
TextComponent.of(minChunk.getBlockZ()),
TextComponent.of(maxChunk.getBlockX()),
TextComponent.of(maxChunk.getBlockY()),
TextComponent.of(maxChunk.getBlockZ())
));
} else {
final BlockVector2 min2D;
BlockVector3 minChunk;
if (coordinates != null) {
// coords specified
min2D = useChunkCoordinates
minChunk = useChunkCoordinates
? coordinates
: ChunkStore.toChunk(coordinates.toBlockVector3());
: ChunkStore.toChunk3d(coordinates);
} else {
// use player loc
if (actor instanceof Locatable) {
min2D = ChunkStore.toChunk(((Locatable) actor).getBlockLocation().toVector().toBlockPoint());
minChunk = ChunkStore.toChunk3d(((Locatable) actor).getBlockLocation().toVector().toBlockPoint());
} else {
throw new StopExecutionException(TextComponent.of("A player or coordinates are required."));
}
}
min = BlockVector3.at(min2D.getBlockX() * 16, 0, min2D.getBlockZ() * 16);
min = minChunk.shl(CHUNK_SHIFTS, CHUNK_SHIFTS_Y, CHUNK_SHIFTS);
max = min.add(15, world.getMaxY(), 15);
actor.print(Caption.of("worldedit.chunk.selected", TextComponent.of(min2D.getBlockX()),
TextComponent.of(min2D.getBlockZ())));
actor.print(Caption.of("worldedit.chunk.selected",
TextComponent.of(minChunk.getBlockX()),
TextComponent.of(minChunk.getBlockY()),
TextComponent.of(minChunk.getBlockZ())));
}
final CuboidRegionSelector selector;
@ -285,7 +299,9 @@ public class SelectionCommands {
@CommandPermissions("worldedit.wand")
public void wand(Player player, LocalSession session,
@Switch(name = 'n', desc = "Get a navigation wand") boolean navWand) throws WorldEditException {
//FAWE start
session.loadDefaults(player, true);
//FAWE end
String wandId = navWand ? session.getNavWandItem() : session.getWandItem();
if (wandId == null) {
wandId = navWand ? we.getConfiguration().navigationWand : we.getConfiguration().wandItem;
@ -296,12 +312,14 @@ public class SelectionCommands {
return;
}
player.giveItem(new BaseItemStack(itemType, 1));
//FAWE start - instance-iate session
if (navWand) {
session.setTool(itemType, NavigationWand.INSTANCE);
player.print(Caption.of("worldedit.wand.navwand.info"));
} else {
session.setTool(itemType, SelectionWand.INSTANCE);
player.print(Caption.of("worldedit.wand.selwand.info"));
//FAWE end
}
}
@ -459,6 +477,7 @@ public class SelectionCommands {
boolean clipboardInfo) throws WorldEditException {
Region region;
if (clipboardInfo) {
//FAWE start - Modify for cross server clipboards
ClipboardHolder root = session.getClipboard();
int index = 0;
for (ClipboardHolder holder : root.getHolders()) {
@ -488,6 +507,7 @@ public class SelectionCommands {
index++;
}
return;
//FAWE end
} else {
region = session.getSelection(world);
@ -572,7 +592,9 @@ public class SelectionCommands {
aliases = { ";", "/desel", "/deselect" },
desc = "Choose a region selector"
)
//FAWE start
@CommandPermissions("worldedit.analysis.sel")
//FAWE end
public void select(Actor actor, World world, LocalSession session,
@Arg(desc = "Selector to switch to", def = "")
SelectorChoice selector,
@ -625,6 +647,7 @@ public class SelectionCommands {
limit.ifPresent(integer -> actor.print(Caption.of("worldedit.select.convex.limit-message", TextComponent.of(integer))));
break;
}
//FAWE start
case POLYHEDRAL:
newSelector = new PolyhedralRegionSelector(world);
actor.print(Caption.of("fawe.selection.sel.convex.polyhedral"));
@ -640,6 +663,7 @@ public class SelectionCommands {
actor.print(Caption.of("fawe.selection.sel.fuzzy"));
actor.print(Caption.of("fawe.selection.sel.list"));
break;
//FAWE end
case LIST:
default:
CommandListBox box = new CommandListBox("Selection modes", null, null);

View File

@ -20,7 +20,7 @@
package com.sk89q.worldedit.command;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.object.brush.InspectBrush;
import com.fastasyncworldedit.core.command.tool.brush.InspectBrush;
import com.google.common.collect.Collections2;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
@ -143,8 +143,10 @@ public class ToolCommands {
static void setToolNone(Player player, LocalSession session, boolean isBrush)
throws InvalidToolBindException {
//FAWE start
isBrush = session.getTool(player) instanceof BrushTool;
session.setTool(player.getItemInHand(HandSide.MAIN_HAND).getType(), null);
//FAWE end
player.print(Caption.of(isBrush ? "worldedit.brush.none.equip" : "worldedit.tool.none.equip"));
}
@ -183,7 +185,9 @@ public class ToolCommands {
)
@CommandPermissions("worldedit.setwand")
public void selwand(Player player, LocalSession session) throws WorldEditException {
//FAWE start - instance-inized
setTool(player, session, SelectionWand.INSTANCE, "worldedit.tool.selwand.equip");
//FAWE end
}
@Command(
@ -193,7 +197,9 @@ public class ToolCommands {
)
@CommandPermissions("worldedit.setwand")
public void navwand(Player player, LocalSession session) throws WorldEditException {
//FAWE start - instance-inized
setTool(player, session, NavigationWand.INSTANCE, "worldedit.tool.navwand.equip");
//FAWE end
}
@Command(
@ -206,6 +212,7 @@ public class ToolCommands {
setTool(player, session, new QueryTool(), "worldedit.tool.info.equip");
}
//FAWE start
@Command(
name = "inspect",
aliases = { "/inspect" },
@ -215,6 +222,7 @@ public class ToolCommands {
public void inspectBrush(Player player, LocalSession session) throws WorldEditException {
setTool(player, session, new InspectBrush(), "worldedit.tool.info.equip");
}
//FAWE end
@Command(
name = "tree",

View File

@ -20,9 +20,9 @@
package com.sk89q.worldedit.command;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.object.brush.BrushSettings;
import com.fastasyncworldedit.core.object.brush.TargetMode;
import com.fastasyncworldedit.core.object.brush.scroll.Scroll;
import com.fastasyncworldedit.core.command.tool.brush.BrushSettings;
import com.fastasyncworldedit.core.command.tool.TargetMode;
import com.fastasyncworldedit.core.command.tool.scroll.Scroll;
import com.fastasyncworldedit.core.util.MathMan;
import com.fastasyncworldedit.core.util.StringMan;
import com.google.common.collect.Iterables;
@ -61,6 +61,7 @@ public class ToolUtilCommands {
this.we = we;
}
//FAWE start - destination mask > mask
@Command(
name = "mask",
aliases = "/mask",
@ -90,6 +91,7 @@ public class ToolUtilCommands {
player.print(Caption.of("worldedit.tool.mask.set"));
}
}
//FAWE end
@Command(
name = "material",
@ -100,6 +102,7 @@ public class ToolUtilCommands {
public void material(Player player, LocalSession session,
@Arg(desc = "The pattern of blocks to use")
Pattern pattern,
//FAWE start - add offhand
@Switch(name = 'h', desc = "Whether the offhand should be considered or not")
boolean offHand, Arguments arguments) throws WorldEditException {
BrushTool tool = session.getBrushTool(player, false);
@ -116,6 +119,7 @@ public class ToolUtilCommands {
settings.addSetting(BrushSettings.SettingType.FILL, lastArg);
tool.update();
}
//FAWE end
player.print(Caption.of("worldedit.tool.material.set"));
}
@ -128,7 +132,7 @@ public class ToolUtilCommands {
public void range(Player player, LocalSession session,
@Arg(desc = "The range of the brush")
int range) throws WorldEditException {
session.getBrushTool(player, false).setRange(range);
session.getBrushTool(player.getItemInHand(HandSide.MAIN_HAND).getType()).setRange(range);
player.print(Caption.of("worldedit.tool.range.set"));
}
@ -186,6 +190,7 @@ public class ToolUtilCommands {
}
}
//FAWE start
@Command(
name = "primary",
aliases = { "/primary" },
@ -358,4 +363,5 @@ public class ToolUtilCommands {
// tool.update();
// player.print(TranslatableComponent.of("fawe.worldedit.brush.brush.transform"));
// }
//FAWE end
}

View File

@ -1,105 +0,0 @@
// TODO: Ping @MattBDev to reimplement 2020-02-04
//package com.sk89q.worldedit.command;
//
//import com.boydti.fawe.object.extent.Linear3DTransform;
//import com.boydti.fawe.object.extent.LinearTransform;
//import com.boydti.fawe.object.extent.OffsetExtent;
//import com.boydti.fawe.object.extent.PatternTransform;
//import com.boydti.fawe.object.extent.RandomOffsetTransform;
//import com.boydti.fawe.object.extent.RandomTransform;
//import com.boydti.fawe.object.extent.ResettableExtent;
//import com.boydti.fawe.object.extent.ScaleTransform;
//import com.boydti.fawe.object.extent.TransformExtent;
//import com.boydti.fawe.util.ExtentTraverser;
//import com.sk89q.worldedit.LocalSession;
//import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
//import com.sk89q.worldedit.entity.Player;
//import com.sk89q.worldedit.extension.platform.Actor;
//import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
//import com.sk89q.worldedit.function.pattern.Pattern;
//import com.sk89q.worldedit.math.transform.AffineTransform;
//import java.util.Set;
//import org.enginehub.piston.annotation.Command;
//import org.enginehub.piston.annotation.CommandContainer;
//import org.enginehub.piston.annotation.param.Arg;
//
//@CommandContainer//(superTypes = CommandPermissionsConditionGenerator.Registration.class)
//public class TransformCommands {
//
// @Command(
// name = "#linear",
// aliases = {"#l"},
// desc = "Sequentially pick from a list of transform"
// )
// public ResettableExtent linear(Actor actor, LocalSession session, @Arg(name = "other", desc = "ResettableExtent", def = "#null") ResettableExtent other) {
// if (other instanceof RandomTransform) {
// Set<ResettableExtent> extents = ((RandomTransform) other).getExtents();
// return new LinearTransform(extents.toArray(new ResettableExtent[0]));
// }
// return other;
// }
//
// @Command(
// name = "#linear3d",
// aliases = {"#l3d"},
// desc = "Use the x,y,z coordinate to pick a transform from the list"
// )
// public ResettableExtent linear3d(Actor actor, LocalSession session, @Arg(name = "other", desc = "ResettableExtent", def = "#null") ResettableExtent other) {
// if (other instanceof RandomTransform) {
// Set<ResettableExtent> extents = ((RandomTransform) other).getExtents();
// return new Linear3DTransform(extents.toArray(new ResettableExtent[0]));
// }
// return other;
// }
//
// @Command(
// name = "#pattern",
// desc = "Always use a specific pattern"
// )
// public ResettableExtent pattern(Actor actor, LocalSession session, @Arg(desc = "Pattern") Pattern pattern, @Arg(name = "other", desc = "ResettableExtent", def = "#null") ResettableExtent other) {
// return new PatternTransform(other, pattern);
// }
//
// @Command(
// name = "#offset",
// desc = "Offset transform"
// )
// public ResettableExtent offset(Actor actor, LocalSession session, double x, double y, double z, @Arg(name = "other", desc = "ResettableExtent", def = "#null") ResettableExtent other) {
// return new OffsetExtent(other, (int) x, (int) y, (int) z);
// }
//
// @Command(
// name = "#spread",
// aliases = {"#randomoffset"},
// desc = "Random offset transform"
//)
// public ResettableExtent randomOffset(Actor actor, LocalSession session, double x, double y, double z, @Arg(name = "other", desc = "ResettableExtent", def = "#null") ResettableExtent other) {
// return new RandomOffsetTransform(other, (int) x, (int) y, (int) z);
// }
//
// @Command(
// name = "#scale",
// desc = "All changes will be scaled"
// )
// public ResettableExtent scale(Actor actor, LocalSession session, double x, double y, double z, @Arg(name = "other", desc = "ResettableExtent", def = "#null") ResettableExtent other) {
// return new ScaleTransform(other, x, y, z);
// }
//
// @Command(
// name = "#rotate",
// desc = "All changes will be rotate around the initial position"
// )
// public ResettableExtent rotate(Player player, LocalSession session, double x, double y, double z, @Arg(name = "other", desc = "ResettableExtent", def = "#null") ResettableExtent other) {
// ExtentTraverser<TransformExtent> traverser = new ExtentTraverser<>(other).find(TransformExtent.class);
// BlockTransformExtent affine = traverser != null ? traverser.get() : null;
// if (affine == null) {
// other = affine = new TransformExtent(other);
// }
// AffineTransform transform = (AffineTransform) affine.getTransform();
// transform = transform.rotateX(x);
// transform = transform.rotateY(y);
// transform = transform.rotateZ(z);
// affine.setTransform(transform);
// return other;
// }
//}

View File

@ -22,8 +22,8 @@ package com.sk89q.worldedit.command;
import com.fastasyncworldedit.core.Fawe;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.object.DelegateConsumer;
import com.fastasyncworldedit.core.object.function.QuadFunction;
import com.fastasyncworldedit.core.util.task.DelegateConsumer;
import com.fastasyncworldedit.core.function.QuadFunction;
import com.fastasyncworldedit.core.util.MainUtil;
import com.fastasyncworldedit.core.util.TaskManager;
import com.fastasyncworldedit.core.util.image.ImageUtil;
@ -204,13 +204,17 @@ public class UtilityCommands {
public int fill(Actor actor, LocalSession session, EditSession editSession,
@Arg(desc = "The blocks to fill with")
Pattern pattern,
//FAWE start - we take an expression over a double
@Arg(desc = "The radius to fill in")
Expression radiusExp,
//FAWE end
@Arg(desc = "The depth to fill", def = "1")
int depth,
@Arg(desc = "The direction to move", def = "down")
@Direction BlockVector3 direction) throws WorldEditException, EvaluationException {
//FAWE start
double radius = radiusExp.evaluate();
//FAWE end
radius = Math.max(1, radius);
we.checkMaxRadius(radius);
depth = Math.max(1, depth);
@ -222,22 +226,6 @@ public class UtilityCommands {
}
/*
@Command(
name = "/fillr",
desc = "Fill a hole recursively"
name = "patterns",
desc = "View help about patterns",
descFooter = "Patterns determine what blocks are placed\n" +
" - Use [brackets] for arguments\n" +
" - Use , to OR multiple\n" +
"e.g., #surfacespread[10][#existing],andesite\n" +
"More Info: https://git.io/vSPmA"
)
@CommandQueued(false)
@CommandPermissions("worldedit.patterns")
public void patterns(Player player, LocalSession session, InjectedValueAccess args) throws WorldEditException {
displayModifierHelp(player, DefaultPatternParser.class, args);
}
@Command(
name = "masks",
@ -303,11 +291,15 @@ public class UtilityCommands {
public int fillr(Actor actor, LocalSession session, EditSession editSession,
@Arg(desc = "The blocks to fill with")
Pattern pattern,
//FAWE start - we take an expression over a double
@Arg(desc = "The radius to fill in")
Expression radiusExp,
//FAWE end
@Arg(desc = "The depth to fill", def = "")
Integer depth) throws WorldEditException {
//FAWE start
double radius = radiusExp.evaluate();
//FAWE end
radius = Math.max(1, radius);
we.checkMaxRadius(radius);
depth = depth == null ? Integer.MAX_VALUE : Math.max(1, depth);
@ -326,12 +318,16 @@ public class UtilityCommands {
@CommandPermissions("worldedit.drain")
@Logging(PLACEMENT)
public int drain(Actor actor, LocalSession session, EditSession editSession,
//FAWE start - we take an expression over a double
@Arg(desc = "The radius to drain")
Expression radiusExp,
//FAWE end
@Switch(name = 'w', desc = "Also un-waterlog blocks")
boolean waterlogged,
//FAWE start
@Switch(name = 'p', desc = "Also remove water plants")
boolean plants) throws WorldEditException {
//FAWE end
double radius = radiusExp.evaluate();
radius = Math.max(0, radius);
we.checkMaxRadius(radius);
@ -637,8 +633,10 @@ public class UtilityCommands {
flags.or(CreatureButcher.Flags.ARMOR_STAND, killArmorStands, "worldedit.butcher.armorstands");
flags.or(CreatureButcher.Flags.WATER, killWater, "worldedit.butcher.water");
//FAWE start - run this sync
int finalRadius = radius;
int killed = TaskManager.IMP.sync(() -> killMatchingEntities(finalRadius, actor, flags::createFunction));
//FAWE end
actor.print(Caption.of(
"worldedit.butcher.killed",
@ -666,7 +664,9 @@ public class UtilityCommands {
return 0;
}
//FAWE start - run this sync
int removed = TaskManager.IMP.sync(() -> killMatchingEntities(radius, actor, remover::createFunction));
//FAWE end
actor.print(Caption.of("worldedit.remove.removed", TextComponent.of(removed)));
return removed;
}
@ -694,7 +694,7 @@ public class UtilityCommands {
}
session.remember(editSession);
editSession.flushSession();
editSession.close();
return killed;
}
@ -749,6 +749,7 @@ public class UtilityCommands {
}
//FAWE start
@Command(
name = "/confirm",
desc = "Confirm a command"
@ -1064,5 +1065,6 @@ public class UtilityCommands {
name.append(relative.getPath());
return name.toString();
}
//FAWE end
}

View File

@ -77,6 +77,7 @@ public class WorldEditCommands {
)
@CommandPermissions(queued = false)
public void version(Actor actor) {
//FAWE start - get own version format
FaweVersion fVer = Fawe.get().getVersion();
String fVerStr = fVer == null ? "unknown" : "-" + fVer.build;
actor.print(TextComponent.of("FastAsyncWorldEdit" + fVerStr + " created by Empire92, MattBDev, IronApollo, dordsor21 and NotMyFault"));
@ -95,6 +96,7 @@ public class WorldEditCommands {
}
actor.printInfo(TextComponent.of("Wiki: https://github.com/IntellectualSites/FastAsyncWorldEdit-Documentation/wiki"));
//FAWE end
PlatformManager pm = we.getPlatformManager();
@ -130,10 +132,13 @@ public class WorldEditCommands {
public void reload(Actor actor) {
we.getPlatformManager().queryCapability(Capability.CONFIGURATION).reload();
we.getEventBus().post(new ConfigurationLoadEvent(we.getPlatformManager().queryCapability(Capability.CONFIGURATION).getConfiguration()));
//FAWE start
Fawe.get().setupConfigs();
//FAWE end
actor.print(Caption.of("worldedit.reload.config"));
}
//FAWE start
@Command(
name = "debugpaste",
desc = "Writes a report of latest.log, config.yml, config-legacy.yml, strings.json to https://athion.net/ISPaster/paste"
@ -171,6 +176,7 @@ public class WorldEditCommands {
}
}
}
//FAWE end
@Command(
name = "cui",

View File

@ -28,7 +28,6 @@ import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.internal.annotation.Direction;
import com.sk89q.worldedit.internal.annotation.MultiDirection;
import com.sk89q.worldedit.internal.annotation.OptionalArg;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import org.enginehub.piston.CommandManager;

View File

@ -19,10 +19,11 @@
package com.sk89q.worldedit.command.argument;
import com.fastasyncworldedit.core.object.brush.scroll.Scroll;
import com.fastasyncworldedit.core.command.tool.scroll.Scroll;
import com.google.common.collect.ImmutableSet;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.command.util.HookMode;
import com.sk89q.worldedit.extent.TracingExtent;
import com.sk89q.worldedit.util.SideEffect;
import com.sk89q.worldedit.util.TreeGenerator;
import org.enginehub.piston.CommandManager;
@ -58,6 +59,8 @@ public final class EnumConverter {
basic(HookMode.class));
commandManager.registerConverter(Key.of(Scroll.Action.class),
basic(Scroll.Action.class));
commandManager.registerConverter(Key.of(TracingExtent.Action.class),
basic(TracingExtent.Action.class));
}
private static <E extends Enum<E>> ArgumentConverter<E> basic(Class<E> enumClass) {

View File

@ -19,7 +19,7 @@
package com.sk89q.worldedit.command.argument;
import com.fastasyncworldedit.core.object.extent.SupplyingExtent;
import com.fastasyncworldedit.core.extent.SupplyingExtent;
import com.sk89q.worldedit.EmptyClipboardException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;

View File

@ -1,22 +1,3 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.command.argument;
import com.sk89q.worldedit.math.BlockVector3;

View File

@ -30,7 +30,9 @@ public enum SelectorChoice {
HULL,
POLYHEDRON,
LIST,
//FAWE start
FUZZY,
MAGIC,
POLYHEDRAL
//FAWE end
}

View File

@ -42,7 +42,9 @@ public class WorldConverter implements ArgumentConverter<World> {
commandManager.registerConverter(Key.of(World.class), WORLD_CONVERTER);
}
//FAWE start - Accessed by LocationConverter
public static final WorldConverter WORLD_CONVERTER = new WorldConverter();
//FAWE end
private final TextComponent choices;

View File

@ -17,5 +17,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* The following classes are FAWE additions:
*
* @see com.sk89q.worldedit.command.argument.ExpressionConverter
* @see com.sk89q.worldedit.command.argument.LocationConverter
*/
@org.enginehub.piston.util.NonnullByDefault
package com.sk89q.worldedit.command.argument;

View File

@ -0,0 +1,6 @@
/**
* The following classes are FAWE additions:
*
* @see com.sk89q.worldedit.command.HistorySubCommands
*/
package com.sk89q.worldedit.command;

View File

@ -36,7 +36,7 @@ import com.sk89q.worldedit.world.block.BlockTypes;
*/
public class AreaPickaxe implements BlockTool {
private int range;
private final int range;
public AreaPickaxe(int range) {
this.range = range;

View File

@ -30,9 +30,12 @@ import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.block.BaseBlock;
import javax.annotation.Nullable;
/**
* A mode that replaces one block.
*/
@ -50,11 +53,12 @@ public class BlockReplacer implements DoubleActionBlockTool {
}
@Override
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) {
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked, @Nullable Direction face) {
BlockBag bag = session.getBlockBag(player);
try (EditSession editSession = session.createEditSession(player, "BlockReplacer")) {
try (EditSession editSession = session.createEditSession(player)) {
try {
editSession.disableBuffering();
BlockVector3 position = clicked.toVector().toBlockPoint();
editSession.setBlock(position, pattern);
} catch (MaxChangedBlocksException ignored) {
@ -72,7 +76,7 @@ public class BlockReplacer implements DoubleActionBlockTool {
@Override
public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) {
public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked, @Nullable Direction face) {
BaseBlock targetBlock = player.getWorld().getFullBlock(clicked.toVector().toBlockPoint());
if (targetBlock != null) {

View File

@ -20,15 +20,15 @@
package com.sk89q.worldedit.command.tool;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.object.brush.BrushSettings;
import com.fastasyncworldedit.core.object.brush.MovableTool;
import com.fastasyncworldedit.core.object.brush.ResettableTool;
import com.fastasyncworldedit.core.object.brush.TargetMode;
import com.fastasyncworldedit.core.object.brush.scroll.Scroll;
import com.fastasyncworldedit.core.object.brush.scroll.ScrollTool;
import com.fastasyncworldedit.core.object.extent.ResettableExtent;
import com.fastasyncworldedit.core.object.mask.MaskedTargetBlock;
import com.fastasyncworldedit.core.object.pattern.PatternTraverser;
import com.fastasyncworldedit.core.command.tool.brush.BrushSettings;
import com.fastasyncworldedit.core.command.tool.MovableTool;
import com.fastasyncworldedit.core.command.tool.ResettableTool;
import com.fastasyncworldedit.core.command.tool.TargetMode;
import com.fastasyncworldedit.core.command.tool.scroll.Scroll;
import com.fastasyncworldedit.core.command.tool.scroll.ScrollTool;
import com.fastasyncworldedit.core.extent.ResettableExtent;
import com.fastasyncworldedit.core.function.mask.MaskedTargetBlock;
import com.fastasyncworldedit.core.function.pattern.PatternTraverser;
import com.fastasyncworldedit.core.util.BrushCache;
import com.fastasyncworldedit.core.util.MaskTraverser;
import com.fastasyncworldedit.core.util.StringMan;
@ -65,23 +65,25 @@ import static com.google.common.base.Preconditions.checkNotNull;
* Builds a shape at the place being looked at.
*/
public class BrushTool
implements DoubleActionTraceTool, ScrollTool, MovableTool, ResettableTool, Serializable {
//FAWE start - All implements but TraceTool
implements DoubleActionTraceTool, ScrollTool, MovableTool, ResettableTool, Serializable, TraceTool {
// TODO:
// Serialize methods
// serialize BrushSettings (primary and secondary only if different)
// set transient values e.g., context
public enum BrushAction {
enum BrushAction {
PRIMARY, SECONDARY
}
//FAWE end
protected static int MAX_RANGE = 500;
protected static int DEFAULT_RANGE = 240; // 500 is laggy as the default
protected int range = -1;
private TargetMode targetMode = TargetMode.TARGET_BLOCK_RANGE;
private Mask traceMask = null;
//FAWE start
protected static int DEFAULT_RANGE = 240; // 500 is laggy as the default
private TargetMode targetMode = TargetMode.TARGET_BLOCK_RANGE;
private int targetOffset;
private transient BrushSettings primary = new BrushSettings();
@ -89,6 +91,7 @@ public class BrushTool
private transient BrushSettings context = primary;
private transient BaseItem holder;
//FAWE end
/**
* Construct the tool.
@ -100,6 +103,7 @@ public class BrushTool
getContext().addPermission(permission);
}
//FAWE start
public BrushTool() {
}
@ -192,15 +196,6 @@ public class BrushTool
update();
}
/**
* Get the filter.
*
* @return the filter
*/
public Mask getMask() {
return getContext().getMask();
}
/**
* Get the filter.
*
@ -229,6 +224,16 @@ public class BrushTool
this.getContext().setMask(filter);
update();
}
//FAWE end
/**
* Get the filter.
*
* @return the filter
*/
public Mask getMask() {
return getContext().getMask();
}
/**
* Get the mask used for identifying where to stop traces.
@ -250,6 +255,7 @@ public class BrushTool
update();
}
//FAWE start
/**
* Set the block filter used for identifying blocks to replace.
*
@ -259,6 +265,7 @@ public class BrushTool
this.getContext().setSourceMask(filter);
update();
}
//FAWE end
/**
* Set the brush.
@ -267,11 +274,13 @@ public class BrushTool
* @param permission the permission
*/
public void setBrush(Brush brush, String permission) {
//FAWE start - We use our own logic
BrushSettings current = getContext();
current.clearPerms();
current.setBrush(brush);
current.addPermission(permission);
update();
//FAWE end
}
/**
@ -350,9 +359,12 @@ public class BrushTool
@Override
public boolean actPrimary(Platform server, LocalConfiguration config, Player player,
LocalSession session) {
//FAWE start - Use logic previously declared as FAWE-like
return act(BrushAction.PRIMARY, player, session);
//FAWE end
}
//FAWE start
public BlockVector3 getPosition(EditSession editSession, Player player) {
Location loc = player.getLocation();
switch (targetMode) {
@ -524,4 +536,5 @@ public class BrushTool
public boolean move(Player player) {
return false;
}
//FAWE end
}

View File

@ -20,7 +20,7 @@
package com.sk89q.worldedit.command.tool;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.object.collection.LocalBlockVectorSet;
import com.fastasyncworldedit.core.math.LocalBlockVectorSet;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
@ -120,8 +120,10 @@ public class FloatingTreeRemover implements BlockTool {
* @return a set containing all blocks in the tree/shroom or null if this is not a floating tree/shroom.
*/
private Set<BlockVector3> bfs(World world, BlockVector3 origin) {
//FAWE start - Use a LBVS over a HashMap & LinkedList
final LocalBlockVectorSet visited = new LocalBlockVectorSet();
final LocalBlockVectorSet queue = new LocalBlockVectorSet();
//FAWE end
queue.add(origin);
visited.add(origin);

View File

@ -77,11 +77,13 @@ public class FloodFillTool implements BlockTool {
try (EditSession editSession = session.createEditSession(player, "FloodFillTool")) {
try {
//FAWE start - Respect masks
Mask mask = initialType.toMask(editSession);
BlockReplace function = new BlockReplace(editSession, pattern);
RecursiveVisitor visitor = new RecursiveVisitor(mask, function, range);
visitor.visit(origin);
Operations.completeLegacy(visitor);
//FAWE end
} catch (MaxChangedBlocksException e) {
player.print(Caption.of("worldedit.tool.max-block-changes"));
} finally {

View File

@ -21,11 +21,18 @@ package com.sk89q.worldedit.command.tool;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.util.formatting.text.Component;
public class InvalidToolBindException extends WorldEditException {
private ItemType item;
private final ItemType item;
public InvalidToolBindException(ItemType item, Component msg) {
super(msg);
this.item = item;
}
@Deprecated
public InvalidToolBindException(ItemType item, String msg) {
super(msg);
this.item = item;

View File

@ -27,12 +27,17 @@ import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.util.Location;
//FAWE start - enum-ized
public enum NavigationWand implements DoubleActionTraceTool {
INSTANCE;
//FAWE end
private static final String PRIMARY_PERMISSION = "worldedit.navigation.thru.tool";
private static final String SECONDARY_PERMISSION = "worldedit.navigation.jumpto.tool";
@Override
public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
if (!player.hasPermission("worldedit.navigation.jumpto.tool")) {
if (!player.hasPermission(SECONDARY_PERMISSION)) {
return false;
}
final int maxDist = config.navigationWandMaxDistance;
@ -50,7 +55,7 @@ public enum NavigationWand implements DoubleActionTraceTool {
@Override
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
if (!player.hasPermission("worldedit.navigation.thru.tool")) {
if (!player.hasPermission(PRIMARY_PERMISSION)) {
return false;
}
final int maxDist = config.navigationWandMaxDistance;
@ -66,6 +71,6 @@ public enum NavigationWand implements DoubleActionTraceTool {
@Override
public boolean canUse(Actor actor) {
return actor.hasPermission("worldedit.navigation.jumpto.tool"); // check should be here
return actor.hasPermission(PRIMARY_PERMISSION) || actor.hasPermission(SECONDARY_PERMISSION);
}
}

View File

@ -19,7 +19,7 @@
package com.sk89q.worldedit.command.tool;
import com.fastasyncworldedit.core.object.mask.IdMask;
import com.fastasyncworldedit.core.function.mask.IdMask;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
@ -75,6 +75,7 @@ public class RecursivePickaxe implements BlockTool {
try (EditSession editSession = session.createEditSession(player, "RecursivePickaxe")) {
editSession.getSurvivalExtent().setToolUse(config.superPickaxeManyDrop);
//FAWE start
final int radius = (int) range;
final BlockReplace replace = new BlockReplace(editSession, (BlockTypes.AIR.getDefaultState()));
editSession.setMask(null);
@ -83,6 +84,7 @@ public class RecursivePickaxe implements BlockTool {
//visitor.visit(pos);
//Operations.completeBlindly(visitor);
recurse(server, editSession, world, pos, origin, radius, initialType, visitor.getVisited());
//FAWE end
editSession.flushQueue();
session.remember(editSession);
}

View File

@ -29,36 +29,46 @@ import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits;
import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.Location;
import org.apache.logging.log4j.Logger;
import javax.annotation.Nullable;
//FAWE start - enum-ized
public enum SelectionWand implements DoubleActionBlockTool {
INSTANCE;
//FAWE end
private static final Logger LOGGER = LogManagerCompat.getLogger();
@Override
public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) {
public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked, @Nullable Direction face) {
RegionSelector selector = session.getRegionSelector(player.getWorld());
BlockVector3 blockPoint = clicked.toVector().toBlockPoint();
if (selector.selectPrimary(blockPoint, ActorSelectorLimits.forActor(player))) {
//FAWE start
if (Settings.IMP.EXPERIMENTAL.OTHER) {
LOGGER.info("actSecondary Hit and about to explain with explainPrimarySelection");
}
//FAWE end
selector.explainPrimarySelection(player, session, blockPoint);
}
return true;
}
@Override
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) {
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked, @Nullable Direction face) {
RegionSelector selector = session.getRegionSelector(player.getWorld());
BlockVector3 blockPoint = clicked.toVector().toBlockPoint();
if (selector.selectSecondary(blockPoint, ActorSelectorLimits.forActor(player))) {
//FAWE start
if (Settings.IMP.EXPERIMENTAL.OTHER) {
LOGGER.info("actPrimary Hit and about to explain with explainSecondarySelection");
}
//FAWE end
selector.explainSecondarySelection(player, session, blockPoint);
}
return true;

View File

@ -28,11 +28,14 @@ import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import javax.annotation.Nullable;
/**
* A super pickaxe mode that removes one block.
*/
@ -44,7 +47,7 @@ public class SinglePickaxe implements BlockTool {
}
@Override
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) {
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked, @Nullable Direction face) {
World world = (World) clicked.getExtent();
BlockVector3 blockPoint = clicked.toBlockPoint();
final BlockType blockType = world.getBlock(blockPoint).getBlockType();

View File

@ -28,15 +28,18 @@ import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.TreeGenerator;
import javax.annotation.Nullable;
/**
* Plants a tree.
*/
public class TreePlanter implements BlockTool {
private TreeGenerator.TreeType treeType;
private final TreeGenerator.TreeType treeType;
public TreePlanter(TreeGenerator.TreeType treeType) {
this.treeType = treeType;
@ -48,7 +51,7 @@ public class TreePlanter implements BlockTool {
}
@Override
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) {
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked, @Nullable Direction face) {
try (EditSession editSession = session.createEditSession(player)) {
try {

View File

@ -33,7 +33,7 @@ import java.util.List;
public class ButcherBrush implements Brush {
private CreatureButcher flags;
private final CreatureButcher flags;
public ButcherBrush(CreatureButcher flags) {
this.flags = flags;

View File

@ -27,7 +27,7 @@ import com.sk89q.worldedit.world.block.BlockTypes;
public class CylinderBrush implements Brush {
private int height;
private final int height;
public CylinderBrush(int height) {
this.height = height;

View File

@ -36,6 +36,7 @@ public class GravityBrush implements Brush {
@Override
public void build(EditSession editSession, BlockVector3 position, Pattern pattern, double size) throws MaxChangedBlocksException {
//FAWE start - Ours operates differently to upstream, but does the same
double endY = position.getY() + size;
double startPerformY = Math.max(0, position.getY() - size);
double startCheckY = fullHeight ? 0 : startPerformY;
@ -54,5 +55,6 @@ public class GravityBrush implements Brush {
}
}
}
//FAWE end
}
}

View File

@ -27,7 +27,7 @@ import com.sk89q.worldedit.world.block.BlockTypes;
public class HollowCylinderBrush implements Brush {
private int height;
private final int height;
public HollowCylinderBrush(int height) {
this.height = height;

View File

@ -37,7 +37,7 @@ import javax.annotation.Nullable;
public class SmoothBrush implements Brush {
private final Mask mask;
private int iterations;
private final int iterations;
public SmoothBrush(int iterations) {
this(iterations, null);

View File

@ -36,10 +36,10 @@ import com.sk89q.worldedit.util.task.Supervisor;
import org.apache.logging.log4j.Logger;
import org.enginehub.piston.exception.CommandException;
import org.enginehub.piston.exception.CommandExecutionException;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.Callable;
import java.util.function.Consumer;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
@ -57,6 +57,8 @@ public final class AsyncCommandBuilder<T> {
private String description;
@Nullable
private Component delayMessage;
@Nullable
private Component workingMessage;
@Nullable
private Component successMessage;
@ -90,11 +92,22 @@ public final class AsyncCommandBuilder<T> {
return sendMessageAfterDelay(TextComponent.of(checkNotNull(message)));
}
@Deprecated
public AsyncCommandBuilder<T> sendMessageAfterDelay(Component message) {
return setDelayMessage(message);
}
public AsyncCommandBuilder<T> setDelayMessage(Component message) {
this.delayMessage = checkNotNull(message);
return this;
}
public AsyncCommandBuilder<T> setWorkingMessage(Component message) {
checkNotNull(this.delayMessage, "Must have a delay message if using a working message");
this.workingMessage = checkNotNull(message);
return this;
}
public AsyncCommandBuilder<T> onSuccess(@Nullable Component message, @Nullable Consumer<T> consumer) {
checkArgument(message != null || consumer != null, "Can't have null message AND consumer");
this.successMessage = message;
@ -145,7 +158,7 @@ public final class AsyncCommandBuilder<T> {
if (successMessage != null) {
sender.print(successMessage);
}
} catch (Exception orig) {
} catch (Throwable orig) {
Component failure = failureMessage != null ? failureMessage : TextComponent.of("An error occurred");
try {
if (exceptionConverter != null) {

View File

@ -146,7 +146,9 @@ public class EntityRemover {
EntityProperties registryType = entity.getFacet(EntityProperties.class);
if (registryType != null) {
if (type.matches(registryType)) {
//FAWE start - Calling this async violates thread safety
TaskManager.IMP.sync(entity::remove);
//FAWE end
return true;
}
}

View File

@ -25,6 +25,7 @@ import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import javax.annotation.Nullable;
import java.util.Timer;
import static com.google.common.base.Preconditions.checkNotNull;
@ -32,7 +33,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
public class FutureProgressListener implements Runnable {
private static final Timer timer = new Timer();
private static final int MESSAGE_DELAY = 1000;
private static final int MESSAGE_DELAY = 1000; // 1 second
private static final int MESSAGE_PERIOD = 10000; // 10 seconds
private final MessageTimerTask task;
@ -42,11 +44,15 @@ public class FutureProgressListener implements Runnable {
}
public FutureProgressListener(Actor sender, Component message) {
this(sender, message, null);
}
public FutureProgressListener(Actor sender, Component message, @Nullable Component workingMessage) {
checkNotNull(sender);
checkNotNull(message);
task = new MessageTimerTask(sender, message);
timer.schedule(task, MESSAGE_DELAY);
task = new MessageTimerTask(sender, message, workingMessage);
timer.scheduleAtFixedRate(task, MESSAGE_DELAY, MESSAGE_PERIOD);
}
@Override
@ -56,11 +62,15 @@ public class FutureProgressListener implements Runnable {
@Deprecated
public static void addProgressListener(ListenableFuture<?> future, Actor sender, String message) {
future.addListener(new FutureProgressListener(sender, message), MoreExecutors.directExecutor());
addProgressListener(future, sender, TextComponent.of(message));
}
public static void addProgressListener(ListenableFuture<?> future, Actor sender, Component message) {
future.addListener(new FutureProgressListener(sender, message), MoreExecutors.directExecutor());
}
public static void addProgressListener(ListenableFuture<?> future, Actor sender, Component message, Component workingMessage) {
future.addListener(new FutureProgressListener(sender, message, workingMessage), MoreExecutors.directExecutor());
}
}

View File

@ -23,6 +23,7 @@ import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import javax.annotation.Nullable;
import java.util.TimerTask;
import static com.google.common.base.Preconditions.checkNotNull;
@ -31,23 +32,35 @@ public class MessageTimerTask extends TimerTask {
private final Actor sender;
private final Component message;
@Nullable
private final Component workingMessage;
private boolean hasRunBefore = false;
@Deprecated
MessageTimerTask(Actor sender, String message) {
this(sender, TextComponent.of(message));
this(sender, TextComponent.of(message), null);
}
MessageTimerTask(Actor sender, Component message) {
MessageTimerTask(Actor sender, Component message, @Nullable Component workingMessage) {
checkNotNull(sender);
checkNotNull(message);
this.sender = sender;
this.message = message;
this.workingMessage = workingMessage;
}
@Override
public void run() {
sender.printDebug(message);
if (!hasRunBefore) {
sender.printDebug(message);
hasRunBefore = true;
} else if (workingMessage != null) {
sender.printDebug(workingMessage);
} else {
cancel();
}
}
}

View File

@ -31,7 +31,9 @@ public class PermissionCondition implements Command.Condition {
private static final Key<Actor> ACTOR_KEY = Key.of(Actor.class);
private final Set<String> permissions;
//FAWE start
private final boolean queued;
//FAWE end
public PermissionCondition(Set<String> permissions) {
this(permissions, true);
@ -54,7 +56,9 @@ public class PermissionCondition implements Command.Condition {
.orElse(false);
}
//FAWE start
public boolean isQueued() {
return queued;
}
//FAWE end
}

View File

@ -179,6 +179,7 @@ public final class SuggestionHelper {
return registry.keySet().stream().filter(search);
}
//FAWE start
/**
* Returns a stream of suggestions for positive doubles.
*
@ -231,4 +232,5 @@ public final class SuggestionHelper {
}
return true;
}
//FAWE end
}

View File

@ -42,7 +42,7 @@ public final class WorldEditAsyncCommandBuilder {
public static void createAndSendMessage(Actor actor, Callable<Component> task, @Nullable Component desc) {
final AsyncCommandBuilder<Component> builder = AsyncCommandBuilder.wrap(task, actor);
if (desc != null) {
builder.sendMessageAfterDelay(desc);
builder.setDelayMessage(desc);
}
builder
.onSuccess((String) null, actor::printInfo)

View File

@ -0,0 +1,16 @@
package com.sk89q.worldedit.command.util.annotation;
import com.fastasyncworldedit.core.regions.FaweMaskManager;
import org.enginehub.piston.inject.InjectAnnotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD})
@InjectAnnotation
public @interface AllowedRegion {
FaweMaskManager.MaskType value() default FaweMaskManager.MaskType.OWNER;
}

View File

@ -0,0 +1,39 @@
package com.sk89q.worldedit.command.util.annotation;
import com.fastasyncworldedit.core.configuration.Settings;
import com.sk89q.worldedit.command.util.annotation.Confirm;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import org.enginehub.piston.CommandParameters;
import org.enginehub.piston.exception.StopExecutionException;
import org.enginehub.piston.gen.CommandCallListener;
import org.enginehub.piston.inject.Key;
import java.lang.reflect.Method;
import java.util.Optional;
/**
* Logs called commands to a logger.
*/
public class ConfirmHandler implements CommandCallListener {
@Override
public void beforeCall(Method method, CommandParameters parameters) {
Confirm confirmAnnotation = method.getAnnotation(Confirm.class);
if (confirmAnnotation == null) {
return;
}
Optional<Actor> actorOpt = parameters.injectedValue(Key.of(Actor.class));
if (!actorOpt.isPresent()) {
return;
}
Actor actor = actorOpt.get();
// don't check confirmation if actor doesn't need to confirm
if (!Settings.IMP.getLimit(actor).CONFIRM_LARGE) {
return;
}
if (!confirmAnnotation.value().passes(actor, parameters, 1)) {
throw new StopExecutionException(TextComponent.empty());
}
}
}

View File

@ -0,0 +1,11 @@
package com.sk89q.worldedit.command.util.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Link {
Class clazz() default Link.class;
String value();
}

View File

@ -0,0 +1,17 @@
package com.sk89q.worldedit.command.util.annotation;
import org.enginehub.piston.inject.InjectAnnotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotates a {@code List<BlockState>} parameter to inject a list of BlockStates.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
@InjectAnnotation
public @interface PatternList {
}

View File

@ -0,0 +1,11 @@
package com.sk89q.worldedit.command.util.annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Step {
Class clazz() default Link.class;
double value() default 1;
}

View File

@ -0,0 +1,14 @@
package com.sk89q.worldedit.command.util.annotation;
import org.enginehub.piston.inject.InjectAnnotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.METHOD})
@InjectAnnotation
public @interface Time {
}

View File

@ -0,0 +1,12 @@
/**
* The following classes are FAWE additions:
*
* @see com.sk89q.worldedit.command.util.annotation.AllowedRegion
* @see com.sk89q.worldedit.command.util.annotation.Confirm
* @see com.sk89q.worldedit.command.util.annotation.ConfirmHandler
* @see com.sk89q.worldedit.command.util.annotation.Link
* @see com.sk89q.worldedit.command.util.annotation.PatternList
* @see com.sk89q.worldedit.command.util.annotation.Step
* @see com.sk89q.worldedit.command.util.annotation.Time
*/
package com.sk89q.worldedit.command.util.annotation;