Improved rollback speeds, now up to 2,000% faster
This commit is contained in:
parent
591110cbb2
commit
67d9f2f832
2 changed files with 45 additions and 176 deletions
|
|
@ -8,13 +8,12 @@ import java.text.NumberFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
|
@ -135,7 +134,6 @@ public class Rollback extends Queue {
|
||||||
}
|
}
|
||||||
|
|
||||||
TreeMap<Long, Integer> chunkList = new TreeMap<>();
|
TreeMap<Long, Integer> chunkList = new TreeMap<>();
|
||||||
HashMap<Long, HashMap<Integer, Object>> adjacentDataList = new HashMap<>();
|
|
||||||
HashMap<Long, ArrayList<Object[]>> dataList = new HashMap<>();
|
HashMap<Long, ArrayList<Object[]>> dataList = new HashMap<>();
|
||||||
HashMap<Long, ArrayList<Object[]>> itemDataList = new HashMap<>();
|
HashMap<Long, ArrayList<Object[]>> itemDataList = new HashMap<>();
|
||||||
|
|
||||||
|
|
@ -213,122 +211,16 @@ public class Rollback extends Queue {
|
||||||
if (modifyList.get(chunkKey) == null) {
|
if (modifyList.get(chunkKey) == null) {
|
||||||
// Integer[][] chunkSections = new Integer[((worldMax - worldMin) >> 4)][];
|
// Integer[][] chunkSections = new Integer[((worldMax - worldMin) >> 4)][];
|
||||||
// adjacentDataList.put(chunkKey, chunkSections);
|
// adjacentDataList.put(chunkKey, chunkSections);
|
||||||
adjacentDataList.put(chunkKey, new HashMap<>());
|
|
||||||
dataList.put(chunkKey, new ArrayList<>());
|
dataList.put(chunkKey, new ArrayList<>());
|
||||||
itemDataList.put(chunkKey, new ArrayList<>());
|
itemDataList.put(chunkKey, new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (listC == 0) {
|
|
||||||
BlockData blockData = null;
|
|
||||||
int rowTypeRaw = (Integer) result[6];
|
|
||||||
byte[] rowBlockData = (byte[]) result[13];
|
|
||||||
String blockDataString = Util.byteDataToString(rowBlockData, rowTypeRaw);
|
|
||||||
if (blockDataString != null && blockDataString.length() > 0) {
|
|
||||||
try {
|
|
||||||
blockData = Bukkit.getServer().createBlockData(blockDataString);
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
// corrupt BlockData, let the server automatically set the BlockData instead
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Object[][] adjacentList = adjacentDataList.get(chunkKey);
|
|
||||||
|
|
||||||
int negativeOffset = (-(worldMin) >> 4);
|
|
||||||
int chunkSection = ((rowY >> 4) + negativeOffset);
|
|
||||||
if (adjacentList[chunkSection] == null) {
|
|
||||||
adjacentList[chunkSection] = new BlockData[4096];
|
|
||||||
}
|
|
||||||
|
|
||||||
int sectionCoordinate = ((rowX & 15) * 16) + ((rowY & 15) * 256) + (rowZ & 15);
|
|
||||||
if (rollbackType == 1) {
|
|
||||||
if (adjacentList[chunkSection][sectionCoordinate] == null) {
|
|
||||||
adjacentList[chunkSection][sectionCoordinate] = blockData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
adjacentList[chunkSection][sectionCoordinate] = blockData;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
int chunkCoordinate = ((rowX & 15) * 16) + (rowY * 256) + (rowZ & 15);
|
|
||||||
HashMap<Integer, Object> adjacentList = adjacentDataList.get(chunkKey);
|
|
||||||
if (rollbackType == 1) {
|
|
||||||
adjacentList.putIfAbsent(chunkCoordinate, blockData);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
adjacentList.put(chunkCoordinate, blockData);
|
|
||||||
}
|
|
||||||
|
|
||||||
result[13] = blockDataString;
|
|
||||||
}
|
|
||||||
|
|
||||||
modifyList.get(chunkKey).add(result);
|
modifyList.get(chunkKey).add(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
listC++;
|
listC++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<Long> adjacentDataKeySet = new HashSet<>(adjacentDataList.keySet());
|
|
||||||
for (long chunkKey : adjacentDataKeySet) {
|
|
||||||
HashMap<Integer, Object> adjacentData = new HashMap<>(adjacentDataList.get(chunkKey));
|
|
||||||
for (Entry<Integer, Object> entry : adjacentData.entrySet()) {
|
|
||||||
if (entry.getValue() instanceof Boolean) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int chunkCoordinate = entry.getKey();
|
|
||||||
int cy = (chunkCoordinate < 0 ? chunkCoordinate - 255 : chunkCoordinate) / 256;
|
|
||||||
int levelData = (chunkCoordinate - (cy * 256));
|
|
||||||
int cx = levelData / 16;
|
|
||||||
int cz = levelData - (cx * 16);
|
|
||||||
|
|
||||||
int chunkX = (int) chunkKey;
|
|
||||||
int chunkZ = (int) (chunkKey >> 32);
|
|
||||||
int chunkBlockX = chunkX << 4;
|
|
||||||
int chunkBlockZ = chunkZ << 4;
|
|
||||||
int blockX = chunkBlockX + cx;
|
|
||||||
int blockZ = chunkBlockZ + cz;
|
|
||||||
int blockY = cy;
|
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
int scanX = blockX;
|
|
||||||
int scanZ = blockZ;
|
|
||||||
|
|
||||||
switch (i) {
|
|
||||||
case 0:
|
|
||||||
scanX = scanX + 1;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
scanX = scanX - 1;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
scanZ = scanZ + 1;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
scanZ = scanZ - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int scanChunkX = scanX >> 4;
|
|
||||||
int scanChunkZ = scanZ >> 4;
|
|
||||||
long scanChunkKey = scanChunkX & 0xffffffffL | (scanChunkZ & 0xffffffffL) << 32;
|
|
||||||
int scanCoordinate = ((scanX & 15) * 16) + (blockY * 256) + (scanZ & 15);
|
|
||||||
|
|
||||||
if (!adjacentDataList.containsKey(scanChunkKey)) {
|
|
||||||
adjacentDataList.put(scanChunkKey, new HashMap<Integer, Object>());
|
|
||||||
}
|
|
||||||
|
|
||||||
HashMap<Integer, Object> data = adjacentDataList.get(scanChunkKey);
|
|
||||||
if (!data.containsKey(scanCoordinate)) {
|
|
||||||
data.put(scanCoordinate, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
adjacentData.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rollbackType == 1) { // Restore
|
if (rollbackType == 1) { // Restore
|
||||||
Iterator<Map.Entry<Long, ArrayList<Object[]>>> dlIterator = dataList.entrySet().iterator();
|
Iterator<Map.Entry<Long, ArrayList<Object[]>>> dlIterator = dataList.entrySet().iterator();
|
||||||
while (dlIterator.hasNext()) {
|
while (dlIterator.hasNext()) {
|
||||||
|
|
@ -387,6 +279,7 @@ public class Rollback extends Queue {
|
||||||
|
|
||||||
ArrayList<Object[]> data = finalBlockList.get(chunkKey);
|
ArrayList<Object[]> data = finalBlockList.get(chunkKey);
|
||||||
ArrayList<Object[]> itemData = finalItemList.get(chunkKey);
|
ArrayList<Object[]> itemData = finalItemList.get(chunkKey);
|
||||||
|
Map<Block, BlockData> chunkChanges = new LinkedHashMap<>();
|
||||||
Map<String, Integer> hangingDelay = new HashMap<>();
|
Map<String, Integer> hangingDelay = new HashMap<>();
|
||||||
|
|
||||||
int finalChunkX = (int) chunkKey;
|
int finalChunkX = (int) chunkKey;
|
||||||
|
|
@ -409,7 +302,8 @@ public class Rollback extends Queue {
|
||||||
int rowRolledBack = (Integer) row[9];
|
int rowRolledBack = (Integer) row[9];
|
||||||
int rowWorldId = (Integer) row[10];
|
int rowWorldId = (Integer) row[10];
|
||||||
byte[] rowMeta = (byte[]) row[12];
|
byte[] rowMeta = (byte[]) row[12];
|
||||||
String blockDataString = (String) row[13];
|
byte[] rowBlockData = (byte[]) row[13];
|
||||||
|
String blockDataString = Util.byteDataToString(rowBlockData, rowTypeRaw);
|
||||||
Material rowType = Util.getType(rowTypeRaw);
|
Material rowType = Util.getType(rowTypeRaw);
|
||||||
|
|
||||||
List<Object> meta = null;
|
List<Object> meta = null;
|
||||||
|
|
@ -636,46 +530,6 @@ public class Rollback extends Queue {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (changeBlock) {
|
if (changeBlock) {
|
||||||
/* Check nearby blocks to determine if physics needs to be updated */
|
|
||||||
boolean updatePhysics = false;
|
|
||||||
if (rawBlockData != null && oldTypeMaterial != null && oldTypeMaterial.isSolid()) { // verify we're checking a block
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
int scanX = rowX;
|
|
||||||
int scanZ = rowZ;
|
|
||||||
|
|
||||||
switch (i) {
|
|
||||||
case 0:
|
|
||||||
scanX = scanX + 1;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
scanX = scanX - 1;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
scanZ = scanZ + 1;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
scanZ = scanZ - 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
int scanChunkX = scanX >> 4;
|
|
||||||
int scanChunkZ = scanZ >> 4;
|
|
||||||
long scanChunkKey = scanChunkX & 0xffffffffL | (scanChunkZ & 0xffffffffL) << 32;
|
|
||||||
int scanCoordinate = ((scanX & 15) * 16) + (rowY * 256) + (scanZ & 15);
|
|
||||||
|
|
||||||
HashMap<Integer, Object> adjacentData = adjacentDataList.get(scanChunkKey);
|
|
||||||
Object adjacentBlock = adjacentData.get(scanCoordinate);
|
|
||||||
if (adjacentBlock instanceof Boolean) {
|
|
||||||
adjacentBlock = bukkitWorld.getBlockAt(scanX, rowY, scanZ).getBlockData();
|
|
||||||
adjacentData.put(scanCoordinate, adjacentBlock);
|
|
||||||
}
|
|
||||||
if (adjacentBlock instanceof MultipleFacing) {
|
|
||||||
updatePhysics = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If modifying the head of a piston, update the base piston block to prevent it from being destroyed */
|
/* If modifying the head of a piston, update the base piston block to prevent it from being destroyed */
|
||||||
if (changeBlockData instanceof PistonHead) {
|
if (changeBlockData instanceof PistonHead) {
|
||||||
PistonHead pistonHead = (PistonHead) changeBlockData;
|
PistonHead pistonHead = (PistonHead) changeBlockData;
|
||||||
|
|
@ -751,7 +605,7 @@ public class Rollback extends Queue {
|
||||||
block.setBlockData(waterlogged);
|
block.setBlockData(waterlogged);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Util.setTypeAndData(block, rowType, blockData, true);
|
Util.prepareTypeAndData(chunkChanges, block, rowType, blockData, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (countBlock) {
|
if (countBlock) {
|
||||||
|
|
@ -759,7 +613,7 @@ public class Rollback extends Queue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((rowType == Material.AIR) && ((oldTypeMaterial == Material.SNOW))) {
|
else if ((rowType == Material.AIR) && ((oldTypeMaterial == Material.SNOW))) {
|
||||||
Util.setTypeAndData(block, rowType, blockData, true);
|
Util.prepareTypeAndData(chunkChanges, block, rowType, blockData, true);
|
||||||
if (countBlock) {
|
if (countBlock) {
|
||||||
blockCount1++;
|
blockCount1++;
|
||||||
}
|
}
|
||||||
|
|
@ -814,7 +668,7 @@ public class Rollback extends Queue {
|
||||||
Waterlogged waterlogged = (Waterlogged) currentBlockData;
|
Waterlogged waterlogged = (Waterlogged) currentBlockData;
|
||||||
if (waterlogged.isWaterlogged()) {
|
if (waterlogged.isWaterlogged()) {
|
||||||
boolean physics = (changeBlockData instanceof Chest);
|
boolean physics = (changeBlockData instanceof Chest);
|
||||||
Util.setTypeAndData(block, Material.WATER, Material.WATER.createBlockData(), physics);
|
Util.prepareTypeAndData(chunkChanges, block, Material.WATER, Material.WATER.createBlockData(), physics);
|
||||||
remove = false;
|
remove = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -829,7 +683,7 @@ public class Rollback extends Queue {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (remove) {
|
if (remove) {
|
||||||
boolean physics = updatePhysics;
|
boolean physics = true;
|
||||||
if ((changeType == Material.NETHER_PORTAL) || changeBlockData instanceof MultipleFacing || changeBlockData instanceof Snow || changeBlockData instanceof Stairs || changeBlockData instanceof RedstoneWire || changeBlockData instanceof Chest) {
|
if ((changeType == Material.NETHER_PORTAL) || changeBlockData instanceof MultipleFacing || changeBlockData instanceof Snow || changeBlockData instanceof Stairs || changeBlockData instanceof RedstoneWire || changeBlockData instanceof Chest) {
|
||||||
physics = true;
|
physics = true;
|
||||||
}
|
}
|
||||||
|
|
@ -847,7 +701,7 @@ public class Rollback extends Queue {
|
||||||
int worldMinHeight = BukkitAdapter.ADAPTER.getMinHeight(bukkitWorld);
|
int worldMinHeight = BukkitAdapter.ADAPTER.getMinHeight(bukkitWorld);
|
||||||
if (bisectLocation.getBlockY() >= worldMinHeight && bisectLocation.getBlockY() < worldMaxHeight) {
|
if (bisectLocation.getBlockY() >= worldMinHeight && bisectLocation.getBlockY() < worldMaxHeight) {
|
||||||
Block bisectBlock = block.getWorld().getBlockAt(bisectLocation);
|
Block bisectBlock = block.getWorld().getBlockAt(bisectLocation);
|
||||||
Util.setTypeAndData(bisectBlock, rowType, null, physics);
|
Util.prepareTypeAndData(chunkChanges, bisectBlock, rowType, null, physics);
|
||||||
|
|
||||||
if (countBlock) {
|
if (countBlock) {
|
||||||
blockCount1++;
|
blockCount1++;
|
||||||
|
|
@ -855,7 +709,7 @@ public class Rollback extends Queue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Util.setTypeAndData(block, rowType, null, physics);
|
Util.prepareTypeAndData(chunkChanges, block, rowType, null, physics);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (countBlock) {
|
if (countBlock) {
|
||||||
|
|
@ -864,7 +718,7 @@ public class Rollback extends Queue {
|
||||||
}
|
}
|
||||||
else if ((rowType == Material.SPAWNER)) {
|
else if ((rowType == Material.SPAWNER)) {
|
||||||
try {
|
try {
|
||||||
Util.setTypeAndData(block, rowType, blockData, false);
|
Util.prepareTypeAndData(chunkChanges, block, rowType, blockData, false);
|
||||||
CreatureSpawner mobSpawner = (CreatureSpawner) block.getState();
|
CreatureSpawner mobSpawner = (CreatureSpawner) block.getState();
|
||||||
mobSpawner.setSpawnedType(Util.getSpawnerType(rowData));
|
mobSpawner.setSpawnedType(Util.getSpawnerType(rowData));
|
||||||
mobSpawner.update();
|
mobSpawner.update();
|
||||||
|
|
@ -878,7 +732,7 @@ public class Rollback extends Queue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((rowType == Material.SKELETON_SKULL) || (rowType == Material.SKELETON_WALL_SKULL) || (rowType == Material.WITHER_SKELETON_SKULL) || (rowType == Material.WITHER_SKELETON_WALL_SKULL) || (rowType == Material.ZOMBIE_HEAD) || (rowType == Material.ZOMBIE_WALL_HEAD) || (rowType == Material.PLAYER_HEAD) || (rowType == Material.PLAYER_WALL_HEAD) || (rowType == Material.CREEPER_HEAD) || (rowType == Material.CREEPER_WALL_HEAD) || (rowType == Material.DRAGON_HEAD) || (rowType == Material.DRAGON_WALL_HEAD)) { // skull
|
else if ((rowType == Material.SKELETON_SKULL) || (rowType == Material.SKELETON_WALL_SKULL) || (rowType == Material.WITHER_SKELETON_SKULL) || (rowType == Material.WITHER_SKELETON_WALL_SKULL) || (rowType == Material.ZOMBIE_HEAD) || (rowType == Material.ZOMBIE_WALL_HEAD) || (rowType == Material.PLAYER_HEAD) || (rowType == Material.PLAYER_WALL_HEAD) || (rowType == Material.CREEPER_HEAD) || (rowType == Material.CREEPER_WALL_HEAD) || (rowType == Material.DRAGON_HEAD) || (rowType == Material.DRAGON_WALL_HEAD)) { // skull
|
||||||
Util.setTypeAndData(block, rowType, blockData, false);
|
Util.prepareTypeAndData(chunkChanges, block, rowType, blockData, false);
|
||||||
if (rowData > 0) {
|
if (rowData > 0) {
|
||||||
Queue.queueSkullUpdate(rowUser, block.getState(), rowData);
|
Queue.queueSkullUpdate(rowUser, block.getState(), rowData);
|
||||||
}
|
}
|
||||||
|
|
@ -888,7 +742,7 @@ public class Rollback extends Queue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (Tag.SIGNS.isTagged(rowType)) {// sign
|
else if (Tag.SIGNS.isTagged(rowType)) {// sign
|
||||||
Util.setTypeAndData(block, rowType, blockData, false);
|
Util.prepareTypeAndData(chunkChanges, block, rowType, blockData, false);
|
||||||
Queue.queueSignUpdate(rowUser, block.getState(), rollbackType, rowTime);
|
Queue.queueSignUpdate(rowUser, block.getState(), rollbackType, rowTime);
|
||||||
|
|
||||||
if (countBlock) {
|
if (countBlock) {
|
||||||
|
|
@ -896,7 +750,7 @@ public class Rollback extends Queue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (BlockGroup.SHULKER_BOXES.contains(rowType)) {
|
else if (BlockGroup.SHULKER_BOXES.contains(rowType)) {
|
||||||
Util.setTypeAndData(block, rowType, blockData, false);
|
Util.prepareTypeAndData(chunkChanges, block, rowType, blockData, false);
|
||||||
if (countBlock) {
|
if (countBlock) {
|
||||||
blockCount1++;
|
blockCount1++;
|
||||||
}
|
}
|
||||||
|
|
@ -911,7 +765,7 @@ public class Rollback extends Queue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rowType == Material.COMMAND_BLOCK || rowType == Material.REPEATING_COMMAND_BLOCK || rowType == Material.CHAIN_COMMAND_BLOCK) { // command block
|
else if (rowType == Material.COMMAND_BLOCK || rowType == Material.REPEATING_COMMAND_BLOCK || rowType == Material.CHAIN_COMMAND_BLOCK) { // command block
|
||||||
Util.setTypeAndData(block, rowType, blockData, false);
|
Util.prepareTypeAndData(chunkChanges, block, rowType, blockData, false);
|
||||||
if (countBlock) {
|
if (countBlock) {
|
||||||
blockCount1++;
|
blockCount1++;
|
||||||
}
|
}
|
||||||
|
|
@ -935,7 +789,7 @@ public class Rollback extends Queue {
|
||||||
block.setBlockData(waterlogged);
|
block.setBlockData(waterlogged);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Util.setTypeAndData(block, rowType, blockData, false);
|
Util.prepareTypeAndData(chunkChanges, block, rowType, blockData, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (countBlock) {
|
if (countBlock) {
|
||||||
|
|
@ -943,7 +797,7 @@ public class Rollback extends Queue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((rowType == Material.NETHER_PORTAL) && rowAction == 0) {
|
else if ((rowType == Material.NETHER_PORTAL) && rowAction == 0) {
|
||||||
Util.setTypeAndData(block, Material.FIRE, null, true);
|
Util.prepareTypeAndData(chunkChanges, block, Material.FIRE, null, true);
|
||||||
}
|
}
|
||||||
else if (rowType == Material.IRON_DOOR || BlockGroup.DOORS.contains(rowType)) {
|
else if (rowType == Material.IRON_DOOR || BlockGroup.DOORS.contains(rowType)) {
|
||||||
if (countBlock) {
|
if (countBlock) {
|
||||||
|
|
@ -951,7 +805,7 @@ public class Rollback extends Queue {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockData != null) {
|
if (blockData != null) {
|
||||||
Util.setTypeAndData(block, rowType, blockData, false);
|
Util.prepareTypeAndData(chunkChanges, block, rowType, blockData, false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
block.setType(rowType, false);
|
block.setType(rowType, false);
|
||||||
|
|
@ -995,7 +849,7 @@ public class Rollback extends Queue {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blockData != null) {
|
if (blockData != null) {
|
||||||
Util.setTypeAndData(block, rowType, blockData, false);
|
Util.prepareTypeAndData(chunkChanges, block, rowType, blockData, false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
block.setType(rowType, false);
|
block.setType(rowType, false);
|
||||||
|
|
@ -1024,7 +878,7 @@ public class Rollback extends Queue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (rowType.name().endsWith("_BANNER")) {
|
else if (rowType.name().endsWith("_BANNER")) {
|
||||||
Util.setTypeAndData(block, rowType, blockData, false);
|
Util.prepareTypeAndData(chunkChanges, block, rowType, blockData, false);
|
||||||
if (countBlock) {
|
if (countBlock) {
|
||||||
blockCount1++;
|
blockCount1++;
|
||||||
}
|
}
|
||||||
|
|
@ -1050,7 +904,7 @@ public class Rollback extends Queue {
|
||||||
block.setType(Material.AIR); // Clear existing container to prevent errors
|
block.setType(Material.AIR); // Clear existing container to prevent errors
|
||||||
|
|
||||||
boolean isChest = (blockData instanceof Chest);
|
boolean isChest = (blockData instanceof Chest);
|
||||||
Util.setTypeAndData(block, rowType, blockData, (isChest));
|
Util.prepareTypeAndData(chunkChanges, block, rowType, blockData, (isChest));
|
||||||
if (isChest) {
|
if (isChest) {
|
||||||
ChestTool.updateDoubleChest(block, blockData, false);
|
ChestTool.updateDoubleChest(block, blockData, false);
|
||||||
}
|
}
|
||||||
|
|
@ -1060,7 +914,7 @@ public class Rollback extends Queue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (BlockGroup.UPDATE_STATE.contains(rowType) || rowType.name().contains("CANDLE")) {
|
else if (BlockGroup.UPDATE_STATE.contains(rowType) || rowType.name().contains("CANDLE")) {
|
||||||
Util.setTypeAndData(block, rowType, blockData, true);
|
Util.prepareTypeAndData(chunkChanges, block, rowType, blockData, true);
|
||||||
ChestTool.updateDoubleChest(block, blockData, true);
|
ChestTool.updateDoubleChest(block, blockData, true);
|
||||||
if (countBlock) {
|
if (countBlock) {
|
||||||
blockCount1++;
|
blockCount1++;
|
||||||
|
|
@ -1083,22 +937,24 @@ public class Rollback extends Queue {
|
||||||
int worldMinHeight = BukkitAdapter.ADAPTER.getMinHeight(bukkitWorld);
|
int worldMinHeight = BukkitAdapter.ADAPTER.getMinHeight(bukkitWorld);
|
||||||
if (bisectLocation.getBlockY() >= worldMinHeight && bisectLocation.getBlockY() < worldMaxHeight) {
|
if (bisectLocation.getBlockY() >= worldMinHeight && bisectLocation.getBlockY() < worldMaxHeight) {
|
||||||
Block bisectBlock = block.getWorld().getBlockAt(bisectLocation);
|
Block bisectBlock = block.getWorld().getBlockAt(bisectLocation);
|
||||||
Util.setTypeAndData(bisectBlock, rowType, bisectData, false);
|
Util.prepareTypeAndData(chunkChanges, bisectBlock, rowType, bisectData, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Util.setTypeAndData(block, rowType, blockData, false);
|
Util.prepareTypeAndData(chunkChanges, block, rowType, blockData, false);
|
||||||
if (countBlock) {
|
if (countBlock) {
|
||||||
blockCount1++;
|
blockCount1++;
|
||||||
blockCount1++;
|
blockCount1++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
boolean physics = updatePhysics;
|
boolean physics = true;
|
||||||
|
/*
|
||||||
if (blockData instanceof MultipleFacing || BukkitAdapter.ADAPTER.isWall(blockData) || blockData instanceof Snow || blockData instanceof Stairs || blockData instanceof RedstoneWire || blockData instanceof Chest) {
|
if (blockData instanceof MultipleFacing || BukkitAdapter.ADAPTER.isWall(blockData) || blockData instanceof Snow || blockData instanceof Stairs || blockData instanceof RedstoneWire || blockData instanceof Chest) {
|
||||||
physics = !(blockData instanceof Snow) || block.getY() <= BukkitAdapter.ADAPTER.getMinHeight(block.getWorld()) || (block.getWorld().getBlockAt(block.getX(), block.getY() - 1, block.getZ()).getType().equals(Material.GRASS_BLOCK));
|
physics = !(blockData instanceof Snow) || block.getY() <= BukkitAdapter.ADAPTER.getMinHeight(block.getWorld()) || (block.getWorld().getBlockAt(block.getX(), block.getY() - 1, block.getZ()).getType().equals(Material.GRASS_BLOCK));
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
Util.setTypeAndData(block, rowType, blockData, physics);
|
Util.prepareTypeAndData(chunkChanges, block, rowType, blockData, physics);
|
||||||
if (countBlock) {
|
if (countBlock) {
|
||||||
blockCount1++;
|
blockCount1++;
|
||||||
}
|
}
|
||||||
|
|
@ -1122,6 +978,14 @@ public class Rollback extends Queue {
|
||||||
hangingDelay.clear();
|
hangingDelay.clear();
|
||||||
data.clear();
|
data.clear();
|
||||||
|
|
||||||
|
// Apply cached changes
|
||||||
|
for (Entry<Block, BlockData> chunkChange : chunkChanges.entrySet()) {
|
||||||
|
Block changeBlock = chunkChange.getKey();
|
||||||
|
BlockData changeBlockData = chunkChange.getValue();
|
||||||
|
Util.setTypeAndData(changeBlock, null, changeBlockData, true);
|
||||||
|
}
|
||||||
|
chunkChanges.clear();
|
||||||
|
|
||||||
Object container = null;
|
Object container = null;
|
||||||
Material containerType = null;
|
Material containerType = null;
|
||||||
boolean containerInit = false;
|
boolean containerInit = false;
|
||||||
|
|
@ -1287,7 +1151,6 @@ public class Rollback extends Queue {
|
||||||
}
|
}
|
||||||
|
|
||||||
chunkList.clear();
|
chunkList.clear();
|
||||||
adjacentDataList.clear();
|
|
||||||
dataList.clear();
|
dataList.clear();
|
||||||
itemDataList.clear();
|
itemDataList.clear();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1188,16 +1188,22 @@ public class Util extends Queue {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setTypeAndData(Block block, Material type, BlockData blockData) {
|
public static void prepareTypeAndData(Map<Block, BlockData> map, Block block, Material type, BlockData blockData, boolean update) {
|
||||||
if (blockData == null) {
|
if (blockData == null) {
|
||||||
blockData = createBlockData(type);
|
blockData = createBlockData(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
block.setBlockData(blockData);
|
if (!update) {
|
||||||
|
setTypeAndData(block, type, blockData, update);
|
||||||
|
map.remove(block);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
map.put(block, blockData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void setTypeAndData(Block block, Material type, BlockData blockData, boolean update) {
|
public static void setTypeAndData(Block block, Material type, BlockData blockData, boolean update) {
|
||||||
if (blockData == null) {
|
if (blockData == null && type != null) {
|
||||||
blockData = createBlockData(type);
|
blockData = createBlockData(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue