Various major

Add regen
Add //history [find|restore|rollback|summary|clear]
 - history commands are interactable
 - inspect brush info is interactable
Commands are now logged to a searchable database
Fix some cases of id/ordinal mismatch
This commit is contained in:
Jesse Boyd
2019-11-23 04:31:48 +00:00
parent edcaeb6cfe
commit 1844d4dba7
56 changed files with 1236 additions and 924 deletions

View File

@ -1,56 +0,0 @@
package com.boydti.fawe.bukkit;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.TranslatableComponent;
import com.boydti.fawe.object.FaweCommand;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitBlockCommandSender;
import com.sk89q.worldedit.bukkit.BukkitCommandSender;
import com.sk89q.worldedit.bukkit.WorldEditPlugin;
import com.sk89q.worldedit.extension.platform.Actor;
import org.bukkit.command.BlockCommandSender;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class BukkitCommand implements CommandExecutor {
private final FaweCommand cmd;
public BukkitCommand(FaweCommand cmd) {
this.cmd = cmd;
}
@Override
public boolean onCommand(@NotNull CommandSender sender, Command cmd, String label, String[] args) {
final Actor plr = wrapCommandSender(sender);
if (!sender.hasPermission(this.cmd.getPerm()) && !sender.isOp()) {
plr.printError(TranslatableComponent.of("fawe.error.no.perm", TextComponent.of(this.cmd.getPerm())));
return true;
}
this.cmd.executeSafe(plr, args);
return true;
}
/**
* Used to wrap a Bukkit Player as a WorldEdit Player.
*
* @param player a player
* @return a wrapped player
*/
public com.sk89q.worldedit.bukkit.BukkitPlayer wrapPlayer(Player player) {
return BukkitAdapter.adapt(player);
}
public Actor wrapCommandSender(CommandSender sender) {
if (sender instanceof Player) {
return wrapPlayer((Player) sender);
} else if (sender instanceof BlockCommandSender) {
return new BukkitBlockCommandSender(WorldEditPlugin.getInstance(), (BlockCommandSender) sender);
}
return new BukkitCommandSender(WorldEditPlugin.getInstance(), sender);
}
}

View File

@ -3,6 +3,7 @@ package com.boydti.fawe.bukkit.adapter.mc1_14;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
import com.bekvon.bukkit.residence.commands.set;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.IChunkSet;
@ -67,26 +68,18 @@ import org.jetbrains.annotations.NotNull;
public class BukkitGetBlocks_1_14 extends CharGetBlocks {
public ChunkSection[] sections;
public Chunk nmsChunk;
public CraftWorld world;
public WorldServer world;
public int X, Z;
// private boolean forceLoad;
public BukkitGetBlocks_1_14(World world, int X, int Z, boolean forceLoad) {
this.world = (CraftWorld) world;
this.X = X;
this.Z = Z;
// if (forceLoad) {
// this.world.getHandle().setForceLoaded(X, Z, this.forceLoad = true);
// }
public BukkitGetBlocks_1_14(World world, int X, int Z) {
this(((CraftWorld) world).getHandle(), X, Z);
}
// @Override
// protected void finalize() {
// if (forceLoad) {
// this.world.getHandle().setForceLoaded(X, Z, forceLoad = false);
// }
// }
public BukkitGetBlocks_1_14(WorldServer world, int X, int Z) {
this.world = world;
this.X = X;
this.Z = Z;
}
public int getX() {
return X;
@ -133,14 +126,16 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks {
@Override
public CompoundTag getEntity(UUID uuid) {
org.bukkit.entity.Entity bukkitEnt = world.getEntity(uuid);
if (bukkitEnt != null) {
Entity entity = world.getEntity(uuid);
if (entity != null) {
org.bukkit.entity.Entity bukkitEnt = entity.getBukkitEntity();
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
}
for (List<Entity> entry : getChunk().getEntitySlices()) {
if (entry != null) {
for (Entity entity : entry) {
if (uuid.equals(entity.getUniqueID())) {
for (Entity ent : entry) {
if (uuid.equals(ent.getUniqueID())) {
org.bukkit.entity.Entity bukkitEnt = ent.getBukkitEntity();
return BukkitAdapter.adapt(bukkitEnt).getState().getNbtData();
}
}
@ -235,7 +230,7 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks {
@Override
public <T extends Future<T>> T call(IChunkSet set, Runnable finalizer) {
try {
WorldServer nmsWorld = world.getHandle();
WorldServer nmsWorld = world;
Chunk nmsChunk = BukkitAdapter_1_14.ensureLoaded(nmsWorld, X, Z);
// Remove existing tiles
@ -633,7 +628,7 @@ public class BukkitGetBlocks_1_14 extends CharGetBlocks {
synchronized (this) {
tmp = nmsChunk;
if (tmp == null) {
nmsChunk = tmp = BukkitAdapter_1_14.ensureLoaded(this.world.getHandle(), X, Z);
nmsChunk = tmp = BukkitAdapter_1_14.ensureLoaded(this.world, X, Z);
}
}
}

View File

@ -10,6 +10,7 @@ import org.bukkit.World;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.function.Supplier;
import static com.google.common.base.Preconditions.checkNotNull;
@ -19,10 +20,10 @@ public class GriefPreventionFilter extends CuboidRegionFilter {
public GriefPreventionFilter(World world) {
checkNotNull(world);
this.claims = TaskManager.IMP.sync(new RunnableVal<Collection<Claim>>() {
this.claims = TaskManager.IMP.sync(new Supplier<Collection<Claim>>() {
@Override
public void run(Collection<Claim> claims) {
this.value = new ArrayDeque<>(GriefPrevention.instance.dataStore.getClaims());
public Collection<Claim> get() {
return new ArrayDeque<>(GriefPrevention.instance.dataStore.getClaims());
}
});
this.world = world;

View File

@ -3,6 +3,7 @@ package com.boydti.fawe.bukkit.filter;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.slf4j.LoggerFactory.getLogger;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.regions.general.CuboidRegionFilter;
@ -26,20 +27,17 @@ public class WorldGuardFilter extends CuboidRegionFilter {
}
@Override
public void calculateRegions() {
TaskManager.IMP.sync(new RunnableVal<Object>() {
@Override
public void run(Object value) {
WorldGuardFilter.this.manager = WorldGuard.getInstance().getPlatform().getRegionContainer().get(FaweAPI.getWorld(world.getName()));
for (ProtectedRegion region : manager.getRegions().values()) {
BlockVector3 min = region.getMinimumPoint();
BlockVector3 max = region.getMaximumPoint();
if (max.getBlockX() - min.getBlockX() > 1024 || max.getBlockZ() - min.getBlockZ() > 1024) {
getLogger(WorldGuardFilter.class).debug("Large or complex region shapes cannot be optimized. Filtering will be slower");
large = true;
break;
}
add(min.toBlockVector2(), max.toBlockVector2());
Fawe.get().getQueueHandler().sync(() -> {
WorldGuardFilter.this.manager = WorldGuard.getInstance().getPlatform().getRegionContainer().get(FaweAPI.getWorld(world.getName()));
for (ProtectedRegion region : manager.getRegions().values()) {
BlockVector3 min = region.getMinimumPoint();
BlockVector3 max = region.getMaximumPoint();
if (max.getBlockX() - min.getBlockX() > 1024 || max.getBlockZ() - min.getBlockZ() > 1024) {
getLogger(WorldGuardFilter.class).debug("Large or complex region shapes cannot be optimized. Filtering will be slower");
large = true;
break;
}
add(min.toBlockVector2(), max.toBlockVector2());
}
});
}

View File

@ -74,27 +74,6 @@ public class BukkitBlockCommandSender extends AbstractNonPlayerActor implements
}
}
@Override
public void print(String msg) {
for (String part : msg.split("\n")) {
print(TextComponent.of(part, TextColor.GRAY));
}
}
@Override
public void printDebug(String msg) {
for (String part : msg.split("\n")) {
print(TextComponent.of(part, TextColor.GRAY));
}
}
@Override
public void printError(String msg) {
for (String part : msg.split("\n")) {
print(TextComponent.of(part, TextColor.RED));
}
}
@Override
public void print(Component component) {
TextAdapter.sendComponent(sender, WorldEditText.format(component, getLocale()));

View File

@ -74,27 +74,6 @@ public class BukkitCommandSender extends AbstractNonPlayerActor {
}
}
@Override
public void print(String msg) {
for (String part : msg.split("\n")) {
sender.sendMessage("\u00A7d" + part);
}
}
@Override
public void printDebug(String msg) {
for (String part : msg.split("\n")) {
sender.sendMessage("\u00A77" + part);
}
}
@Override
public void printError(String msg) {
for (String part : msg.split("\n")) {
sender.sendMessage("\u00A7c" + part);
}
}
@Override
public void print(Component component) {
TextAdapter.sendComponent(sender, WorldEditText.format(component, getLocale()));

View File

@ -190,6 +190,10 @@ public class BukkitWorld extends AbstractWorld {
@Override
public boolean regenerate(Region region, EditSession editSession) {
BukkitImplAdapter adapter = WorldEditPlugin.getInstance().getBukkitImplAdapter();
if (adapter != null) {
return adapter.regenerate(this, region, editSession);
}
/*
BaseBlock[] history = new BaseBlock[16 * 16 * (getMaxY() + 1)];
@ -560,7 +564,7 @@ public class BukkitWorld extends AbstractWorld {
@Override
public IChunkGet get(int chunkX, int chunkZ) {
return new BukkitGetBlocks_1_14(getWorldChecked(), chunkX, chunkZ, Settings.IMP.QUEUE.POOL);
return new BukkitGetBlocks_1_14(getWorldChecked(), chunkX, chunkZ);
}
@Override

View File

@ -24,11 +24,13 @@ import com.boydti.fawe.beta.implementation.packet.ChunkPacket;
import com.boydti.fawe.bukkit.FaweBukkit;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.blocks.BaseItem;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.util.Direction;
import com.sk89q.worldedit.world.DataFixer;
@ -232,4 +234,8 @@ public interface BukkitImplAdapter<T> extends IBukkitAdapter {
default void sendFakeChunk(org.bukkit.World world, Player player, ChunkPacket packet) {
throw new UnsupportedOperationException("Cannot send fake chunks");
}
default boolean regenerate(com.sk89q.worldedit.world.World world, Region region, EditSession editSession) {
return editSession.regenerate(region);
}
}

View File

@ -20,23 +20,35 @@
package com.sk89q.worldedit.bukkit.adapter.impl;
import com.bekvon.bukkit.residence.commands.material;
import com.bekvon.bukkit.residence.commands.server;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.beta.implementation.packet.ChunkPacket;
import com.boydti.fawe.beta.implementation.queue.SingleThreadQueueExtent;
import com.boydti.fawe.bukkit.adapter.BukkitQueueHandler;
import com.boydti.fawe.bukkit.adapter.mc1_14.BlockMaterial_1_14;
import com.boydti.fawe.bukkit.adapter.mc1_14.BukkitAdapter_1_14;
import com.boydti.fawe.bukkit.adapter.mc1_14.BukkitGetBlocks_1_14;
import com.boydti.fawe.bukkit.adapter.mc1_14.MapChunkUtil_1_14;
import com.boydti.fawe.bukkit.adapter.mc1_14.nbt.LazyCompoundTag_1_14;
import com.google.common.io.Files;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.blocks.TileEntityBlock;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.bukkit.BukkitWorld;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.CachedBukkitAdapter;
import com.sk89q.worldedit.bukkit.adapter.IDelegateBukkitImplAdapter;
import com.sk89q.worldedit.bukkit.adapter.impl.Spigot_v1_14_R4;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.LazyBaseEntity;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
@ -50,6 +62,7 @@ import net.minecraft.server.v1_14_R1.Block;
import net.minecraft.server.v1_14_R1.BlockPosition;
import net.minecraft.server.v1_14_R1.Chunk;
import net.minecraft.server.v1_14_R1.ChunkCoordIntPair;
import net.minecraft.server.v1_14_R1.ChunkProviderServer;
import net.minecraft.server.v1_14_R1.ChunkSection;
import net.minecraft.server.v1_14_R1.Entity;
import net.minecraft.server.v1_14_R1.EntityPlayer;
@ -58,6 +71,7 @@ import net.minecraft.server.v1_14_R1.IBlockData;
import net.minecraft.server.v1_14_R1.IRegistry;
import net.minecraft.server.v1_14_R1.ItemStack;
import net.minecraft.server.v1_14_R1.MinecraftKey;
import net.minecraft.server.v1_14_R1.MinecraftServer;
import net.minecraft.server.v1_14_R1.NBTBase;
import net.minecraft.server.v1_14_R1.NBTTagCompound;
import net.minecraft.server.v1_14_R1.NBTTagInt;
@ -65,11 +79,13 @@ import net.minecraft.server.v1_14_R1.PacketPlayOutMapChunk;
import net.minecraft.server.v1_14_R1.PlayerChunk;
import net.minecraft.server.v1_14_R1.TileEntity;
import net.minecraft.server.v1_14_R1.World;
import net.minecraft.server.v1_14_R1.WorldNBTStorage;
import net.minecraft.server.v1_14_R1.WorldServer;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_14_R1.CraftChunk;
import org.bukkit.craftbukkit.v1_14_R1.CraftServer;
import org.bukkit.craftbukkit.v1_14_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_14_R1.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_14_R1.entity.CraftEntity;
@ -80,6 +96,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.OptionalInt;
@ -358,4 +376,53 @@ public final class FAWE_Spigot_v1_14_R4 extends CachedBukkitAdapter implements I
}
return parent.fromNative(foreign);
}
@Override
public boolean regenerate(com.sk89q.worldedit.world.World world, Region region, EditSession editSession) {
WorldServer originalWorld = ((CraftWorld) world).getHandle();
ChunkProviderServer provider = originalWorld.getChunkProvider();
if (!(provider instanceof ChunkProviderServer)) {
return false;
}
File saveFolder = Files.createTempDir();
// register this just in case something goes wrong
// normally it should be deleted at the end of this method
saveFolder.deleteOnExit();
try {
CraftServer server = originalWorld.getServer();
WorldNBTStorage originalDataManager = originalWorld.getDataManager();
WorldNBTStorage saveHandler = new WorldNBTStorage(saveFolder, originalDataManager.getDirectory().getName(), server.getServer(), originalDataManager.getDataFixer());
try (WorldServer freshWorld = new WorldServer(server.getServer(),
server.getServer().executorService, saveHandler,
originalWorld.worldData,
originalWorld.worldProvider.getDimensionManager(),
originalWorld.getMethodProfiler(),
server.getServer().worldLoadListenerFactory.create(11),
((CraftWorld) world).getEnvironment(),
server.getGenerator(world.getName()))) {
// Pre-gen all the chunks
// We need to also pull one more chunk in every direction
CuboidRegion expandedPreGen = new CuboidRegion(region.getMinimumPoint().subtract(16, 0, 16), region.getMaximumPoint().add(16, 0, 16));
for (BlockVector2 chunk : expandedPreGen.getChunks()) {
freshWorld.getChunkAt(chunk.getBlockX(), chunk.getBlockZ());
}
// TODO optimize
SingleThreadQueueExtent extent = new SingleThreadQueueExtent();
extent.init(null, (x, z) -> new BukkitGetBlocks_1_14(freshWorld, x, z), null);
for (BlockVector3 vec : region) {
editSession.setBlock(vec, extent.getFullBlock(vec));
}
} catch (IOException e) {
throw new RuntimeException(e);
}
} catch (MaxChangedBlocksException e) {
throw new RuntimeException(e);
} finally {
saveFolder.delete();
}
return true;
}
}