mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2024-12-22 17:27:38 +00:00
[Forge] Make //regen work better
It now creates a brand-new world, generates the appropriate section there, and copies it over to the original world.
This commit is contained in:
parent
e9419f4280
commit
1752963288
@ -19,16 +19,22 @@
|
||||
|
||||
package com.sk89q.worldedit.forge;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
import com.sk89q.jnbt.CompoundTag;
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.BlockVector;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.Vector2D;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BaseItem;
|
||||
import com.sk89q.worldedit.blocks.BaseItemStack;
|
||||
import com.sk89q.worldedit.blocks.LazyBlock;
|
||||
import com.sk89q.worldedit.entity.BaseEntity;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.history.change.BlockChange;
|
||||
import com.sk89q.worldedit.internal.Constants;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.Direction;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
@ -36,40 +42,55 @@ import com.sk89q.worldedit.util.TreeGenerator.TreeType;
|
||||
import com.sk89q.worldedit.world.AbstractWorld;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import com.sk89q.worldedit.world.registry.WorldData;
|
||||
import net.minecraft.block.*;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockLeaves;
|
||||
import net.minecraft.block.BlockOldLeaf;
|
||||
import net.minecraft.block.BlockOldLog;
|
||||
import net.minecraft.block.BlockPlanks;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.EntityList;
|
||||
import net.minecraft.entity.item.EntityItem;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.server.management.PlayerChunkMap;
|
||||
import net.minecraft.server.management.PlayerChunkMapEntry;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.EnumActionResult;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.IChunkGenerator;
|
||||
import net.minecraft.world.chunk.IChunkProvider;
|
||||
import net.minecraft.world.chunk.storage.AnvilSaveHandler;
|
||||
import net.minecraft.world.gen.ChunkProviderServer;
|
||||
import net.minecraft.world.gen.feature.*;
|
||||
import net.minecraft.world.gen.feature.WorldGenBigMushroom;
|
||||
import net.minecraft.world.gen.feature.WorldGenBigTree;
|
||||
import net.minecraft.world.gen.feature.WorldGenBirchTree;
|
||||
import net.minecraft.world.gen.feature.WorldGenCanopyTree;
|
||||
import net.minecraft.world.gen.feature.WorldGenMegaJungle;
|
||||
import net.minecraft.world.gen.feature.WorldGenMegaPineTree;
|
||||
import net.minecraft.world.gen.feature.WorldGenSavannaTree;
|
||||
import net.minecraft.world.gen.feature.WorldGenShrub;
|
||||
import net.minecraft.world.gen.feature.WorldGenSwamp;
|
||||
import net.minecraft.world.gen.feature.WorldGenTaiga1;
|
||||
import net.minecraft.world.gen.feature.WorldGenTaiga2;
|
||||
import net.minecraft.world.gen.feature.WorldGenTrees;
|
||||
import net.minecraft.world.gen.feature.WorldGenerator;
|
||||
import net.minecraftforge.common.DimensionManager;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
@ -80,7 +101,6 @@ public class ForgeWorld extends AbstractWorld {
|
||||
|
||||
private static final Random random = new Random();
|
||||
private static final int UPDATE = 1, NOTIFY = 2;
|
||||
private static final Logger logger = Logger.getLogger(ForgeWorld.class.getCanonicalName());
|
||||
|
||||
private static final IBlockState JUNGLE_LOG = Blocks.LOG.getDefaultState().withProperty(BlockOldLog.VARIANT, BlockPlanks.EnumType.JUNGLE);
|
||||
private static final IBlockState JUNGLE_LEAF = Blocks.LEAVES.getDefaultState().withProperty(BlockOldLeaf.VARIANT, BlockPlanks.EnumType.JUNGLE).withProperty(BlockLeaves.CHECK_DECAY, Boolean.valueOf(false));
|
||||
@ -246,73 +266,41 @@ public class ForgeWorld extends AbstractWorld {
|
||||
if (!(provider instanceof ChunkProviderServer)) {
|
||||
return false;
|
||||
}
|
||||
BaseBlock[] history = new BaseBlock[256 * (getMaxY() + 1)];
|
||||
|
||||
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();
|
||||
|
||||
for (Vector2D chunk : region.getChunks()) {
|
||||
Vector min = new Vector(chunk.getBlockX() * 16, 0, chunk.getBlockZ() * 16);
|
||||
WorldServer originalWorld = (WorldServer) getWorld();
|
||||
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int y = 0; y < getMaxY() + 1; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
Vector pt = min.add(x, y, z);
|
||||
int index = y * 16 * 16 + z * 16 + x;
|
||||
history[index] = editSession.getBlock(pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
PlayerChunkMap playerManager = ((WorldServer) getWorld()).getPlayerChunkMap();
|
||||
List<EntityPlayerMP> oldWatchers = null;
|
||||
Chunk mcChunk = null;
|
||||
try {
|
||||
ChunkProviderServer chunkServer = (ChunkProviderServer) provider;
|
||||
IChunkGenerator gen = chunkServer.chunkGenerator;
|
||||
long pos = ChunkPos.asLong(chunk.getBlockX(), chunk.getBlockZ());
|
||||
if (chunkServer.chunkExists(chunk.getBlockX(), chunk.getBlockZ())) {
|
||||
mcChunk = chunkServer.loadChunk(chunk.getBlockX(), chunk.getBlockZ());
|
||||
PlayerChunkMapEntry entry = playerManager.getEntry(chunk.getBlockX(), chunk.getBlockZ());
|
||||
if (entry != null) {
|
||||
oldWatchers = entry.players;
|
||||
playerManager.removeEntry(entry);
|
||||
}
|
||||
mcChunk.onChunkUnload();
|
||||
}
|
||||
chunkServer.droppedChunksSet.remove(pos);
|
||||
chunkServer.id2ChunkMap.remove(pos);
|
||||
mcChunk = gen.provideChunk(chunk.getBlockX(), chunk.getBlockZ());
|
||||
chunkServer.id2ChunkMap.put(pos, mcChunk);
|
||||
if (mcChunk != null) {
|
||||
mcChunk.onChunkLoad();
|
||||
mcChunk.populateChunk(chunkServer, chunkServer.chunkGenerator);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
logger.log(Level.WARNING, "Failed to generate chunk", t);
|
||||
return false;
|
||||
}
|
||||
MinecraftServer server = originalWorld.getMinecraftServer();
|
||||
AnvilSaveHandler saveHandler = new AnvilSaveHandler(saveFolder,
|
||||
originalWorld.getSaveHandler().getWorldDirectory().getName(), true, server.getDataFixer());
|
||||
World freshWorld = new WorldServer(server, saveHandler, originalWorld.getWorldInfo(),
|
||||
originalWorld.provider.getDimension(), originalWorld.theProfiler).init();
|
||||
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int y = 0; y < getMaxY() + 1; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
Vector pt = min.add(x, y, z);
|
||||
int index = y * 16 * 16 + z * 16 + x;
|
||||
|
||||
if (!region.contains(pt))
|
||||
editSession.smartSetBlock(pt, history[index]);
|
||||
else {
|
||||
editSession.getChangeSet().add(new BlockChange(pt.toBlockVector(), history[index], editSession.getBlock(pt)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// We don't need to recreate the ChunkMapEntry unless there are players
|
||||
// but addPlayer handles that for us
|
||||
if (oldWatchers != null) {
|
||||
for (EntityPlayerMP player : oldWatchers) {
|
||||
playerManager.addPlayer(player);
|
||||
}
|
||||
// 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 (Vector2D chunk : expandedPreGen.getChunks()) {
|
||||
freshWorld.getChunkFromChunkCoords(chunk.getBlockX(), chunk.getBlockZ());
|
||||
}
|
||||
|
||||
ForgeWorld from = new ForgeWorld(freshWorld);
|
||||
try {
|
||||
for (BlockVector vec : region) {
|
||||
editSession.setBlock(vec, from.getBlock(vec));
|
||||
}
|
||||
} catch (MaxChangedBlocksException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
saveFolder.delete();
|
||||
DimensionManager.setWorld(originalWorld.provider.getDimension(), null, server);
|
||||
DimensionManager.setWorld(originalWorld.provider.getDimension(), originalWorld, server);
|
||||
}
|
||||
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
Loading…
Reference in New Issue
Block a user