This commit is contained in:
Jesse Boyd
2020-01-04 10:12:33 +00:00
66 changed files with 878 additions and 862 deletions

View File

@ -29,7 +29,6 @@ import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.DataException;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
@ -55,11 +54,10 @@ public class AnvilChunk implements Chunk {
/**
* Construct the chunk with a compound tag.
*
* @param world the world to construct the chunk for
* @param tag the tag to read
* @throws DataException on a data error
*/
public AnvilChunk(World world, CompoundTag tag) throws DataException {
public AnvilChunk(CompoundTag tag) throws DataException {
rootTag = tag;
rootX = NBTUtils.getChildTag(rootTag.getValue(), "xPos", IntTag.class).getValue();
@ -261,13 +259,11 @@ public class AnvilChunk implements Chunk {
WorldEdit.logger.warn("Unknown legacy block " + id + ":" + data + " found when loading legacy anvil chunk.");
return BlockTypes.AIR.getDefaultState().toBaseBlock();
}
if (state.getMaterial().hasContainer()) {
CompoundTag tileEntity = getBlockTileEntity(position);
if (tileEntity != null) {
return state.toBaseBlock(tileEntity);
}
}
return state.toBaseBlock();
}

View File

@ -226,9 +226,9 @@ public class AnvilChunk13 implements Chunk {
BlockState[] sectionBlocks = blocks[section];
BlockState state = sectionBlocks != null ? sectionBlocks[(yIndex << 8) | (z << 4) | x] : BlockTypes.AIR.getDefaultState();
if (state.getMaterial().hasContainer()) {
CompoundTag tileEntity = getBlockTileEntity(position);
if (tileEntity != null) {
return state.toBaseBlock(tileEntity);
}

View File

@ -28,7 +28,6 @@ import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.DataException;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockTypes;
@ -55,11 +54,10 @@ public class OldChunk implements Chunk {
/**
* Construct the chunk with a compound tag.
*
* @param world the world
* @param tag the tag
* @throws DataException
*/
public OldChunk(World world, CompoundTag tag) throws DataException {
public OldChunk(CompoundTag tag) throws DataException {
rootTag = tag;
blocks = NBTUtils.getChildTag(rootTag.getValue(), "Blocks", ByteArrayTag.class).getValue();
@ -185,13 +183,12 @@ public class OldChunk implements Chunk {
WorldEdit.logger.warn("Unknown legacy block " + id + ":" + dataVal + " found when loading legacy anvil chunk.");
return BlockTypes.AIR.getDefaultState().toBaseBlock();
}
if (state.getBlockType().getMaterial().hasContainer()) {
CompoundTag tileEntity = getBlockTileEntity(position);
if (tileEntity != null) {
return state.toBaseBlock(tileEntity);
}
}
return state.toBaseBlock();
}

View File

@ -20,34 +20,19 @@
package com.sk89q.worldedit.world.storage;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.DataException;
import com.sk89q.worldedit.world.DataFixer;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.chunk.AnvilChunk;
import com.sk89q.worldedit.world.chunk.AnvilChunk13;
import com.sk89q.worldedit.world.chunk.Chunk;
import com.sk89q.worldedit.world.chunk.OldChunk;
import java.io.Closeable;
import java.io.IOException;
import java.util.Map;
/**
* Represents chunk storage mechanisms.
*/
public abstract class ChunkStore implements Closeable {
/**
* The DataVersion for Minecraft 1.13
*/
private static final int DATA_VERSION_MC_1_13 = 1519;
/**
* {@code >>} - to chunk
* {@code <<} - from chunk
@ -85,46 +70,7 @@ public abstract class ChunkStore implements Closeable {
*/
public Chunk getChunk(BlockVector2 position, World world) throws DataException, IOException {
CompoundTag rootTag = getChunkTag(position, world);
Map<String, Tag> children = rootTag.getValue();
CompoundTag tag = null;
// Find Level tag
for (Map.Entry<String, Tag> entry : children.entrySet()) {
if (entry.getKey().equals("Level")) {
if (entry.getValue() instanceof CompoundTag) {
tag = (CompoundTag) entry.getValue();
break;
} else {
throw new ChunkStoreException("CompoundTag expected for 'Level'; got " + entry.getValue().getClass().getName());
}
}
}
if (tag == null) {
throw new ChunkStoreException("Missing root 'Level' tag");
}
int dataVersion = rootTag.getInt("DataVersion");
if (dataVersion == 0) dataVersion = -1;
final Platform platform = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING);
final int currentDataVersion = platform.getDataVersion();
if (tag.getValue().containsKey("Sections") && dataVersion < currentDataVersion) { // only fix up MCA format, DFU doesn't support MCR chunks
final DataFixer dataFixer = platform.getDataFixer();
if (dataFixer != null) {
return new AnvilChunk13((CompoundTag) dataFixer.fixUp(DataFixer.FixTypes.CHUNK, rootTag, dataVersion).getValue().get("Level"));
}
}
if (dataVersion >= DATA_VERSION_MC_1_13) {
return new AnvilChunk13(tag);
}
Map<String, Tag> tags = tag.getValue();
if (tags.containsKey("Sections")) {
return new AnvilChunk(world, tag);
}
return new OldChunk(world, tag);
return ChunkStoreHelper.getChunk(rootTag);
}
@Override

View File

@ -0,0 +1,117 @@
/*
* 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 Lesser 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 Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.world.storage;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.world.DataException;
import com.sk89q.worldedit.world.DataFixer;
import com.sk89q.worldedit.world.chunk.AnvilChunk;
import com.sk89q.worldedit.world.chunk.AnvilChunk13;
import com.sk89q.worldedit.world.chunk.Chunk;
import com.sk89q.worldedit.world.chunk.OldChunk;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
public class ChunkStoreHelper {
@FunctionalInterface
public interface ChunkDataInputSupplier {
InputStream openInputStream() throws DataException, IOException;
}
public static CompoundTag readCompoundTag(ChunkDataInputSupplier input) throws DataException, IOException {
try (InputStream stream = input.openInputStream();
NBTInputStream nbt = new NBTInputStream(stream)) {
Tag tag = nbt.readNamedTag().getTag();
if (!(tag instanceof CompoundTag)) {
throw new ChunkStoreException("CompoundTag expected for chunk; got "
+ tag.getClass().getName());
}
return (CompoundTag) tag;
}
}
/**
* The DataVersion for Minecraft 1.13
*/
private static final int DATA_VERSION_MC_1_13 = 1519;
/**
* Convert a chunk NBT tag into a {@link Chunk} implementation.
*
* @param rootTag the root tag of the chunk
* @return a Chunk implementation
* @throws DataException if the rootTag is not valid chunk data
*/
public static Chunk getChunk(CompoundTag rootTag) throws DataException {
Map<String, Tag> children = rootTag.getValue();
CompoundTag tag = null;
// Find Level tag
for (Map.Entry<String, Tag> entry : children.entrySet()) {
if (entry.getKey().equals("Level")) {
if (entry.getValue() instanceof CompoundTag) {
tag = (CompoundTag) entry.getValue();
break;
} else {
throw new ChunkStoreException("CompoundTag expected for 'Level'; got " + entry.getValue().getClass().getName());
}
}
}
if (tag == null) {
throw new ChunkStoreException("Missing root 'Level' tag");
}
int dataVersion = rootTag.getInt("DataVersion");
if (dataVersion == 0) dataVersion = -1;
final Platform platform = WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING);
final int currentDataVersion = platform.getDataVersion();
if (tag.getValue().containsKey("Sections") && dataVersion < currentDataVersion) { // only fix up MCA format, DFU doesn't support MCR chunks
final DataFixer dataFixer = platform.getDataFixer();
if (dataFixer != null) {
return new AnvilChunk13((CompoundTag) dataFixer.fixUp(DataFixer.FixTypes.CHUNK, rootTag, dataVersion).getValue().get("Level"));
}
}
if (dataVersion >= DATA_VERSION_MC_1_13) {
return new AnvilChunk13(tag);
}
Map<String, Tag> tags = tag.getValue();
if (tags.containsKey("Sections")) {
return new AnvilChunk(tag);
}
return new OldChunk(tag);
}
private ChunkStoreHelper() {
}
}

View File

@ -20,12 +20,9 @@
package com.sk89q.worldedit.world.storage;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.world.DataException;
import com.sk89q.worldedit.world.World;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
@ -78,18 +75,9 @@ public abstract class LegacyChunkStore extends ChunkStore {
String filename = "c." + Integer.toString(x, 36)
+ "." + Integer.toString(z, 36) + ".dat";
InputStream stream = getInputStream(folder1, folder2, filename);
Tag tag;
try (NBTInputStream nbt = new NBTInputStream(new GZIPInputStream(stream))) {
tag = nbt.readNamedTag().getTag();
if (!(tag instanceof CompoundTag)) {
throw new ChunkStoreException("CompoundTag expected for chunk; got "
+ tag.getClass().getName());
}
return (CompoundTag) tag;
}
return ChunkStoreHelper.readCompoundTag(() ->
new GZIPInputStream(getInputStream(folder1, folder2, filename))
);
}
private static int divisorMod(int a, int n) {