Various
Per world session history index when using disk Configurable clipboard/history save locations Fixed and optimized packet sending History caching optimizations (instant now)
This commit is contained in:
parent
97ca92eedf
commit
1ed87eabbc
@ -314,10 +314,6 @@ public class FaweBukkit implements IFawe, Listener {
|
|||||||
public void onPlayerChangedWorld(PlayerChangedWorldEvent event) {
|
public void onPlayerChangedWorld(PlayerChangedWorldEvent event) {
|
||||||
Player player = event.getPlayer();
|
Player player = event.getPlayer();
|
||||||
FawePlayer fp = FawePlayer.wrap(player);
|
FawePlayer fp = FawePlayer.wrap(player);
|
||||||
if (Settings.HISTORY.USE_DISK) {
|
|
||||||
fp.getSession().clearHistory();
|
|
||||||
fp.loadSessionsFromDisk(fp.getWorld());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -134,9 +134,7 @@ public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMa
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void refreshChunk(World world, CHUNK chunk) {
|
public void refreshChunk(FaweChunk fs) {}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean regenerateChunk(World world, int x, int z) {
|
public boolean regenerateChunk(World world, int x, int z) {
|
||||||
|
@ -34,15 +34,12 @@ import java.util.UUID;
|
|||||||
import net.minecraft.server.v1_10_R1.Block;
|
import net.minecraft.server.v1_10_R1.Block;
|
||||||
import net.minecraft.server.v1_10_R1.BlockPosition;
|
import net.minecraft.server.v1_10_R1.BlockPosition;
|
||||||
import net.minecraft.server.v1_10_R1.Blocks;
|
import net.minecraft.server.v1_10_R1.Blocks;
|
||||||
import net.minecraft.server.v1_10_R1.ChunkCoordIntPair;
|
|
||||||
import net.minecraft.server.v1_10_R1.ChunkSection;
|
import net.minecraft.server.v1_10_R1.ChunkSection;
|
||||||
import net.minecraft.server.v1_10_R1.DataBits;
|
import net.minecraft.server.v1_10_R1.DataBits;
|
||||||
import net.minecraft.server.v1_10_R1.DataPaletteBlock;
|
import net.minecraft.server.v1_10_R1.DataPaletteBlock;
|
||||||
import net.minecraft.server.v1_10_R1.Entity;
|
import net.minecraft.server.v1_10_R1.Entity;
|
||||||
import net.minecraft.server.v1_10_R1.EntityHuman;
|
|
||||||
import net.minecraft.server.v1_10_R1.EntityPlayer;
|
import net.minecraft.server.v1_10_R1.EntityPlayer;
|
||||||
import net.minecraft.server.v1_10_R1.EntityTracker;
|
import net.minecraft.server.v1_10_R1.EntityTracker;
|
||||||
import net.minecraft.server.v1_10_R1.EntityTrackerEntry;
|
|
||||||
import net.minecraft.server.v1_10_R1.EntityTypes;
|
import net.minecraft.server.v1_10_R1.EntityTypes;
|
||||||
import net.minecraft.server.v1_10_R1.EnumDifficulty;
|
import net.minecraft.server.v1_10_R1.EnumDifficulty;
|
||||||
import net.minecraft.server.v1_10_R1.EnumGamemode;
|
import net.minecraft.server.v1_10_R1.EnumGamemode;
|
||||||
@ -52,7 +49,6 @@ import net.minecraft.server.v1_10_R1.IDataManager;
|
|||||||
import net.minecraft.server.v1_10_R1.MinecraftServer;
|
import net.minecraft.server.v1_10_R1.MinecraftServer;
|
||||||
import net.minecraft.server.v1_10_R1.NBTTagCompound;
|
import net.minecraft.server.v1_10_R1.NBTTagCompound;
|
||||||
import net.minecraft.server.v1_10_R1.NibbleArray;
|
import net.minecraft.server.v1_10_R1.NibbleArray;
|
||||||
import net.minecraft.server.v1_10_R1.PacketPlayOutEntityDestroy;
|
|
||||||
import net.minecraft.server.v1_10_R1.PacketPlayOutMapChunk;
|
import net.minecraft.server.v1_10_R1.PacketPlayOutMapChunk;
|
||||||
import net.minecraft.server.v1_10_R1.PlayerChunk;
|
import net.minecraft.server.v1_10_R1.PlayerChunk;
|
||||||
import net.minecraft.server.v1_10_R1.PlayerChunkMap;
|
import net.minecraft.server.v1_10_R1.PlayerChunkMap;
|
||||||
@ -246,86 +242,54 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void refreshChunk(World world, Chunk chunk) {
|
public void refreshChunk(FaweChunk fc) {
|
||||||
|
BukkitChunk_1_10 fs = (BukkitChunk_1_10) fc;
|
||||||
|
Chunk chunk = fs.getChunk();
|
||||||
if (!chunk.isLoaded()) {
|
if (!chunk.isLoaded()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
net.minecraft.server.v1_10_R1.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
|
net.minecraft.server.v1_10_R1.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
|
||||||
ChunkCoordIntPair pos = nmsChunk.k(); // getPosition()
|
|
||||||
WorldServer w = (WorldServer) nmsChunk.getWorld();
|
WorldServer w = (WorldServer) nmsChunk.getWorld();
|
||||||
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
|
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
|
||||||
PlayerChunk playerChunk = chunkMap.getChunk(pos.x, pos.z);
|
PlayerChunk playerChunk = chunkMap.getChunk(nmsChunk.locX, nmsChunk.locZ);
|
||||||
if (playerChunk == null) {
|
if (playerChunk == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HashSet<EntityPlayer> set = new HashSet<EntityPlayer>(playerChunk.c);
|
if (playerChunk.c.isEmpty()) {
|
||||||
EntityTracker tracker = w.getTracker();
|
|
||||||
// Get players
|
|
||||||
final HashSet<EntityPlayer> players = new HashSet<>();
|
|
||||||
for (EntityHuman human : w.players) {
|
|
||||||
if (set.contains(human)) {
|
|
||||||
players.add((EntityPlayer) human);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (players.size() == 0) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HashSet<EntityTrackerEntry> entities = new HashSet<>();
|
|
||||||
Collection<Entity>[] entitieSlices = (Collection<Entity>[]) getEntitySlices.invoke(nmsChunk);
|
|
||||||
for (Collection<Entity> slice : entitieSlices) {
|
|
||||||
if (slice == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (Entity ent : slice) {
|
|
||||||
EntityTrackerEntry entry = tracker.trackedEntities.get(ent.getId());
|
|
||||||
if (entry == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
entities.add(entry);
|
|
||||||
PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(ent.getId());
|
|
||||||
for (EntityPlayer player : players) {
|
|
||||||
player.playerConnection.sendPacket(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Send chunks
|
// Send chunks
|
||||||
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, 65535);
|
int mask = fc.getBitMask();
|
||||||
for (EntityPlayer player : players) {
|
if (mask == 65535 && hasEntities(nmsChunk)) {
|
||||||
|
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, 65280);
|
||||||
|
for (EntityPlayer player : playerChunk.c) {
|
||||||
player.playerConnection.sendPacket(packet);
|
player.playerConnection.sendPacket(packet);
|
||||||
}
|
}
|
||||||
// send ents
|
mask = 255;
|
||||||
for (Collection<Entity> slice : entitieSlices) {
|
|
||||||
if (slice == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (final Entity ent : slice) {
|
|
||||||
final EntityTrackerEntry entry = tracker.trackedEntities.get(ent.getId());
|
|
||||||
if (entry == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
TaskManager.IMP.later(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (EntityPlayer player : players) {
|
|
||||||
boolean result = entry.trackedPlayers.remove(player);
|
|
||||||
if (result && ent != player) {
|
|
||||||
entry.updatePlayer(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 2);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
MainUtil.handleError(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, mask);
|
||||||
|
for (EntityPlayer player : playerChunk.c) {
|
||||||
|
player.playerConnection.sendPacket(packet);
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasEntities(net.minecraft.server.v1_10_R1.Chunk nmsChunk) {
|
||||||
|
try {
|
||||||
|
final Collection<Entity>[] entities = (Collection<Entity>[]) getEntitySlices.invoke(nmsChunk);
|
||||||
|
for (int i = 0; i < entities.length; i++) {
|
||||||
|
Collection<Entity> slice = entities[i];
|
||||||
|
if (slice != null && !slice.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable ignore) {}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeLighting(ChunkSection[] sections, RelightMode mode, boolean sky) {
|
public boolean removeLighting(ChunkSection[] sections, RelightMode mode, boolean sky) {
|
||||||
if (mode != RelightMode.NONE) {
|
if (mode != RelightMode.NONE) {
|
||||||
@ -548,8 +512,7 @@ public class BukkitQueue_1_10 extends BukkitQueue_0<Chunk, ChunkSection[], Chunk
|
|||||||
net.minecraft.server.v1_10_R1.World nmsWorld = nmsChunk.world;
|
net.minecraft.server.v1_10_R1.World nmsWorld = nmsChunk.world;
|
||||||
ChunkSection[] sections = nmsChunk.getSections();
|
ChunkSection[] sections = nmsChunk.getSections();
|
||||||
Class<? extends net.minecraft.server.v1_10_R1.Chunk> clazzChunk = nmsChunk.getClass();
|
Class<? extends net.minecraft.server.v1_10_R1.Chunk> clazzChunk = nmsChunk.getClass();
|
||||||
final Field ef = clazzChunk.getDeclaredField("entitySlices");
|
final Collection<Entity>[] entities = (Collection<Entity>[]) getEntitySlices.invoke(nmsChunk);
|
||||||
final Collection<Entity>[] entities = (Collection<Entity>[]) ef.get(nmsChunk);
|
|
||||||
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
|
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
|
||||||
// Remove entities
|
// Remove entities
|
||||||
for (int i = 0; i < entities.length; i++) {
|
for (int i = 0; i < entities.length; i++) {
|
||||||
|
@ -35,7 +35,6 @@ import net.minecraft.server.v1_7_R4.ChunkSection;
|
|||||||
import net.minecraft.server.v1_7_R4.Entity;
|
import net.minecraft.server.v1_7_R4.Entity;
|
||||||
import net.minecraft.server.v1_7_R4.EntityPlayer;
|
import net.minecraft.server.v1_7_R4.EntityPlayer;
|
||||||
import net.minecraft.server.v1_7_R4.EntityTracker;
|
import net.minecraft.server.v1_7_R4.EntityTracker;
|
||||||
import net.minecraft.server.v1_7_R4.EntityTrackerEntry;
|
|
||||||
import net.minecraft.server.v1_7_R4.EntityTypes;
|
import net.minecraft.server.v1_7_R4.EntityTypes;
|
||||||
import net.minecraft.server.v1_7_R4.EnumDifficulty;
|
import net.minecraft.server.v1_7_R4.EnumDifficulty;
|
||||||
import net.minecraft.server.v1_7_R4.EnumGamemode;
|
import net.minecraft.server.v1_7_R4.EnumGamemode;
|
||||||
@ -44,7 +43,6 @@ import net.minecraft.server.v1_7_R4.LongHashMap;
|
|||||||
import net.minecraft.server.v1_7_R4.MinecraftServer;
|
import net.minecraft.server.v1_7_R4.MinecraftServer;
|
||||||
import net.minecraft.server.v1_7_R4.NBTTagCompound;
|
import net.minecraft.server.v1_7_R4.NBTTagCompound;
|
||||||
import net.minecraft.server.v1_7_R4.NibbleArray;
|
import net.minecraft.server.v1_7_R4.NibbleArray;
|
||||||
import net.minecraft.server.v1_7_R4.PacketPlayOutEntityDestroy;
|
|
||||||
import net.minecraft.server.v1_7_R4.PacketPlayOutMapChunk;
|
import net.minecraft.server.v1_7_R4.PacketPlayOutMapChunk;
|
||||||
import net.minecraft.server.v1_7_R4.PlayerChunkMap;
|
import net.minecraft.server.v1_7_R4.PlayerChunkMap;
|
||||||
import net.minecraft.server.v1_7_R4.ServerNBTManager;
|
import net.minecraft.server.v1_7_R4.ServerNBTManager;
|
||||||
@ -453,8 +451,12 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
|
|||||||
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
|
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void refreshChunk(World world, Chunk chunk) {
|
public void refreshChunk(FaweChunk fc) {
|
||||||
|
BukkitChunk_1_7 fs = (BukkitChunk_1_7) fc;
|
||||||
|
Chunk chunk = fs.getChunk();
|
||||||
if (!chunk.isLoaded()) {
|
if (!chunk.isLoaded()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -483,52 +485,34 @@ public class BukkitQueue17 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkSec
|
|||||||
if (players.size() == 0) {
|
if (players.size() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HashSet<EntityTrackerEntry> entities = new HashSet<>();
|
|
||||||
List<Entity>[] entitieSlices = nmsChunk.entitySlices;
|
|
||||||
for (List<Entity> slice : entitieSlices) {
|
|
||||||
if (slice == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (Entity ent : slice) {
|
|
||||||
EntityTrackerEntry entry = (EntityTrackerEntry) tracker.trackedEntities.get(ent.getId());
|
|
||||||
if (entry == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
entities.add(entry);
|
|
||||||
PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(ent.getId());
|
|
||||||
for (EntityPlayer player : players) {
|
|
||||||
player.playerConnection.sendPacket(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Send chunks
|
// Send chunks
|
||||||
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, false, 65535, 25);
|
int mask = fc.getBitMask();
|
||||||
|
if (mask == 65535 && hasEntities(nmsChunk)) {
|
||||||
|
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, false, 65280, 25);
|
||||||
for (EntityPlayer player : players) {
|
for (EntityPlayer player : players) {
|
||||||
player.playerConnection.sendPacket(packet);
|
player.playerConnection.sendPacket(packet);
|
||||||
}
|
}
|
||||||
// send ents
|
mask = 255;
|
||||||
for (final EntityTrackerEntry entry : entities) {
|
}
|
||||||
try {
|
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, false, mask, 25);
|
||||||
TaskManager.IMP.later(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (EntityPlayer player : players) {
|
for (EntityPlayer player : players) {
|
||||||
boolean result = entry.trackedPlayers.remove(player);
|
player.playerConnection.sendPacket(packet);
|
||||||
if (result && entry.tracker != player) {
|
|
||||||
entry.updatePlayer(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 2);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
MainUtil.handleError(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
MainUtil.handleError(e);
|
MainUtil.handleError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasEntities(net.minecraft.server.v1_7_R4.Chunk nmsChunk) {
|
||||||
|
for (int i = 0; i < nmsChunk.entitySlices.length; i++) {
|
||||||
|
List<Entity> slice = nmsChunk.entitySlices[i];
|
||||||
|
if (slice != null && !slice.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeLighting(ChunkSection[] sections, RelightMode mode, boolean sky) {
|
public boolean removeLighting(ChunkSection[] sections, RelightMode mode, boolean sky) {
|
||||||
if (mode == RelightMode.ALL) {
|
if (mode == RelightMode.ALL) {
|
||||||
|
@ -30,12 +30,10 @@ import java.util.Set;
|
|||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import net.minecraft.server.v1_8_R3.Block;
|
import net.minecraft.server.v1_8_R3.Block;
|
||||||
import net.minecraft.server.v1_8_R3.BlockPosition;
|
import net.minecraft.server.v1_8_R3.BlockPosition;
|
||||||
import net.minecraft.server.v1_8_R3.ChunkCoordIntPair;
|
|
||||||
import net.minecraft.server.v1_8_R3.ChunkSection;
|
import net.minecraft.server.v1_8_R3.ChunkSection;
|
||||||
import net.minecraft.server.v1_8_R3.Entity;
|
import net.minecraft.server.v1_8_R3.Entity;
|
||||||
import net.minecraft.server.v1_8_R3.EntityPlayer;
|
import net.minecraft.server.v1_8_R3.EntityPlayer;
|
||||||
import net.minecraft.server.v1_8_R3.EntityTracker;
|
import net.minecraft.server.v1_8_R3.EntityTracker;
|
||||||
import net.minecraft.server.v1_8_R3.EntityTrackerEntry;
|
|
||||||
import net.minecraft.server.v1_8_R3.EntityTypes;
|
import net.minecraft.server.v1_8_R3.EntityTypes;
|
||||||
import net.minecraft.server.v1_8_R3.EnumDifficulty;
|
import net.minecraft.server.v1_8_R3.EnumDifficulty;
|
||||||
import net.minecraft.server.v1_8_R3.EnumSkyBlock;
|
import net.minecraft.server.v1_8_R3.EnumSkyBlock;
|
||||||
@ -43,7 +41,6 @@ import net.minecraft.server.v1_8_R3.LongHashMap;
|
|||||||
import net.minecraft.server.v1_8_R3.MinecraftServer;
|
import net.minecraft.server.v1_8_R3.MinecraftServer;
|
||||||
import net.minecraft.server.v1_8_R3.NBTTagCompound;
|
import net.minecraft.server.v1_8_R3.NBTTagCompound;
|
||||||
import net.minecraft.server.v1_8_R3.NibbleArray;
|
import net.minecraft.server.v1_8_R3.NibbleArray;
|
||||||
import net.minecraft.server.v1_8_R3.PacketPlayOutEntityDestroy;
|
|
||||||
import net.minecraft.server.v1_8_R3.PacketPlayOutMapChunk;
|
import net.minecraft.server.v1_8_R3.PacketPlayOutMapChunk;
|
||||||
import net.minecraft.server.v1_8_R3.PlayerChunkMap;
|
import net.minecraft.server.v1_8_R3.PlayerChunkMap;
|
||||||
import net.minecraft.server.v1_8_R3.ServerNBTManager;
|
import net.minecraft.server.v1_8_R3.ServerNBTManager;
|
||||||
@ -429,24 +426,21 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void refreshChunk(World world, Chunk chunk) {
|
public void refreshChunk(FaweChunk fc) {
|
||||||
|
BukkitChunk_1_8 fs = (BukkitChunk_1_8) fc;
|
||||||
|
Chunk chunk = fs.getChunk();
|
||||||
if (!chunk.isLoaded()) {
|
if (!chunk.isLoaded()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
net.minecraft.server.v1_8_R3.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
|
net.minecraft.server.v1_8_R3.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
|
||||||
ChunkCoordIntPair pos = nmsChunk.j(); // getPosition()
|
|
||||||
WorldServer w = (WorldServer) nmsChunk.getWorld();
|
WorldServer w = (WorldServer) nmsChunk.getWorld();
|
||||||
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
|
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
|
||||||
int x = pos.x;
|
int x = nmsChunk.locX;
|
||||||
int z = pos.z;
|
int z = nmsChunk.locZ;
|
||||||
if (!chunkMap.isChunkInUse(x, z)) {
|
if (!chunkMap.isChunkInUse(x, z)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HashSet<EntityPlayer> set = new HashSet<EntityPlayer>();
|
|
||||||
EntityTracker tracker = w.getTracker();
|
|
||||||
// Get players
|
|
||||||
|
|
||||||
Field fieldChunkMap = chunkMap.getClass().getDeclaredField("d");
|
Field fieldChunkMap = chunkMap.getClass().getDeclaredField("d");
|
||||||
fieldChunkMap.setAccessible(true);
|
fieldChunkMap.setAccessible(true);
|
||||||
LongHashMap<Object> map = (LongHashMap<Object>) fieldChunkMap.get(chunkMap);
|
LongHashMap<Object> map = (LongHashMap<Object>) fieldChunkMap.get(chunkMap);
|
||||||
@ -454,56 +448,38 @@ public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], ChunkS
|
|||||||
Object playerChunk = map.getEntry(pair);
|
Object playerChunk = map.getEntry(pair);
|
||||||
Field fieldPlayers = playerChunk.getClass().getDeclaredField("b");
|
Field fieldPlayers = playerChunk.getClass().getDeclaredField("b");
|
||||||
fieldPlayers.setAccessible(true);
|
fieldPlayers.setAccessible(true);
|
||||||
final HashSet<EntityPlayer> players = new HashSet<>((Collection<EntityPlayer>)fieldPlayers.get(playerChunk));
|
Collection<EntityPlayer> players = (Collection<EntityPlayer>) fieldPlayers.get(playerChunk);
|
||||||
if (players.size() == 0) {
|
if (players.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HashSet<EntityTrackerEntry> entities = new HashSet<>();
|
|
||||||
List<Entity>[] entitieSlices = nmsChunk.getEntitySlices();
|
|
||||||
for (List<Entity> slice : entitieSlices) {
|
|
||||||
if (slice == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (Entity ent : slice) {
|
|
||||||
EntityTrackerEntry entry = tracker.trackedEntities.get(ent.getId());
|
|
||||||
if (entry == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
entities.add(entry);
|
|
||||||
PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(ent.getId());
|
|
||||||
for (EntityPlayer player : players) {
|
|
||||||
player.playerConnection.sendPacket(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Send chunks
|
// Send chunks
|
||||||
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, false, 65535);
|
int mask = fc.getBitMask();
|
||||||
|
if (mask == 65535 && hasEntities(nmsChunk)) {
|
||||||
|
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, false, 65280);
|
||||||
for (EntityPlayer player : players) {
|
for (EntityPlayer player : players) {
|
||||||
player.playerConnection.sendPacket(packet);
|
player.playerConnection.sendPacket(packet);
|
||||||
}
|
}
|
||||||
// send ents
|
mask = 255;
|
||||||
for (final EntityTrackerEntry entry : entities) {
|
}
|
||||||
try {
|
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, false, mask);
|
||||||
TaskManager.IMP.later(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (EntityPlayer player : players) {
|
for (EntityPlayer player : players) {
|
||||||
boolean result = entry.trackedPlayers.remove(player);
|
player.playerConnection.sendPacket(packet);
|
||||||
if (result && entry.tracker != player) {
|
|
||||||
entry.updatePlayer(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 2);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
MainUtil.handleError(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
MainUtil.handleError(e);
|
MainUtil.handleError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasEntities(net.minecraft.server.v1_8_R3.Chunk nmsChunk) {
|
||||||
|
for (int i = 0; i < nmsChunk.entitySlices.length; i++) {
|
||||||
|
List<Entity> slice = nmsChunk.entitySlices[i];
|
||||||
|
if (slice != null && !slice.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeLighting(ChunkSection[] sections, RelightMode mode, boolean sky) {
|
public boolean removeLighting(ChunkSection[] sections, RelightMode mode, boolean sky) {
|
||||||
if (mode == RelightMode.ALL) {
|
if (mode == RelightMode.ALL) {
|
||||||
|
@ -34,16 +34,13 @@ import java.util.UUID;
|
|||||||
import net.minecraft.server.v1_9_R2.Block;
|
import net.minecraft.server.v1_9_R2.Block;
|
||||||
import net.minecraft.server.v1_9_R2.BlockPosition;
|
import net.minecraft.server.v1_9_R2.BlockPosition;
|
||||||
import net.minecraft.server.v1_9_R2.Blocks;
|
import net.minecraft.server.v1_9_R2.Blocks;
|
||||||
import net.minecraft.server.v1_9_R2.ChunkCoordIntPair;
|
|
||||||
import net.minecraft.server.v1_9_R2.ChunkSection;
|
import net.minecraft.server.v1_9_R2.ChunkSection;
|
||||||
import net.minecraft.server.v1_9_R2.DataBits;
|
import net.minecraft.server.v1_9_R2.DataBits;
|
||||||
import net.minecraft.server.v1_9_R2.DataPalette;
|
import net.minecraft.server.v1_9_R2.DataPalette;
|
||||||
import net.minecraft.server.v1_9_R2.DataPaletteBlock;
|
import net.minecraft.server.v1_9_R2.DataPaletteBlock;
|
||||||
import net.minecraft.server.v1_9_R2.Entity;
|
import net.minecraft.server.v1_9_R2.Entity;
|
||||||
import net.minecraft.server.v1_9_R2.EntityHuman;
|
|
||||||
import net.minecraft.server.v1_9_R2.EntityPlayer;
|
import net.minecraft.server.v1_9_R2.EntityPlayer;
|
||||||
import net.minecraft.server.v1_9_R2.EntityTracker;
|
import net.minecraft.server.v1_9_R2.EntityTracker;
|
||||||
import net.minecraft.server.v1_9_R2.EntityTrackerEntry;
|
|
||||||
import net.minecraft.server.v1_9_R2.EntityTypes;
|
import net.minecraft.server.v1_9_R2.EntityTypes;
|
||||||
import net.minecraft.server.v1_9_R2.EnumDifficulty;
|
import net.minecraft.server.v1_9_R2.EnumDifficulty;
|
||||||
import net.minecraft.server.v1_9_R2.EnumSkyBlock;
|
import net.minecraft.server.v1_9_R2.EnumSkyBlock;
|
||||||
@ -52,7 +49,6 @@ import net.minecraft.server.v1_9_R2.IDataManager;
|
|||||||
import net.minecraft.server.v1_9_R2.MinecraftServer;
|
import net.minecraft.server.v1_9_R2.MinecraftServer;
|
||||||
import net.minecraft.server.v1_9_R2.NBTTagCompound;
|
import net.minecraft.server.v1_9_R2.NBTTagCompound;
|
||||||
import net.minecraft.server.v1_9_R2.NibbleArray;
|
import net.minecraft.server.v1_9_R2.NibbleArray;
|
||||||
import net.minecraft.server.v1_9_R2.PacketPlayOutEntityDestroy;
|
|
||||||
import net.minecraft.server.v1_9_R2.PacketPlayOutMapChunk;
|
import net.minecraft.server.v1_9_R2.PacketPlayOutMapChunk;
|
||||||
import net.minecraft.server.v1_9_R2.PlayerChunk;
|
import net.minecraft.server.v1_9_R2.PlayerChunk;
|
||||||
import net.minecraft.server.v1_9_R2.PlayerChunkMap;
|
import net.minecraft.server.v1_9_R2.PlayerChunkMap;
|
||||||
@ -128,81 +124,50 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Chu
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void refreshChunk(World world, Chunk chunk) {
|
public void refreshChunk(FaweChunk fc) {
|
||||||
|
BukkitChunk_1_9 fs = (BukkitChunk_1_9) fc;
|
||||||
|
Chunk chunk = fs.getChunk();
|
||||||
if (!chunk.isLoaded()) {
|
if (!chunk.isLoaded()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
net.minecraft.server.v1_9_R2.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
|
net.minecraft.server.v1_9_R2.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
|
||||||
ChunkCoordIntPair pos = nmsChunk.k(); // getPosition()
|
|
||||||
WorldServer w = (WorldServer) nmsChunk.getWorld();
|
WorldServer w = (WorldServer) nmsChunk.getWorld();
|
||||||
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
|
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
|
||||||
PlayerChunk playerChunk = chunkMap.getChunk(pos.x, pos.z);
|
PlayerChunk playerChunk = chunkMap.getChunk(nmsChunk.locX, nmsChunk.locZ);
|
||||||
if (playerChunk == null) {
|
if (playerChunk == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HashSet<EntityPlayer> set = new HashSet<EntityPlayer>(playerChunk.c);
|
if (playerChunk.c.isEmpty()) {
|
||||||
EntityTracker tracker = w.getTracker();
|
|
||||||
// Get players
|
|
||||||
final HashSet<EntityPlayer> players = new HashSet<>();
|
|
||||||
for (EntityHuman human : w.players) {
|
|
||||||
if (set.contains(human)) {
|
|
||||||
players.add((EntityPlayer) human);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (players.size() == 0) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HashSet<EntityTrackerEntry> entities = new HashSet<>();
|
|
||||||
List<Entity>[] entitieSlices = playerChunk.chunk.getEntitySlices();
|
|
||||||
for (List<Entity> slice : entitieSlices) {
|
|
||||||
if (slice == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (Entity ent : slice) {
|
|
||||||
EntityTrackerEntry entry = tracker.trackedEntities.get(ent.getId());
|
|
||||||
if (entry == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
entities.add(entry);
|
|
||||||
PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(ent.getId());
|
|
||||||
for (EntityPlayer player : players) {
|
|
||||||
player.playerConnection.sendPacket(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Send chunks
|
// Send chunks
|
||||||
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(playerChunk.chunk, 65535);
|
int mask = fc.getBitMask();
|
||||||
for (EntityPlayer player : players) {
|
if (mask == 65535 && hasEntities(nmsChunk)) {
|
||||||
|
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, 65280);
|
||||||
|
for (EntityPlayer player : playerChunk.c) {
|
||||||
player.playerConnection.sendPacket(packet);
|
player.playerConnection.sendPacket(packet);
|
||||||
}
|
}
|
||||||
// send ents
|
mask = 255;
|
||||||
for (List<Entity> slice : entitieSlices) {
|
|
||||||
if (slice == null) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
for (final Entity ent : slice) {
|
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, mask);
|
||||||
final EntityTrackerEntry entry = tracker.trackedEntities.get(ent.getId());
|
for (EntityPlayer player : playerChunk.c) {
|
||||||
if (entry == null) {
|
player.playerConnection.sendPacket(packet);
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
try {
|
|
||||||
TaskManager.IMP.later(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (EntityPlayer player : players) {
|
|
||||||
boolean result = entry.trackedPlayers.remove(player);
|
|
||||||
if (result && ent != player) {
|
|
||||||
entry.updatePlayer(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 2);
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
MainUtil.handleError(e);
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasEntities(net.minecraft.server.v1_9_R2.Chunk nmsChunk) {
|
||||||
|
for (int i = 0; i < nmsChunk.entitySlices.length; i++) {
|
||||||
|
List<Entity> slice = nmsChunk.entitySlices[i];
|
||||||
|
if (slice != null && !slice.isEmpty()) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public World createWorld(final WorldCreator creator) {
|
public World createWorld(final WorldCreator creator) {
|
||||||
|
@ -55,6 +55,7 @@ import com.sk89q.worldedit.history.change.EntityCreate;
|
|||||||
import com.sk89q.worldedit.history.change.EntityRemove;
|
import com.sk89q.worldedit.history.change.EntityRemove;
|
||||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||||
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
|
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
|
||||||
|
import com.sk89q.worldedit.session.SessionManager;
|
||||||
import com.sk89q.worldedit.util.command.parametric.ParametricBuilder;
|
import com.sk89q.worldedit.util.command.parametric.ParametricBuilder;
|
||||||
import com.sk89q.worldedit.world.registry.BundledBlockData;
|
import com.sk89q.worldedit.world.registry.BundledBlockData;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -179,8 +180,8 @@ public class Fawe {
|
|||||||
* Implementation dependent stuff
|
* Implementation dependent stuff
|
||||||
*/
|
*/
|
||||||
this.setupConfigs();
|
this.setupConfigs();
|
||||||
MainUtil.deleteOlder(new File(IMP.getDirectory(), "history"), TimeUnit.DAYS.toMillis(Settings.HISTORY.DELETE_AFTER_DAYS));
|
MainUtil.deleteOlder(MainUtil.getFile(IMP.getDirectory(), Settings.PATHS.HISTORY), TimeUnit.DAYS.toMillis(Settings.HISTORY.DELETE_AFTER_DAYS));
|
||||||
MainUtil.deleteOlder(new File(IMP.getDirectory(), "clipboard"), TimeUnit.DAYS.toMillis(Settings.CLIPBOARD.DELETE_AFTER_DAYS));
|
MainUtil.deleteOlder(MainUtil.getFile(IMP.getDirectory(), Settings.PATHS.CLIPBOARD), TimeUnit.DAYS.toMillis(Settings.CLIPBOARD.DELETE_AFTER_DAYS));
|
||||||
|
|
||||||
TaskManager.IMP = this.IMP.getTaskManager();
|
TaskManager.IMP = this.IMP.getTaskManager();
|
||||||
TaskManager.IMP.repeat(timer = new FaweTimer(), 1);
|
TaskManager.IMP.repeat(timer = new FaweTimer(), 1);
|
||||||
@ -276,6 +277,7 @@ public class Fawe {
|
|||||||
EditSession.inject(); // Custom block placer + optimizations
|
EditSession.inject(); // Custom block placer + optimizations
|
||||||
EditSessionEvent.inject(); // Add EditSession to event
|
EditSessionEvent.inject(); // Add EditSession to event
|
||||||
LocalSession.inject(); // Add remember order / queue flushing
|
LocalSession.inject(); // Add remember order / queue flushing
|
||||||
|
SessionManager.inject(); // Custom session saving
|
||||||
// Commands
|
// Commands
|
||||||
BrushCommands.inject(); // Translations + heightmap
|
BrushCommands.inject(); // Translations + heightmap
|
||||||
ToolCommands.inject(); // Translations + inspect
|
ToolCommands.inject(); // Translations + inspect
|
||||||
|
@ -257,7 +257,7 @@ public class FaweAPI {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static List<DiskStorageHistory> getBDFiles(FaweLocation origin, UUID user, int radius, long timediff, boolean shallow) {
|
public static List<DiskStorageHistory> getBDFiles(FaweLocation origin, UUID user, int radius, long timediff, boolean shallow) {
|
||||||
File history = new File(Fawe.imp().getDirectory(), "history" + File.separator + origin.world);
|
File history = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.PATHS.HISTORY + File.separator + origin.world);
|
||||||
if (!history.exists()) {
|
if (!history.exists()) {
|
||||||
return new ArrayList<>();
|
return new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,13 @@ public class Settings extends Config {
|
|||||||
})
|
})
|
||||||
public static int MAX_MEMORY_PERCENT = 95;
|
public static int MAX_MEMORY_PERCENT = 95;
|
||||||
|
|
||||||
|
@Comment("Paths for various directories")
|
||||||
|
public static final class PATHS {
|
||||||
|
public static String HISTORY = "history";
|
||||||
|
public static String CLIPBOARD = "clipboard";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Create // This value will be generated automatically
|
@Create // This value will be generated automatically
|
||||||
public static ConfigBlock<LIMITS> LIMITS = null;
|
public static ConfigBlock<LIMITS> LIMITS = null;
|
||||||
|
|
||||||
@ -129,7 +136,8 @@ public class Settings extends Config {
|
|||||||
public static int CHUNK_WAIT_MS = 100;
|
public static int CHUNK_WAIT_MS = 100;
|
||||||
@Comment("Delete history on disk after a number of days")
|
@Comment("Delete history on disk after a number of days")
|
||||||
public static int DELETE_AFTER_DAYS = 7;
|
public static int DELETE_AFTER_DAYS = 7;
|
||||||
@Comment("Delete history in memory on logout (does not effect disk)")
|
@Comment("Delete history in memory on logout (does not effect disk) (BROKEN, USE DISK INSTEAD)")
|
||||||
|
@Final // Deprecated
|
||||||
public static boolean DELETE_ON_LOGOUT = true;
|
public static boolean DELETE_ON_LOGOUT = true;
|
||||||
@Comment({
|
@Comment({
|
||||||
"If history should be enabled by default for plugins using WorldEdit:",
|
"If history should be enabled by default for plugins using WorldEdit:",
|
||||||
@ -227,7 +235,7 @@ public class Settings extends Config {
|
|||||||
" - 1 = Optimal (Relight changed light sources and changed blocks)",
|
" - 1 = Optimal (Relight changed light sources and changed blocks)",
|
||||||
" - 2 = All (Slowly relight every blocks)"
|
" - 2 = All (Slowly relight every blocks)"
|
||||||
})
|
})
|
||||||
public static int MODE = 2;
|
public static int MODE = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void save(File file) {
|
public static void save(File file) {
|
||||||
|
@ -6,6 +6,7 @@ import com.boydti.fawe.config.Settings;
|
|||||||
import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory;
|
import com.boydti.fawe.logging.rollback.RollbackOptimizedHistory;
|
||||||
import com.boydti.fawe.object.RunnableVal;
|
import com.boydti.fawe.object.RunnableVal;
|
||||||
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
||||||
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
import com.boydti.fawe.util.TaskManager;
|
||||||
import com.sk89q.worldedit.Vector;
|
import com.sk89q.worldedit.Vector;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
@ -42,7 +43,7 @@ public class RollbackDatabase {
|
|||||||
public RollbackDatabase(final String world) throws SQLException, ClassNotFoundException {
|
public RollbackDatabase(final String world) throws SQLException, ClassNotFoundException {
|
||||||
this.prefix = "";
|
this.prefix = "";
|
||||||
this.world = world;
|
this.world = world;
|
||||||
this.dbLocation = new File(Fawe.imp().getDirectory(), "history" + File.separator + world + File.separator + "summary.db");
|
this.dbLocation = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.PATHS.HISTORY + File.separator + world + File.separator + "summary.db");
|
||||||
connection = openConnection();
|
connection = openConnection();
|
||||||
CREATE_TABLE = "CREATE TABLE IF NOT EXISTS `" + prefix + "edits` (`player` BLOB(16) NOT NULL,`id` INT NOT NULL,`x1` INT NOT NULL,`y1` INT NOT NULL,`z1` INT NOT NULL,`x2` INT NOT NULL,`y2` INT NOT NULL,`z2` INT NOT NULL,`time` INT NOT NULL, PRIMARY KEY (player, id))";
|
CREATE_TABLE = "CREATE TABLE IF NOT EXISTS `" + prefix + "edits` (`player` BLOB(16) NOT NULL,`id` INT NOT NULL,`x1` INT NOT NULL,`y1` INT NOT NULL,`z1` INT NOT NULL,`x2` INT NOT NULL,`y2` INT NOT NULL,`z2` INT NOT NULL,`time` INT NOT NULL, PRIMARY KEY (player, id))";
|
||||||
INSERT_EDIT = "INSERT INTO `" + prefix + "edits` (`player`,`id`,`x1`,`y1`,`z1`,`x2`,`y2`,`z2`,`time`) VALUES(?,?,?,?,?,?,?,?,?)";
|
INSERT_EDIT = "INSERT INTO `" + prefix + "edits` (`player`,`id`,`x1`,`y1`,`z1`,`x2`,`y2`,`z2`,`time`) VALUES(?,?,?,?,?,?,?,?,?)";
|
||||||
|
@ -22,6 +22,7 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
|
|||||||
public short[] air;
|
public short[] air;
|
||||||
public short[] relight;
|
public short[] relight;
|
||||||
public int[][] biomes;
|
public int[][] biomes;
|
||||||
|
private int bitMask = -1;
|
||||||
|
|
||||||
public T chunk;
|
public T chunk;
|
||||||
|
|
||||||
@ -103,6 +104,23 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
|
|||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBitMask() {
|
||||||
|
if (bitMask == -1) {
|
||||||
|
this.bitMask = 0;
|
||||||
|
for (int section = 0; section < ids.length; section++) {
|
||||||
|
if (ids[section] != null) {
|
||||||
|
bitMask += 1 << section;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bitMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBitMask(int value) {
|
||||||
|
this.bitMask = value;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the raw data for a section
|
* Get the raw data for a section
|
||||||
* @param i
|
* @param i
|
||||||
|
@ -66,7 +66,7 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void sendChunk(final FaweChunk fc) {
|
public void sendChunk(final FaweChunk fc) {
|
||||||
refreshChunk(getWorld(), (CHUNK) fc.getChunk());
|
refreshChunk(fc);
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void setFullbright(CHUNKSECTION sections);
|
public abstract void setFullbright(CHUNKSECTION sections);
|
||||||
@ -159,7 +159,7 @@ public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> ex
|
|||||||
|
|
||||||
public abstract void setBlockLight(SECTION section, int x, int y, int z, int value);
|
public abstract void setBlockLight(SECTION section, int x, int y, int z, int value);
|
||||||
|
|
||||||
public abstract void refreshChunk(WORLD world, CHUNK chunk);
|
public abstract void refreshChunk(FaweChunk fs);
|
||||||
|
|
||||||
public abstract CharFaweChunk getPrevious(CharFaweChunk fs, CHUNKSECTION sections, Map<?, ?> tiles, Collection<?>[] entities, Set<UUID> createdEntities, boolean all) throws Exception;
|
public abstract CharFaweChunk getPrevious(CharFaweChunk fs, CHUNKSECTION sections, Map<?, ?> tiles, Collection<?>[] entities, Set<UUID> createdEntities, boolean all) throws Exception;
|
||||||
|
|
||||||
|
@ -100,7 +100,15 @@ public class NMSRelighter {
|
|||||||
public void sendChunks() {
|
public void sendChunks() {
|
||||||
for (Map.Entry<Long, RelightSkyEntry> entry : skyToRelight.entrySet()) {
|
for (Map.Entry<Long, RelightSkyEntry> entry : skyToRelight.entrySet()) {
|
||||||
RelightSkyEntry chunk = entry.getValue();
|
RelightSkyEntry chunk = entry.getValue();
|
||||||
queue.sendChunk(queue.getFaweChunk(chunk.x, chunk.z));
|
CharFaweChunk fc = (CharFaweChunk) queue.getFaweChunk(chunk.x, chunk.z);
|
||||||
|
int mask = 0;
|
||||||
|
for (int y = 0; y < chunk.fix.length; y++) {
|
||||||
|
if (chunk.fix[y]) {
|
||||||
|
mask += 1 << y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fc.setBitMask(mask);
|
||||||
|
queue.sendChunk(fc);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,12 @@ public abstract class FaweChunk<T> {
|
|||||||
*/
|
*/
|
||||||
public abstract char[][] getCombinedIdArrays();
|
public abstract char[][] getCombinedIdArrays();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The modified sections
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public abstract int getBitMask();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the combined block id at a location<br>
|
* Get the combined block id at a location<br>
|
||||||
* combined = (id <<<< 4) + data
|
* combined = (id <<<< 4) + data
|
||||||
|
@ -4,8 +4,6 @@ import com.boydti.fawe.Fawe;
|
|||||||
import com.boydti.fawe.FaweAPI;
|
import com.boydti.fawe.FaweAPI;
|
||||||
import com.boydti.fawe.config.BBC;
|
import com.boydti.fawe.config.BBC;
|
||||||
import com.boydti.fawe.config.Settings;
|
import com.boydti.fawe.config.Settings;
|
||||||
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
|
||||||
import com.boydti.fawe.object.changeset.FaweStreamChangeSet;
|
|
||||||
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
|
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
|
||||||
import com.boydti.fawe.object.exception.FaweException;
|
import com.boydti.fawe.object.exception.FaweException;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
@ -30,9 +28,6 @@ import com.sk89q.worldedit.world.World;
|
|||||||
import com.sk89q.worldedit.world.registry.WorldData;
|
import com.sk89q.worldedit.world.registry.WorldData;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
@ -111,23 +106,6 @@ public abstract class FawePlayer<T> {
|
|||||||
if (Settings.CLIPBOARD.USE_DISK) {
|
if (Settings.CLIPBOARD.USE_DISK) {
|
||||||
loadClipboardFromDisk();
|
loadClipboardFromDisk();
|
||||||
}
|
}
|
||||||
if (getSession() == null || getPlayer() == null || session.getSize() != 0 || !Settings.HISTORY.USE_DISK) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
UUID uuid = getUUID();
|
|
||||||
String currentWorldName = getLocation().world;
|
|
||||||
World world = getWorld();
|
|
||||||
if (world != null) {
|
|
||||||
if (Fawe.imp().getWorldName(world).equals(currentWorldName)) {
|
|
||||||
getSession().clearHistory();
|
|
||||||
loadSessionsFromDisk(world);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
MainUtil.handleError(e);
|
|
||||||
Fawe.debug("Failed to load history for: " + getName());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -135,7 +113,7 @@ public abstract class FawePlayer<T> {
|
|||||||
* - Should already be called if history on disk is enabled
|
* - Should already be called if history on disk is enabled
|
||||||
*/
|
*/
|
||||||
public void loadClipboardFromDisk() {
|
public void loadClipboardFromDisk() {
|
||||||
File file = new File(Fawe.imp().getDirectory(), "clipboard" + File.separator + getUUID() + ".bd");
|
File file = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.PATHS.CLIPBOARD + File.separator + getUUID() + ".bd");
|
||||||
try {
|
try {
|
||||||
if (file.exists() && file.length() > 5) {
|
if (file.exists() && file.length() > 5) {
|
||||||
DiskOptimizedClipboard doc = new DiskOptimizedClipboard(file);
|
DiskOptimizedClipboard doc = new DiskOptimizedClipboard(file);
|
||||||
@ -174,45 +152,14 @@ public abstract class FawePlayer<T> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Load all the undo EditSession's from disk for a world <br>
|
* Load all the undo EditSession's from disk for a world <br>
|
||||||
* - Usually already called when a player joins or changes world
|
* - Usually already called when necessary
|
||||||
* @param world
|
* @param world
|
||||||
*/
|
*/
|
||||||
public void loadSessionsFromDisk(final World world) {
|
public void loadSessionsFromDisk(final World world) {
|
||||||
if (world == null) {
|
if (world == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
final long start = System.currentTimeMillis();
|
getSession().loadSessionHistoryFromDisk(getUUID(), world);
|
||||||
final UUID uuid = getUUID();
|
|
||||||
final List<Integer> editIds = new ArrayList<>();
|
|
||||||
final File folder = new File(Fawe.imp().getDirectory(), "history" + File.separator + Fawe.imp().getWorldName(world) + File.separator + uuid);
|
|
||||||
if (folder.isDirectory()) {
|
|
||||||
for (File file : folder.listFiles()) {
|
|
||||||
if (file.getName().endsWith(".bd")) {
|
|
||||||
int index = Integer.parseInt(file.getName().split("\\.")[0]);
|
|
||||||
editIds.add(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (editIds.size() > 0) {
|
|
||||||
BBC.INDEXING_HISTORY.send(this, editIds.size());
|
|
||||||
TaskManager.IMP.async(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
Collections.sort(editIds);
|
|
||||||
for (int i = editIds.size() - 1; i >= 0; i--) {
|
|
||||||
int index = editIds.get(i);
|
|
||||||
FaweStreamChangeSet set = new DiskStorageHistory(world, uuid, index);
|
|
||||||
EditSession edit = set.toEditSession(FawePlayer.this);
|
|
||||||
if (world.equals(getWorld())) {
|
|
||||||
session.remember(edit, false, false, Integer.MAX_VALUE);
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
BBC.INDEXING_COMPLETE.send(FawePlayer.this, (System.currentTimeMillis() - start) / 1000d);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -417,9 +364,10 @@ public abstract class FawePlayer<T> {
|
|||||||
*/
|
*/
|
||||||
public void unregister() {
|
public void unregister() {
|
||||||
if (Settings.HISTORY.DELETE_ON_LOGOUT) {
|
if (Settings.HISTORY.DELETE_ON_LOGOUT) {
|
||||||
getSession().setClipboard(null);
|
session = getSession();
|
||||||
getSession().clearHistory();
|
|
||||||
WorldEdit.getInstance().removeSession(getPlayer());
|
WorldEdit.getInstance().removeSession(getPlayer());
|
||||||
|
session.setClipboard(null);
|
||||||
|
session.clearHistory();
|
||||||
}
|
}
|
||||||
Fawe.get().unregister(getName());
|
Fawe.get().unregister(getName());
|
||||||
}
|
}
|
||||||
|
@ -35,11 +35,6 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
|
|||||||
private File entfFile;
|
private File entfFile;
|
||||||
private File enttFile;
|
private File enttFile;
|
||||||
|
|
||||||
/**
|
|
||||||
* Summary of this change (not accurate for larger edits)
|
|
||||||
*/
|
|
||||||
private DiskStorageSummary summary;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Block data
|
* Block data
|
||||||
*
|
*
|
||||||
@ -50,33 +45,20 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
|
|||||||
* { short rel x, short rel z, unsigned byte y, short combinedFrom, short combinedTo }
|
* { short rel x, short rel z, unsigned byte y, short combinedFrom, short combinedTo }
|
||||||
*/
|
*/
|
||||||
private OutputStream osBD;
|
private OutputStream osBD;
|
||||||
|
|
||||||
// NBT From
|
// NBT From
|
||||||
private NBTOutputStream osNBTF;
|
private NBTOutputStream osNBTF;
|
||||||
|
|
||||||
// NBT To
|
// NBT To
|
||||||
private NBTOutputStream osNBTT;
|
private NBTOutputStream osNBTT;
|
||||||
|
|
||||||
// Entity Create From
|
// Entity Create From
|
||||||
private NBTOutputStream osENTCF;
|
private NBTOutputStream osENTCF;
|
||||||
|
|
||||||
// Entity Create To
|
// Entity Create To
|
||||||
private NBTOutputStream osENTCT;
|
private NBTOutputStream osENTCT;
|
||||||
|
|
||||||
private int index;
|
private int index;
|
||||||
|
|
||||||
public void deleteFiles() {
|
|
||||||
bdFile.delete();
|
|
||||||
nbtfFile.delete();
|
|
||||||
nbttFile.delete();
|
|
||||||
entfFile.delete();
|
|
||||||
enttFile.delete();
|
|
||||||
}
|
|
||||||
|
|
||||||
public DiskStorageHistory(World world, UUID uuid) {
|
public DiskStorageHistory(World world, UUID uuid) {
|
||||||
super(world);
|
super(world);
|
||||||
String base = "history" + File.separator + Fawe.imp().getWorldName(world) + File.separator + uuid;
|
File folder = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.PATHS.HISTORY + File.separator + Fawe.imp().getWorldName(world) + File.separator + uuid);
|
||||||
File folder = new File(Fawe.imp().getDirectory(), base);
|
|
||||||
int max = 0;
|
int max = 0;
|
||||||
if (folder.exists()) {
|
if (folder.exists()) {
|
||||||
for (File file : folder.listFiles()) {
|
for (File file : folder.listFiles()) {
|
||||||
@ -97,16 +79,34 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
|
|||||||
init(uuid, index);
|
init(uuid, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DiskStorageHistory(File folder, World world, UUID uuid, int i) {
|
||||||
|
super(world);
|
||||||
|
this.uuid = uuid;
|
||||||
|
this.index = i;
|
||||||
|
initFiles(folder);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initFiles(File folder) {
|
||||||
|
nbtfFile = new File(folder, index + ".nbtf");
|
||||||
|
nbttFile = new File(folder, index + ".nbtt");
|
||||||
|
entfFile = new File(folder, index + ".entf");
|
||||||
|
enttFile = new File(folder, index + ".entt");
|
||||||
|
bdFile = new File(folder, index + ".bd");
|
||||||
|
}
|
||||||
|
|
||||||
private void init(UUID uuid, int i) {
|
private void init(UUID uuid, int i) {
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.index = i;
|
this.index = i;
|
||||||
String base = "history" + File.separator + Fawe.imp().getWorldName(getWorld()) + File.separator + uuid;
|
File folder = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.PATHS.HISTORY + File.separator + Fawe.imp().getWorldName(getWorld()) + File.separator + uuid);
|
||||||
base += File.separator + i;
|
initFiles(folder);
|
||||||
nbtfFile = new File(Fawe.imp().getDirectory(), base + ".nbtf");
|
}
|
||||||
nbttFile = new File(Fawe.imp().getDirectory(), base + ".nbtt");
|
|
||||||
entfFile = new File(Fawe.imp().getDirectory(), base + ".entf");
|
public void deleteFiles() {
|
||||||
enttFile = new File(Fawe.imp().getDirectory(), base + ".entt");
|
bdFile.delete();
|
||||||
bdFile = new File(Fawe.imp().getDirectory(), base + ".bd");
|
nbtfFile.delete();
|
||||||
|
nbttFile.delete();
|
||||||
|
entfFile.delete();
|
||||||
|
enttFile.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
public UUID getUUID() {
|
public UUID getUUID() {
|
||||||
@ -162,6 +162,27 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
|
|||||||
return 80;
|
return 80;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getSizeOnDisk() {
|
||||||
|
int total = 0;
|
||||||
|
if (bdFile.exists()) {
|
||||||
|
total += bdFile.getTotalSpace();
|
||||||
|
}
|
||||||
|
if (nbtfFile.exists()) {
|
||||||
|
total += entfFile.getTotalSpace();
|
||||||
|
}
|
||||||
|
if (nbttFile.exists()) {
|
||||||
|
total += entfFile.getTotalSpace();
|
||||||
|
}
|
||||||
|
if (entfFile.exists()) {
|
||||||
|
total += entfFile.getTotalSpace();
|
||||||
|
}
|
||||||
|
if (enttFile.exists()) {
|
||||||
|
total += entfFile.getTotalSpace();
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public OutputStream getBlockOS(int x, int y, int z) throws IOException {
|
public OutputStream getBlockOS(int x, int y, int z) throws IOException {
|
||||||
if (osBD != null) {
|
if (osBD != null) {
|
||||||
@ -281,14 +302,11 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DiskStorageSummary summarize(RegionWrapper requiredRegion, boolean shallow) {
|
public DiskStorageSummary summarize(RegionWrapper requiredRegion, boolean shallow) {
|
||||||
if (summary != null) {
|
|
||||||
return summary;
|
|
||||||
}
|
|
||||||
if (bdFile.exists()) {
|
if (bdFile.exists()) {
|
||||||
int ox = getOriginX();
|
int ox = getOriginX();
|
||||||
int oz = getOriginZ();
|
int oz = getOriginZ();
|
||||||
if ((ox != 0 || oz != 0) && !requiredRegion.isIn(ox, oz)) {
|
if ((ox != 0 || oz != 0) && !requiredRegion.isIn(ox, oz)) {
|
||||||
return summary = new DiskStorageSummary(ox, oz);
|
return new DiskStorageSummary(ox, oz);
|
||||||
}
|
}
|
||||||
try (FileInputStream fis = new FileInputStream(bdFile)) {
|
try (FileInputStream fis = new FileInputStream(bdFile)) {
|
||||||
FaweInputStream gis = MainUtil.getCompressedIS(fis);
|
FaweInputStream gis = MainUtil.getCompressedIS(fis);
|
||||||
@ -298,7 +316,7 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
|
|||||||
ox = ((gis.read() << 24) + (gis.read() << 16) + (gis.read() << 8) + (gis.read() << 0));
|
ox = ((gis.read() << 24) + (gis.read() << 16) + (gis.read() << 8) + (gis.read() << 0));
|
||||||
oz = ((gis.read() << 24) + (gis.read() << 16) + (gis.read() << 8) + (gis.read() << 0));
|
oz = ((gis.read() << 24) + (gis.read() << 16) + (gis.read() << 8) + (gis.read() << 0));
|
||||||
setOrigin(ox, oz);
|
setOrigin(ox, oz);
|
||||||
summary = new DiskStorageSummary(ox, oz);
|
DiskStorageSummary summary = new DiskStorageSummary(ox, oz);
|
||||||
if (!requiredRegion.isIn(ox, oz)) {
|
if (!requiredRegion.isIn(ox, oz)) {
|
||||||
fis.close();
|
fis.close();
|
||||||
gis.close();
|
gis.close();
|
||||||
@ -323,7 +341,7 @@ public class DiskStorageHistory extends FaweStreamChangeSet {
|
|||||||
MainUtil.handleError(e);
|
MainUtil.handleError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return summary;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IntegerPair readHeader() {
|
public IntegerPair readHeader() {
|
||||||
|
@ -50,6 +50,10 @@ public abstract class FaweStreamChangeSet extends FaweChangeSet {
|
|||||||
|
|
||||||
public abstract long getSizeInMemory();
|
public abstract long getSizeInMemory();
|
||||||
|
|
||||||
|
public long getSizeOnDisk() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
public abstract OutputStream getBlockOS(int x, int y, int z) throws IOException;
|
public abstract OutputStream getBlockOS(int x, int y, int z) throws IOException;
|
||||||
public abstract NBTOutputStream getEntityCreateOS() throws IOException;
|
public abstract NBTOutputStream getEntityCreateOS() throws IOException;
|
||||||
public abstract NBTOutputStream getEntityRemoveOS() throws IOException;
|
public abstract NBTOutputStream getEntityRemoveOS() throws IOException;
|
||||||
|
@ -56,7 +56,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
|
|||||||
private int last;
|
private int last;
|
||||||
|
|
||||||
public DiskOptimizedClipboard(int width, int height, int length, UUID uuid) {
|
public DiskOptimizedClipboard(int width, int height, int length, UUID uuid) {
|
||||||
this(width, height, length, new File(Fawe.imp().getDirectory(), "clipboard" + File.separator + uuid + ".bd"));
|
this(width, height, length, MainUtil.getFile(Fawe.imp().getDirectory(), Settings.PATHS.CLIPBOARD + File.separator + uuid + ".bd"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public DiskOptimizedClipboard(File file) throws IOException {
|
public DiskOptimizedClipboard(File file) throws IOException {
|
||||||
@ -176,7 +176,7 @@ public class DiskOptimizedClipboard extends FaweClipboard implements Closeable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DiskOptimizedClipboard(int width, int height, int length) {
|
public DiskOptimizedClipboard(int width, int height, int length) {
|
||||||
this(width, height, length, new File(Fawe.imp().getDirectory(), "clipboard" + File.separator + UUID.randomUUID()));
|
this(width, height, length, MainUtil.getFile(Fawe.imp().getDirectory(), Settings.PATHS.CLIPBOARD + File.separator + UUID.randomUUID() + ".bd"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
|
@ -1028,8 +1028,9 @@ public class EditSession implements Extent {
|
|||||||
public void undo(final EditSession editSession) {
|
public void undo(final EditSession editSession) {
|
||||||
final UndoContext context = new UndoContext();
|
final UndoContext context = new UndoContext();
|
||||||
context.setExtent(editSession.bypassAll);
|
context.setExtent(editSession.bypassAll);
|
||||||
|
ChangeSet changeSet = getChangeSet();
|
||||||
editSession.getQueue().setChangeTask(null);
|
editSession.getQueue().setChangeTask(null);
|
||||||
Operations.completeSmart(ChangeSetExecutor.createUndo(getChangeSet(), context), new Runnable() {
|
Operations.completeSmart(ChangeSetExecutor.createUndo(changeSet, context), new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
editSession.flushQueue();
|
editSession.flushQueue();
|
||||||
@ -1046,8 +1047,9 @@ public class EditSession implements Extent {
|
|||||||
public void redo(final EditSession editSession) {
|
public void redo(final EditSession editSession) {
|
||||||
final UndoContext context = new UndoContext();
|
final UndoContext context = new UndoContext();
|
||||||
context.setExtent(editSession.bypassAll);
|
context.setExtent(editSession.bypassAll);
|
||||||
|
ChangeSet changeSet = getChangeSet();
|
||||||
editSession.getQueue().setChangeTask(null);
|
editSession.getQueue().setChangeTask(null);
|
||||||
Operations.completeSmart(ChangeSetExecutor.createRedo(getChangeSet(), context), new Runnable() {
|
Operations.completeSmart(ChangeSetExecutor.createRedo(changeSet, context), new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
editSession.flushQueue();
|
editSession.flushQueue();
|
||||||
|
@ -19,7 +19,13 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit;
|
package com.sk89q.worldedit;
|
||||||
|
|
||||||
|
import com.boydti.fawe.Fawe;
|
||||||
|
import com.boydti.fawe.config.Settings;
|
||||||
|
import com.boydti.fawe.object.FaweInputStream;
|
||||||
|
import com.boydti.fawe.object.FaweOutputStream;
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
|
import com.boydti.fawe.object.changeset.DiskStorageHistory;
|
||||||
|
import com.boydti.fawe.object.changeset.FaweChangeSet;
|
||||||
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
|
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
|
||||||
import com.boydti.fawe.util.EditSessionBuilder;
|
import com.boydti.fawe.util.EditSessionBuilder;
|
||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
@ -50,15 +56,24 @@ import com.sk89q.worldedit.session.ClipboardHolder;
|
|||||||
import com.sk89q.worldedit.session.request.Request;
|
import com.sk89q.worldedit.session.request.Request;
|
||||||
import com.sk89q.worldedit.world.World;
|
import com.sk89q.worldedit.world.World;
|
||||||
import com.sk89q.worldedit.world.snapshot.Snapshot;
|
import com.sk89q.worldedit.world.snapshot.Snapshot;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileFilter;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.ListIterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
import java.util.UUID;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||||
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
@ -78,14 +93,37 @@ public class LocalSession {
|
|||||||
// Session related
|
// Session related
|
||||||
private transient RegionSelector selector = new CuboidRegionSelector();
|
private transient RegionSelector selector = new CuboidRegionSelector();
|
||||||
private transient boolean placeAtPos1 = false;
|
private transient boolean placeAtPos1 = false;
|
||||||
private transient List<EditSession> history = Collections.synchronizedList(new LinkedList<EditSession>());
|
private transient List<Object> history = Collections.synchronizedList(new LinkedList<Object>() {
|
||||||
private transient volatile int historyPointer = 0;
|
@Override
|
||||||
|
public void add(int index, Object element) { // Integer = Lazy evaluated FaweChangeSet
|
||||||
|
if (element instanceof Integer || element instanceof FaweChangeSet) {
|
||||||
|
super.add(index, element);
|
||||||
|
} else {
|
||||||
|
throw new ClassCastException("Must add either Integer (index) or FaweChangeSet");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public Object get(int index) {
|
||||||
|
Object value = super.get(index);
|
||||||
|
if (value instanceof Integer) {
|
||||||
|
value = getChangeSet(value);
|
||||||
|
set(index, value);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object remove(int index) {
|
||||||
|
return getChangeSet(super.remove(index));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
private transient volatile Integer historyNegativeIndex;
|
||||||
private transient volatile long historySize = 0;
|
private transient volatile long historySize = 0;
|
||||||
private transient ClipboardHolder clipboard;
|
private transient ClipboardHolder clipboard;
|
||||||
private transient boolean toolControl = true;
|
private transient boolean toolControl = true;
|
||||||
private transient boolean superPickaxe = false;
|
private transient boolean superPickaxe = false;
|
||||||
private transient BlockTool pickaxeMode = new SinglePickaxe();
|
private transient BlockTool pickaxeMode = new SinglePickaxe();
|
||||||
private transient Map<Integer, Tool> tools = new HashMap<Integer, Tool>();
|
private transient Map<Integer, Tool> tools = new HashMap<>();
|
||||||
private transient int maxBlocksChanged = -1;
|
private transient int maxBlocksChanged = -1;
|
||||||
private transient boolean useInventory;
|
private transient boolean useInventory;
|
||||||
private transient Snapshot snapshot;
|
private transient Snapshot snapshot;
|
||||||
@ -95,6 +133,10 @@ public class LocalSession {
|
|||||||
private transient Mask mask;
|
private transient Mask mask;
|
||||||
private transient TimeZone timezone = TimeZone.getDefault();
|
private transient TimeZone timezone = TimeZone.getDefault();
|
||||||
|
|
||||||
|
// May be null
|
||||||
|
private transient World currentWorld;
|
||||||
|
private transient UUID uuid;
|
||||||
|
|
||||||
// Saved properties
|
// Saved properties
|
||||||
private String lastScript;
|
private String lastScript;
|
||||||
private RegionSelectorType defaultSelector;
|
private RegionSelectorType defaultSelector;
|
||||||
@ -136,6 +178,97 @@ public class LocalSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param uuid
|
||||||
|
* @param world
|
||||||
|
* @return If any loading occured
|
||||||
|
*/
|
||||||
|
public boolean loadSessionHistoryFromDisk(UUID uuid, World world) {
|
||||||
|
if (world == null || uuid == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!world.equals(currentWorld)) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
// Save history
|
||||||
|
saveHistoryNegativeIndex(uuid, currentWorld);
|
||||||
|
history.clear();
|
||||||
|
currentWorld = world;
|
||||||
|
// Load history
|
||||||
|
if (loadHistoryChangeSets(uuid, currentWorld)) {
|
||||||
|
loadHistoryNegativeIndex(uuid, currentWorld);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
historyNegativeIndex = 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean loadHistoryChangeSets(UUID uuid, World world) {
|
||||||
|
final List<Integer> editIds = new ArrayList<>();
|
||||||
|
final File folder = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.PATHS.HISTORY + File.separator + Fawe.imp().getWorldName(world) + File.separator + uuid);
|
||||||
|
if (folder.isDirectory()) {
|
||||||
|
final FileNameExtensionFilter filter = new FileNameExtensionFilter("BlockData files","bd");
|
||||||
|
folder.listFiles(new FileFilter() {
|
||||||
|
@Override
|
||||||
|
public boolean accept(File pathname) {
|
||||||
|
String name = pathname.getName();
|
||||||
|
int i = name.lastIndexOf('.');
|
||||||
|
if ((name.length() == i + 3) && (name.charAt(i + 1) == 'b' && name.charAt(i + 2) == 'd')) {
|
||||||
|
int index = Integer.parseInt(name.substring(0, i));
|
||||||
|
editIds.add(index);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
historySize = 0;
|
||||||
|
if (editIds.size() > 0) {
|
||||||
|
Collections.sort(editIds);
|
||||||
|
for (int index : editIds) {
|
||||||
|
history.add(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return editIds.size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadHistoryNegativeIndex(UUID uuid, World world) {
|
||||||
|
File file = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.PATHS.HISTORY + File.separator + Fawe.imp().getWorldName(world) + File.separator + uuid + File.separator + "index");
|
||||||
|
if (file.exists()) {
|
||||||
|
try {
|
||||||
|
FaweInputStream is = new FaweInputStream(new FileInputStream(file));
|
||||||
|
historyNegativeIndex = Math.min(Math.max(0, is.readInt()), history.size());
|
||||||
|
is.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
historyNegativeIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void saveHistoryNegativeIndex(UUID uuid, World world) {
|
||||||
|
if (world == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
File file = MainUtil.getFile(Fawe.imp().getDirectory(), Settings.PATHS.HISTORY + File.separator + Fawe.imp().getWorldName(world) + File.separator + uuid + File.separator + "index");
|
||||||
|
if (getHistoryNegativeIndex() != 0) {
|
||||||
|
try {
|
||||||
|
if (file.exists()) {
|
||||||
|
file.getParentFile().mkdirs();
|
||||||
|
file.createNewFile();
|
||||||
|
}
|
||||||
|
FaweOutputStream os = new FaweOutputStream(new FileOutputStream(file));
|
||||||
|
os.writeInt(getHistoryNegativeIndex());
|
||||||
|
os.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} else if (file.exists()) {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get whether this session is "dirty" and has changes that needs to
|
* Get whether this session is "dirty" and has changes that needs to
|
||||||
* be committed.
|
* be committed.
|
||||||
@ -153,6 +286,29 @@ public class LocalSession {
|
|||||||
dirty.set(true);
|
dirty.set(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getHistoryIndex() {
|
||||||
|
return history.size() - 1 - (historyNegativeIndex == null ? 0 : historyNegativeIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getHistoryNegativeIndex() {
|
||||||
|
return (historyNegativeIndex == null ? historyNegativeIndex = 0 : historyNegativeIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHistoryIndex(int value) {
|
||||||
|
historyNegativeIndex = history.size() - value - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean save() {
|
||||||
|
saveHistoryNegativeIndex(uuid, currentWorld);
|
||||||
|
if (defaultSelector == RegionSelectorType.CUBOID) {
|
||||||
|
defaultSelector = null;
|
||||||
|
}
|
||||||
|
if (lastScript != null || defaultSelector != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get whether this session is "dirty" and has changes that needs to
|
* Get whether this session is "dirty" and has changes that needs to
|
||||||
* be committed, and reset it to {@code false}.
|
* be committed, and reset it to {@code false}.
|
||||||
@ -187,7 +343,7 @@ public class LocalSession {
|
|||||||
*/
|
*/
|
||||||
public void clearHistory() {
|
public void clearHistory() {
|
||||||
history.clear();
|
history.clear();
|
||||||
historyPointer = 0;
|
historyNegativeIndex = 0;
|
||||||
historySize = 0;
|
historySize = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,6 +359,16 @@ public class LocalSession {
|
|||||||
remember(editSession, true, false, limit);
|
remember(editSession, true, false, limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private FaweChangeSet getChangeSet(Object o) {
|
||||||
|
if (o instanceof FaweChangeSet) {
|
||||||
|
return (FaweChangeSet) o;
|
||||||
|
}
|
||||||
|
if (o instanceof Integer) {
|
||||||
|
return new DiskStorageHistory(currentWorld, this.uuid, (Integer) o);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
public void remember(final EditSession editSession, final boolean append, final boolean sendMessage, int limitMb) {
|
public void remember(final EditSession editSession, final boolean append, final boolean sendMessage, int limitMb) {
|
||||||
if (editSession == null || editSession.getChangeSet() == null || limitMb == 0 || ((historySize >> 20) > limitMb && !append)) {
|
if (editSession == null || editSession.getChangeSet() == null || limitMb == 0 || ((historySize >> 20) > limitMb && !append)) {
|
||||||
return;
|
return;
|
||||||
@ -213,27 +379,41 @@ public class LocalSession {
|
|||||||
if (editSession.size() == 0 || editSession.hasFastMode()) {
|
if (editSession.size() == 0 || editSession.hasFastMode()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
FawePlayer fp = editSession.getPlayer();
|
||||||
|
if (fp != null) {
|
||||||
|
loadSessionHistoryFromDisk(fp.getUUID(), editSession.getWorld());
|
||||||
|
}
|
||||||
// Destroy any sessions after this undo point
|
// Destroy any sessions after this undo point
|
||||||
if (append) {
|
if (append) {
|
||||||
while (historyPointer < history.size()) {
|
int size = getHistoryNegativeIndex();
|
||||||
EditSession item = history.get(historyPointer);
|
ListIterator<Object> iter = history.listIterator();
|
||||||
historySize -= MainUtil.getSizeInMemory(item.getChangeSet());
|
int i = 0;
|
||||||
history.remove(historyPointer);
|
int cutoffIndex = history.size() - getHistoryNegativeIndex();
|
||||||
|
while (iter.hasNext()) {
|
||||||
|
Object item = iter.next();
|
||||||
|
if (++i > cutoffIndex) {
|
||||||
|
if (item instanceof FaweChangeSet) {
|
||||||
|
FaweChangeSet changeSet = (FaweChangeSet) item;
|
||||||
|
historySize -= MainUtil.getSizeInMemory(changeSet);
|
||||||
|
}
|
||||||
|
iter.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
historySize += MainUtil.getSizeInMemory(editSession.getChangeSet());
|
}
|
||||||
|
FaweChangeSet changeSet = (FaweChangeSet) editSession.getChangeSet();
|
||||||
|
historySize += MainUtil.getSizeInMemory(changeSet);
|
||||||
if (append) {
|
if (append) {
|
||||||
history.add(editSession);
|
history.add(changeSet);
|
||||||
historyPointer = history.size();
|
if (getHistoryNegativeIndex() != 0) {
|
||||||
|
setDirty();
|
||||||
|
historyNegativeIndex = 0;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
history.add(0, editSession);
|
history.add(0, changeSet);
|
||||||
historyPointer++;
|
|
||||||
}
|
}
|
||||||
while ((history.size() > MAX_HISTORY_SIZE || (historySize >> 20) > limitMb) && history.size() > 1) {
|
while ((history.size() > MAX_HISTORY_SIZE || (historySize >> 20) > limitMb) && history.size() > 1) {
|
||||||
EditSession item = history.get(0);
|
FaweChangeSet item = (FaweChangeSet) history.remove(0);
|
||||||
historySize -= MainUtil.getSizeInMemory(item.getChangeSet());
|
historySize -= MainUtil.getSizeInMemory(item);
|
||||||
history.remove(0);
|
|
||||||
historyPointer--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,20 +437,26 @@ public class LocalSession {
|
|||||||
*/
|
*/
|
||||||
public EditSession undo(@Nullable BlockBag newBlockBag, Player player) {
|
public EditSession undo(@Nullable BlockBag newBlockBag, Player player) {
|
||||||
checkNotNull(player);
|
checkNotNull(player);
|
||||||
--historyPointer;
|
loadSessionHistoryFromDisk(player.getUniqueId(), player.getWorld());
|
||||||
if (historyPointer >= 0) {
|
if (getHistoryNegativeIndex() < history.size()) {
|
||||||
EditSession editSession = history.get(historyPointer);
|
FaweChangeSet changeSet = (FaweChangeSet) history.get(getHistoryIndex());
|
||||||
EditSession newEditSession = new EditSessionBuilder(editSession.getWorld())
|
EditSession newEditSession = new EditSessionBuilder(changeSet.getWorld())
|
||||||
.allowedRegionsEverywhere()
|
.allowedRegionsEverywhere()
|
||||||
.checkMemory(false)
|
.checkMemory(false)
|
||||||
.changeSetNull()
|
.changeSet(changeSet)
|
||||||
.fastmode(true)
|
.fastmode(false)
|
||||||
.limitUnlimited()
|
.limitUnlimited()
|
||||||
.build();
|
.build();
|
||||||
editSession.undo(newEditSession);
|
newEditSession.undo(newEditSession);
|
||||||
return editSession;
|
setDirty();
|
||||||
|
historyNegativeIndex++;
|
||||||
|
return newEditSession;
|
||||||
} else {
|
} else {
|
||||||
historyPointer = 0;
|
int size = history.size();
|
||||||
|
if (getHistoryNegativeIndex() != size) {
|
||||||
|
historyNegativeIndex = history.size();
|
||||||
|
setDirty();
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -295,20 +481,21 @@ public class LocalSession {
|
|||||||
*/
|
*/
|
||||||
public EditSession redo(@Nullable BlockBag newBlockBag, Player player) {
|
public EditSession redo(@Nullable BlockBag newBlockBag, Player player) {
|
||||||
checkNotNull(player);
|
checkNotNull(player);
|
||||||
if (historyPointer < history.size()) {
|
loadSessionHistoryFromDisk(player.getUniqueId(), player.getWorld());
|
||||||
EditSession editSession = history.get(historyPointer);
|
if (getHistoryNegativeIndex() > 0) {
|
||||||
EditSession newEditSession = new EditSessionBuilder(editSession.getWorld())
|
setDirty();
|
||||||
|
historyNegativeIndex--;
|
||||||
|
FaweChangeSet changeSet = (FaweChangeSet) history.get(getHistoryIndex());
|
||||||
|
EditSession newEditSession = new EditSessionBuilder(changeSet.getWorld())
|
||||||
.allowedRegionsEverywhere()
|
.allowedRegionsEverywhere()
|
||||||
.checkMemory(false)
|
.checkMemory(false)
|
||||||
.changeSetNull()
|
.changeSet(changeSet)
|
||||||
.fastmode(true)
|
.fastmode(false)
|
||||||
.limitUnlimited()
|
.limitUnlimited()
|
||||||
.build();
|
.build();
|
||||||
editSession.redo(newEditSession);
|
newEditSession.redo(newEditSession);
|
||||||
++historyPointer;
|
return newEditSession;
|
||||||
return editSession;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +91,6 @@ public class HistoryCommands {
|
|||||||
Vector top = origin.add(radius, radius, radius);
|
Vector top = origin.add(radius, radius, radius);
|
||||||
RollbackDatabase database = DBHandler.IMP.getDatabase(Fawe.imp().getWorldName(world));
|
RollbackDatabase database = DBHandler.IMP.getDatabase(Fawe.imp().getWorldName(world));
|
||||||
final AtomicInteger count = new AtomicInteger();
|
final AtomicInteger count = new AtomicInteger();
|
||||||
System.out.println("ROLLING BACK");
|
|
||||||
database.getPotentialEdits(other, System.currentTimeMillis() - timeDiff, bot, top, new RunnableVal<DiskStorageHistory>() {
|
database.getPotentialEdits(other, System.currentTimeMillis() - timeDiff, bot, top, new RunnableVal<DiskStorageHistory>() {
|
||||||
@Override
|
@Override
|
||||||
public void run(DiskStorageHistory edit) {
|
public void run(DiskStorageHistory edit) {
|
||||||
|
@ -19,8 +19,6 @@
|
|||||||
|
|
||||||
package com.sk89q.worldedit.session;
|
package com.sk89q.worldedit.session;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.Futures;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
import com.google.common.util.concurrent.ListeningExecutorService;
|
import com.google.common.util.concurrent.ListeningExecutorService;
|
||||||
import com.google.common.util.concurrent.MoreExecutors;
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
import com.sk89q.worldedit.LocalConfiguration;
|
import com.sk89q.worldedit.LocalConfiguration;
|
||||||
@ -33,19 +31,16 @@ import com.sk89q.worldedit.session.storage.SessionStore;
|
|||||||
import com.sk89q.worldedit.session.storage.VoidStore;
|
import com.sk89q.worldedit.session.storage.VoidStore;
|
||||||
import com.sk89q.worldedit.util.concurrency.EvenMoreExecutors;
|
import com.sk89q.worldedit.util.concurrency.EvenMoreExecutors;
|
||||||
import com.sk89q.worldedit.util.eventbus.Subscribe;
|
import com.sk89q.worldedit.util.eventbus.Subscribe;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Timer;
|
import java.util.Timer;
|
||||||
import java.util.TimerTask;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
@ -58,14 +53,22 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||||||
*/
|
*/
|
||||||
public class SessionManager {
|
public class SessionManager {
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public static int EXPIRATION_GRACE = 600000;
|
public static int EXPIRATION_GRACE = 600000;
|
||||||
private static final int FLUSH_PERIOD = 1000 * 30;
|
|
||||||
private static final ListeningExecutorService executorService = MoreExecutors.listeningDecorator(EvenMoreExecutors.newBoundedCachedThreadPool(0, 1, 5));
|
private static final ListeningExecutorService executorService = MoreExecutors.listeningDecorator(EvenMoreExecutors.newBoundedCachedThreadPool(0, 1, 5));
|
||||||
private static final Logger log = Logger.getLogger(SessionManager.class.getCanonicalName());
|
private static final Logger log = Logger.getLogger(SessionManager.class.getCanonicalName());
|
||||||
private final Timer timer = new Timer();
|
private final Timer timer = new Timer();
|
||||||
private final WorldEdit worldEdit;
|
private final WorldEdit worldEdit;
|
||||||
private final Map<UUID, SessionHolder> sessions = new HashMap<UUID, SessionHolder>();
|
private final Map<UUID, SessionHolder> sessions = new ConcurrentHashMap<UUID, SessionHolder>();
|
||||||
private SessionStore store = new VoidStore();
|
private SessionStore store = new VoidStore();
|
||||||
|
private File path;
|
||||||
|
|
||||||
|
// Added //
|
||||||
|
|
||||||
|
// private final ConcurrentLinkedDeque<SessionHolder> toSave = new ConcurrentLinkedDeque<>();
|
||||||
|
///////////
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new session manager.
|
* Create a new session manager.
|
||||||
@ -77,7 +80,6 @@ public class SessionManager {
|
|||||||
this.worldEdit = worldEdit;
|
this.worldEdit = worldEdit;
|
||||||
|
|
||||||
worldEdit.getEventBus().register(this);
|
worldEdit.getEventBus().register(this);
|
||||||
timer.schedule(new SessionTracker(), FLUSH_PERIOD, FLUSH_PERIOD);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -191,46 +193,28 @@ public class SessionManager {
|
|||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private void save(SessionHolder holder) {
|
||||||
* Save a map of sessions to disk.
|
SessionKey key = holder.key;
|
||||||
*
|
|
||||||
* @param sessions a map of sessions to save
|
|
||||||
* @return a future that completes on save or error
|
|
||||||
*/
|
|
||||||
private ListenableFuture<?> commit(final Map<SessionKey, LocalSession> sessions) {
|
|
||||||
checkNotNull(sessions);
|
|
||||||
|
|
||||||
if (sessions.isEmpty()) {
|
|
||||||
return Futures.immediateFuture(sessions);
|
|
||||||
}
|
|
||||||
|
|
||||||
return executorService.submit(new Callable<Object>() {
|
|
||||||
@Override
|
|
||||||
public Object call() throws Exception {
|
|
||||||
Exception exception = null;
|
|
||||||
|
|
||||||
for (Map.Entry<SessionKey, LocalSession> entry : sessions.entrySet()) {
|
|
||||||
SessionKey key = entry.getKey();
|
|
||||||
|
|
||||||
if (key.isPersistent()) {
|
if (key.isPersistent()) {
|
||||||
try {
|
try {
|
||||||
store.save(getKey(key), entry.getValue());
|
if (holder.session.compareAndResetDirty()) {
|
||||||
|
if (holder.session.save()) {
|
||||||
|
store.save(getKey(key), holder.session);
|
||||||
|
} else if (path != null) {
|
||||||
|
File file = new File(path, getKey(key) + ".json");
|
||||||
|
if (file.exists()) {
|
||||||
|
if (!file.delete()) {
|
||||||
|
file.deleteOnExit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
log.log(Level.WARNING, "Failed to write session for UUID " + getKey(key), e);
|
log.log(Level.WARNING, "Failed to write session for UUID " + getKey(key), e);
|
||||||
exception = e;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exception != null) {
|
|
||||||
throw exception;
|
|
||||||
}
|
|
||||||
|
|
||||||
return sessions;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the key to use in the map for an owner.
|
* Get the key to use in the map for an owner.
|
||||||
*
|
*
|
||||||
@ -264,13 +248,16 @@ public class SessionManager {
|
|||||||
*/
|
*/
|
||||||
public synchronized void remove(SessionOwner owner) {
|
public synchronized void remove(SessionOwner owner) {
|
||||||
checkNotNull(owner);
|
checkNotNull(owner);
|
||||||
sessions.remove(getKey(owner));
|
save(sessions.remove(getKey(owner)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all sessions.
|
* Remove all sessions.
|
||||||
*/
|
*/
|
||||||
public synchronized void clear() {
|
public synchronized void clear() {
|
||||||
|
for (Map.Entry<UUID, SessionHolder> entry : sessions.entrySet()) {
|
||||||
|
save(entry.getValue());
|
||||||
|
}
|
||||||
sessions.clear();
|
sessions.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,6 +266,7 @@ public class SessionManager {
|
|||||||
LocalConfiguration config = event.getConfiguration();
|
LocalConfiguration config = event.getConfiguration();
|
||||||
File dir = new File(config.getWorkingDirectory(), "sessions");
|
File dir = new File(config.getWorkingDirectory(), "sessions");
|
||||||
store = new JsonFileSessionStore(dir);
|
store = new JsonFileSessionStore(dir);
|
||||||
|
this.path = dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -295,42 +283,9 @@ public class SessionManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public static Class<?> inject() {
|
||||||
* Removes inactive sessions after they have been inactive for a period
|
return SessionManager.class;
|
||||||
* of time. Commits them as well.
|
|
||||||
*/
|
|
||||||
private class SessionTracker extends TimerTask {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
synchronized (SessionManager.this) {
|
|
||||||
long now = System.currentTimeMillis();
|
|
||||||
Iterator<SessionHolder> it = sessions.values().iterator();
|
|
||||||
Map<SessionKey, LocalSession> saveQueue = new HashMap<SessionKey, LocalSession>();
|
|
||||||
|
|
||||||
while (it.hasNext()) {
|
|
||||||
SessionHolder stored = it.next();
|
|
||||||
if (stored.key.isActive()) {
|
|
||||||
stored.lastActive = now;
|
|
||||||
|
|
||||||
if (stored.session.compareAndResetDirty()) {
|
|
||||||
saveQueue.put(stored.key, stored.session);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (now - stored.lastActive > EXPIRATION_GRACE) {
|
|
||||||
if (stored.session.compareAndResetDirty()) {
|
|
||||||
saveQueue.put(stored.key, stored.session);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
it.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!saveQueue.isEmpty()) {
|
|
||||||
commit(saveQueue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -1,7 +1,6 @@
|
|||||||
package com.boydti.fawe.forge;
|
package com.boydti.fawe.forge;
|
||||||
|
|
||||||
import com.boydti.fawe.Fawe;
|
import com.boydti.fawe.Fawe;
|
||||||
import com.boydti.fawe.config.Settings;
|
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -72,10 +71,6 @@ public class ForgeMain {
|
|||||||
FawePlayer fp = FawePlayer.wrap(player);
|
FawePlayer fp = FawePlayer.wrap(player);
|
||||||
if (fp.getMeta("lastWorld") != event.getWorld()) {
|
if (fp.getMeta("lastWorld") != event.getWorld()) {
|
||||||
fp.setMeta("lastWorld", event.getWorld());
|
fp.setMeta("lastWorld", event.getWorld());
|
||||||
if (Settings.HISTORY.USE_DISK) {
|
|
||||||
fp.getSession().clearHistory();
|
|
||||||
fp.loadSessionsFromDisk(fp.getWorld());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ import com.boydti.fawe.object.RunnableVal;
|
|||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.boydti.fawe.util.MathMan;
|
import com.boydti.fawe.util.MathMan;
|
||||||
import com.boydti.fawe.util.ReflectionUtils;
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.ListTag;
|
import com.sk89q.jnbt.ListTag;
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
@ -18,6 +17,7 @@ import com.sk89q.jnbt.Tag;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -31,20 +31,16 @@ import net.minecraft.block.Block;
|
|||||||
import net.minecraft.block.state.IBlockState;
|
import net.minecraft.block.state.IBlockState;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityList;
|
import net.minecraft.entity.EntityList;
|
||||||
import net.minecraft.entity.EntityTracker;
|
|
||||||
import net.minecraft.entity.EntityTrackerEntry;
|
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
import net.minecraft.init.Blocks;
|
import net.minecraft.init.Blocks;
|
||||||
import net.minecraft.nbt.NBTBase;
|
import net.minecraft.nbt.NBTBase;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.network.play.server.SPacketChunkData;
|
import net.minecraft.network.play.server.SPacketChunkData;
|
||||||
import net.minecraft.network.play.server.SPacketDestroyEntities;
|
|
||||||
import net.minecraft.server.management.PlayerChunkMap;
|
import net.minecraft.server.management.PlayerChunkMap;
|
||||||
import net.minecraft.server.management.PlayerChunkMapEntry;
|
import net.minecraft.server.management.PlayerChunkMapEntry;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.ClassInheritanceMultiMap;
|
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||||
import net.minecraft.util.IntHashMap;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.ChunkPos;
|
import net.minecraft.util.math.ChunkPos;
|
||||||
import net.minecraft.world.EnumSkyBlock;
|
import net.minecraft.world.EnumSkyBlock;
|
||||||
@ -513,7 +509,9 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void refreshChunk(World world, net.minecraft.world.chunk.Chunk nmsChunk) {
|
public void refreshChunk(FaweChunk fc) {
|
||||||
|
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
||||||
|
Chunk nmsChunk = fs.getChunk();
|
||||||
if (!nmsChunk.isLoaded()) {
|
if (!nmsChunk.isLoaded()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -523,75 +521,44 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
|
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
|
||||||
int x = pos.chunkXPos;
|
int x = pos.chunkXPos;
|
||||||
int z = pos.chunkZPos;
|
int z = pos.chunkZPos;
|
||||||
if (!chunkMap.contains(x, z)) {
|
PlayerChunkMapEntry chunkMapEntry = chunkMap.getEntry(x, z);
|
||||||
|
if (chunkMapEntry == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EntityTracker tracker = w.getEntityTracker();
|
final ArrayDeque<EntityPlayerMP> players = new ArrayDeque<>();
|
||||||
HashSet<EntityPlayerMP> players = new HashSet<>();
|
chunkMapEntry.hasPlayerMatching(input -> {
|
||||||
for (EntityPlayer player : w.playerEntities) {
|
players.add(input);
|
||||||
if (player instanceof EntityPlayerMP) {
|
return false;
|
||||||
if (chunkMap.isPlayerWatchingChunk((EntityPlayerMP) player, x, z)) {
|
});
|
||||||
players.add((EntityPlayerMP) player);
|
int mask = fc.getBitMask();
|
||||||
}
|
if (mask == 65535 && hasEntities(nmsChunk)) {
|
||||||
}
|
SPacketChunkData packet = new SPacketChunkData(nmsChunk, 65280);
|
||||||
}
|
|
||||||
if (players.size() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
HashSet<EntityTrackerEntry> entities = new HashSet<>();
|
|
||||||
ClassInheritanceMultiMap<Entity>[] entitieSlices = nmsChunk.getEntityLists();
|
|
||||||
IntHashMap<EntityTrackerEntry> entries = null;
|
|
||||||
for (Field field : tracker.getClass().getDeclaredFields()) {
|
|
||||||
if (field.getType() == IntHashMap.class) {
|
|
||||||
field.setAccessible(true);
|
|
||||||
entries = (IntHashMap<EntityTrackerEntry>) field.get(tracker);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (ClassInheritanceMultiMap<Entity> slice : entitieSlices) {
|
|
||||||
if (slice == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (Entity ent : slice) {
|
|
||||||
EntityTrackerEntry entry = entries != null ? entries.lookup(ent.getEntityId()) : null;
|
|
||||||
if (entry == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
entities.add(entry);
|
|
||||||
SPacketDestroyEntities packet = new SPacketDestroyEntities(ent.getEntityId());
|
|
||||||
for (EntityPlayerMP player : players) {
|
for (EntityPlayerMP player : players) {
|
||||||
player.connection.sendPacket(packet);
|
player.connection.sendPacket(packet);
|
||||||
}
|
}
|
||||||
|
mask = 255;
|
||||||
}
|
}
|
||||||
}
|
SPacketChunkData packet = new SPacketChunkData(nmsChunk, mask);
|
||||||
// Send chunks
|
|
||||||
SPacketChunkData packet = new SPacketChunkData(nmsChunk, 65535);
|
|
||||||
for (EntityPlayerMP player : players) {
|
for (EntityPlayerMP player : players) {
|
||||||
player.connection.sendPacket(packet);
|
player.connection.sendPacket(packet);
|
||||||
}
|
}
|
||||||
// send ents
|
|
||||||
for (EntityTrackerEntry entry : entities) {
|
|
||||||
try {
|
|
||||||
TaskManager.IMP.later(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (EntityPlayerMP player : players) {
|
|
||||||
boolean result = entry.trackingPlayers.remove(player);
|
|
||||||
if (result && entry.getTrackedEntity() != player) {
|
|
||||||
entry.updatePlayerEntity(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 2);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
MainUtil.handleError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
MainUtil.handleError(e);
|
MainUtil.handleError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasEntities(Chunk nmsChunk) {
|
||||||
|
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||||
|
for (int i = 0; i < entities.length; i++) {
|
||||||
|
ClassInheritanceMultiMap<Entity> slice = entities[i];
|
||||||
|
if (slice != null && !slice.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FaweChunk<Chunk> getFaweChunk(int x, int z) {
|
public FaweChunk<Chunk> getFaweChunk(int x, int z) {
|
||||||
return new ForgeChunk_All(this, x, z);
|
return new ForgeChunk_All(this, x, z);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package com.boydti.fawe.forge;
|
package com.boydti.fawe.forge;
|
||||||
|
|
||||||
import com.boydti.fawe.Fawe;
|
import com.boydti.fawe.Fawe;
|
||||||
import com.boydti.fawe.config.Settings;
|
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
import cpw.mods.fml.common.FMLCommonHandler;
|
import cpw.mods.fml.common.FMLCommonHandler;
|
||||||
import cpw.mods.fml.common.Mod;
|
import cpw.mods.fml.common.Mod;
|
||||||
@ -73,10 +72,6 @@ public class ForgeMain {
|
|||||||
FawePlayer fp = FawePlayer.wrap(player);
|
FawePlayer fp = FawePlayer.wrap(player);
|
||||||
if (fp.getMeta("lastWorld") != event.world) {
|
if (fp.getMeta("lastWorld") != event.world) {
|
||||||
fp.setMeta("lastWorld", event.world);
|
fp.setMeta("lastWorld", event.world);
|
||||||
if (Settings.HISTORY.USE_DISK) {
|
|
||||||
fp.getSession().clearHistory();
|
|
||||||
fp.loadSessionsFromDisk(fp.getWorld());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,6 @@ import com.boydti.fawe.object.RunnableVal;
|
|||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.boydti.fawe.util.MathMan;
|
import com.boydti.fawe.util.MathMan;
|
||||||
import com.boydti.fawe.util.ReflectionUtils;
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.ListTag;
|
import com.sk89q.jnbt.ListTag;
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
@ -31,17 +30,13 @@ import java.util.UUID;
|
|||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityList;
|
import net.minecraft.entity.EntityList;
|
||||||
import net.minecraft.entity.EntityTracker;
|
|
||||||
import net.minecraft.entity.EntityTrackerEntry;
|
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
import net.minecraft.nbt.NBTBase;
|
import net.minecraft.nbt.NBTBase;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.network.play.server.S13PacketDestroyEntities;
|
|
||||||
import net.minecraft.network.play.server.S21PacketChunkData;
|
import net.minecraft.network.play.server.S21PacketChunkData;
|
||||||
import net.minecraft.server.management.PlayerManager;
|
import net.minecraft.server.management.PlayerManager;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.IntHashMap;
|
|
||||||
import net.minecraft.util.LongHashMap;
|
import net.minecraft.util.LongHashMap;
|
||||||
import net.minecraft.world.ChunkCoordIntPair;
|
import net.minecraft.world.ChunkCoordIntPair;
|
||||||
import net.minecraft.world.ChunkPosition;
|
import net.minecraft.world.ChunkPosition;
|
||||||
@ -216,21 +211,21 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
};
|
};
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void refreshChunk(World world, net.minecraft.world.chunk.Chunk nmsChunk) {
|
public void refreshChunk(FaweChunk fc) {
|
||||||
|
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
||||||
|
Chunk nmsChunk = fs.getChunk();
|
||||||
if (!nmsChunk.isChunkLoaded) {
|
if (!nmsChunk.isChunkLoaded) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ChunkCoordIntPair pos = nmsChunk.getChunkCoordIntPair();
|
|
||||||
WorldServer w = (WorldServer) nmsChunk.worldObj;
|
WorldServer w = (WorldServer) nmsChunk.worldObj;
|
||||||
PlayerManager chunkMap = w.getPlayerManager();
|
PlayerManager chunkMap = w.getPlayerManager();
|
||||||
int x = pos.chunkXPos;
|
int x = nmsChunk.xPosition;
|
||||||
int z = pos.chunkZPos;
|
int z = nmsChunk.zPosition;
|
||||||
if (!chunkMap.func_152621_a(x, z)) {
|
if (!chunkMap.func_152621_a(x, z)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EntityTracker tracker = w.getEntityTracker();
|
HashSet<EntityPlayerMP> players = new HashSet<>();
|
||||||
final HashSet<EntityPlayerMP> players = new HashSet<>();
|
|
||||||
for (EntityPlayer player : (List<EntityPlayer>) w.playerEntities) {
|
for (EntityPlayer player : (List<EntityPlayer>) w.playerEntities) {
|
||||||
if (player instanceof EntityPlayerMP) {
|
if (player instanceof EntityPlayerMP) {
|
||||||
if (chunkMap.isPlayerWatchingChunk((EntityPlayerMP) player, x, z)) {
|
if (chunkMap.isPlayerWatchingChunk((EntityPlayerMP) player, x, z)) {
|
||||||
@ -241,60 +236,34 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
if (players.size() == 0) {
|
if (players.size() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HashSet<EntityTrackerEntry> entities = new HashSet<>();
|
int mask = fc.getBitMask();
|
||||||
Collection<Entity>[] entitieSlices = nmsChunk.entityLists;
|
if (mask == 65535 && hasEntities(nmsChunk)) {
|
||||||
IntHashMap entries = null;
|
S21PacketChunkData packet = new S21PacketChunkData(nmsChunk, false, 65280);
|
||||||
for (Field field : tracker.getClass().getDeclaredFields()) {
|
|
||||||
if (field.getType() == IntHashMap.class) {
|
|
||||||
field.setAccessible(true);
|
|
||||||
entries = (IntHashMap) field.get(tracker);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (Collection<Entity> slice : entitieSlices) {
|
|
||||||
if (slice == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (Entity ent : slice) {
|
|
||||||
EntityTrackerEntry entry = entries != null ? (EntityTrackerEntry) entries.lookup(ent.getEntityId()) : null;
|
|
||||||
if (entry == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
entities.add(entry);
|
|
||||||
S13PacketDestroyEntities packet = new S13PacketDestroyEntities(ent.getEntityId());
|
|
||||||
for (EntityPlayerMP player : players) {
|
for (EntityPlayerMP player : players) {
|
||||||
player.playerNetServerHandler.sendPacket(packet);
|
player.playerNetServerHandler.sendPacket(packet);
|
||||||
}
|
}
|
||||||
|
mask = 255;
|
||||||
}
|
}
|
||||||
}
|
S21PacketChunkData packet = new S21PacketChunkData(nmsChunk, false, mask);
|
||||||
// Send chunks
|
|
||||||
S21PacketChunkData packet = new S21PacketChunkData(nmsChunk, false, 65535);
|
|
||||||
for (EntityPlayerMP player : players) {
|
for (EntityPlayerMP player : players) {
|
||||||
player.playerNetServerHandler.sendPacket(packet);
|
player.playerNetServerHandler.sendPacket(packet);
|
||||||
}
|
}
|
||||||
// send ents
|
|
||||||
for (final EntityTrackerEntry entry : entities) {
|
|
||||||
try {
|
|
||||||
TaskManager.IMP.later(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (EntityPlayerMP player : players) {
|
|
||||||
boolean result = entry.trackingPlayers.remove(player);
|
|
||||||
if (result && entry.myEntity != player) {
|
|
||||||
entry.tryStartWachingThis(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 2);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
MainUtil.handleError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
MainUtil.handleError(e);
|
MainUtil.handleError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasEntities(Chunk nmsChunk) {
|
||||||
|
for (int i = 0; i < nmsChunk.entityLists.length; i++) {
|
||||||
|
List slice = nmsChunk.entityLists[i];
|
||||||
|
if (slice != null && !slice.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
public boolean setComponents(FaweChunk fc, RunnableVal<FaweChunk> changeTask) {
|
||||||
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package com.boydti.fawe.forge;
|
package com.boydti.fawe.forge;
|
||||||
|
|
||||||
import com.boydti.fawe.Fawe;
|
import com.boydti.fawe.Fawe;
|
||||||
import com.boydti.fawe.config.Settings;
|
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -73,10 +72,6 @@ public class ForgeMain {
|
|||||||
FawePlayer fp = FawePlayer.wrap(player);
|
FawePlayer fp = FawePlayer.wrap(player);
|
||||||
if (fp.getMeta("lastWorld") != event.world) {
|
if (fp.getMeta("lastWorld") != event.world) {
|
||||||
fp.setMeta("lastWorld", event.world);
|
fp.setMeta("lastWorld", event.world);
|
||||||
if (Settings.HISTORY.USE_DISK) {
|
|
||||||
fp.getSession().clearHistory();
|
|
||||||
fp.loadSessionsFromDisk(fp.getWorld());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ import com.boydti.fawe.object.RunnableVal;
|
|||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.boydti.fawe.util.MathMan;
|
import com.boydti.fawe.util.MathMan;
|
||||||
import com.boydti.fawe.util.ReflectionUtils;
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.ListTag;
|
import com.sk89q.jnbt.ListTag;
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
@ -29,19 +28,15 @@ import java.util.UUID;
|
|||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityList;
|
import net.minecraft.entity.EntityList;
|
||||||
import net.minecraft.entity.EntityTracker;
|
|
||||||
import net.minecraft.entity.EntityTrackerEntry;
|
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
import net.minecraft.nbt.NBTBase;
|
import net.minecraft.nbt.NBTBase;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.network.play.server.S13PacketDestroyEntities;
|
|
||||||
import net.minecraft.network.play.server.S21PacketChunkData;
|
import net.minecraft.network.play.server.S21PacketChunkData;
|
||||||
import net.minecraft.server.management.PlayerManager;
|
import net.minecraft.server.management.PlayerManager;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.BlockPos;
|
import net.minecraft.util.BlockPos;
|
||||||
import net.minecraft.util.ClassInheritanceMultiMap;
|
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||||
import net.minecraft.util.IntHashMap;
|
|
||||||
import net.minecraft.world.ChunkCoordIntPair;
|
import net.minecraft.world.ChunkCoordIntPair;
|
||||||
import net.minecraft.world.EnumSkyBlock;
|
import net.minecraft.world.EnumSkyBlock;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
@ -453,20 +448,20 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void refreshChunk(World world, net.minecraft.world.chunk.Chunk nmsChunk) {
|
public void refreshChunk(FaweChunk fc) {
|
||||||
|
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
||||||
|
Chunk nmsChunk = fs.getChunk();
|
||||||
if (!nmsChunk.isLoaded()) {
|
if (!nmsChunk.isLoaded()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ChunkCoordIntPair pos = nmsChunk.getChunkCoordIntPair();
|
|
||||||
WorldServer w = (WorldServer) nmsChunk.getWorld();
|
WorldServer w = (WorldServer) nmsChunk.getWorld();
|
||||||
PlayerManager chunkMap = w.getPlayerManager();
|
PlayerManager chunkMap = w.getPlayerManager();
|
||||||
int x = pos.chunkXPos;
|
int x = nmsChunk.xPosition;
|
||||||
int z = pos.chunkZPos;
|
int z = nmsChunk.zPosition;
|
||||||
if (!chunkMap.hasPlayerInstance(x, z)) {
|
if (!chunkMap.hasPlayerInstance(x, z)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EntityTracker tracker = w.getEntityTracker();
|
|
||||||
HashSet<EntityPlayerMP> players = new HashSet<>();
|
HashSet<EntityPlayerMP> players = new HashSet<>();
|
||||||
for (EntityPlayer player : w.playerEntities) {
|
for (EntityPlayer player : w.playerEntities) {
|
||||||
if (player instanceof EntityPlayerMP) {
|
if (player instanceof EntityPlayerMP) {
|
||||||
@ -478,60 +473,35 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
if (players.size() == 0) {
|
if (players.size() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HashSet<EntityTrackerEntry> entities = new HashSet<>();
|
int mask = fc.getBitMask();
|
||||||
ClassInheritanceMultiMap<Entity>[] entitieSlices = nmsChunk.getEntityLists();
|
if (mask == 65535 && hasEntities(nmsChunk)) {
|
||||||
IntHashMap<EntityTrackerEntry> entries = null;
|
S21PacketChunkData packet = new S21PacketChunkData(nmsChunk, false, 65280);
|
||||||
for (Field field : tracker.getClass().getDeclaredFields()) {
|
|
||||||
if (field.getType() == IntHashMap.class) {
|
|
||||||
field.setAccessible(true);
|
|
||||||
entries = (IntHashMap<EntityTrackerEntry>) field.get(tracker);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (ClassInheritanceMultiMap<Entity> slice : entitieSlices) {
|
|
||||||
if (slice == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (Entity ent : slice) {
|
|
||||||
EntityTrackerEntry entry = entries != null ? entries.lookup(ent.getEntityId()) : null;
|
|
||||||
if (entry == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
entities.add(entry);
|
|
||||||
S13PacketDestroyEntities packet = new S13PacketDestroyEntities(ent.getEntityId());
|
|
||||||
for (EntityPlayerMP player : players) {
|
for (EntityPlayerMP player : players) {
|
||||||
player.playerNetServerHandler.sendPacket(packet);
|
player.playerNetServerHandler.sendPacket(packet);
|
||||||
}
|
}
|
||||||
|
mask = 255;
|
||||||
}
|
}
|
||||||
}
|
S21PacketChunkData packet = new S21PacketChunkData(nmsChunk, false, mask);
|
||||||
// Send chunks
|
|
||||||
S21PacketChunkData packet = new S21PacketChunkData(nmsChunk, false, 65535);
|
|
||||||
for (EntityPlayerMP player : players) {
|
for (EntityPlayerMP player : players) {
|
||||||
player.playerNetServerHandler.sendPacket(packet);
|
player.playerNetServerHandler.sendPacket(packet);
|
||||||
}
|
}
|
||||||
// send ents
|
|
||||||
for (EntityTrackerEntry entry : entities) {
|
|
||||||
try {
|
|
||||||
TaskManager.IMP.later(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (EntityPlayerMP player : players) {
|
|
||||||
boolean result = entry.trackingPlayers.remove(player);
|
|
||||||
if (result && entry.trackedEntity != player) {
|
|
||||||
entry.updatePlayerEntity(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 2);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
MainUtil.handleError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
MainUtil.handleError(e);
|
MainUtil.handleError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasEntities(Chunk nmsChunk) {
|
||||||
|
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||||
|
for (int i = 0; i < entities.length; i++) {
|
||||||
|
ClassInheritanceMultiMap<Entity> slice = entities[i];
|
||||||
|
if (slice != null && !slice.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FaweChunk<Chunk> getFaweChunk(int x, int z) {
|
public FaweChunk<Chunk> getFaweChunk(int x, int z) {
|
||||||
return new ForgeChunk_All(this, x, z);
|
return new ForgeChunk_All(this, x, z);
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package com.boydti.fawe.forge;
|
package com.boydti.fawe.forge;
|
||||||
|
|
||||||
import com.boydti.fawe.Fawe;
|
import com.boydti.fawe.Fawe;
|
||||||
import com.boydti.fawe.config.Settings;
|
|
||||||
import com.boydti.fawe.object.FawePlayer;
|
import com.boydti.fawe.object.FawePlayer;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -72,10 +71,6 @@ public class ForgeMain {
|
|||||||
FawePlayer fp = FawePlayer.wrap(player);
|
FawePlayer fp = FawePlayer.wrap(player);
|
||||||
if (fp.getMeta("lastWorld") != event.getWorld()) {
|
if (fp.getMeta("lastWorld") != event.getWorld()) {
|
||||||
fp.setMeta("lastWorld", event.getWorld());
|
fp.setMeta("lastWorld", event.getWorld());
|
||||||
if (Settings.HISTORY.USE_DISK) {
|
|
||||||
fp.getSession().clearHistory();
|
|
||||||
fp.loadSessionsFromDisk(fp.getWorld());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,6 @@ import com.boydti.fawe.object.RunnableVal;
|
|||||||
import com.boydti.fawe.util.MainUtil;
|
import com.boydti.fawe.util.MainUtil;
|
||||||
import com.boydti.fawe.util.MathMan;
|
import com.boydti.fawe.util.MathMan;
|
||||||
import com.boydti.fawe.util.ReflectionUtils;
|
import com.boydti.fawe.util.ReflectionUtils;
|
||||||
import com.boydti.fawe.util.TaskManager;
|
|
||||||
import com.sk89q.jnbt.CompoundTag;
|
import com.sk89q.jnbt.CompoundTag;
|
||||||
import com.sk89q.jnbt.ListTag;
|
import com.sk89q.jnbt.ListTag;
|
||||||
import com.sk89q.jnbt.StringTag;
|
import com.sk89q.jnbt.StringTag;
|
||||||
@ -18,6 +17,7 @@ import com.sk89q.jnbt.Tag;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -31,20 +31,16 @@ import net.minecraft.block.Block;
|
|||||||
import net.minecraft.block.state.IBlockState;
|
import net.minecraft.block.state.IBlockState;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityList;
|
import net.minecraft.entity.EntityList;
|
||||||
import net.minecraft.entity.EntityTracker;
|
|
||||||
import net.minecraft.entity.EntityTrackerEntry;
|
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.entity.player.EntityPlayerMP;
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
import net.minecraft.init.Blocks;
|
import net.minecraft.init.Blocks;
|
||||||
import net.minecraft.nbt.NBTBase;
|
import net.minecraft.nbt.NBTBase;
|
||||||
import net.minecraft.nbt.NBTTagCompound;
|
import net.minecraft.nbt.NBTTagCompound;
|
||||||
import net.minecraft.network.play.server.SPacketChunkData;
|
import net.minecraft.network.play.server.SPacketChunkData;
|
||||||
import net.minecraft.network.play.server.SPacketDestroyEntities;
|
|
||||||
import net.minecraft.server.management.PlayerChunkMap;
|
import net.minecraft.server.management.PlayerChunkMap;
|
||||||
import net.minecraft.server.management.PlayerChunkMapEntry;
|
import net.minecraft.server.management.PlayerChunkMapEntry;
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
import net.minecraft.util.ClassInheritanceMultiMap;
|
import net.minecraft.util.ClassInheritanceMultiMap;
|
||||||
import net.minecraft.util.IntHashMap;
|
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.ChunkPos;
|
import net.minecraft.util.math.ChunkPos;
|
||||||
import net.minecraft.world.EnumSkyBlock;
|
import net.minecraft.world.EnumSkyBlock;
|
||||||
@ -513,7 +509,9 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void refreshChunk(World world, net.minecraft.world.chunk.Chunk nmsChunk) {
|
public void refreshChunk(FaweChunk fc) {
|
||||||
|
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
||||||
|
Chunk nmsChunk = fs.getChunk();
|
||||||
if (!nmsChunk.isLoaded()) {
|
if (!nmsChunk.isLoaded()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -523,74 +521,42 @@ public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, ExtendedBlo
|
|||||||
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
|
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
|
||||||
int x = pos.chunkXPos;
|
int x = pos.chunkXPos;
|
||||||
int z = pos.chunkZPos;
|
int z = pos.chunkZPos;
|
||||||
if (!chunkMap.contains(x, z)) {
|
PlayerChunkMapEntry chunkMapEntry = chunkMap.getEntry(x, z);
|
||||||
|
if (chunkMapEntry == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
EntityTracker tracker = w.getEntityTracker();
|
final ArrayDeque<EntityPlayerMP> players = new ArrayDeque<>();
|
||||||
HashSet<EntityPlayerMP> players = new HashSet<>();
|
chunkMapEntry.hasPlayerMatching(input -> {
|
||||||
for (EntityPlayer player : w.playerEntities) {
|
players.add(input);
|
||||||
if (player instanceof EntityPlayerMP) {
|
return false;
|
||||||
if (chunkMap.isPlayerWatchingChunk((EntityPlayerMP) player, x, z)) {
|
});
|
||||||
players.add((EntityPlayerMP) player);
|
int mask = fc.getBitMask();
|
||||||
}
|
if (mask == 65535 && hasEntities(nmsChunk)) {
|
||||||
}
|
SPacketChunkData packet = new SPacketChunkData(nmsChunk, 65280);
|
||||||
}
|
|
||||||
if (players.size() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
HashSet<EntityTrackerEntry> entities = new HashSet<>();
|
|
||||||
ClassInheritanceMultiMap<Entity>[] entitieSlices = nmsChunk.getEntityLists();
|
|
||||||
IntHashMap<EntityTrackerEntry> entries = null;
|
|
||||||
for (Field field : tracker.getClass().getDeclaredFields()) {
|
|
||||||
if (field.getType() == IntHashMap.class) {
|
|
||||||
field.setAccessible(true);
|
|
||||||
entries = (IntHashMap<EntityTrackerEntry>) field.get(tracker);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (ClassInheritanceMultiMap<Entity> slice : entitieSlices) {
|
|
||||||
if (slice == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (Entity ent : slice) {
|
|
||||||
EntityTrackerEntry entry = entries != null ? entries.lookup(ent.getEntityId()) : null;
|
|
||||||
if (entry == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
entities.add(entry);
|
|
||||||
SPacketDestroyEntities packet = new SPacketDestroyEntities(ent.getEntityId());
|
|
||||||
for (EntityPlayerMP player : players) {
|
for (EntityPlayerMP player : players) {
|
||||||
player.connection.sendPacket(packet);
|
player.connection.sendPacket(packet);
|
||||||
}
|
}
|
||||||
|
mask = 255;
|
||||||
}
|
}
|
||||||
}
|
SPacketChunkData packet = new SPacketChunkData(nmsChunk, mask);
|
||||||
// Send chunks
|
|
||||||
SPacketChunkData packet = new SPacketChunkData(nmsChunk, 65535);
|
|
||||||
for (EntityPlayerMP player : players) {
|
for (EntityPlayerMP player : players) {
|
||||||
player.connection.sendPacket(packet);
|
player.connection.sendPacket(packet);
|
||||||
}
|
}
|
||||||
// send ents
|
|
||||||
for (EntityTrackerEntry entry : entities) {
|
|
||||||
try {
|
|
||||||
TaskManager.IMP.later(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
for (EntityPlayerMP player : players) {
|
|
||||||
boolean result = entry.trackingPlayers.remove(player);
|
|
||||||
if (result && entry.getTrackedEntity() != player) {
|
|
||||||
entry.updatePlayerEntity(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 2);
|
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
MainUtil.handleError(e);
|
MainUtil.handleError(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Throwable e) {
|
|
||||||
MainUtil.handleError(e);
|
public boolean hasEntities(Chunk nmsChunk) {
|
||||||
|
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||||
|
for (int i = 0; i < entities.length; i++) {
|
||||||
|
ClassInheritanceMultiMap<Entity> slice = entities[i];
|
||||||
|
if (slice != null && !slice.isEmpty()) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public FaweChunk<Chunk> getFaweChunk(int x, int z) {
|
public FaweChunk<Chunk> getFaweChunk(int x, int z) {
|
||||||
|
Loading…
Reference in New Issue
Block a user