visual chunk

This commit is contained in:
Jesse Boyd 2019-07-20 15:32:15 +10:00
parent 85ebee7da7
commit ee5e15eda3
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
13 changed files with 309 additions and 196 deletions

View File

@ -50,6 +50,7 @@ dependencies {
tasks.withType(JavaCompile).configureEach {
dependsOn(":worldedit-libs:build")
it.options.compilerArgs << "-Xmaxerrs" << "10000"
it.options.compilerArgs.add("-Aarg.name.key.prefix=")
}

View File

@ -6,5 +6,5 @@ package com.boydti.fawe.beta;
public interface IBlocks extends Trimable {
boolean hasSection(int layer);
IChunkSet reset();
IBlocks reset();
}

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.beta;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.math.MutableBlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.biome.BiomeType;
@ -16,7 +17,7 @@ import java.util.concurrent.Future;
* Represents a chunk in the queue {@link IQueueExtent}
* Used for getting and setting blocks / biomes / entities
*/
public interface IChunk<T extends Future<T>> extends Trimable, Callable<T> {
public interface IChunk<T extends Future<T>> extends Trimable, Callable<T>, IChunkGet {
/**
* Initialize at the location
* @param extent
@ -25,6 +26,8 @@ public interface IChunk<T extends Future<T>> extends Trimable, Callable<T> {
*/
void init(IQueueExtent extent, int X, int Z);
IQueueExtent getQueue();
int getX();
int getZ();
@ -81,9 +84,17 @@ public interface IChunk<T extends Future<T>> extends Trimable, Callable<T> {
boolean setBlock(int x, int y, int z, BlockStateHolder block);
/* get - from the world */
BiomeType getBiome(int x, int z);
BiomeType getBiomeType(int x, int z);
BlockState getBlock(int x, int y, int z);
BaseBlock getFullBlock(int x, int y, int z);
CompoundTag getTag(int x, int y, int z);
@Override
default IBlocks reset() {
init(getQueue(), getX(), getZ());
return this;
}
}

View File

@ -1,6 +1,5 @@
package com.boydti.fawe.beta;
import com.sk89q.worldedit.math.MutableBlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
@ -42,8 +41,8 @@ public interface IDelegateChunk<U extends IChunk> extends IChunk {
}
@Override
default BiomeType getBiome(final int x, final int z) {
return getParent().getBiome(x, z);
default BiomeType getBiomeType(final int x, final int z) {
return getParent().getBiomeType(x, z);
}
@Override

View File

@ -1,7 +1,7 @@
package com.boydti.fawe.beta;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.implementation.WorldChunkCache;
import com.boydti.fawe.object.exception.FaweException;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.biome.BiomeType;
@ -82,18 +82,19 @@ public interface IQueueExtent extends Flushable, Trimable, Extent {
default BiomeType getBiome(final int x, final int z) {
final IChunk chunk = getCachedChunk(x >> 4, z >> 4);
return chunk.getBiome(x & 15, z & 15);
return chunk.getBiomeType(x & 15, z & 15);
}
@Override
default BlockVector3 getMinimumPoint() {
return getWorld().getMinimumPoint();
return BlockVector3.at(-30000000, 0, -30000000);
}
@Override
default BlockVector3 getMaximumPoint() {
return getWorld().getMaximumPoint();
return BlockVector3.at(30000000, FaweCache.WORLD_MAX_Y, 30000000);
}
/**
* Create a new root IChunk object<br>
* - Full chunks will be reused, so a more optimized chunk can be returned in that case<br>

View File

@ -9,10 +9,8 @@ import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.beta.IQueueExtent;
import com.boydti.fawe.beta.implementation.SingleThreadQueueExtent;
import com.boydti.fawe.beta.implementation.WorldChunkCache;
import com.boydti.fawe.beta.implementation.blocks.CharSetBlocks;
import com.boydti.fawe.util.MathMan;
import com.sk89q.worldedit.math.MutableBlockVector3;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
@ -45,6 +43,16 @@ public abstract class ChunkHolder implements IChunk, Supplier<IChunkGet> {
// block.flood(get, set, mask, block, );
}
@Override
public CompoundTag getTag(int x, int y, int z) {
return delegate.getFullBlock(this, x, y, z).getNbtData(); // TODO NOT IMPLEMENTED (add getTag delegate)
}
@Override
public boolean hasSection(int layer) {
return get != null && get.hasSection(layer);
}
@Override
public void filterBlocks(final Filter filter, ChunkFilterBlock block, @Nullable Region region) {
final IChunkGet get = getOrCreateGet();
@ -157,7 +165,7 @@ public abstract class ChunkHolder implements IChunk, Supplier<IChunkGet> {
}
@Override
public BiomeType getBiome(final int x, final int z) {
public BiomeType getBiomeType(final int x, final int z) {
return delegate.getBiome(this, x, z);
}
@ -202,7 +210,7 @@ public abstract class ChunkHolder implements IChunk, Supplier<IChunkGet> {
public BiomeType getBiome(final ChunkHolder chunk, final int x, final int z) {
chunk.getOrCreateGet();
chunk.delegate = GET;
return chunk.getBiome(x, z);
return chunk.getBiomeType(x, z);
}
@Override
@ -266,7 +274,7 @@ public abstract class ChunkHolder implements IChunk, Supplier<IChunkGet> {
public BiomeType getBiome(final ChunkHolder chunk, final int x, final int z) {
chunk.getOrCreateGet();
chunk.delegate = BOTH;
return chunk.getBiome(x, z);
return chunk.getBiomeType(x, z);
}
@Override

View File

@ -0,0 +1,83 @@
package com.boydti.fawe.command;
import com.google.common.collect.ImmutableSet;
import org.enginehub.piston.Command;
import org.enginehub.piston.CommandManager;
import org.enginehub.piston.CommandParseResult;
import org.enginehub.piston.converter.ArgumentConverter;
import org.enginehub.piston.inject.InjectedValueAccess;
import org.enginehub.piston.inject.Key;
import org.enginehub.piston.suggestion.Suggestion;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.stream.Stream;
public class CommandProcessor implements CommandManager {
private final CommandManager parent;
public CommandProcessor(CommandManager parent) {
this.parent = parent;
}
@Override
public Command.Builder newCommand(String s) {
return parent.newCommand(s);
}
@Override
public void register(Command command) {
parent.register(command);
}
@Override
public void register(String name, Consumer<Command.Builder> registrationProcess) {
parent.register(name, registrationProcess);
}
@Override
public void registerManager(CommandManager manager) {
parent.registerManager(manager);
}
@Override
public Stream<Command> getAllCommands() {
return parent.getAllCommands();
}
@Override
public boolean containsCommand(String name) {
return parent.containsCommand(name);
}
@Override
public Optional<Command> getCommand(String s) {
return parent.getCommand(s);
}
@Override
public ImmutableSet<Suggestion> getSuggestions(InjectedValueAccess injectedValueAccess, List<String> list) {
return parent.getSuggestions(injectedValueAccess, list);
}
@Override
public CommandParseResult parse(InjectedValueAccess injectedValueAccess, List<String> list) {
return parent.parse(injectedValueAccess, list);
}
@Override
public int execute(InjectedValueAccess context, List<String> args) {
return parent.execute(context, args);
}
@Override
public <T> void registerConverter(Key<T> key, ArgumentConverter<T> argumentConverter) {
parent.registerConverter(key, argumentConverter);
}
@Override
public <T> Optional<ArgumentConverter<T>> getConverter(Key<T> key) {
return parent.getConverter(key);
}
}

View File

@ -1,175 +1,48 @@
package com.boydti.fawe.object.brush.visualization;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.collection.SparseBitSet;
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
import com.boydti.fawe.util.MathMan;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.boydti.fawe.beta.implementation.blocks.BitSetBlocks;
import com.boydti.fawe.beta.implementation.holder.ChunkHolder;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.Future;
/**
* FAWE visualizations display glass (20) as a placeholder
* - Using a non transparent block can cause FPS lag
*/
public class VisualChunk extends FaweChunk<FaweChunk> {
public class VisualChunk extends ChunkHolder {
public static BlockState VISUALIZE_BLOCK = BlockTypes.BLACK_STAINED_GLASS.getDefaultState();
private final IChunk parent;
private final VisualExtent extent;
public static BlockStateHolder VISUALIZE_BLOCK = BlockTypes.BLACK_STAINED_GLASS.getDefaultState();
private SparseBitSet add;
private SparseBitSet remove;
/**
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
*
* @param x
* @param z
*/
public VisualChunk(int x, int z) {
super(null, x, z);
this.add = new SparseBitSet();
this.remove = new SparseBitSet();
public VisualChunk(IChunk parent, VisualExtent extent) {
this.parent = parent;
this.extent = extent;
}
protected VisualChunk(int x, int z, SparseBitSet add, SparseBitSet remove) {
super(null, x, z);
this.add = add;
this.remove = remove;
}
public int size() {
return add.cardinality() + remove.cardinality();
}
private final int getIndex(int x, int y, int z) {
return MathMan.tripleBlockCoordChar(x, y, z);
public IChunk getParent() {
return parent;
}
@Override
public int getBitMask() {
return 0;
public Future call() {
return extent.sendChunkUpdate(this);
}
@Override
public int getBlockCombinedId(int x, int y, int z) {
int index = getIndex(x, y, z);
if (add.get(index)) {
return VISUALIZE_BLOCK.getInternalId();
} else if (remove.get(index)) {
return 1;
} else {
return 0;
public IChunkGet get() {
if (parent instanceof ChunkHolder) {
return ((ChunkHolder) parent).get();
}
return parent;
}
@Override
public void forEachQueuedBlock(FaweChunkVisitor onEach) {
int index = -1;
while ((index = add.nextSetBit(index + 1)) != -1) {
int x = MathMan.untripleBlockCoordX(index);
int y = MathMan.untripleBlockCoordY(index);
int z = MathMan.untripleBlockCoordZ(index);
onEach.run(x, y, z, VISUALIZE_BLOCK.getInternalId());
}
index = -1;
while ((index = remove.nextSetBit(index + 1)) != -1) {
int x = MathMan.untripleBlockCoordX(index);
int y = MathMan.untripleBlockCoordY(index);
int z = MathMan.untripleBlockCoordZ(index);
onEach.run(x, y, z, 1);
}
}
@Override
public BiomeType[] getBiomeArray() {
return new BiomeType[256];
}
@Override
public FaweChunk getChunk() {
return this;
}
@Override
public void setTile(int x, int y, int z, CompoundTag tile) {
// Unsupported
}
@Override
public void setEntity(CompoundTag entity) {
// Unsupported
}
@Override
public void removeEntity(UUID uuid) {
// Unsupported
}
@Override
public void setBlock(int x, int y, int z, int combinedId) {
int index = getIndex(x, y, z);
try {
if (BlockTypes.getFromStateId(combinedId).getMaterial().isAir()) {
add.clear(index);
remove.set(index);
} else {
remove.clear(index);
add.set(index);
}
} catch (Throwable e) {
e.printStackTrace();
}
}
public void unset(int x, int y, int z) {
int index = getIndex(x, y, z);
remove.clear(index);
add.clear(index);
}
@Override
public Set<CompoundTag> getEntities() {
return new HashSet<>();
}
@Override
public Set<UUID> getEntityRemoves() {
return new HashSet<>();
}
@Override
public Map<Short, CompoundTag> getTiles() {
return new HashMap<>();
}
@Override
public CompoundTag getTile(int x, int y, int z) {
return null;
}
@Override
public void setBiome(int x, int z, BiomeType biome) {
// Unsupported
}
@Override
public FaweChunk copy(boolean shallow) {
if (shallow) {
return new VisualChunk(getX(), getZ(), add, remove);
} else {
return new VisualChunk(getX(), getZ(), add.clone(), remove.clone());
}
}
@Override
public FaweChunk call() {
return this;
public IChunkSet set() {
return new BitSetBlocks(VISUALIZE_BLOCK);
}
}

View File

@ -14,6 +14,8 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import java.util.concurrent.Future;
public class VisualExtent extends AbstractDelegateExtent {
private final IQueueExtent queue;
@ -95,4 +97,8 @@ public class VisualExtent extends AbstractDelegateExtent {
queue.sendBlockUpdate(chunk, players);
}
}
public Future sendChunkUpdate(VisualChunk visualChunk) {
return null; // TODO NOT IMPLEMENTED
}
}

View File

@ -45,6 +45,27 @@ public class StringMan {
return false;
}
public static boolean containsIgnoreCase(String haystack, String needle) {
final int length = needle.length();
if (length == 0)
return true; // Empty string is contained
final char firstLo = Character.toLowerCase(needle.charAt(0));
final char firstUp = Character.toUpperCase(needle.charAt(0));
for (int i = haystack.length() - length; i >= 0; i--) {
// Quick check before calling the more expensive regionMatches() method:
final char ch = haystack.charAt(i);
if (ch != firstLo && ch != firstUp)
continue;
if (haystack.regionMatches(true, i, needle, 0, length))
return true;
}
return false;
}
public static int findMatchingBracket(CharSequence sequence, int index) {
char startC = sequence.charAt(index);
char lookC = getMatchingBracket(startC);

View File

@ -0,0 +1,136 @@
package com.sk89q.worldedit.command;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.StringMan;
import com.sk89q.worldedit.command.util.CommandPermissions;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import org.enginehub.piston.annotation.Command;
import org.enginehub.piston.annotation.CommandContainer;
import org.enginehub.piston.annotation.param.Arg;
import java.io.File;
import java.io.IOException;
import java.util.Locale;
import java.util.UUID;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
@CommandContainer
public class SchemListFilters {
public class Filter {
public boolean listPrivate() {
return true;
}
public boolean listPublic() {
return false;
}
public File getPath(File root) {
return root;
}
public boolean applies(File file) {
return true;
}
}
@Command(
name = "all",
desc = "List both public and private schematics"
)
public Filter all() {
return new Filter() {
@Override
public boolean listPublic() {
return true;
}
};
}
@Command(
name = "private",
aliases = {"me", "mine", "local"},
desc = "List your personal schematics"
)
public Filter local() {
return new Filter();
}
@Command(
name = "public",
aliases = {"global"},
desc = "List public schematics"
)
public Filter global() {
return new Filter() {
@Override
public boolean listPrivate() {
return false;
}
@Override
public boolean listPublic() {
return true;
}
};
}
@Command(
name = "",
desc = "wildcard"
)
public Filter wildcard(Actor actor, String arg) {
arg = arg.replace("/", File.separator);
String argLower = arg.toLowerCase(Locale.ROOT);
if (arg.endsWith("/") || arg.endsWith(File.separator)) {
if (arg.length() > 3 && arg.length() <= 16) {
// possible player name
}
} else {
if (StringMan.containsAny(arg, "\\^$.|?+(){}<>~$!%^&*+-/")) {
Pattern pattern;
try {
pattern = Pattern.compile(argLower);
} catch (PatternSyntaxException ignore) {
pattern = Pattern.compile(Pattern.quote(argLower));
}
Pattern finalPattern = pattern;
return new Filter() {
@Override
public boolean applies(File file) {
String path = file.getPath().toLowerCase(Locale.ROOT);
return finalPattern.matcher(path).find();
}
};
}
return new Filter() {
@Override
public boolean applies(File file) {
return StringMan.containsIgnoreCase(file.getPath(), argLower);
}
};
}
if (arg.endsWith("/") || arg.endsWith(File.separator)) {
arg = arg.replace("/", File.separator);
String newDirFilter = dirFilter + arg;
boolean exists = new File(dir, newDirFilter).exists() || playerFolder && MainUtil.resolveRelative(new File(dir, actor.getUniqueId() + newDirFilter)).exists();
if (!exists) {
arg = arg.substring(0, arg.length() - File.separator.length());
if (arg.length() > 3 && arg.length() <= 16) {
UUID fromName = Fawe.imp().getUUID(arg);
if (fromName != null) {
newDirFilter = dirFilter + fromName + File.separator;
listGlobal = true;
}
}
}
dirFilter = newDirFilter;
}
else {
filters.add(arg);
}
}
}

View File

@ -30,6 +30,7 @@ import com.boydti.fawe.object.RunnableVal3;
import com.boydti.fawe.object.clipboard.MultiClipboardHolder;
import com.boydti.fawe.object.clipboard.URIClipboardHolder;
import com.boydti.fawe.object.clipboard.remap.ClipboardRemapper;
import com.boydti.fawe.object.schematic.MinecraftStructure;
import com.boydti.fawe.object.schematic.StructureFormat;
import com.boydti.fawe.util.MainUtil;

View File

@ -104,7 +104,7 @@ import org.enginehub.piston.annotation.param.Switch;
* Utility commands.
*/
@CommandContainer(superTypes = {CommandPermissionsConditionGenerator.Registration.class, CommandQueuedConditionGenerator.Registration.class})
@Command(aliases = {}, desc = "Various utility commands: [More Info](http://wiki.sk89q.com/wiki/WorldEdit/Utilities)")
//@Command(aliases = {}, desc = "Various utility commands: [More Info](http://wiki.sk89q.com/wiki/WorldEdit/Utilities)")
public class UtilityCommands {
private final WorldEdit we;
@ -693,34 +693,6 @@ public class UtilityCommands {
PrintCommandHelp.help(command, page, listSubCommands, we, actor);
}
protected static CommandMapping detectCommand(Dispatcher dispatcher, String command, boolean isRootLevel) {
CommandMapping mapping;
// First try the command as entered
mapping = dispatcher.get(command);
if (mapping != null) {
return mapping;
}
// Then if we're looking at root commands and the user didn't use
// any slashes, let's try double slashes and then single slashes.
// However, be aware that there exists different single slash
// and double slash commands in WorldEdit
if (isRootLevel && !command.contains("/")) {
mapping = dispatcher.get("//" + command);
if (mapping != null) {
return mapping;
}
mapping = dispatcher.get("/" + command);
if (mapping != null) {
return mapping;
}
}
return null;
}
public static void list(File dir, Actor actor, InjectedValueAccess args, @Range(min = 0) int page, String formatName, boolean playerFolder, String onClickCmd) {
list(dir, actor, args, page, -1, formatName, playerFolder, new RunnableVal3<Message, URI, String>() {
@Override
@ -800,6 +772,7 @@ public class UtilityCommands {
public static int getFiles(File dir, Actor actor, InjectedValueAccess args, @Range(min = 0) int page, int perPage, String formatName, boolean playerFolder, Consumer<File> forEachFile) {
Consumer<File> rootFunction = forEachFile;
//schem list all <path>
int len = args.argsLength();
List<String> filters = new ArrayList<>();