mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2024-11-22 13:16:45 +01:00
Update BlockTracker to use Spigot API directly instead of compatibility
layer Fixes #4692 Fixes #4698
This commit is contained in:
parent
ddc9a69f4b
commit
dd550feb65
@ -21,7 +21,6 @@ import com.gmail.nossr50.skills.repair.Repair;
|
||||
import com.gmail.nossr50.skills.salvage.Salvage;
|
||||
import com.gmail.nossr50.skills.woodcutting.WoodcuttingManager;
|
||||
import com.gmail.nossr50.util.*;
|
||||
import com.gmail.nossr50.util.compat.layers.world.WorldCompatibilityLayer;
|
||||
import com.gmail.nossr50.util.player.UserManager;
|
||||
import com.gmail.nossr50.util.skills.SkillUtils;
|
||||
import com.gmail.nossr50.util.sounds.SoundManager;
|
||||
@ -131,12 +130,10 @@ public class BlockListener implements Listener {
|
||||
|
||||
BlockFace direction = event.getDirection();
|
||||
Block movedBlock;
|
||||
WorldCompatibilityLayer worldCompatibilityLayer = mcMMO.getCompatibilityManager().getWorldCompatibilityLayer();
|
||||
|
||||
for (Block block : event.getBlocks()) {
|
||||
movedBlock = block.getRelative(direction);
|
||||
|
||||
if(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, movedBlock)) {
|
||||
if(BlockUtils.isWithinWorldBounds(movedBlock)) {
|
||||
mcMMO.getPlaceStore().setTrue(movedBlock);
|
||||
}
|
||||
}
|
||||
@ -161,15 +158,13 @@ public class BlockListener implements Listener {
|
||||
BlockFace direction = event.getDirection();
|
||||
Block movedBlock = event.getBlock().getRelative(direction);
|
||||
|
||||
WorldCompatibilityLayer worldCompatibilityLayer = mcMMO.getCompatibilityManager().getWorldCompatibilityLayer();
|
||||
|
||||
//Spigot makes bad things happen in its API
|
||||
if(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, movedBlock)) {
|
||||
if(BlockUtils.isWithinWorldBounds(movedBlock)) {
|
||||
mcMMO.getPlaceStore().setTrue(movedBlock);
|
||||
}
|
||||
|
||||
for (Block block : event.getBlocks()) {
|
||||
if(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, block)) {
|
||||
if(BlockUtils.isWithinWorldBounds(block)) {
|
||||
mcMMO.getPlaceStore().setTrue(block.getRelative(direction));
|
||||
}
|
||||
}
|
||||
@ -192,10 +187,9 @@ public class BlockListener implements Listener {
|
||||
BlockState blockState = event.getNewState();
|
||||
|
||||
if(ExperienceConfig.getInstance().isSnowExploitPrevented() && BlockUtils.shouldBeWatched(blockState)) {
|
||||
WorldCompatibilityLayer worldCompatibilityLayer = mcMMO.getCompatibilityManager().getWorldCompatibilityLayer();
|
||||
Block block = blockState.getBlock();
|
||||
|
||||
if(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, block)) {
|
||||
if(BlockUtils.isWithinWorldBounds(block)) {
|
||||
mcMMO.getPlaceStore().setTrue(block);
|
||||
}
|
||||
}
|
||||
@ -215,10 +209,9 @@ public class BlockListener implements Listener {
|
||||
|
||||
if(ExperienceConfig.getInstance().preventStoneLavaFarming()) {
|
||||
BlockState newState = event.getNewState();
|
||||
WorldCompatibilityLayer worldCompatibilityLayer = mcMMO.getCompatibilityManager().getWorldCompatibilityLayer();
|
||||
|
||||
if(newState.getType() != Material.OBSIDIAN && ExperienceConfig.getInstance().doesBlockGiveSkillXP(PrimarySkillType.MINING, newState.getBlockData())) {
|
||||
if(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, newState.getBlock())) {
|
||||
if(BlockUtils.isWithinWorldBounds(newState.getBlock())) {
|
||||
mcMMO.getPlaceStore().setTrue(newState);
|
||||
}
|
||||
}
|
||||
@ -243,9 +236,7 @@ public class BlockListener implements Listener {
|
||||
return;
|
||||
}
|
||||
|
||||
WorldCompatibilityLayer worldCompatibilityLayer = mcMMO.getCompatibilityManager().getWorldCompatibilityLayer();
|
||||
|
||||
if(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, block)) {
|
||||
if(BlockUtils.isWithinWorldBounds(block)) {
|
||||
//NOTE: BlockMultiPlace has its own logic so don't handle anything that would overlap
|
||||
if (!(event instanceof BlockMultiPlaceEvent)) {
|
||||
mcMMO.getPlaceStore().setTrue(blockState);
|
||||
@ -283,10 +274,8 @@ public class BlockListener implements Listener {
|
||||
BlockState blockState = replacedBlockState.getBlock().getState();
|
||||
Block block = blockState.getBlock();
|
||||
|
||||
WorldCompatibilityLayer worldCompatibilityLayer = mcMMO.getCompatibilityManager().getWorldCompatibilityLayer();
|
||||
|
||||
/* Check if the blocks placed should be monitored so they do not give out XP in the future */
|
||||
if(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, block)) {
|
||||
if(BlockUtils.isWithinWorldBounds(block)) {
|
||||
//Updated: 10/5/2021
|
||||
//Note: For some reason Azalea trees trigger this event but no other tree does (as of 10/5/2021) but if this changes in the future we may need to update this
|
||||
if(BlockUtils.isPartOfTree(event.getBlockPlaced())) {
|
||||
@ -311,9 +300,7 @@ public class BlockListener implements Listener {
|
||||
return;
|
||||
|
||||
// Minecraft is dumb, the events still throw when a plant "grows" higher than the max block height. Even though no new block is created
|
||||
WorldCompatibilityLayer worldCompatibilityLayer = mcMMO.getCompatibilityManager().getWorldCompatibilityLayer();
|
||||
|
||||
if(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, block)) {
|
||||
if(BlockUtils.isWithinWorldBounds(block)) {
|
||||
mcMMO.getPlaceStore().setFalse(block);
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.skills.repair.Repair;
|
||||
import com.gmail.nossr50.skills.salvage.Salvage;
|
||||
import com.gmail.nossr50.util.compat.layers.world.WorldCompatibilityLayer;
|
||||
import com.gmail.nossr50.util.random.RandomChanceSkill;
|
||||
import com.gmail.nossr50.util.random.RandomChanceUtil;
|
||||
import org.bukkit.Material;
|
||||
@ -302,11 +301,17 @@ public final class BlockUtils {
|
||||
return hasWoodcuttingXP(block.getState()) || isNonWoodPartOfTree(block.getType());
|
||||
}
|
||||
|
||||
public static boolean isWithinWorldBounds(@NotNull WorldCompatibilityLayer worldCompatibilityLayer, @NotNull Block block) {
|
||||
/**
|
||||
* Checks to see if a Block is within the world bounds
|
||||
* Prevent processing blocks from other plugins (or perhaps odd spigot anomalies) from sending blocks that can't exist within the world
|
||||
* @param block
|
||||
* @return
|
||||
*/
|
||||
public static boolean isWithinWorldBounds(@NotNull Block block) {
|
||||
World world = block.getWorld();
|
||||
|
||||
//World min height = inclusive | World max height = exclusive
|
||||
return block.getY() >= worldCompatibilityLayer.getMinWorldHeight(world) && block.getY() < worldCompatibilityLayer.getMaxWorldHeight(world);
|
||||
return block.getY() >= world.getMinHeight() && block.getY() < world.getMaxHeight();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package com.gmail.nossr50.util.blockmeta;
|
||||
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -25,7 +24,7 @@ public class BitSetChunkStore implements ChunkStore {
|
||||
private transient boolean dirty = false;
|
||||
|
||||
public BitSetChunkStore(@NotNull World world, int cx, int cz) {
|
||||
this(world.getUID(), mcMMO.getCompatibilityManager().getWorldCompatibilityLayer().getMinWorldHeight(world), world.getMaxHeight(), cx, cz);
|
||||
this(world.getUID(), world.getMinHeight(), world.getMaxHeight(), cx, cz);
|
||||
}
|
||||
|
||||
private BitSetChunkStore(@NotNull UUID worldUid, int worldMin, int worldMax, int cx, int cz) {
|
||||
@ -109,23 +108,23 @@ public class BitSetChunkStore implements ChunkStore {
|
||||
return (z * 16 + x) + (256 * (y + yOffset));
|
||||
}
|
||||
|
||||
private static int getWorldMin(@NotNull UUID worldUid, int storedWorldMin) {
|
||||
private static int getWorldMin(@NotNull UUID worldUid) {
|
||||
World world = Bukkit.getWorld(worldUid);
|
||||
|
||||
// Not sure how this case could come up, but might as well handle it gracefully. Loading a chunkstore for an unloaded world?
|
||||
if (world == null)
|
||||
return storedWorldMin;
|
||||
throw new RuntimeException("Cannot grab a minimum world height for an unloaded world");
|
||||
|
||||
return mcMMO.getCompatibilityManager().getWorldCompatibilityLayer().getMinWorldHeight(world);
|
||||
return world.getMinHeight();
|
||||
}
|
||||
|
||||
private static int getWorldMax(@NotNull UUID worldUid, int storedWorldMax)
|
||||
private static int getWorldMax(@NotNull UUID worldUid)
|
||||
{
|
||||
World world = Bukkit.getWorld(worldUid);
|
||||
|
||||
// Not sure how this case could come up, but might as well handle it gracefully. Loading a chunkstore for an unloaded world?
|
||||
if (world == null)
|
||||
return storedWorldMax;
|
||||
throw new RuntimeException("Cannot grab a maximum world height for an unloaded world");
|
||||
|
||||
return world.getMaxHeight();
|
||||
}
|
||||
@ -171,8 +170,8 @@ public class BitSetChunkStore implements ChunkStore {
|
||||
in.readFully(temp);
|
||||
BitSet stored = BitSet.valueOf(temp);
|
||||
|
||||
int currentWorldMin = getWorldMin(worldUid, worldMin);
|
||||
int currentWorldMax = getWorldMax(worldUid, worldMax);
|
||||
int currentWorldMin = getWorldMin(worldUid);
|
||||
int currentWorldMax = getWorldMax(worldUid);
|
||||
|
||||
// The order in which the world height update code occurs here is important, the world max truncate math only holds up if done before adjusting for min changes
|
||||
// Lop off extra data if world max has shrunk
|
||||
@ -273,8 +272,8 @@ public class BitSetChunkStore implements ChunkStore {
|
||||
|
||||
public @NotNull BitSetChunkStore convert()
|
||||
{
|
||||
int currentWorldMin = getWorldMin(worldUid, 0);
|
||||
int currentWorldMax = getWorldMax(worldUid, worldMax);
|
||||
int currentWorldMin = getWorldMin(worldUid);
|
||||
int currentWorldMax = getWorldMax(worldUid);
|
||||
|
||||
BitSetChunkStore converted = new BitSetChunkStore(worldUid, currentWorldMin, currentWorldMax, cx, cz);
|
||||
|
||||
|
@ -10,12 +10,9 @@ import com.gmail.nossr50.util.compat.layers.persistentdata.SpigotPersistentDataL
|
||||
import com.gmail.nossr50.util.compat.layers.persistentdata.SpigotPersistentDataLayer_1_14;
|
||||
import com.gmail.nossr50.util.compat.layers.skills.AbstractMasterAnglerCompatibility;
|
||||
import com.gmail.nossr50.util.compat.layers.skills.MasterAnglerCompatibilityLayer;
|
||||
import com.gmail.nossr50.util.compat.layers.world.WorldCompatibilityLayer;
|
||||
import com.gmail.nossr50.util.compat.layers.world.WorldCompatibilityLayer_1_16_4;
|
||||
import com.gmail.nossr50.util.nms.NMSVersion;
|
||||
import com.gmail.nossr50.util.platform.MinecraftGameVersion;
|
||||
import com.gmail.nossr50.util.text.StringUtils;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -40,7 +37,6 @@ public class CompatibilityManager {
|
||||
private AbstractPersistentDataLayer persistentDataLayer;
|
||||
private AbstractBungeeSerializerCompatibilityLayer bungeeSerializerCompatibilityLayer;
|
||||
private AbstractMasterAnglerCompatibility masterAnglerCompatibility;
|
||||
private WorldCompatibilityLayer worldCompatibilityLayer;
|
||||
|
||||
public CompatibilityManager(@NotNull MinecraftGameVersion minecraftGameVersion) {
|
||||
mcMMO.p.getLogger().info("Loading compatibility layers...");
|
||||
@ -71,29 +67,10 @@ public class CompatibilityManager {
|
||||
initPersistentDataLayer();
|
||||
initBungeeSerializerLayer();
|
||||
initMasterAnglerLayer();
|
||||
initWorldCompatibilityLayer();
|
||||
|
||||
isFullyCompatibleServerSoftware = true;
|
||||
}
|
||||
|
||||
private void initWorldCompatibilityLayer() {
|
||||
if(minecraftGameVersion.isAtLeast(1, 17, 0)) {
|
||||
worldCompatibilityLayer = new WorldCompatibilityLayer_1_16_4();
|
||||
} else {
|
||||
worldCompatibilityLayer = new WorldCompatibilityLayer() {
|
||||
@Override
|
||||
public int getMinWorldHeight(@NotNull World world) {
|
||||
return WorldCompatibilityLayer.super.getMinWorldHeight(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxWorldHeight(@NotNull World world) {
|
||||
return WorldCompatibilityLayer.super.getMaxWorldHeight(world);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
private void initMasterAnglerLayer() {
|
||||
if(minecraftGameVersion.isAtLeast(1, 16, 3)) {
|
||||
masterAnglerCompatibility = new MasterAnglerCompatibilityLayer();
|
||||
@ -202,10 +179,6 @@ public class CompatibilityManager {
|
||||
return masterAnglerCompatibility;
|
||||
}
|
||||
|
||||
public @NotNull WorldCompatibilityLayer getWorldCompatibilityLayer() {
|
||||
return worldCompatibilityLayer;
|
||||
}
|
||||
|
||||
public @Nullable MinecraftGameVersion getMinecraftGameVersion() {
|
||||
return minecraftGameVersion;
|
||||
}
|
||||
|
@ -1,11 +0,0 @@
|
||||
package com.gmail.nossr50.util.compat.layers.world;
|
||||
|
||||
import com.gmail.nossr50.util.compat.CompatibilityLayer;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public interface WorldCompatibilityLayer extends CompatibilityLayer {
|
||||
default int getMinWorldHeight(@NotNull World world) { return 0; }
|
||||
|
||||
default int getMaxWorldHeight(@NotNull World world) { return 256; }
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package com.gmail.nossr50.util.compat.layers.world;
|
||||
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class WorldCompatibilityLayer_1_16_4 implements WorldCompatibilityLayer {
|
||||
@Override
|
||||
public int getMinWorldHeight(@NotNull World world) {
|
||||
return world.getMinHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxWorldHeight(@NotNull World world) {
|
||||
return world.getMaxHeight();
|
||||
}
|
||||
}
|
@ -4,7 +4,6 @@ package com.gmail.nossr50.util.blockmeta;
|
||||
import com.gmail.nossr50.mcMMO;
|
||||
import com.gmail.nossr50.util.BlockUtils;
|
||||
import com.gmail.nossr50.util.compat.CompatibilityManager;
|
||||
import com.gmail.nossr50.util.compat.layers.world.WorldCompatibilityLayer;
|
||||
import com.gmail.nossr50.util.platform.PlatformManager;
|
||||
import com.google.common.io.Files;
|
||||
import org.bukkit.Bukkit;
|
||||
@ -39,9 +38,6 @@ class ChunkStoreTest {
|
||||
}
|
||||
|
||||
private World mockWorld;
|
||||
private CompatibilityManager compatibilityManager;
|
||||
private WorldCompatibilityLayer worldCompatibilityLayer;
|
||||
private PlatformManager platformManager;
|
||||
|
||||
private MockedStatic<Bukkit> bukkitMock;
|
||||
private MockedStatic<mcMMO> mcMMOMock;
|
||||
@ -57,24 +53,10 @@ class ChunkStoreTest {
|
||||
bukkitMock = Mockito.mockStatic(Bukkit.class);
|
||||
bukkitMock.when(() -> Bukkit.getWorld(worldUUID)).thenReturn(mockWorld);
|
||||
|
||||
platformManager = Mockito.mock(PlatformManager.class);
|
||||
compatibilityManager = Mockito.mock(CompatibilityManager.class);
|
||||
worldCompatibilityLayer = Mockito.mock(WorldCompatibilityLayer.class);
|
||||
|
||||
mcMMOMock = Mockito.mockStatic(mcMMO.class);
|
||||
|
||||
mcMMOMock.when(() -> mcMMO.getPlatformManager()).thenReturn(platformManager);
|
||||
Assertions.assertNotNull(mcMMO.getPlatformManager());
|
||||
|
||||
mcMMOMock.when(() -> mcMMO.getCompatibilityManager()).thenReturn(compatibilityManager);
|
||||
Assertions.assertNotNull(mcMMO.getCompatibilityManager());
|
||||
|
||||
Mockito.when(platformManager.getCompatibilityManager()).thenReturn(compatibilityManager);
|
||||
Mockito.when(platformManager.getCompatibilityManager().getWorldCompatibilityLayer()).thenReturn(worldCompatibilityLayer);
|
||||
Assertions.assertNotNull(mcMMO.getCompatibilityManager().getWorldCompatibilityLayer());
|
||||
Mockito.when(worldCompatibilityLayer.getMinWorldHeight(mockWorld)).thenReturn(LEGACY_WORLD_HEIGHT_MIN);
|
||||
Mockito.when(worldCompatibilityLayer.getMaxWorldHeight(mockWorld)).thenReturn(LEGACY_WORLD_HEIGHT_MAX);
|
||||
|
||||
Mockito.when(mockWorld.getMinHeight()).thenReturn(LEGACY_WORLD_HEIGHT_MIN);
|
||||
Mockito.when(mockWorld.getMaxHeight()).thenReturn(LEGACY_WORLD_HEIGHT_MAX);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
@ -85,7 +67,7 @@ class ChunkStoreTest {
|
||||
|
||||
@Test
|
||||
void testIndexOutOfBounds() {
|
||||
Mockito.when(mcMMO.getCompatibilityManager().getWorldCompatibilityLayer().getMinWorldHeight(mockWorld)).thenReturn(-64);
|
||||
Mockito.when(mockWorld.getMinHeight()).thenReturn(-64);
|
||||
HashChunkManager hashChunkManager = new HashChunkManager();
|
||||
|
||||
// Top Block
|
||||
@ -96,7 +78,7 @@ class ChunkStoreTest {
|
||||
|
||||
@Test
|
||||
void testSetTrue() {
|
||||
Mockito.when(mcMMO.getCompatibilityManager().getWorldCompatibilityLayer().getMinWorldHeight(mockWorld)).thenReturn(-64);
|
||||
Mockito.when(mockWorld.getMinHeight()).thenReturn(-64);
|
||||
HashChunkManager hashChunkManager = new HashChunkManager();
|
||||
int radius = 2; // Could be anything but drastically changes test time
|
||||
|
||||
@ -117,7 +99,7 @@ class ChunkStoreTest {
|
||||
Block bottomBlock = initMockBlock(1337, 0, -1337);
|
||||
Assertions.assertFalse(hashChunkManager.isTrue(bottomBlock));
|
||||
|
||||
Assertions.assertTrue(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, bottomBlock));
|
||||
Assertions.assertTrue(BlockUtils.isWithinWorldBounds(bottomBlock));
|
||||
hashChunkManager.setTrue(bottomBlock);
|
||||
Assertions.assertTrue(hashChunkManager.isTrue(bottomBlock));
|
||||
|
||||
@ -125,7 +107,7 @@ class ChunkStoreTest {
|
||||
Block topBlock = initMockBlock(1337, 255, -1337);
|
||||
Assertions.assertFalse(hashChunkManager.isTrue(topBlock));
|
||||
|
||||
Assertions.assertTrue(BlockUtils.isWithinWorldBounds(worldCompatibilityLayer, topBlock));
|
||||
Assertions.assertTrue(BlockUtils.isWithinWorldBounds(topBlock));
|
||||
hashChunkManager.setTrue(topBlock);
|
||||
Assertions.assertTrue(hashChunkManager.isTrue(topBlock));
|
||||
}
|
||||
@ -161,7 +143,7 @@ class ChunkStoreTest {
|
||||
|
||||
@Test
|
||||
void testNegativeWorldMin() throws IOException {
|
||||
Mockito.when(mcMMO.getCompatibilityManager().getWorldCompatibilityLayer().getMinWorldHeight(mockWorld)).thenReturn(-64);
|
||||
Mockito.when(mockWorld.getMinHeight()).thenReturn(-64);
|
||||
|
||||
BitSetChunkStore original = new BitSetChunkStore(mockWorld, 1, 2);
|
||||
original.setTrue(14, -32, 12);
|
||||
@ -180,8 +162,9 @@ class ChunkStoreTest {
|
||||
original.setTrue(13, 3, 12);
|
||||
byte[] serializedBytes = serializeChunkstore(original);
|
||||
|
||||
Mockito.when(mcMMO.getCompatibilityManager().getWorldCompatibilityLayer().getMinWorldHeight(mockWorld)).thenReturn(-64);
|
||||
Mockito.when(mockWorld.getMinHeight()).thenReturn(-64);
|
||||
ChunkStore deserialized = BitSetChunkStore.Serialization.readChunkStore(new DataInputStream(new ByteArrayInputStream(serializedBytes)));
|
||||
assert deserialized != null;
|
||||
assertEqualIgnoreMinMax(original, deserialized);
|
||||
}
|
||||
|
||||
@ -202,6 +185,7 @@ class ChunkStoreTest {
|
||||
original.setTrue(13, 89, 12);
|
||||
byte[] serializedBytes = serializeChunkstore(original);
|
||||
ChunkStore deserialized = BitSetChunkStore.Serialization.readChunkStore(new DataInputStream(new ByteArrayInputStream(serializedBytes)));
|
||||
assert deserialized != null;
|
||||
assertEqual(original, deserialized);
|
||||
}
|
||||
|
||||
@ -221,6 +205,7 @@ class ChunkStoreTest {
|
||||
try (DataInputStream is = region.getInputStream(original.getChunkX(), original.getChunkZ())) {
|
||||
Assertions.assertNotNull(is);
|
||||
ChunkStore deserialized = BitSetChunkStore.Serialization.readChunkStore(is);
|
||||
assert deserialized != null;
|
||||
assertEqual(original, deserialized);
|
||||
}
|
||||
region.close();
|
||||
@ -299,7 +284,6 @@ class ChunkStoreTest {
|
||||
}
|
||||
|
||||
public static class LegacyChunkStore implements ChunkStore, Serializable {
|
||||
|
||||
private static final long serialVersionUID = -1L;
|
||||
transient private boolean dirty = false;
|
||||
public boolean[][][] store;
|
||||
|
Loading…
Reference in New Issue
Block a user