Skip to content

Commit

Permalink
Implement SchematicPasteOptions + clean up (#22)
Browse files Browse the repository at this point in the history
  • Loading branch information
avaerian committed Sep 6, 2023
1 parent 33116a2 commit cc16c7f
Show file tree
Hide file tree
Showing 14 changed files with 215 additions and 75 deletions.
2 changes: 2 additions & 0 deletions main/src/main/java/org/minerift/ether/EtherPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import org.minerift.ether.debug.*;
import org.minerift.ether.island.IslandManager;
import org.minerift.ether.nms.NMSAccess;
import org.minerift.ether.schematic.pasters.SpongeSchematicPaster;
import org.minerift.ether.schematic.types.SchematicType;
import org.minerift.ether.work.WorkQueue;

import java.util.logging.Level;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.minerift.ether.EtherPlugin;
import org.minerift.ether.nms.NMSAccess;
import org.minerift.ether.schematic.SchematicFileReadException;
import org.minerift.ether.schematic.SchematicPasteOptions;
import org.minerift.ether.schematic.types.Schematic;
import org.minerift.ether.util.BukkitUtils;
import org.minerift.ether.util.math.Vec3i;
Expand All @@ -28,7 +27,6 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command
return false;
}

final NMSAccess nmsAccess = EtherPlugin.getInstance().getNMS();
final Player plr = (Player) sender;
final Vec3i pos = BukkitUtils.getPosAsVec3i(plr.getLocation());
final String worldName = plr.getWorld().getName();
Expand All @@ -43,7 +41,7 @@ public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command

// Attempt to paste
Schematic.fromFile(file).handle((schem) -> {
schem.paste(pos, worldName);
schem.paste(pos, worldName, SchematicPasteOptions.DEFAULT);
plr.sendMessage("Schematic pasted successfully!");
}, this::schemFail);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.google.common.base.Preconditions;
import org.bukkit.entity.Player;
import org.minerift.ether.schematic.SchematicPasteOptions;
import org.minerift.ether.schematic.types.Schematic;
import org.minerift.ether.user.EtherUser;
import org.minerift.ether.util.math.Vec3i;
Expand All @@ -27,7 +28,9 @@ public static Island run(IslandGrid grid, EtherUser user) {
// TODO: Paste schematic/structure onto tile
File file = null;
Vec3i pos = Vec3i.ZERO;
Schematic.fromFile(file).handle((schem) -> schem.paste(pos, plr.getWorld().getName()), (ex) -> { throw new RuntimeException(ex); });
Schematic.fromFile(file).handle((schem) -> {
schem.paste(pos, plr.getWorld().getName(), SchematicPasteOptions.builder().copyBiomes(true).build());
}, (ex) -> { throw new RuntimeException(ex); });

// Teleport player

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.minerift.ether.schematic;

@Deprecated
public class SchematicPasteFlags {

public static final byte IGNORE_AIR_BLOCKS = 1;
public static final byte WITH_BIOMES = 2;
public static final byte WITH_ENTITIES = 4;

public static SchematicPasteFlags of(int flags) {
return new SchematicPasteFlags(flags);
}

public static SchematicPasteFlags of(int flag, int ... flags) {
for(int f : flags) {
flag |= f;
}
return new SchematicPasteFlags(flag);
}

private final int flags;
private SchematicPasteFlags(int flags) {
this.flags = flags;
}

public void has(int flag, Runnable callback) {
if(has(flag)) {
callback.run();
}
}

public boolean has(int flag) {
return (flags & flag) != 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package org.minerift.ether.schematic;

import org.minerift.ether.util.math.Vec3i;

public class SchematicPasteOptions {

/**
* Default SchematicPasteOptions with no changes.
* Everything is defaulted to false or 0.
*/
public static final SchematicPasteOptions EMPTY_DEFAULT;

/**
* Preferred default SchematicPasteOptions.
* Will copy biomes and entities with zero offset and no ignored air blocks.
*/
public static final SchematicPasteOptions DEFAULT;

static {
EMPTY_DEFAULT = SchematicPasteOptions.builder().build();
DEFAULT = SchematicPasteOptions.builder()
.copyBiomes(true)
.copyEntities(true)
.build();
}

public final boolean copyBiomes;
public final boolean copyEntities;
public final boolean ignoreAirBlocks;
public final Vec3i offset;

private SchematicPasteOptions(SchematicPasteOptions.Builder builder) {
this.copyBiomes = builder.copyBiomes;
this.copyEntities = builder.copyEntities;
this.ignoreAirBlocks = builder.ignoreAirBlocks;
this.offset = builder.offset;
}

public static SchematicPasteOptions.Builder builder() {
return new Builder();
}

public static class Builder {
private boolean copyBiomes;
private boolean copyEntities;
private boolean ignoreAirBlocks;
private Vec3i offset;

private Builder() {
this.copyBiomes = false;
this.copyEntities = false;
this.ignoreAirBlocks = false;
this.offset = Vec3i.ZERO;
}

public Builder copyBiomes(boolean val) {
this.copyBiomes = val;
return this;
}

public Builder copyEntities(boolean val) {
this.copyEntities = val;
return this;
}

public Builder ignoreAirBlocks(boolean val) {
this.ignoreAirBlocks = val;
return this;
}

public Builder setOffset(Vec3i val) {
this.offset = val;
return this;
}

public SchematicPasteOptions build() {
return new SchematicPasteOptions(this);
}
}

}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package org.minerift.ether.schematic.pasters;

import org.minerift.ether.schematic.SchematicPasteOptions;
import org.minerift.ether.schematic.types.Schematic;
import org.minerift.ether.util.math.Vec3i;

public interface ISchematicPaster<S extends Schematic> {
void paste(S schem, Vec3i pos, String worldName);
void paste(S schem, Vec3i pos, String worldName, SchematicPasteOptions options);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
import org.bukkit.block.Biome;
import org.minerift.ether.EtherPlugin;
import org.minerift.ether.nms.NMSAccess;
import org.minerift.ether.schematic.SchematicPasteOptions;
import org.minerift.ether.schematic.types.SpongeSchematic;
import org.minerift.ether.util.math.Vec3i;

public class SpongeSchematicPaster implements ISchematicPaster<SpongeSchematic> {

@Override
public void paste(SpongeSchematic schem, Vec3i pos, String worldName) {
public void paste(SpongeSchematic schem, Vec3i pos, String worldName, SchematicPasteOptions options) {

final World world = Bukkit.getWorld(worldName);
Preconditions.checkNotNull(world, String.format("World %s could not be found!", worldName));
Expand All @@ -21,25 +22,30 @@ public void paste(SpongeSchematic schem, Vec3i pos, String worldName) {
final Vec3i.Mutable worldPasteLoc = pos.asMutable();
worldPasteLoc.add(schem.getOffset());

schem.getBlocks().forEach(block -> block.getPos().add(worldPasteLoc));
schem.getBiomes().forEach(biome -> biome.getPos().add(worldPasteLoc));
schem.getEntities().forEach(entity -> entity.getPos().add(worldPasteLoc));
// TODO: ignore air blocks based on options

// Lazily set blocks
schem.getBlocks().forEach(block -> block.getPos().add(worldPasteLoc)); // translate to proper pos
final NMSAccess nmsAccess = EtherPlugin.getInstance().getNMS();
nmsAccess.setBlocksAsyncLazy(schem.getBlocks(), world);

// Set biomes
schem.getBiomes().forEach(biomeArchetype -> {
final Biome biome = biomeArchetype.getBiome();
final Vec3i biomePos = biomeArchetype.getPos();
world.setBiome(biomePos.getX(), biomePos.getY(), biomePos.getZ(), biome);
});

// Place entities
/*schem.getEntities().forEach(entityArchetype -> {
nmsAccess.spawnEntity(entityArchetype, world);
});*/
if(options.copyBiomes) {
schem.getBiomes().forEach(biomeArchetype -> {
biomeArchetype.getPos().add(worldPasteLoc); // translate to proper pos
final Biome biome = biomeArchetype.getBiome();
final Vec3i biomePos = biomeArchetype.getPos();
world.setBiome(biomePos.getX(), biomePos.getY(), biomePos.getZ(), biome);
});
}

if(options.copyEntities) {
schem.getEntities().forEach(entity -> entity.getPos().add(worldPasteLoc)); // translate to proper pos
// TODO: Place entities
/*schem.getEntities().forEach(entityArchetype -> {
nmsAccess.spawnEntity(entityArchetype, world);
});*/
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,29 +8,37 @@
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.session.ClipboardHolder;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.minerift.ether.schematic.SchematicPasteOptions;
import org.minerift.ether.schematic.types.WorldEditSchematic;
import org.minerift.ether.util.math.Vec3i;

public class WESchematicPaster implements ISchematicPaster<WorldEditSchematic> {

@Override
public void paste(WorldEditSchematic schem, Vec3i pos, String worldName) {
public void paste(WorldEditSchematic schem, Vec3i pos, String worldName, SchematicPasteOptions options) {

final World world = Bukkit.getWorld(worldName);
Preconditions.checkNotNull(world, String.format("World %s could not be found!", worldName));

try(EditSession editSession = WorldEdit.getInstance().newEditSession(BukkitAdapter.adapt(world))) {

Clipboard clipboard = schem.getClipboard();
ClipboardHolder holder = new ClipboardHolder(clipboard);
final Clipboard clipboard = schem.getClipboard();
final ClipboardHolder holder = new ClipboardHolder(clipboard);

final Vec3i.Mutable vecTo = options.offset.asMutable();
vecTo.add(pos);

final BlockVector3 to = BlockVector3.at(vecTo.getX(), vecTo.getY(), vecTo.getZ());

Operation operation = holder.createPaste(editSession)
.to(clipboard.getOrigin().add(pos.getX(), pos.getY(), pos.getZ()))
.copyBiomes(false)
.copyEntities(true)
.ignoreAirBlocks(true)
.to(to)
.copyBiomes(options.copyBiomes)
.copyEntities(options.copyEntities)
.ignoreAirBlocks(options.ignoreAirBlocks)
.build();

Operations.completeLegacy(operation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,36 @@

import java.io.File;
import java.io.IOException;
import java.util.concurrent.atomic.AtomicReference;

public class SpongeSchematicReader implements ISchematicReader<SpongeSchematic> {

@Override
public Result<SpongeSchematic, SchematicFileReadException> read(File file) {

AtomicReference<Result<SpongeSchematic, SchematicFileReadException>> result = new AtomicReference<>(new Result<>());
Result<SpongeSchematic, SchematicFileReadException> result = new Result<>();
ReaderContext.from(file).handle((ctx) -> {
boolean success = true;
try {
ReadStages.INIT.read(ctx);
ReadStages.METADATA.read(ctx);
ReadStages.BLOCK_ENTITIES.read(ctx);
ReadStages.BLOCK_STATES.read(ctx);
ReadStages.BIOMES.read(ctx);
ReadStages.ENTITIES.read(ctx);
} catch (SchematicFileReadException e) {
// Delegate exception to result
result.get().err(e);
success = false;
}

// Set result to new SpongeSchematic
if(success) {
result.get().ok(ctx.builder.build());
}
result.ok(ctx.builder.build());

try {
ctx.close();
} catch (IOException e) {
throw new RuntimeException(e);
} catch (SchematicFileReadException ex) {
// Delegate exception to result
result.err(ex);
} catch (IOException ex) {
// Failed to close context; this should be notified
throw new RuntimeException(ex);
}
},
// Handle context error
(ex) -> result.get().err(ex));
// Delegate context error to result
result::err);

return result.get();
return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.google.common.base.Preconditions;
import org.minerift.ether.EtherPlugin;
import org.minerift.ether.schematic.SchematicFileReadException;
import org.minerift.ether.schematic.SchematicPasteOptions;
import org.minerift.ether.util.Result;
import org.minerift.ether.util.math.Vec3i;

Expand All @@ -27,10 +28,12 @@ static Result<Schematic, SchematicFileReadException> fromFile(File file) {

SchematicType getType();

void paste(Vec3i pos, String worldName);
void paste(Vec3i pos, String worldName, SchematicPasteOptions options);

int getWidth();
int getHeight();
int getLength();

Vec3i getOffset();

}
Loading

0 comments on commit cc16c7f

Please sign in to comment.