3
0
Mirror von https://github.com/IntellectualSites/FastAsyncWorldEdit.git synchronisiert 2024-11-19 17:30:08 +01:00

Merge branch 'main' into feat/feature-placement

# Conflicts:
#	worldedit-core/src/main/java/com/sk89q/worldedit/LocalSession.java
Dieser Commit ist enthalten in:
dordsor21 2024-06-07 19:17:15 +01:00
Commit 0e87ee5185
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: 1E53E88969FFCF0B
34 geänderte Dateien mit 941 neuen und 214 gelöschten Zeilen

Datei anzeigen

@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Label conflicting PRs - name: Label conflicting PRs
uses: eps1lon/actions-label-merge-conflict@v3.0.1 uses: eps1lon/actions-label-merge-conflict@v3.0.2
with: with:
dirtyLabel: "unresolved-merge-conflict" dirtyLabel: "unresolved-merge-conflict"
repoToken: "${{ secrets.GITHUB_TOKEN }}" repoToken: "${{ secrets.GITHUB_TOKEN }}"

Datei anzeigen

@ -14,7 +14,7 @@ mapmanager = "1.8.0-SNAPSHOT"
griefprevention = "17.0.0" griefprevention = "17.0.0"
griefdefender = "2.1.0-SNAPSHOT" griefdefender = "2.1.0-SNAPSHOT"
residence = "4.5._13.1" residence = "4.5._13.1"
towny = "0.100.2.11" towny = "0.100.2.12"
plotsquared = "7.3.8" plotsquared = "7.3.8"
# Third party # Third party
@ -22,7 +22,7 @@ bstats = "3.0.2"
sparsebitset = "1.3" sparsebitset = "1.3"
parallelgzip = "1.0.5" parallelgzip = "1.0.5"
adventure = "4.17.0" adventure = "4.17.0"
adventure-bukkit = "4.3.2" adventure-bukkit = "4.3.3"
checkerqual = "3.43.0" checkerqual = "3.43.0"
truezip = "6.8.4" truezip = "6.8.4"
auto-value = "1.10.4" auto-value = "1.10.4"

Datei anzeigen

@ -12,6 +12,6 @@ repositories {
dependencies { dependencies {
// url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.4-R0.1-SNAPSHOT // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.4-R0.1-SNAPSHOT
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.4-R0.1-20240424.165410-174") the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.4-R0.1-20240528.102248-175")
compileOnly(libs.paperlib) compileOnly(libs.paperlib)
} }

Datei anzeigen

@ -12,6 +12,6 @@ repositories {
dependencies { dependencies {
// url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.6-R0.1-SNAPSHOT/ // url=https://repo.papermc.io/service/rest/repository/browse/maven-public/io/papermc/paper/dev-bundle/1.20.6-R0.1-SNAPSHOT/
the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.6-R0.1-20240526.222003-87") the<PaperweightUserDependenciesExtension>().paperDevBundle("1.20.6-R0.1-20240602.222958-106")
compileOnly(libs.paperlib) compileOnly(libs.paperlib)
} }

Datei anzeigen

@ -1,6 +1,5 @@
package com.fastasyncworldedit.bukkit.regions.plotsquared; package com.fastasyncworldedit.bukkit.regions.plotsquared;
import com.fastasyncworldedit.core.FaweAPI;
import com.fastasyncworldedit.core.configuration.Caption; import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.regions.FaweMask; import com.fastasyncworldedit.core.regions.FaweMask;
import com.fastasyncworldedit.core.regions.FaweMaskManager; import com.fastasyncworldedit.core.regions.FaweMaskManager;
@ -174,22 +173,21 @@ public class PlotSquaredFeature extends FaweMaskManager {
return null; return null;
} }
Region maskedRegion;
if (regions.size() == 1) {
final World world = player.getWorld(); final World world = player.getWorld();
int min = area != null ? area.getMinBuildHeight() : world.getMinY(); int min = area != null ? area.getMinBuildHeight() : world.getMinY();
// PlotSquared uses exclusive max height, WorldEdit uses inclusive max height -> subtract 1 // PlotSquared uses exclusive max height, WorldEdit uses inclusive max height -> subtract 1
int max = area != null ? Math.min(world.getMaxY(), area.getMaxBuildHeight() - 1) : world.getMaxY(); int max = area != null ? Math.min(world.getMaxY(), area.getMaxBuildHeight() - 1) : world.getMaxY();
Region maskedRegion;
if (regions.size() == 1) {
final CuboidRegion region = regions.iterator().next(); final CuboidRegion region = regions.iterator().next();
final BlockVector3 pos1 = BlockVector3.at(region.getMinimumX(), min, region.getMinimumZ()); final BlockVector3 pos1 = BlockVector3.at(region.getMinimumX(), min, region.getMinimumZ());
final BlockVector3 pos2 = BlockVector3.at(region.getMaximumX(), max, region.getMaximumZ()); final BlockVector3 pos2 = BlockVector3.at(region.getMaximumX(), max, region.getMaximumZ());
maskedRegion = new CuboidRegion(pos1, pos2); maskedRegion = new CuboidRegion(pos1, pos2);
} else { } else {
World world = FaweAPI.getWorld(area.getWorldName());
List<Region> weRegions = regions.stream().map( List<Region> weRegions = regions.stream().map(
r -> new CuboidRegion(world, BlockVector3.at(r.getMinimumX(), r.getMinimumY(), r.getMinimumZ()), r -> new CuboidRegion(world, BlockVector3.at(r.getMinimumX(), min, r.getMinimumZ()),
BlockVector3.at(r.getMaximumX(), r.getMaximumY(), r.getMaximumZ()) BlockVector3.at(r.getMaximumX(), max, r.getMaximumZ())
)).collect(Collectors.toList()); )).collect(Collectors.toList());
maskedRegion = new RegionIntersection(world, weRegions); maskedRegion = new RegionIntersection(world, weRegions);
} }

Datei anzeigen

@ -668,6 +668,13 @@ public class Settings extends Config {
@Comment({"The web interface for clipboards", " - All schematics are anonymous and private", " - Downloads can be deleted by the user", " - Supports clipboard uploads, downloads and saves",}) @Comment({"The web interface for clipboards", " - All schematics are anonymous and private", " - Downloads can be deleted by the user", " - Supports clipboard uploads, downloads and saves",})
public String URL = "https://schem.intellectualsites.com/fawe/"; public String URL = "https://schem.intellectualsites.com/fawe/";
@Comment({"The url of the backend server (Arkitektonika)"})
public String ARKITEKTONIKA_BACKEND_URL = "https://api.schematic.cloud/";
@Comment({"The url used to generate a download link from.", "{key} will be replaced with the generated key"})
public String ARKITEKTONIKA_DOWNLOAD_URL = "https://schematic.cloud/download/{key}";
@Comment({"The url used to generate a deletion link from.", "{key} will be replaced with the generated key"})
public String ARKITEKTONIKA_DELETE_URL = "https://schematic.cloud/delete/{key}";
@Comment("The maximum amount of time in seconds the plugin can attempt to load images for.") @Comment("The maximum amount of time in seconds the plugin can attempt to load images for.")
public int MAX_IMAGE_LOAD_TIME = 5; public int MAX_IMAGE_LOAD_TIME = 5;

Datei anzeigen

@ -58,7 +58,7 @@ public interface IBatchProcessor {
/** /**
* Utility method to trim a chunk based on min and max Y (inclusive). * Utility method to trim a chunk based on min and max Y (inclusive).
* *
* @param keepInsideRange if all blocks inside the range (inclusive) should be kept (default) * @param keepInsideRange if all blocks inside the range (inclusive) should be kept (default), or removed
* @return false if chunk is empty of blocks * @return false if chunk is empty of blocks
*/ */
default boolean trimY(IChunkSet set, int minY, int maxY, final boolean keepInsideRange) { default boolean trimY(IChunkSet set, int minY, int maxY, final boolean keepInsideRange) {
@ -74,16 +74,14 @@ public interface IBatchProcessor {
for (int i = 0; i < index; i++) { for (int i = 0; i < index; i++) {
arr[i] = BlockTypesCache.ReservedIDs.__RESERVED__; arr[i] = BlockTypesCache.ReservedIDs.__RESERVED__;
} }
} else {
arr = new char[4096];
}
set.setBlocks(layer, arr); set.setBlocks(layer, arr);
}
} else { } else {
set.setBlocks(layer, null); set.setBlocks(layer, null);
} }
} }
} }
for (int layer = maxLayer; layer < set.getMaxSectionPosition(); layer++) { for (int layer = maxLayer; layer <= set.getMaxSectionPosition(); layer++) {
if (set.hasSection(layer)) { if (set.hasSection(layer)) {
if (layer == maxLayer) { if (layer == maxLayer) {
char[] arr = set.loadIfPresent(layer); char[] arr = set.loadIfPresent(layer);
@ -92,10 +90,8 @@ public interface IBatchProcessor {
for (int i = index; i < arr.length; i++) { for (int i = index; i < arr.length; i++) {
arr[i] = BlockTypesCache.ReservedIDs.__RESERVED__; arr[i] = BlockTypesCache.ReservedIDs.__RESERVED__;
} }
} else {
arr = new char[4096];
}
set.setBlocks(layer, arr); set.setBlocks(layer, arr);
}
} else { } else {
set.setBlocks(layer, null); set.setBlocks(layer, null);
} }

Datei anzeigen

@ -222,7 +222,7 @@ public class ThreadUnsafeCharBlocks implements IChunkSet, IBlocks {
} }
public void set(int x, int y, int z, char value) { public void set(int x, int y, int z, char value) {
final int layer = y >> 4; final int layer = (y >> 4) - minSectionPosition;
final int index = (y & 15) << 8 | z << 4 | x; final int index = (y & 15) << 8 | z << 4 | x;
try { try {
blocks[layer][index] = value; blocks[layer][index] = value;

Datei anzeigen

@ -59,12 +59,12 @@ public class UpdateNotification {
Document doc = db.parse(body); Document doc = db.parse(body);
faweVersion = doc.getElementsByTagName("lastSuccessfulBuild").item(0).getFirstChild().getTextContent(); faweVersion = doc.getElementsByTagName("lastSuccessfulBuild").item(0).getFirstChild().getTextContent();
FaweVersion faweVersion = Fawe.instance().getVersion(); FaweVersion faweVersion = Fawe.instance().getVersion();
if (faweVersion.build == 0 && !faweVersion.snapshot) { if (faweVersion.build == 0 && faweVersion.snapshot) {
LOGGER.warn("You are using a snapshot or a custom version of FAWE. This is not an official build distributed " + LOGGER.warn("You are using a snapshot or a custom version of FAWE. This is not an official build distributed " +
"via https://www.spigotmc.org/resources/13932/"); "via https://www.spigotmc.org/resources/13932/");
return; return;
} }
if (faweVersion.build < Integer.parseInt(UpdateNotification.faweVersion)) { if (faweVersion.snapshot && faweVersion.build < Integer.parseInt(UpdateNotification.faweVersion)) {
hasUpdate = true; hasUpdate = true;
int versionDifference = Integer.parseInt(UpdateNotification.faweVersion) - faweVersion.build; int versionDifference = Integer.parseInt(UpdateNotification.faweVersion) - faweVersion.build;
LOGGER.warn( LOGGER.warn(

Datei anzeigen

@ -0,0 +1,4 @@
package com.fastasyncworldedit.core.util.arkitektonika;
public record ArkitektonikaResponse(String downloadKey, String deletionKey) {
}

Datei anzeigen

@ -0,0 +1,58 @@
package com.fastasyncworldedit.core.util.arkitektonika;
import com.fastasyncworldedit.core.internal.exception.FaweException;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.sk89q.worldedit.extent.clipboard.io.share.ClipboardShareMetadata;
import com.sk89q.worldedit.extent.clipboard.io.share.ShareOutputProvider;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.UUID;
public class ArkitektonikaSchematicUploader {
private static final String BOUNDARY_IDENTIFIER = "--";
private static final HttpClient HTTP_CLIENT = HttpClient.newHttpClient();
private final String apiUrl;
public ArkitektonikaSchematicUploader(String apiUrl) {
this.apiUrl = apiUrl.endsWith("/") ? apiUrl.substring(0, apiUrl.length() - 1) : apiUrl;
}
public ArkitektonikaResponse uploadBlocking(ClipboardShareMetadata meta, ShareOutputProvider provider) throws IOException,
InterruptedException {
String boundary = UUID.randomUUID().toString();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
provider.writeTo(outputStream);
final HttpRequest.BodyPublisher bodyPublisher = HttpRequest.BodyPublishers.concat(
HttpRequest.BodyPublishers.ofString(BOUNDARY_IDENTIFIER + boundary + "\r\n"),
HttpRequest.BodyPublishers.ofString("Content-Disposition: form-data; name=\"schematic\"; filename=\"" + meta.name() + "." + meta.format().getPrimaryFileExtension() + "\"\r\n\r\n"),
HttpRequest.BodyPublishers.ofByteArray(outputStream.toByteArray()),
HttpRequest.BodyPublishers.ofString("\r\n" + BOUNDARY_IDENTIFIER + boundary + BOUNDARY_IDENTIFIER)
);
final HttpResponse<String> response = HTTP_CLIENT.send(HttpRequest.newBuilder()
.uri(URI.create(this.apiUrl + "/upload"))
.header("Content-Type", "multipart/form-data; boundary=\"" + boundary + "\"")
.POST(bodyPublisher).build(), HttpResponse.BodyHandlers.ofString());
if (response.statusCode() != 200) {
throw new FaweException(TextComponent
.of("Arkitektonika returned status code " + response.statusCode())
.color(TextColor.RED));
}
JsonObject json = JsonParser.parseString(response.body()).getAsJsonObject();
return new ArkitektonikaResponse(
json.get("download_key").getAsString(),
json.get("delete_key").getAsString()
);
}
}

Datei anzeigen

@ -0,0 +1,61 @@
package com.fastasyncworldedit.core.util.gson;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.util.concurrency.LazyReference;
import com.sk89q.worldedit.util.nbt.TagStringIO;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.item.ItemTypes;
import java.io.IOException;
import java.lang.reflect.Type;
public final class BaseItemAdapter implements JsonDeserializer<BaseItem>, JsonSerializer<BaseItem> {
@Override
public BaseItem deserialize(JsonElement json, Type type, JsonDeserializationContext cont) throws JsonParseException {
JsonObject jsonObject = json.getAsJsonObject();
JsonElement id = jsonObject.get("id");
if (id != null) {
ItemType itemType = ItemTypes.get(id.getAsString());
if (itemType == null) {
throw new JsonParseException("Could not parse item type `" + id + "`");
}
return new BaseItem(itemType);
}
ItemType itemType = cont.deserialize(jsonObject.get("itemType").getAsJsonObject(), ItemType.class);
JsonElement nbt = jsonObject.get("nbt");
if (nbt == null) {
return new BaseItem(itemType);
}
try {
return new BaseItem(itemType, LazyReference.computed(TagStringIO.get().asCompound(nbt.getAsString())));
} catch (IOException e) {
throw new JsonParseException("Could not deserialize BaseItem", e);
}
}
@Override
public JsonElement serialize(
final BaseItem baseItem,
final Type type,
final JsonSerializationContext jsonSerializationContext
) {
JsonObject obj = new JsonObject();
obj.add("itemType", jsonSerializationContext.serialize(baseItem.getType()));
try {
obj.add("nbt", baseItem.getNbt() == null ? null : new JsonPrimitive(TagStringIO.get().asString(baseItem.getNbt())));
return obj;
} catch (IOException e) {
throw new JsonParseException("Could not deserialize BaseItem", e);
}
}
}

Datei anzeigen

@ -52,6 +52,7 @@ import com.sk89q.worldedit.command.tool.SelectionWand;
import com.sk89q.worldedit.command.tool.SinglePickaxe; import com.sk89q.worldedit.command.tool.SinglePickaxe;
import com.sk89q.worldedit.command.tool.Tool; import com.sk89q.worldedit.command.tool.Tool;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Locatable; import com.sk89q.worldedit.extension.platform.Locatable;
import com.sk89q.worldedit.extent.NullExtent; import com.sk89q.worldedit.extent.NullExtent;
@ -80,7 +81,6 @@ import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BaseBlock; import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState; import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.item.ItemType; import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.item.ItemTypes;
import com.sk89q.worldedit.world.snapshot.experimental.Snapshot; import com.sk89q.worldedit.world.snapshot.experimental.Snapshot;
import com.zaxxer.sparsebits.SparseBitSet; import com.zaxxer.sparsebits.SparseBitSet;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@ -182,8 +182,10 @@ public class LocalSession implements TextureHolder {
private String lastScript; private String lastScript;
private RegionSelectorType defaultSelector; private RegionSelectorType defaultSelector;
private boolean useServerCUI = false; // Save this to not annoy players. private boolean useServerCUI = false; // Save this to not annoy players.
private ItemType wandItem; //FAWE start - allow NBT
private ItemType navWandItem; private BaseItem wandItem;
private BaseItem navWandItem;
//FAWE end
/** /**
* Construct the object. * Construct the object.
@ -1199,7 +1201,7 @@ public class LocalSession implements TextureHolder {
tool = tools.get(item.getInternalId()); tool = tools.get(item.getInternalId());
} }
if (tool == SelectionWand.INSTANCE && !SelectionWand.INSTANCE.canUse(player)) { if (tool == SelectionWand.INSTANCE && !SelectionWand.INSTANCE.canUse(player)) {
tools.remove(wandItem.getInternalId()); tools.remove(wandItem.getType().getInternalId());
loadDefaults(player, true); // Permissions have changed so redo the player's current tools. loadDefaults(player, true); // Permissions have changed so redo the player's current tools.
return null; return null;
} }
@ -1253,18 +1255,20 @@ public class LocalSession implements TextureHolder {
if (loadDefaults || force) { if (loadDefaults || force) {
loadDefaults = false; loadDefaults = false;
LocalConfiguration config = WorldEdit.getInstance().getConfiguration(); LocalConfiguration config = WorldEdit.getInstance().getConfiguration();
ParserContext context = new ParserContext();
context.setActor(actor);
if (wandItem == null) { if (wandItem == null) {
wandItem = ItemTypes.parse(config.wandItem); wandItem = WorldEdit.getInstance().getItemFactory().parseFromInput(config.wandItem, context);
} }
if (navWandItem == null) { if (navWandItem == null) {
navWandItem = ItemTypes.parse(config.navigationWand); navWandItem = WorldEdit.getInstance().getItemFactory().parseFromInput(config.navigationWand, context);
} }
synchronized (this.tools) { synchronized (this.tools) {
if (tools.get(navWandItem.getInternalId()) == null && NavigationWand.INSTANCE.canUse(actor)) { if (tools.get(navWandItem.getType().getInternalId()) == null && NavigationWand.INSTANCE.canUse(actor)) {
tools.put(navWandItem.getInternalId(), NavigationWand.INSTANCE); tools.put(navWandItem.getType().getInternalId(), NavigationWand.INSTANCE);
} }
if (tools.get(wandItem.getInternalId()) == null && SelectionWand.INSTANCE.canUse(actor)) { if (tools.get(wandItem.getType().getInternalId()) == null && SelectionWand.INSTANCE.canUse(actor)) {
tools.put(wandItem.getInternalId(), SelectionWand.INSTANCE); tools.put(wandItem.getType().getInternalId(), SelectionWand.INSTANCE);
} }
} }
} }
@ -1334,10 +1338,24 @@ public class LocalSession implements TextureHolder {
* @param item the item type * @param item the item type
* @param tool the tool to set, which can be {@code null} * @param tool the tool to set, which can be {@code null}
* @throws InvalidToolBindException if the item can't be bound to that item * @throws InvalidToolBindException if the item can't be bound to that item
* @deprecated use {@link #setTool(BaseItem, Tool)}
*/ */
@Deprecated
public void setTool(ItemType item, @Nullable Tool tool) throws InvalidToolBindException { public void setTool(ItemType item, @Nullable Tool tool) throws InvalidToolBindException {
if (item.hasBlockType()) { setTool(new BaseItem(item), tool);
throw new InvalidToolBindException(item, Caption.of("worldedit.error.blocks-cant-be-used")); }
/**
* Set the tool.
*
* @param item the item type
* @param tool the tool to set, which can be {@code null}
* @throws InvalidToolBindException if the item can't be bound to that item
* @since TODO
*/
public void setTool(BaseItem item, @Nullable Tool tool) throws InvalidToolBindException {
if (item.getType().hasBlockType()) {
throw new InvalidToolBindException(item.getType(), Caption.of("worldedit.error.blocks-cant-be-used"));
} }
if (tool instanceof SelectionWand) { if (tool instanceof SelectionWand) {
changeTool(this.wandItem, this.wandItem = item, tool); changeTool(this.wandItem, this.wandItem = item, tool);
@ -1348,7 +1366,7 @@ public class LocalSession implements TextureHolder {
setDirty(); setDirty();
return; return;
} }
setTool(item.getDefaultState(), tool, null); setTool(item, tool, null);
} }
public void setTool(Player player, @Nullable Tool tool) throws InvalidToolBindException { public void setTool(Player player, @Nullable Tool tool) throws InvalidToolBindException {
@ -1356,17 +1374,17 @@ public class LocalSession implements TextureHolder {
setTool(item, tool, player); setTool(item, tool, player);
} }
private void changeTool(ItemType oldType, ItemType newType, Tool newTool) { private void changeTool(BaseItem oldItem, BaseItem newItem, Tool newTool) {
if (oldType != null) { if (oldItem != null) {
synchronized (this.tools) { synchronized (this.tools) {
this.tools.remove(oldType.getInternalId()); this.tools.remove(oldItem.getType().getInternalId());
} }
} }
synchronized (this.tools) { synchronized (this.tools) {
if (newTool == null) { if (newTool == null) {
this.tools.remove(newType.getInternalId()); this.tools.remove(newItem.getType().getInternalId());
} else { } else {
this.tools.put(newType.getInternalId(), newTool); this.tools.put(newItem.getType().getInternalId(), newTool);
} }
} }
} }
@ -1376,11 +1394,11 @@ public class LocalSession implements TextureHolder {
if (type.hasBlockType() && type.getBlockType().getMaterial().isAir()) { if (type.hasBlockType() && type.getBlockType().getMaterial().isAir()) {
throw new InvalidToolBindException(type, Caption.of("worldedit.error.blocks-cant-be-used")); throw new InvalidToolBindException(type, Caption.of("worldedit.error.blocks-cant-be-used"));
} else if (tool instanceof SelectionWand) { } else if (tool instanceof SelectionWand) {
changeTool(this.wandItem, this.wandItem = item.getType(), tool); changeTool(this.wandItem, this.wandItem = item, tool);
setDirty(); setDirty();
return; return;
} else if (tool instanceof NavigationWand) { } else if (tool instanceof NavigationWand) {
changeTool(this.navWandItem, this.navWandItem = item.getType(), tool); changeTool(this.navWandItem, this.navWandItem = item, tool);
setDirty(); setDirty();
return; return;
} }
@ -1877,20 +1895,46 @@ public class LocalSession implements TextureHolder {
* Get the preferred wand item for this user, or {@code null} to use the default * Get the preferred wand item for this user, or {@code null} to use the default
* *
* @return item id of wand item, or {@code null} * @return item id of wand item, or {@code null}
* @deprecated use {@link #getWandBaseItem()}
*/ */
@Deprecated
public String getWandItem() { public String getWandItem() {
return wandItem.id(); return wandItem.getType().id();
} }
/** /**
* Get the preferred navigation wand item for this user, or {@code null} to use the default * Get the preferred navigation wand item for this user, or {@code null} to use the default
* *
* @return item id of nav wand item, or {@code null} * @return item id of nav wand item, or {@code null}
* @deprecated use {@link #getNavWandBaseItem()}
*/ */
@Deprecated
public String getNavWandItem() { public String getNavWandItem() {
return navWandItem.id(); return navWandItem.getType().id();
} }
//FAWE start
/**
* Get the preferred wand item for this user, or {@code null} to use the default
*
* @return item id of wand item, or {@code null}
* @since TODO
*/
public BaseItem getWandBaseItem() {
return wandItem == null ? null : new BaseItem(wandItem.getType(), wandItem.getNbtReference());
}
/**
* Get the preferred navigation wand item for this user, or {@code null} to use the default
*
* @return item id of nav wand item, or {@code null}
* @since TODO
*/
public BaseItem getNavWandBaseItem() {
return navWandItem == null ? null : new BaseItem(navWandItem.getType(), navWandItem.getNbtReference());
}
//FAWE end
/** /**
* Get the last block distribution stored in this session. * Get the last block distribution stored in this session.
* *

Datei anzeigen

@ -71,6 +71,7 @@ public class BaseItem implements NbtValued {
* @param itemType The type to set * @param itemType The type to set
*/ */
public void setType(ItemType itemType) { public void setType(ItemType itemType) {
checkNotNull(itemType);
this.itemType = itemType; this.itemType = itemType;
} }

Datei anzeigen

@ -340,7 +340,7 @@ public class ClipboardCommands {
aliases = {"/download"}, aliases = {"/download"},
desc = "Downloads your clipboard through the configured web interface" desc = "Downloads your clipboard through the configured web interface"
) )
@Deprecated @Deprecated(forRemoval = true, since = "TODO")
@CommandPermissions({"worldedit.clipboard.download"}) @CommandPermissions({"worldedit.clipboard.download"})
public void download( public void download(
final Actor actor, final Actor actor,
@ -402,10 +402,7 @@ public class ClipboardCommands {
final Clipboard target; final Clipboard target;
// If we have a transform, bake it into the copy // If we have a transform, bake it into the copy
if (!transform.isIdentity()) { if (!transform.isIdentity()) {
final FlattenedClipboardTransform result = FlattenedClipboardTransform.transform(clipboard, transform); target = clipboard.transform(transform);
target = new BlockArrayClipboard(result.getTransformedRegion(), actor.getUniqueId());
target.setOrigin(clipboard.getOrigin());
Operations.completeLegacy(result.copyTo(target));
} else { } else {
target = clipboard; target = clipboard;
} }

Datei anzeigen

@ -26,7 +26,6 @@ import com.fastasyncworldedit.core.extent.clipboard.MultiClipboardHolder;
import com.fastasyncworldedit.core.extent.clipboard.URIClipboardHolder; import com.fastasyncworldedit.core.extent.clipboard.URIClipboardHolder;
import com.fastasyncworldedit.core.extent.clipboard.io.schematic.MinecraftStructure; import com.fastasyncworldedit.core.extent.clipboard.io.schematic.MinecraftStructure;
import com.fastasyncworldedit.core.util.MainUtil; import com.fastasyncworldedit.core.util.MainUtil;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.sk89q.worldedit.LocalConfiguration; import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
@ -38,13 +37,13 @@ import com.sk89q.worldedit.command.util.CommandPermissions;
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability; import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader; import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.extent.clipboard.io.share.ClipboardShareDestination;
import com.sk89q.worldedit.extent.clipboard.io.share.ClipboardShareMetadata;
import com.sk89q.worldedit.internal.util.LogManagerCompat; import com.sk89q.worldedit.internal.util.LogManagerCompat;
import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.math.transform.Transform;
@ -61,19 +60,15 @@ import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldedit.util.io.Closer; import com.sk89q.worldedit.util.io.Closer;
import com.sk89q.worldedit.util.io.file.FilenameException; import com.sk89q.worldedit.util.io.file.FilenameException;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import com.sk89q.worldedit.util.paste.EngineHubPaste;
import com.sk89q.worldedit.util.paste.PasteMetadata;
import org.enginehub.piston.annotation.Command; import org.enginehub.piston.annotation.Command;
import org.enginehub.piston.annotation.CommandContainer; import org.enginehub.piston.annotation.CommandContainer;
import org.enginehub.piston.annotation.param.Arg; import org.enginehub.piston.annotation.param.Arg;
import org.enginehub.piston.annotation.param.ArgFlag; import org.enginehub.piston.annotation.param.ArgFlag;
import org.enginehub.piston.annotation.param.Switch; import org.enginehub.piston.annotation.param.Switch;
import org.enginehub.piston.exception.CommandException;
import org.enginehub.piston.exception.StopExecutionException; import org.enginehub.piston.exception.StopExecutionException;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.BufferedOutputStream; import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -85,11 +80,9 @@ import java.net.URL;
import java.nio.channels.Channels; import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel; import java.nio.channels.ReadableByteChannel;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Base64;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
@ -98,6 +91,7 @@ import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
import java.util.function.Consumer;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Function; import java.util.function.Function;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -321,7 +315,7 @@ public class SchematicCommands {
Actor actor, LocalSession session, Actor actor, LocalSession session,
@Arg(desc = "File name.") @Arg(desc = "File name.")
String filename, String filename,
//FAWE start - random rotation //FAWE start - use format-name, random rotation
@Arg(desc = "Format name.", def = "") @Arg(desc = "Format name.", def = "")
String formatName, String formatName,
@Switch(name = 'r', desc = "Apply random rotation to the clipboard") @Switch(name = 'r', desc = "Apply random rotation to the clipboard")
@ -445,8 +439,8 @@ public class SchematicCommands {
Actor actor, LocalSession session, Actor actor, LocalSession session,
@Arg(desc = "File name.") @Arg(desc = "File name.")
String filename, String filename,
@Arg(desc = "Format name.", def = "fast") @Arg(desc = "Format name.", def = "fast") //FAWE: def: sponge -> fast
String formatName, ClipboardFormat format,
@Switch(name = 'f', desc = "Overwrite an existing file.") @Switch(name = 'f', desc = "Overwrite an existing file.")
boolean allowOverwrite, boolean allowOverwrite,
//FAWE start //FAWE start
@ -474,12 +468,6 @@ public class SchematicCommands {
dir = new File(dir, actor.getUniqueId().toString()); dir = new File(dir, actor.getUniqueId().toString());
} }
ClipboardFormat format = ClipboardFormats.findByAlias(formatName);
if (format == null) {
actor.print(Caption.of("worldedit.schematic.unknown-format", TextComponent.of(formatName)));
return;
}
boolean other = false; boolean other = false;
if (filename.contains("../")) { if (filename.contains("../")) {
other = true; other = true;
@ -552,34 +540,97 @@ public class SchematicCommands {
public void share(Actor actor, LocalSession session, public void share(Actor actor, LocalSession session,
@Arg(desc = "Schematic name. Defaults to name-millis", def = "") @Arg(desc = "Schematic name. Defaults to name-millis", def = "")
String schematicName, String schematicName,
@Arg(desc = "Format name.", def = "sponge") @Arg(desc = "Share location", def = "arkitektonika") //FAWE: def: ehpaste -> arkitektonika
String formatName) throws WorldEditException { ClipboardShareDestination destination,
if (true) { @Arg(desc = "Format name", def = "fast") //FAWE: def: sponge -> fast
throw new UnsupportedOperationException("This feature is currently not implemented"); ClipboardFormat format) throws WorldEditException {
}
if (worldEdit.getPlatformManager().queryCapability(Capability.GAME_HOOKS).getDataVersion() == -1) { if (worldEdit.getPlatformManager().queryCapability(Capability.GAME_HOOKS).getDataVersion() == -1) {
actor.printError(TranslatableComponent.of("worldedit.schematic.unsupported-minecraft-version")); actor.printError(TranslatableComponent.of("worldedit.schematic.unsupported-minecraft-version"));
return; return;
} }
ClipboardFormat format = ClipboardFormats.findByAlias(formatName);
if (format == null) { if (format == null) {
actor.printError(TranslatableComponent.of("worldedit.schematic.unknown-format", TextComponent.of(formatName))); format = destination.getDefaultFormat();
}
if (!destination.supportsFormat(format)) {
actor.printError(Caption.of( //FAWE: TranslatableComponent -> Caption
"worldedit.schematic.share.unsupported-format",
TextComponent.of(destination.getName()),
TextComponent.of(format.getName())
));
return; return;
} }
ClipboardHolder holder = session.getClipboard(); ClipboardHolder holder = session.getClipboard();
SchematicShareTask task = new SchematicShareTask(actor, format, holder, schematicName); SchematicShareTask task = new SchematicShareTask(actor, holder, destination, format, schematicName);
AsyncCommandBuilder.wrap(task, actor) AsyncCommandBuilder.wrap(task, actor)
.registerWithSupervisor(worldEdit.getSupervisor(), "Sharing schematic") .registerWithSupervisor(worldEdit.getSupervisor(), "Sharing schematic")
.setDelayMessage(TranslatableComponent.of("worldedit.schematic.save.saving")) .setDelayMessage(TranslatableComponent.of("worldedit.schematic.save.saving"))
.setWorkingMessage(TranslatableComponent.of("worldedit.schematic.save.still-saving")) .setWorkingMessage(TranslatableComponent.of("worldedit.schematic.save.still-saving"))
.onSuccess("Shared", (url -> actor.printInfo(TextComponent.of(url.toExternalForm() + ".schem").clickEvent(ClickEvent.openUrl(url.toExternalForm() + ".schem"))))) .onSuccess("Shared", (consumer -> consumer.accept(actor)))
.onFailure("Failed to share schematic", worldEdit.getPlatformManager().getPlatformCommandManager().getExceptionConverter()) .onFailure("Failed to share schematic", worldEdit.getPlatformManager().getPlatformCommandManager().getExceptionConverter())
.buildAndExec(worldEdit.getExecutorService()); .buildAndExec(worldEdit.getExecutorService());
} }
@Command(
name = "delete",
aliases = {"d"},
desc = "Delete a saved schematic"
)
@CommandPermissions("worldedit.schematic.delete")
public void delete(
Actor actor, LocalSession session,
@Arg(desc = "File name.")
String filename
) throws WorldEditException, IOException {
LocalConfiguration config = worldEdit.getConfiguration();
//FAWE start
File working = worldEdit.getWorkingDirectoryPath(config.saveDir).toFile();
File dir = Settings.settings().PATHS.PER_PLAYER_SCHEMATICS ? new File(working, actor.getUniqueId().toString()) : working;
List<File> files = new ArrayList<>();
if (filename.equalsIgnoreCase("*")) {
files.addAll(getFiles(session.getClipboard()));
} else {
File f = MainUtil.resolveRelative(new File(dir, filename));
files.add(f);
}
if (files.isEmpty()) {
actor.print(Caption.of("worldedit.schematic.delete.does-not-exist", TextComponent.of(filename)));
return;
}
for (File f : files) {
if (!MainUtil.isInSubDirectory(working, f) || !f.exists()) {
actor.print(Caption.of("worldedit.schematic.delete.does-not-exist", TextComponent.of(filename)));
continue;
}
if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && !MainUtil.isInSubDirectory(dir, f) && !actor.hasPermission(
"worldedit.schematic.delete.other")) {
actor.print(Caption.of("fawe.error.no-perm", "worldedit.schematic.delete.other"));
continue;
}
if (!deleteFile(f)) {
actor.print(Caption.of("worldedit.schematic.delete.failed", TextComponent.of(filename)));
continue;
}
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();
return true;
}
return false;
}
//FAWE end
@Command( @Command(
name = "formats", name = "formats",
aliases = {"listformats", "f"}, aliases = {"listformats", "f"},
@ -764,68 +815,11 @@ public class SchematicCommands {
} }
@Command(
name = "delete",
aliases = {"d"},
desc = "Delete a saved schematic"
)
@CommandPermissions("worldedit.schematic.delete")
public void delete(
Actor actor, LocalSession session,
@Arg(desc = "File name.")
String filename
) throws WorldEditException, IOException {
LocalConfiguration config = worldEdit.getConfiguration();
File working = worldEdit.getWorkingDirectoryPath(config.saveDir).toFile();
//FAWE start
File dir = Settings.settings().PATHS.PER_PLAYER_SCHEMATICS ? new File(working, actor.getUniqueId().toString()) : working;
List<File> files = new ArrayList<>();
if (filename.equalsIgnoreCase("*")) {
files.addAll(getFiles(session.getClipboard()));
} else {
File f = MainUtil.resolveRelative(new File(dir, filename));
files.add(f);
}
if (files.isEmpty()) {
actor.print(Caption.of("worldedit.schematic.delete.does-not-exist", TextComponent.of(filename)));
return;
}
for (File f : files) {
if (!MainUtil.isInSubDirectory(working, f) || !f.exists()) {
actor.print(Caption.of("worldedit.schematic.delete.does-not-exist", TextComponent.of(filename)));
continue;
}
if (Settings.settings().PATHS.PER_PLAYER_SCHEMATICS && !MainUtil.isInSubDirectory(dir, f) && !actor.hasPermission(
"worldedit.schematic.delete.other")) {
actor.print(Caption.of("fawe.error.no-perm", "worldedit.schematic.delete.other"));
continue;
}
if (!deleteFile(f)) {
actor.print(Caption.of("worldedit.schematic.delete.failed", TextComponent.of(filename)));
continue;
}
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();
return true;
}
return false;
}
//FAWE end
private static class SchematicLoadTask implements Callable<ClipboardHolder> { private static class SchematicLoadTask implements Callable<ClipboardHolder> {
private final Actor actor; private final Actor actor;
private final ClipboardFormat format;
private final File file; private final File file;
private final ClipboardFormat format;
SchematicLoadTask(Actor actor, File file, ClipboardFormat format) { SchematicLoadTask(Actor actor, File file, ClipboardFormat format) {
this.actor = actor; this.actor = actor;
@ -863,19 +857,10 @@ public class SchematicCommands {
this.holder = holder; this.holder = holder;
} }
protected void writeToOutputStream(OutputStream outputStream) throws Exception { protected void writeToOutputStream(OutputStream outputStream) throws IOException, WorldEditException {
Clipboard clipboard = holder.getClipboard(); Clipboard clipboard = holder.getClipboard();
Transform transform = holder.getTransform(); Transform transform = holder.getTransform();
Clipboard target; Clipboard target = clipboard.transform(transform);
// If we have a transform, bake it into the copy
if (transform.isIdentity()) {
target = clipboard;
} else {
FlattenedClipboardTransform result = FlattenedClipboardTransform.transform(clipboard, transform);
target = new BlockArrayClipboard(result.getTransformedRegion());
target.setOrigin(clipboard.getOrigin());
Operations.completeLegacy(result.copyTo(target));
}
try (Closer closer = Closer.create()) { try (Closer closer = Closer.create()) {
OutputStream stream = closer.register(outputStream); OutputStream stream = closer.register(outputStream);
@ -887,9 +872,10 @@ public class SchematicCommands {
} }
private static class SchematicSaveTask extends SchematicOutputTask<Void> { private static class SchematicSaveTask extends SchematicOutputTask<Void> {
private File file; private final Actor actor;
private File file; //FAWE: un-finalize
private final boolean overwrite; private final boolean overwrite;
private final File rootDir; private final File rootDir; //FAWE: add root-dir
SchematicSaveTask( SchematicSaveTask(
Actor actor, Actor actor,
@ -900,9 +886,10 @@ public class SchematicCommands {
boolean overwrite boolean overwrite
) { ) {
super(actor, format, holder); super(actor, format, holder);
this.actor = actor;
this.file = file; this.file = file;
this.rootDir = rootDir;
this.overwrite = overwrite; this.overwrite = overwrite;
this.rootDir = rootDir; //FAWE: add root-dir
} }
@Override @Override
@ -975,10 +962,7 @@ public class SchematicCommands {
if (transform.isIdentity()) { if (transform.isIdentity()) {
target = clipboard; target = clipboard;
} else { } else {
FlattenedClipboardTransform result = FlattenedClipboardTransform.transform(clipboard, transform); target = clipboard.transform(transform);
target = new BlockArrayClipboard(result.getTransformedRegion());
target.setOrigin(clipboard.getOrigin());
Operations.completeLegacy(result.copyTo(target));
} }
try (Closer closer = Closer.create()) { try (Closer closer = Closer.create()) {
@ -1062,29 +1046,31 @@ public class SchematicCommands {
} }
} }
private static class SchematicShareTask extends SchematicOutputTask<URL> { private static class SchematicShareTask extends SchematicOutputTask<Consumer<Actor>> {
private final Actor actor;
private final String name; private final String name;
private final ClipboardShareDestination destination;
SchematicShareTask(Actor actor, ClipboardFormat format, ClipboardHolder holder, String name) { SchematicShareTask(Actor actor,
ClipboardHolder holder,
ClipboardShareDestination destination,
ClipboardFormat format,
String name) {
super(actor, format, holder); super(actor, format, holder);
this.actor = actor;
this.name = name; this.name = name;
this.destination = destination;
} }
@Override @Override
public URL call() throws Exception { public Consumer<Actor> call() throws Exception {
ByteArrayOutputStream baos = new ByteArrayOutputStream(); ClipboardShareMetadata metadata = new ClipboardShareMetadata(
try { format,
writeToOutputStream(baos); this.actor.getName(),
} catch (Exception e) { name == null ? actor.getName() + "-" + System.currentTimeMillis() : name
throw new CommandException(TextComponent.of(e.getMessage()), e, ImmutableList.of()); );
}
EngineHubPaste pasteService = new EngineHubPaste(); return destination.share(metadata, this::writeToOutputStream);
PasteMetadata metadata = new PasteMetadata();
metadata.author = this.actor.getName();
metadata.extension = "schem";
metadata.name = name == null ? actor.getName() + "-" + System.currentTimeMillis() : name;
return pasteService.paste(new String(Base64.getEncoder().encode(baos.toByteArray()), StandardCharsets.UTF_8), metadata).call();
} }
} }

Datei anzeigen

@ -30,6 +30,7 @@ import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession; import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException; import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.BaseItemStack; import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.command.argument.SelectorChoice; import com.sk89q.worldedit.command.argument.SelectorChoice;
import com.sk89q.worldedit.command.tool.NavigationWand; import com.sk89q.worldedit.command.tool.NavigationWand;
@ -38,6 +39,8 @@ import com.sk89q.worldedit.command.util.CommandPermissions;
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator; import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
import com.sk89q.worldedit.command.util.Logging; import com.sk89q.worldedit.command.util.Logging;
import com.sk89q.worldedit.entity.Player; import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.Actor; import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Locatable; import com.sk89q.worldedit.extension.platform.Locatable;
import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits; import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits;
@ -325,22 +328,28 @@ public class SelectionCommands {
//FAWE start //FAWE start
session.loadDefaults(player, true); session.loadDefaults(player, true);
//FAWE end //FAWE end
String wandId = navWand ? session.getNavWandItem() : session.getWandItem(); BaseItem wand = navWand ? session.getNavWandBaseItem() : session.getWandBaseItem();
if (wandId == null) { if (wand == null) {
wandId = navWand ? we.getConfiguration().navigationWand : we.getConfiguration().wandItem; String wandId = navWand ? we.getConfiguration().navigationWand : we.getConfiguration().wandItem;
} //FAWE start - allow item NBT
ItemType itemType = ItemTypes.parse(wandId); ParserContext parserContext = new ParserContext();
if (itemType == null) { parserContext.setActor(player);
parserContext.setSession(session);
try {
wand = WorldEdit.getInstance().getItemFactory().parseFromInput(wandId, parserContext);
} catch (InputParseException e) {
player.print(Caption.of("worldedit.wand.invalid")); player.print(Caption.of("worldedit.wand.invalid"));
return; return;
} }
player.giveItem(new BaseItemStack(itemType, 1)); }
player.giveItem(new BaseItemStack(wand.getType(), wand.getNbtReference(), 1));
//FAWE end
//FAWE start - instance-iate session //FAWE start - instance-iate session
if (navWand) { if (navWand) {
session.setTool(itemType, NavigationWand.INSTANCE); session.setTool(wand, NavigationWand.INSTANCE);
player.print(Caption.of("worldedit.wand.navwand.info")); player.print(Caption.of("worldedit.wand.navwand.info"));
} else { } else {
session.setTool(itemType, SelectionWand.INSTANCE); session.setTool(wand, SelectionWand.INSTANCE);
player.print(Caption.of("worldedit.wand.selwand.info")); player.print(Caption.of("worldedit.wand.selwand.info"));
//FAWE end //FAWE end
} }

Datei anzeigen

@ -153,7 +153,7 @@ public class ToolCommands {
throws InvalidToolBindException { throws InvalidToolBindException {
//FAWE start //FAWE start
isBrush = session.getTool(player) instanceof BrushTool; isBrush = session.getTool(player) instanceof BrushTool;
session.setTool(player.getItemInHand(HandSide.MAIN_HAND).getType(), null); session.setTool(player.getItemInHand(HandSide.MAIN_HAND), null);
//FAWE end //FAWE end
player.print(Caption.of(isBrush ? "worldedit.brush.none.equip" : "worldedit.tool.none.equip")); player.print(Caption.of(isBrush ? "worldedit.brush.none.equip" : "worldedit.tool.none.equip"));
} }
@ -167,7 +167,7 @@ public class ToolCommands {
String translationKey String translationKey
) throws InvalidToolBindException { ) throws InvalidToolBindException {
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND); BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND);
session.setTool(itemStack.getType(), tool); session.setTool(itemStack, tool);
player.print(Caption.of(translationKey, itemStack.getRichName())); player.print(Caption.of(translationKey, itemStack.getRichName()));
sendUnbindInstruction(player, UNBIND_COMMAND_COMPONENT); sendUnbindInstruction(player, UNBIND_COMMAND_COMPONENT);
} }

Datei anzeigen

@ -0,0 +1,76 @@
/*
* 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.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormats;
import com.sk89q.worldedit.extent.clipboard.io.share.ClipboardShareDestination;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import org.enginehub.piston.CommandManager;
import org.enginehub.piston.converter.ArgumentConverter;
import org.enginehub.piston.converter.ConversionResult;
import org.enginehub.piston.converter.FailedConversion;
import org.enginehub.piston.converter.SuccessfulConversion;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.enginehub.piston.inject.Key;
import java.util.List;
import java.util.Set;
import static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix;
public class ClipboardFormatConverter implements ArgumentConverter<ClipboardFormat> {
public static void register(CommandManager commandManager) {
commandManager.registerConverter(Key.of(ClipboardFormat.class),
new ClipboardFormatConverter()
);
}
private final TextComponent choices;
private ClipboardFormatConverter() {
this.choices = TextComponent.of("any clipboard format");
}
@Override
public Component describeAcceptableArguments() {
return this.choices;
}
@Override
public List<String> getSuggestions(String input, InjectedValueAccess context) {
ClipboardShareDestination destination = context.injectedValue(Key.of(ClipboardShareDestination.class)).orElse(null);
return limitByPrefix(ClipboardFormats.getAll().stream()
.filter(format -> destination == null || destination.supportsFormat(format))
.map(ClipboardFormat::getAliases)
.flatMap(Set::stream), input);
}
@Override
public ConversionResult<ClipboardFormat> convert(String s, InjectedValueAccess injectedValueAccess) {
ClipboardFormat result = ClipboardFormats.findByAlias(s);
return result == null
? FailedConversion.from(new IllegalArgumentException("Not a valid schematic format: " + s))
: SuccessfulConversion.fromSingle(result);
}
}

Datei anzeigen

@ -0,0 +1,72 @@
/*
* 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.extent.clipboard.io.share.ClipboardShareDestination;
import com.sk89q.worldedit.extent.clipboard.io.share.ClipboardShareDestinations;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import org.enginehub.piston.CommandManager;
import org.enginehub.piston.converter.ArgumentConverter;
import org.enginehub.piston.converter.ConversionResult;
import org.enginehub.piston.converter.FailedConversion;
import org.enginehub.piston.converter.SuccessfulConversion;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.enginehub.piston.inject.Key;
import java.util.List;
import java.util.Set;
import static org.enginehub.piston.converter.SuggestionHelper.limitByPrefix;
public class ClipboardShareDestinationConverter implements ArgumentConverter<ClipboardShareDestination> {
public static void register(CommandManager commandManager) {
commandManager.registerConverter(Key.of(ClipboardShareDestination.class),
new ClipboardShareDestinationConverter()
);
}
private final TextComponent choices;
private ClipboardShareDestinationConverter() {
this.choices = TextComponent.of("any clipboard share destination");
}
@Override
public Component describeAcceptableArguments() {
return this.choices;
}
@Override
public List<String> getSuggestions(String input, InjectedValueAccess context) {
return limitByPrefix(ClipboardShareDestinations.getAll().stream()
.map(ClipboardShareDestination::getAliases)
.flatMap(Set::stream), input);
}
@Override
public ConversionResult<ClipboardShareDestination> convert(String s, InjectedValueAccess injectedValueAccess) {
ClipboardShareDestination result = ClipboardShareDestinations.findByAlias(s);
return result == null
? FailedConversion.from(new IllegalArgumentException("Not a valid clipboard share destination: " + s))
: SuccessfulConversion.fromSingle(result);
}
}

Datei anzeigen

@ -86,6 +86,8 @@ import com.sk89q.worldedit.command.WorldEditCommandsRegistration;
import com.sk89q.worldedit.command.argument.Arguments; import com.sk89q.worldedit.command.argument.Arguments;
import com.sk89q.worldedit.command.argument.BooleanConverter; import com.sk89q.worldedit.command.argument.BooleanConverter;
import com.sk89q.worldedit.command.argument.Chunk3dVectorConverter; import com.sk89q.worldedit.command.argument.Chunk3dVectorConverter;
import com.sk89q.worldedit.command.argument.ClipboardFormatConverter;
import com.sk89q.worldedit.command.argument.ClipboardShareDestinationConverter;
import com.sk89q.worldedit.command.argument.CommaSeparatedValuesConverter; import com.sk89q.worldedit.command.argument.CommaSeparatedValuesConverter;
import com.sk89q.worldedit.command.argument.DirectionConverter; import com.sk89q.worldedit.command.argument.DirectionConverter;
import com.sk89q.worldedit.command.argument.DirectionVectorConverter; import com.sk89q.worldedit.command.argument.DirectionVectorConverter;
@ -174,7 +176,6 @@ import java.util.stream.Stream;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* Handles the registration and invocation of commands. * Handles the registration and invocation of commands.
* *
@ -272,6 +273,8 @@ public final class PlatformCommandManager {
SideEffectConverter.register(commandManager); SideEffectConverter.register(commandManager);
HeightConverter.register(commandManager); HeightConverter.register(commandManager);
OffsetConverter.register(worldEdit, commandManager); OffsetConverter.register(worldEdit, commandManager);
ClipboardFormatConverter.register(commandManager);
ClipboardShareDestinationConverter.register(commandManager);
//FAWE start //FAWE start
commandManager.registerConverter( commandManager.registerConverter(
Key.of(com.sk89q.worldedit.function.pattern.Pattern.class, Annotations.patternList()), Key.of(com.sk89q.worldedit.function.pattern.Pattern.class, Annotations.patternList()),
@ -604,7 +607,6 @@ public final class PlatformCommandManager {
void registerCommandsWith(Platform platform) { void registerCommandsWith(Platform platform) {
LOGGER.info("Registering commands with " + platform.getClass().getCanonicalName()); LOGGER.info("Registering commands with " + platform.getClass().getCanonicalName());
LocalConfiguration config = platform.getConfiguration(); LocalConfiguration config = platform.getConfiguration();
boolean logging = config.logCommands; boolean logging = config.logCommands;
String path = config.logFile; String path = config.logFile;

Datei anzeigen

@ -31,6 +31,7 @@ import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.EditSessionBuilder; import com.sk89q.worldedit.EditSessionBuilder;
import com.sk89q.worldedit.WorldEdit; import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Entity; import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat; import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter; import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
@ -40,6 +41,7 @@ import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operations; import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.internal.util.ClipboardTransformBaker;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.transform.Transform; import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.regions.Region; import com.sk89q.worldedit.regions.Region;
@ -144,10 +146,9 @@ public interface Clipboard extends Extent, Iterable<BlockVector3>, Closeable, Fl
void setOrigin(BlockVector3 origin); void setOrigin(BlockVector3 origin);
/** /**
* Returns true if the clipboard has biome data. This can be checked since {@link Extent#getBiome(BlockVector2)} * Returns true if the clipboard has biome data. This can be checked since {@link Extent#getBiome(BlockVector3)}
* strongly suggests returning {@link com.sk89q.worldedit.world.biome.BiomeTypes#OCEAN} instead of {@code null} * strongly suggests returning {@link com.sk89q.worldedit.world.biome.BiomeTypes#OCEAN} instead of {@code null}
* if biomes aren't present. However, it might not be desired to set areas to ocean if the clipboard is defaulting * if biomes aren't present.
* to ocean, instead of having biomes explicitly set.
* *
* @return true if the clipboard has biome data set * @return true if the clipboard has biome data set
*/ */
@ -155,6 +156,21 @@ public interface Clipboard extends Extent, Iterable<BlockVector3>, Closeable, Fl
return false; return false;
} }
/**
* Returns a clipboard with a given transform baked in.
*
* <p>
* Note: This method may return the same clipboard object, if a copy is needed then you should check the returned value for identity equality and copy if needed.
* </p>
*
* @param transform The transform
* @return The new clipboard
* @throws WorldEditException if the copy encounters an error
*/
default Clipboard transform(Transform transform) throws WorldEditException {
return ClipboardTransformBaker.bakeTransform(this, transform);
}
//FAWE start //FAWE start
/** /**

Datei anzeigen

@ -73,7 +73,7 @@ public class ClipboardFormats {
checkNotNull(format); checkNotNull(format);
for (String key : format.getAliases()) { for (String key : format.getAliases()) {
String lowKey = key.toLowerCase(Locale.ENGLISH); String lowKey = key.toLowerCase(Locale.ROOT);
ClipboardFormat old = aliasMap.put(lowKey, format); ClipboardFormat old = aliasMap.put(lowKey, format);
if (old != null) { if (old != null) {
aliasMap.put(lowKey, old); aliasMap.put(lowKey, old);
@ -83,7 +83,7 @@ public class ClipboardFormats {
} }
} }
for (String ext : format.getFileExtensions()) { for (String ext : format.getFileExtensions()) {
String lowExt = ext.toLowerCase(Locale.ENGLISH); String lowExt = ext.toLowerCase(Locale.ROOT);
fileExtensionMap.put(lowExt, format); fileExtensionMap.put(lowExt, format);
} }
registeredFormats.add(format); registeredFormats.add(format);
@ -104,7 +104,7 @@ public class ClipboardFormats {
@Nullable @Nullable
public static ClipboardFormat findByAlias(String alias) { public static ClipboardFormat findByAlias(String alias) {
checkNotNull(alias); checkNotNull(alias);
return aliasMap.get(alias.toLowerCase(Locale.ENGLISH).trim()); return aliasMap.get(alias.toLowerCase(Locale.ROOT).trim());
} }
/** /**

Datei anzeigen

@ -0,0 +1,149 @@
/*
* 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.extent.clipboard.io.share;
import com.fastasyncworldedit.core.configuration.Caption;
import com.fastasyncworldedit.core.configuration.Settings;
import com.fastasyncworldedit.core.util.arkitektonika.ArkitektonikaResponse;
import com.fastasyncworldedit.core.util.arkitektonika.ArkitektonikaSchematicUploader;
import com.google.common.collect.ImmutableSet;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.clipboard.io.BuiltInClipboardFormat;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldedit.util.paste.EngineHubPaste;
import com.sk89q.worldedit.util.paste.PasteMetadata;
import java.io.ByteArrayOutputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.function.Consumer;
/**
* A collection of natively supported clipboard share destinations.
*/
public enum BuiltInClipboardShareDestinations implements ClipboardShareDestination {
/**
* The EngineHub pastebin service, at https://paste.enginehub.org/
*/
ENGINEHUB_PASTEBIN("enginehub_paste", "ehpaste") {
@Override
public String getName() {
return "EngineHub Paste";
}
@Override
public Consumer<Actor> share(ClipboardShareMetadata metadata, ShareOutputProvider serializer) throws Exception {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
serializer.writeTo(outputStream);
PasteMetadata pasteMetadata = new PasteMetadata();
pasteMetadata.author = metadata.author();
pasteMetadata.extension = "schem";
pasteMetadata.name = metadata.name();
EngineHubPaste pasteService = new EngineHubPaste();
URL url = pasteService.paste(new String(
Base64.getEncoder().encode(outputStream.toByteArray()),
StandardCharsets.UTF_8
), pasteMetadata).call();
String urlString = url.toExternalForm() + ".schem";
return actor -> actor.printInfo(TextComponent.of(urlString).clickEvent(ClickEvent.openUrl(urlString)));
}
@Override
public ClipboardFormat getDefaultFormat() {
return BuiltInClipboardFormat.SPONGE_SCHEMATIC;
}
@Override
public boolean supportsFormat(ClipboardFormat format) {
return format == getDefaultFormat();
}
},
//FAWE start - add arkitektonika
ARKITEKTONIKA("arkitektonika", "fawe") {
private ArkitektonikaSchematicUploader uploader;
@Override
public String getName() {
return "Arkitektonika";
}
@Override
public Consumer<Actor> share(final ClipboardShareMetadata metadata, final ShareOutputProvider serializer) throws
Exception {
if (uploader == null) {
uploader = new ArkitektonikaSchematicUploader(Settings.settings().WEB.ARKITEKTONIKA_BACKEND_URL);
}
final ArkitektonikaResponse response = uploader.uploadBlocking(metadata, serializer);
final String downloadUrl = Settings.settings().WEB.ARKITEKTONIKA_DOWNLOAD_URL.replace("{key}", response.downloadKey());
final String deletionUrl = Settings.settings().WEB.ARKITEKTONIKA_DELETE_URL.replace("{key}", response.deletionKey());
return actor -> {
actor.print(Caption.of(
"worldedit.schematic.share.response.arkitektonika.download",
Caption.of("worldedit.schematic.share.response.arkitektonika.click-here")
.color(TextColor.GREEN).clickEvent(ClickEvent.openUrl(downloadUrl))
));
actor.print(Caption.of(
"worldedit.schematic.share.response.arkitektonika.delete",
Caption.of("worldedit.schematic.share.response.arkitektonika.click-here")
.color(TextColor.RED).clickEvent(ClickEvent.openUrl(deletionUrl))
));
};
}
@Override
public ClipboardFormat getDefaultFormat() {
return BuiltInClipboardFormat.FAST;
}
@Override
public boolean supportsFormat(final ClipboardFormat format) {
return format == BuiltInClipboardFormat.SPONGE_SCHEMATIC ||
format == BuiltInClipboardFormat.FAST ||
format == BuiltInClipboardFormat.MCEDIT_SCHEMATIC;
}
};
//FAWE end
private final ImmutableSet<String> aliases;
BuiltInClipboardShareDestinations(String... aliases) {
this.aliases = ImmutableSet.copyOf(aliases);
}
@Override
public ImmutableSet<String> getAliases() {
return this.aliases;
}
@Override
public String getName() {
return name();
}
}

Datei anzeigen

@ -0,0 +1,72 @@
/*
* 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.extent.clipboard.io.share;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import java.util.Set;
import java.util.function.Consumer;
public interface ClipboardShareDestination {
/**
* Gets the name of this share destination.
*
* @return The name
*/
String getName();
/**
* Get a set of aliases.
*
* @return a set of aliases
*/
Set<String> getAliases();
/**
* Share a clipboard output stream and return a URL.
*
* <p>
* The serialized schematic can be retrieved by providing an {@link java.io.OutputStream} to {@code serializer}.
* </p>
*
* @param metadata The clipboard metadata
* @param serializer A function taking the {@link java.io.OutputStream}
* @return A consumer to provide the actor with the share results
* @throws Exception if it failed to share
*/
Consumer<Actor> share(ClipboardShareMetadata metadata, ShareOutputProvider serializer) throws Exception;
/**
* Gets the default clipboard format for this share destination.
*
* @return The default format
*/
ClipboardFormat getDefaultFormat();
/**
* Gets whether the share destination supports the given format.
*
* @param format The format
* @return If it's supported
*/
boolean supportsFormat(ClipboardFormat format);
}

Datei anzeigen

@ -0,0 +1,80 @@
/*
* 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.extent.clipboard.io.share;
import com.sk89q.worldedit.WorldEdit;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
public class ClipboardShareDestinations {
private static final Map<String, ClipboardShareDestination> aliasMap = new HashMap<>();
private static final List<ClipboardShareDestination> registeredDestinations = new ArrayList<>();
public static void registerClipboardShareDestination(ClipboardShareDestination destination) {
checkNotNull(destination);
checkState(destination.supportsFormat(destination.getDefaultFormat()), "Destination must accept its default format");
for (String key : destination.getAliases()) {
String lowKey = key.toLowerCase(Locale.ROOT);
ClipboardShareDestination old = aliasMap.put(lowKey, destination);
if (old != null) {
aliasMap.put(lowKey, old);
WorldEdit.logger.warn(destination.getClass().getName() + " cannot override existing alias '" + lowKey + "' used by " + old.getClass().getName());
}
}
registeredDestinations.add(destination);
}
static {
for (BuiltInClipboardShareDestinations destination : BuiltInClipboardShareDestinations.values()) {
registerClipboardShareDestination(destination);
}
}
/**
* Find the clipboard format named by the given alias.
*
* @param alias the alias
* @return the format, otherwise null if none is matched
*/
@Nullable
public static ClipboardShareDestination findByAlias(String alias) {
checkNotNull(alias);
return aliasMap.get(alias.toLowerCase(Locale.ROOT).trim());
}
public static Collection<ClipboardShareDestination> getAll() {
return Collections.unmodifiableCollection(registeredDestinations);
}
private ClipboardShareDestinations() {
}
}

Datei anzeigen

@ -0,0 +1,49 @@
/*
* 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.extent.clipboard.io.share;
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
/**
* Items of metadata about shared clipboards.
*/
public class ClipboardShareMetadata {
private final ClipboardFormat format;
private final String name;
private final String author;
public ClipboardShareMetadata(ClipboardFormat format, String name, String author) {
this.format = format;
this.name = name;
this.author = author;
}
public ClipboardFormat format() {
return this.format;
}
public String name() {
return this.name;
}
public String author() {
return this.author;
}
}

Datei anzeigen

@ -0,0 +1,37 @@
/*
* 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.extent.clipboard.io.share;
import com.sk89q.worldedit.WorldEditException;
import java.io.IOException;
import java.io.OutputStream;
@FunctionalInterface
public interface ShareOutputProvider {
/**
* Provides the share output to {@code stream}.
*
* @throws IOException if it failed
* @throws WorldEditException if WorldEdit failed to serialize to the stream
*/
void writeTo(OutputStream stream) throws IOException, WorldEditException;
}

Datei anzeigen

@ -17,13 +17,16 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.sk89q.worldedit.command; package com.sk89q.worldedit.internal.util;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent; import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard; import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.transform.BlockTransformExtent; import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy; import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operation; import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.transform.AffineTransform; import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.math.transform.CombinedTransform; import com.sk89q.worldedit.math.transform.CombinedTransform;
@ -36,12 +39,10 @@ import static com.google.common.base.Preconditions.checkNotNull;
/** /**
* Helper class to 'bake' a transform into a clipboard. * Helper class to 'bake' a transform into a clipboard.
* *
* <p>This class needs a better name and may need to be made more generic.</p>
*
* @see Clipboard * @see Clipboard
* @see Transform * @see Transform
*/ */
public class FlattenedClipboardTransform { public class ClipboardTransformBaker {
private final Clipboard original; private final Clipboard original;
private final Transform transform; private final Transform transform;
@ -52,7 +53,7 @@ public class FlattenedClipboardTransform {
* @param original the original clipboard * @param original the original clipboard
* @param transform the transform * @param transform the transform
*/ */
private FlattenedClipboardTransform(Clipboard original, Transform transform) { private ClipboardTransformBaker(Clipboard original, Transform transform) {
checkNotNull(original); checkNotNull(original);
checkNotNull(transform); checkNotNull(transform);
this.original = original; this.original = original;
@ -64,7 +65,7 @@ public class FlattenedClipboardTransform {
* *
* @return the transformed region * @return the transformed region
*/ */
public Region getTransformedRegion() { private Region getTransformedRegion() {
Region region = original.getRegion(); Region region = original.getRegion();
Vector3 minimum = region.getMinimumPoint().toVector3(); Vector3 minimum = region.getMinimumPoint().toVector3();
Vector3 maximum = region.getMaximumPoint().toVector3(); Vector3 maximum = region.getMaximumPoint().toVector3();
@ -73,8 +74,7 @@ public class FlattenedClipboardTransform {
new CombinedTransform( new CombinedTransform(
new AffineTransform().translate(original.getOrigin().multiply(-1)), new AffineTransform().translate(original.getOrigin().multiply(-1)),
transform, transform,
new AffineTransform().translate(original.getOrigin()) new AffineTransform().translate(original.getOrigin()));
);
Vector3[] corners = new Vector3[]{ Vector3[] corners = new Vector3[]{
minimum, minimum,
@ -113,7 +113,7 @@ public class FlattenedClipboardTransform {
* @param target the target * @param target the target
* @return the operation * @return the operation
*/ */
public Operation copyTo(Extent target) { private Operation copyTo(Extent target) {
//FAWE start //FAWE start
Extent extent = original; Extent extent = original;
if (transform != null && !transform.isIdentity()) { if (transform != null && !transform.isIdentity()) {
@ -121,11 +121,7 @@ public class FlattenedClipboardTransform {
} }
//FAWE end //FAWE end
ForwardExtentCopy copy = new ForwardExtentCopy( ForwardExtentCopy copy = new ForwardExtentCopy(
extent, extent, original.getRegion(), original.getOrigin(), target, original.getOrigin()
original.getRegion(),
original.getOrigin(),
target,
original.getOrigin()
); );
copy.setTransform(transform); copy.setTransform(transform);
if (original.hasBiomes()) { if (original.hasBiomes()) {
@ -140,9 +136,18 @@ public class FlattenedClipboardTransform {
* @param original the original clipboard * @param original the original clipboard
* @param transform the transform * @param transform the transform
* @return a builder * @return a builder
* @throws WorldEditException if an error occurred during copy
*/ */
public static FlattenedClipboardTransform transform(Clipboard original, Transform transform) { public static Clipboard bakeTransform(Clipboard original, Transform transform) throws WorldEditException {
return new FlattenedClipboardTransform(original, transform); if (transform.isIdentity()) {
return original;
}
ClipboardTransformBaker baker = new ClipboardTransformBaker(original, transform);
Clipboard target = new BlockArrayClipboard(baker.getTransformedRegion());
target.setOrigin(original.getOrigin());
Operations.complete(baker.copyTo(target));
return target;
} }
} }

Datei anzeigen

@ -828,7 +828,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
return set; return set;
} }
for (int layer = get.getMinSectionPosition(); layer < get.getMaxSectionPosition(); layer++) { for (int layer = get.getMinSectionPosition(); layer <= get.getMaxSectionPosition(); layer++) {
if (!set.hasSection(layer)) { if (!set.hasSection(layer)) {
continue; continue;
} }
@ -912,7 +912,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
boolean trimX = lowerX != 0 || upperX != 15; boolean trimX = lowerX != 0 || upperX != 15;
boolean trimZ = lowerZ != 0 || upperZ != 15; boolean trimZ = lowerZ != 0 || upperZ != 15;
for (int layer = get.getMinSectionPosition(); layer < get.getMaxSectionPosition(); layer++) { for (int layer = get.getMinSectionPosition(); layer <= get.getMaxSectionPosition(); layer++) {
if (!set.hasSection(layer)) { if (!set.hasSection(layer)) {
continue; continue;
} }

Datei anzeigen

@ -112,7 +112,7 @@ public class PropertiesConfiguration extends LocalConfiguration {
logFile = getString("log-file", logFile); logFile = getString("log-file", logFile);
logFormat = getString("log-format", logFormat); logFormat = getString("log-format", logFormat);
registerHelp = getBool("register-help", registerHelp); registerHelp = getBool("register-help", registerHelp);
wandItem = getString("wand-item", wandItem).toLowerCase(Locale.ROOT); wandItem = getString("wand-item", wandItem);
try { try {
wandItem = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(wandItem)).id(); wandItem = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(wandItem)).id();
} catch (Throwable ignored) { } catch (Throwable ignored) {
@ -122,7 +122,7 @@ public class PropertiesConfiguration extends LocalConfiguration {
useInventory = getBool("use-inventory", useInventory); useInventory = getBool("use-inventory", useInventory);
useInventoryOverride = getBool("use-inventory-override", useInventoryOverride); useInventoryOverride = getBool("use-inventory-override", useInventoryOverride);
useInventoryCreativeOverride = getBool("use-inventory-creative-override", useInventoryCreativeOverride); useInventoryCreativeOverride = getBool("use-inventory-creative-override", useInventoryCreativeOverride);
navigationWand = getString("nav-wand-item", navigationWand).toLowerCase(Locale.ROOT); navigationWand = getString("nav-wand-item", navigationWand);
try { try {
navigationWand = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(navigationWand)).id(); navigationWand = LegacyMapper.getInstance().getItemFromLegacy(Integer.parseInt(navigationWand)).id();
} catch (Throwable ignored) { } catch (Throwable ignored) {

Datei anzeigen

@ -58,7 +58,7 @@ public class YAMLConfiguration extends LocalConfiguration {
profile = config.getBoolean("debug", profile); profile = config.getBoolean("debug", profile);
traceUnflushedSessions = config.getBoolean("debugging.trace-unflushed-sessions", traceUnflushedSessions); traceUnflushedSessions = config.getBoolean("debugging.trace-unflushed-sessions", traceUnflushedSessions);
wandItem = convertLegacyItem(config.getString("wand-item", wandItem)).toLowerCase(Locale.ROOT); wandItem = convertLegacyItem(config.getString("wand-item", wandItem));
defaultChangeLimit = Math.max(-1, config.getInt( defaultChangeLimit = Math.max(-1, config.getInt(
"limits.max-blocks-changed.default", defaultChangeLimit)); "limits.max-blocks-changed.default", defaultChangeLimit));
@ -130,7 +130,7 @@ public class YAMLConfiguration extends LocalConfiguration {
useInventoryCreativeOverride useInventoryCreativeOverride
); );
navigationWand = convertLegacyItem(config.getString("navigation-wand.item", navigationWand)).toLowerCase(Locale.ROOT); navigationWand = convertLegacyItem(config.getString("navigation-wand.item", navigationWand));
navigationWandMaxDistance = config.getInt("navigation-wand.max-distance", navigationWandMaxDistance); navigationWandMaxDistance = config.getInt("navigation-wand.max-distance", navigationWandMaxDistance);
navigationUseGlass = config.getBoolean("navigation.use-glass", navigationUseGlass); navigationUseGlass = config.getBoolean("navigation.use-glass", navigationUseGlass);

Datei anzeigen

@ -19,10 +19,12 @@
package com.sk89q.worldedit.util.gson; package com.sk89q.worldedit.util.gson;
import com.fastasyncworldedit.core.util.gson.BaseItemAdapter;
import com.fastasyncworldedit.core.util.gson.ItemTypeAdapter; import com.fastasyncworldedit.core.util.gson.ItemTypeAdapter;
import com.fastasyncworldedit.core.util.gson.RegionSelectorAdapter; import com.fastasyncworldedit.core.util.gson.RegionSelectorAdapter;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.math.BlockVector3; import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3; import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.RegionSelector; import com.sk89q.worldedit.regions.RegionSelector;
@ -48,6 +50,7 @@ public final class GsonUtil {
//FAWE start //FAWE start
gsonBuilder.registerTypeAdapter(RegionSelector.class, new RegionSelectorAdapter()); gsonBuilder.registerTypeAdapter(RegionSelector.class, new RegionSelectorAdapter());
gsonBuilder.registerTypeAdapter(ItemType.class, new ItemTypeAdapter()); gsonBuilder.registerTypeAdapter(ItemType.class, new ItemTypeAdapter());
gsonBuilder.registerTypeAdapter(BaseItem.class, new BaseItemAdapter());
//FAWE end //FAWE end
return gsonBuilder; return gsonBuilder;
} }

Datei anzeigen

@ -360,6 +360,11 @@
"worldedit.schematic.save.already-exists": "That schematic already exists. Use the -f flag to overwrite it.", "worldedit.schematic.save.already-exists": "That schematic already exists. Use the -f flag to overwrite it.",
"worldedit.schematic.save.failed-directory": "Could not create folder for schematics!", "worldedit.schematic.save.failed-directory": "Could not create folder for schematics!",
"worldedit.schematic.save.saving": "(Please wait... saving schematic.)", "worldedit.schematic.save.saving": "(Please wait... saving schematic.)",
"worldedit.schematic.save.still-saving": "(Please wait... still saving schematic.)",
"worldedit.schematic.share.unsupported-format": "The schematic share destination \"{0}\" does not support the \"{1}\" format.",
"worldedit.schematic.share.response.arkitektonika.download" : "Download: {0}",
"worldedit.schematic.share.response.arkitektonika.delete" : "Delete: {0}",
"worldedit.schematic.share.response.arkitektonika.click-here" : "[Click here]",
"worldedit.schematic.delete.empty": "Schematic {0} not found!", "worldedit.schematic.delete.empty": "Schematic {0} not found!",
"worldedit.schematic.delete.does-not-exist": "Schematic {0} does not exist!", "worldedit.schematic.delete.does-not-exist": "Schematic {0} does not exist!",
"worldedit.schematic.delete.failed": "Deletion of {0} failed! Is it read-only?", "worldedit.schematic.delete.failed": "Deletion of {0} failed! Is it read-only?",