| 
					
				 | 
			
			
				@@ -1,13 +1,9 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 package com.gmail.nossr50.util.blockmeta; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.gmail.nossr50.mcMMO; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import com.gmail.nossr50.util.BlockUtils; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import com.google.common.io.Files; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.bukkit.Bukkit; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.bukkit.World; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import org.bukkit.block.Block; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import org.jetbrains.annotations.NotNull; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.junit.jupiter.api.*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.mockito.MockedStatic; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import org.mockito.Mockito; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -15,14 +11,13 @@ import org.mockito.Mockito; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.io.*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import java.util.UUID; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-/** 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * Could be a lot better. But some tests are better than none! Tests the major things, still kinda unit-testy. Verifies 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- * that the serialization isn't completely broken. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-class ChunkStoreTest { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import static com.gmail.nossr50.util.blockmeta.BlockStoreTestUtils.*; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import static com.gmail.nossr50.util.blockmeta.UserBlockTrackerTest.recursiveDelete; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import static org.bukkit.Bukkit.getWorld; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import static org.mockito.Mockito.mockStatic; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+import static org.mockito.Mockito.when; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public static final int LEGACY_WORLD_HEIGHT_MAX = 256; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public static final int LEGACY_WORLD_HEIGHT_MIN = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+class ChunkStoreTest { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     private static File tempDir; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @BeforeAll 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -44,151 +39,39 @@ class ChunkStoreTest { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     void setUpMock() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         UUID worldUUID = UUID.randomUUID(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         mockWorld = Mockito.mock(World.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockWorld.getUID()).thenReturn(worldUUID); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockWorld.getMaxHeight()).thenReturn(256); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockWorld.getWorldFolder()).thenReturn(tempDir); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        when(mockWorld.getUID()).thenReturn(worldUUID); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        when(mockWorld.getMaxHeight()).thenReturn(256); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        when(mockWorld.getWorldFolder()).thenReturn(tempDir); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        bukkitMock = Mockito.mockStatic(Bukkit.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        bukkitMock.when(() -> Bukkit.getWorld(worldUUID)).thenReturn(mockWorld); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        bukkitMock = mockStatic(Bukkit.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        bukkitMock.when(() -> getWorld(worldUUID)).thenReturn(mockWorld); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        mcMMOMock = Mockito.mockStatic(mcMMO.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        mcMMOMock = mockStatic(mcMMO.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockWorld.getMinHeight()).thenReturn(LEGACY_WORLD_HEIGHT_MIN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockWorld.getMaxHeight()).thenReturn(LEGACY_WORLD_HEIGHT_MAX); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        when(mockWorld.getMinHeight()).thenReturn(LEGACY_WORLD_HEIGHT_MIN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        when(mockWorld.getMaxHeight()).thenReturn(LEGACY_WORLD_HEIGHT_MAX); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @AfterEach 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     void teardownMock() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         bukkitMock.close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         mcMMOMock.close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @Test 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    void testIndexOutOfBounds() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockWorld.getMinHeight()).thenReturn(-64); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        HashChunkManager hashChunkManager = new HashChunkManager(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // Top Block 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Block illegalHeightBlock = initMockBlock(1337, 256, -1337); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertFalse(hashChunkManager.isTrue(illegalHeightBlock)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertThrows(IndexOutOfBoundsException.class, () -> hashChunkManager.setTrue(illegalHeightBlock)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @Test 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    void testSetTrue() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockWorld.getMinHeight()).thenReturn(-64); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        HashChunkManager hashChunkManager = new HashChunkManager(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        int radius = 2; // Could be anything but drastically changes test time 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for (int x = -radius; x <= radius; x++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            for (int y = mockWorld.getMinHeight(); y < mockWorld.getMaxHeight(); y++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                for (int z = -radius; z <= radius; z++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    Block testBlock = initMockBlock(x, y, z); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    hashChunkManager.setTrue(testBlock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    Assertions.assertTrue(hashChunkManager.isTrue(testBlock)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    hashChunkManager.setFalse(testBlock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    Assertions.assertFalse(hashChunkManager.isTrue(testBlock)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // Bot Block 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Block bottomBlock = initMockBlock(1337, 0, -1337); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertFalse(hashChunkManager.isTrue(bottomBlock)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertTrue(BlockUtils.isWithinWorldBounds(bottomBlock)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        hashChunkManager.setTrue(bottomBlock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertTrue(hashChunkManager.isTrue(bottomBlock)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        // Top Block 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Block topBlock = initMockBlock(1337, 255, -1337); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertFalse(hashChunkManager.isTrue(topBlock)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertTrue(BlockUtils.isWithinWorldBounds(topBlock)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        hashChunkManager.setTrue(topBlock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertTrue(hashChunkManager.isTrue(topBlock)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @Test 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    void testSetValue() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        BitSetChunkStore original = new BitSetChunkStore(mockWorld, 0, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        original.setTrue(0, 0, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertTrue(original.isTrue(0, 0, 0)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        original.setFalse(0, 0, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertFalse(original.isTrue(0, 0, 0)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @Test 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    void testIsEmpty() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        BitSetChunkStore original = new BitSetChunkStore(mockWorld, 0, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertTrue(original.isEmpty()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        original.setTrue(0, 0, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        original.setFalse(0, 0, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertTrue(original.isEmpty()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @Test 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    void testRoundTrip() throws IOException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        BitSetChunkStore original = new BitSetChunkStore(mockWorld, 1, 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        original.setTrue(14, 89, 12); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        original.setTrue(14, 90, 12); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        original.setTrue(13, 89, 12); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        byte[] serializedBytes = serializeChunkstore(original); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ChunkStore deserialized = BitSetChunkStore.Serialization.readChunkStore(new DataInputStream(new ByteArrayInputStream(serializedBytes))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assertEqual(original, deserialized); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @Test 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    void testNegativeWorldMin() throws IOException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockWorld.getMinHeight()).thenReturn(-64); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        BitSetChunkStore original = new BitSetChunkStore(mockWorld, 1, 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        original.setTrue(14, -32, 12); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        original.setTrue(14, -64, 12); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        original.setTrue(13, -63, 12); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        byte[] serializedBytes = serializeChunkstore(original); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ChunkStore deserialized = BitSetChunkStore.Serialization.readChunkStore(new DataInputStream(new ByteArrayInputStream(serializedBytes))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assertEqual(original, deserialized); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @Test 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    void testNegativeWorldMinUpgrade() throws IOException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        BitSetChunkStore original = new BitSetChunkStore(mockWorld, 1, 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        original.setTrue(14, 1, 12); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        original.setTrue(14, 2, 12); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        original.setTrue(13, 3, 12); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        byte[] serializedBytes = serializeChunkstore(original); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockWorld.getMinHeight()).thenReturn(-64); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ChunkStore deserialized = BitSetChunkStore.Serialization.readChunkStore(new DataInputStream(new ByteArrayInputStream(serializedBytes))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert deserialized != null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assertEqualIgnoreMinMax(original, deserialized); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @Test 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    void testChunkCoords() throws IOException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for (int x = -96; x < 0; x++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            int cx = x >> 4; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            int ix = Math.abs(x) % 16; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //System.out.print(cx + ":" + ix + "  "); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Test 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     void testUpgrade() throws IOException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         LegacyChunkStore original = new LegacyChunkStore(mockWorld, 12, 32); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         original.setTrue(14, 89, 12); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         original.setTrue(14, 90, 12); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         original.setTrue(13, 89, 12); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        byte[] serializedBytes = serializeChunkstore(original); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        byte[] serializedBytes = serializeChunkStore(original); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         ChunkStore deserialized = BitSetChunkStore.Serialization.readChunkStore(new DataInputStream(new ByteArrayInputStream(serializedBytes))); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         assert deserialized != null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assertEqual(original, deserialized); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        assertChunkStoreEquals(original, deserialized); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     @Test 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    void testSimpleRegionRoundtrip() throws IOException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    void testSimpleRegionRoundTrip() throws IOException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         LegacyChunkStore original = new LegacyChunkStore(mockWorld, 12, 12); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         original.setTrue(14, 89, 12); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         original.setTrue(14, 90, 12); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -196,7 +79,7 @@ class ChunkStoreTest { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         File file = new File(tempDir, "SimpleRegionRoundTrip.region"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         McMMOSimpleRegionFile region = new McMMOSimpleRegionFile(file, 0, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         try (DataOutputStream outputStream = region.getOutputStream(12, 12)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            outputStream.write(serializeChunkstore(original)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            outputStream.write(serializeChunkStore(original)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         region.close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         region = new McMMOSimpleRegionFile(file, 0, 0); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -204,229 +87,10 @@ class ChunkStoreTest { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             Assertions.assertNotNull(is); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             ChunkStore deserialized = BitSetChunkStore.Serialization.readChunkStore(is); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             assert deserialized != null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            assertEqual(original, deserialized); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            assertChunkStoreEquals(original, deserialized); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         region.close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         file.delete(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @Test 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    void testSimpleRegionRejectsOutOfBounds() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        File file = new File(tempDir, "SimpleRegionRoundTrip.region"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        McMMOSimpleRegionFile region = new McMMOSimpleRegionFile(file, 0, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertThrows(IndexOutOfBoundsException.class, () -> region.getOutputStream(-1, 0)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertThrows(IndexOutOfBoundsException.class, () -> region.getOutputStream(0, -1)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertThrows(IndexOutOfBoundsException.class, () -> region.getOutputStream(32, 0)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertThrows(IndexOutOfBoundsException.class, () -> region.getOutputStream(0, 32)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        region.close(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @Test 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    void testChunkStoreRejectsOutOfBounds() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ChunkStore chunkStore = new BitSetChunkStore(mockWorld, 0, 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertThrows(IndexOutOfBoundsException.class, () -> chunkStore.setTrue(-1, 0, 0)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertThrows(IndexOutOfBoundsException.class, () -> chunkStore.setTrue(0, -1, 0)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertThrows(IndexOutOfBoundsException.class, () -> chunkStore.setTrue(0, 0, -1)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertThrows(IndexOutOfBoundsException.class, () -> chunkStore.setTrue(16, 0, 0)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertThrows(IndexOutOfBoundsException.class, () -> chunkStore.setTrue(0, mockWorld.getMaxHeight(), 0)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertThrows(IndexOutOfBoundsException.class, () -> chunkStore.setTrue(0, 0, 16)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @Test 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    void testRegressionChunkMirrorBug() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ChunkManager chunkManager = new HashChunkManager(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Block mockBlockA = Mockito.mock(Block.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockBlockA.getX()).thenReturn(15); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockBlockA.getZ()).thenReturn(15); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockBlockA.getY()).thenReturn(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockBlockA.getWorld()).thenReturn(mockWorld); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Block mockBlockB = Mockito.mock(Block.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockBlockB.getX()).thenReturn(-15); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockBlockB.getZ()).thenReturn(-15); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockBlockB.getY()).thenReturn(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockBlockB.getWorld()).thenReturn(mockWorld); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        chunkManager.setTrue(mockBlockA); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        chunkManager.setFalse(mockBlockB); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertTrue(chunkManager.isTrue(mockBlockA)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private void assertEqual(ChunkStore expected, ChunkStore actual) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertEquals(expected.getChunkMin(), actual.getChunkMin()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertEquals(expected.getChunkMax(), actual.getChunkMax()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assertEqualIgnoreMinMax(expected, actual); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private void assertEqualIgnoreMinMax(ChunkStore expected, ChunkStore actual) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertEquals(expected.getChunkX(), actual.getChunkX()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertEquals(expected.getChunkZ(), actual.getChunkZ()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Assertions.assertEquals(expected.getWorldId(), actual.getWorldId()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for (int y = Math.min(actual.getChunkMin(), expected.getChunkMin()); y < Math.max(actual.getChunkMax(), expected.getChunkMax()); y++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (expected.getChunkMin() > y || actual.getChunkMin() > y || expected.getChunkMax() <= y || actual.getChunkMax() <= y) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                continue; // Ignore 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            for (int x = 0; x < 16; x++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                for (int z = 0; z < 16; z++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    Assertions.assertEquals(expected.isTrue(x, y, z), actual.isTrue(x, y, z)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private static byte[] serializeChunkstore(@NotNull ChunkStore chunkStore) throws IOException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (chunkStore instanceof BitSetChunkStore) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            BitSetChunkStore.Serialization.writeChunkStore(new DataOutputStream(byteArrayOutputStream), chunkStore); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            new UnitTestObjectOutputStream(byteArrayOutputStream).writeObject(chunkStore); // Serializes the class as if 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                                                                           // it were the old 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                                                                           // PrimitiveChunkStore 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return byteArrayOutputStream.toByteArray(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public static class LegacyChunkStore implements ChunkStore, Serializable { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        private static final long serialVersionUID = -1L; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        transient private boolean dirty = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        public boolean[][][] store; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        private static final int CURRENT_VERSION = 7; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        private static final int MAGIC_NUMBER = 0xEA5EDEBB; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        private final int cx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        private final int cz; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        private final @NotNull UUID worldUid; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        public LegacyChunkStore(@NotNull World world, int cx, int cz) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            this.cx = cx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            this.cz = cz; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            this.worldUid = world.getUID(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            this.store = new boolean[16][16][world.getMaxHeight()]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        public boolean isDirty() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return dirty; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        public void setDirty(boolean dirty) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            this.dirty = dirty; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        public int getChunkX() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return cx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        public int getChunkZ() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return cz; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        public int getChunkMin() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        public int getChunkMax() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return store[0][0].length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        public @NotNull UUID getWorldId() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return worldUid; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        public boolean isTrue(int x, int y, int z) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return store[x][z][y]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        public void setTrue(int x, int y, int z) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (y >= store[0][0].length || y < 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            store[x][z][y] = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            dirty = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        public void setFalse(int x, int y, int z) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (y >= store[0][0].length || y < 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            store[x][z][y] = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            dirty = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        public void set(int x, int y, int z, boolean value) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (y >= store[0][0].length || y < 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            store[x][z][y] = value; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            dirty = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        public boolean isEmpty() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            for (int x = 0; x < 16; x++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                for (int z = 0; z < 16; z++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    for (int y = 0; y < store[0][0].length; y++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        if (store[x][z][y]) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        private void writeObject(@NotNull ObjectOutputStream out) throws IOException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            out.writeInt(MAGIC_NUMBER); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            out.writeInt(CURRENT_VERSION); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            out.writeLong(worldUid.getLeastSignificantBits()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            out.writeLong(worldUid.getMostSignificantBits()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            out.writeInt(cx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            out.writeInt(cz); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            out.writeObject(store); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            dirty = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        private void readObject(@NotNull ObjectInputStream in) throws IOException, ClassNotFoundException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            throw new UnsupportedOperationException(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private static class UnitTestObjectOutputStream extends ObjectOutputStream { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        public UnitTestObjectOutputStream(@NotNull OutputStream outputStream) throws IOException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            super(outputStream); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        @Override 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        public void writeUTF(@NotNull String str) throws IOException { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            // Pretend to be the old class 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (str.equals(LegacyChunkStore.class.getName())) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                str = "com.gmail.nossr50.util.blockmeta.chunkmeta.PrimitiveChunkStore"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            super.writeUTF(str); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @NotNull 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    private Block initMockBlock(int x, int y, int z) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Block mockBlock = Mockito.mock(Block.class); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockBlock.getX()).thenReturn(x); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockBlock.getY()).thenReturn(y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockBlock.getZ()).thenReturn(z); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        Mockito.when(mockBlock.getWorld()).thenReturn(mockWorld); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return mockBlock; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    public static void recursiveDelete(@NotNull File directoryToBeDeleted) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if (directoryToBeDeleted.isDirectory()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            for (File file : directoryToBeDeleted.listFiles()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                recursiveDelete(file); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        directoryToBeDeleted.delete(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 |